The SOAP client does not process XML objects properly; encountering "There is an error in the XML document",

Some users of our WCF web service encounter an exception when trying to parse our answers:

System.InvalidOperationException: There is an error in XML document (5, -349).
   at System.Xml.Serialization.XmlSerializer.Deserialize (XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
   at System.Xml.Serialization.XmlSerializer.Deserialize (XmlReader xmlReader, String encodingStyle)
   at System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse (SoapClientMessage message, WebResponse response, Stream responseStream, Boolean asyncCall)
   at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke (String methodName, Object [] parameters)
   at [Consumer Code]

An internal exception is as follows:

'', hexadecimal value 0x0B, is an invalid character. Line 5, position -349.

   at System.Xml.XmlTextReaderImpl.Throw (Exception e)
   at System.Xml.XmlTextReaderImpl.Throw (String res, String [] args)
   at System.Xml.XmlTextReaderImpl.ThrowInvalidChar (Int32 pos, Char invChar)
   at System.Xml.XmlTextReaderImpl.ParseNumericCharRefInline (Int32 startPos, Boolean expand, BufferBuilder internalSubsetBuilder, Int32 & charCount, EntityType & entityType)
   at System.Xml.XmlTextReaderImpl.ParseCharRefInline (Int32 startPos, Int32 & charCount, EntityType & entityType)
   at System.Xml.XmlTextReaderImpl.ParseText (Int32 & startPos, Int32 & endPos, Int32 & outOrChars)
   at System.Xml.XmlTextReaderImpl.ParseText ()
   at System.Xml.XmlTextReaderImpl.ParseElementContent ()
   at System.Xml.XmlTextReaderImpl.Read ()
   at System.Xml.XmlTextReader.Read ()
   at System.Xml.XmlReader.ReadElementString ()
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReader1.Read43_TextWidgetConfig (Boolean isNullable, Boolean checkType)
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReader1.Read45_TextWidgetInfo (Boolean isNullable, Boolean checkType)
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReader1.Read49_WidgetInfo (Boolean isNullable, Boolean checkType)
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReader1.Read50_InstantPageData (Boolean isNullable, Boolean checkType)
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReader1.Read128_GetInstantPageDataResponse ()
   at Microsoft.Xml.Serialization.GeneratedAssembly.ArrayOfObjectSerializer141.Deserialize (XmlSerializationReader reader)
   at System.Xml.Serialization.XmlSerializer.Deserialize (XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)

The returned client data has vertical tab characters. Looking at our XML, we could see that these characters displayed correctly as entities. Performing a quick Google search, we found that there is an error with XmlSerializerwhere it cannot handle certain objects, which must be fixed by changing the parameter in XML readers with auto-generated proxies.

, , . , , .

  • XmlSerializer ?
  • WCF, , -?

Update:

# 1. XML :

Char:: = # x9 | #xA | #xD | [# x20- # xD7FF] | [# xE000- # xFFFD] | [# X10000- # x10FFFF]

, , DataContractSerializer - . , .

2:

, DataContractSerializer Microsoft Connect.

+3
1

. ; ( ), , . , - - .

, , , , XML:

public class StripInvalidXmlCharactersBehaviorAttribute 
    : Attribute, IOperationBehavior
{
    public void AddBindingParameters(
        OperationDescription operationDescription, 
        BindingParameterCollection bindingParameters)
    {
    }

    public void ApplyClientBehavior(
        OperationDescription operationDescription, 
        ClientOperation clientOperation)
    {
        IOperationBehavior behavior =
            new StripInvalidXmlCharactersBehavior(operationDescription);
        behavior.ApplyClientBehavior(operationDescription, clientOperation);
    }

    public void ApplyDispatchBehavior(
        OperationDescription operationDescription, 
        DispatchOperation dispatchOperation)
    {
        IOperationBehavior behavior =
            new StripInvalidXmlCharactersBehavior(operationDescription);
        behavior.ApplyDispatchBehavior(
            operationDescription, dispatchOperation);
    }

    public void Validate(OperationDescription operationDescription)
    {
    }
}

:

internal class StripInvalidXmlCharactersBehavior 
    : DataContractSerializerOperationBehavior
{
    public StripInvalidXmlCharactersBehavior(OperationDescription opDesc)
        : base(opDesc)
    {
    }

    public override XmlObjectSerializer CreateSerializer(
        Type type, string name, string ns, IList<Type> knownTypes)
    {
        return new InvalidXmlStrippingSerializer(type, name, ns, knownTypes);
    }

    public override XmlObjectSerializer CreateSerializer(
        Type type, XmlDictionaryString name, XmlDictionaryString ns, 
        IList<Type> knownTypes)
    {
        return new InvalidXmlStrippingSerializer(type, name, ns, knownTypes);
    }
}

:

internal class InvalidXmlStrippingSerializer : XmlObjectSerializer
{
    private DataContractSerializer _innerSerializer;

    public InvalidXmlStrippingSerializer(
        Type type, string name, string ns, IList<Type> knownTypes)
    {
        _innerSerializer = 
            new DataContractSerializer(type, name, ns, knownTypes);
    }

    public InvalidXmlStrippingSerializer(
        Type type, XmlDictionaryString name, XmlDictionaryString ns, 
        IList<Type> knownTypes)
    {
        _innerSerializer =
            new DataContractSerializer(type, name, ns, knownTypes);
    }

    public override bool IsStartObject(XmlDictionaryReader reader)
    {
        return _innerSerializer.IsStartObject(reader);
    }

    public override object ReadObject(
        XmlDictionaryReader reader, bool verifyObjectName)
    {
        return _innerSerializer.ReadObject(reader, verifyObjectName);
    }

    public override void WriteEndObject(XmlDictionaryWriter writer)
    {
        _innerSerializer.WriteEndObject(writer);
    }

    public override void WriteObjectContent(
        XmlDictionaryWriter writer, object graph)
    {
        graph = fixBadStringsRecursive(graph);
        _innerSerializer.WriteObjectContent(writer, graph);
    }

    private object fixBadStringsRecursive(object graph)
    {
        var objType = graph.GetType();
        if (objType == typeof(string))
        {
            graph = removeInvalidCharacters(graph as string);
        }
        else if (graph is IEnumerable)
        {
            foreach (var item in graph as IEnumerable)
            {
                fixBadStringsRecursive(item);
            }
        }
        else if (objType.IsClass)
        {
            // Look through the properties of the object 
            foreach (var prop in graph.GetType().GetProperties())
            {
                var propParams = prop.GetIndexParameters();
                if ((propParams == null || propParams.Length == 0)
                    && prop.GetGetMethod() != null)
                {
                    var propVal = prop.GetValue(graph, null);
                    if (propVal != null)
                    {
                        propVal = fixBadStringsRecursive(propVal);
                        if (prop.GetSetMethod() != null)
                        {
                            prop.SetValue(graph, propVal, null);
                        }
                    }
                }
            }
        }
        return graph;
    }

    private static string removeInvalidCharacters(string source)
    {
        // This is per the W3C XML spec:
        // http://www.w3.org/TR/xml/#NT-Char
        return new string(
            (
                from ch in source
                where
                    ch == '\u0009' || ch == '\u000a' || ch == '\u000d'
                    || (ch >= '\u0020' && ch <= '\ud7ff')
                    || (ch >= '\ue000' && ch <= '\ufffd')
                select ch
            ).ToArray()
        );
    }

    public override void WriteStartObject(
        XmlDictionaryWriter writer, object graph)
    {
        _innerSerializer.WriteStartObject(writer, graph);
    }
}

, .

+2

Source: https://habr.com/ru/post/1792618/


All Articles