如果它包含的 xml 变得稍大,为什么我不能反序列化我的对象? [英] Why can't I deserialize my object if the xml it contains gets slightly larger?

查看:30
本文介绍了如果它包含的 xml 变得稍大,为什么我不能反序列化我的对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在尝试使用 REST API 向 Azure 服务总线发送消息并使用 .NET azure 服务总线客户端 API 类接收消息时遇到问题.我可以单独使用 SDK 愉快地使用这些对象发送和接收消息,但在尝试使用 REST api 时遇到问题.

I am having an issue trying to send a message to the Azure service bus using the REST API and have it received using the .NET azure service bus client API classes. I can happily send and receive messages using these objects using the SDK alone, but get problems when trying to use the REST api.

我已将问题缩小到我认为的最小重现.基本上,如果我使用少量 XML 序列化我的对象作为有效负载,那么一切正常.如果我添加更多的 XML,那么反序列化它就会出现异常.这应该剪切并粘贴到一个新的控制台应用程序中以允许重现问题:

I have narrowed the issue down to this minimal repro I think. Basically if I serialize my object with a small amoutn of XML as the payload thee everything works ok. If I add slightly more XML then I get an exception deserializing it. this should cut&paste into a new console application to allow repro of the issue:

using System.IO;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Xml;
using System.Xml.Linq;
using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main(string[] args)
    {
        GetMessageBytes(Guid.NewGuid());
    }

    private static byte[] GetMessageBytes(Guid requestId)
    {
        var payload = XElement.Parse(@"
<blah Type='TransactionRequest' Version='1' xmlns=''>
    <SomeData Type='Request' Selection='All'></SomeData>
</blah>");

        var invalidPayload = XElement.Parse(@"
<blah Type='TransactionRequest' Version='1' xmlns=''>
    <SomeData Type='Request' Selection='All'></SomeData>
    <SomeData Type='Request' Selection='All'></SomeData>
    <SomeData Type='Request' Selection='All'></SomeData>
    <SomeData Type='Request' Selection='All'></SomeData>
    <SomeData Type='Request' Selection='All'></SomeData>
</blah>");
        Message<XElement> message = new Message<XElement>()
        {
            Label = "Label",
            RequestId = requestId,
            Payload = payload
        };

        var messageBytes = EncodeMessage(message);
        var expectedResponse = DecodeMessage<Message<XElement>>(messageBytes);

        message = new Message<XElement>()
        {
            Label = "Label",
            RequestId = requestId,
            Payload = invalidPayload
        };

        messageBytes = EncodeMessage(message);
        expectedResponse = DecodeMessage<Message<XElement>>(messageBytes);
        Console.WriteLine(expectedResponse);
        return messageBytes;
    }

    private static byte[] EncodeMessage<T>(T message)
    {
        DataContractSerializer serializer = new DataContractSerializer(typeof(T));
        var memoryStream = new MemoryStream();
        XmlDictionaryWriter binaryDictionaryWriter = XmlDictionaryWriter.CreateBinaryWriter(memoryStream);
        serializer.WriteObject(binaryDictionaryWriter, message);
        binaryDictionaryWriter.Flush();
        var bytesToPost = memoryStream.GetBuffer();
        return bytesToPost;
    }

    private static T DecodeMessage<T>(byte[] response)
    {
        var ms = new MemoryStream(response);
        var serializer = new DataContractSerializer(typeof(T));
        XmlDictionaryReader binaryDictionaryReader = XmlDictionaryReader.CreateBinaryReader(ms, XmlDictionaryReaderQuotas.Max);

        var message = serializer.ReadObject(binaryDictionaryReader);
        return (T)message;
    }
}

[MessageContract(WrapperName = "Message", WrapperNamespace = "http://blah.co.uk/contracts", IsWrapped = true)]
public sealed class Message<T>        where T : class
{
    [MessageHeader(Namespace = "http://blah.co.uk/contracts", Name = "RequestId")]
    public Guid RequestId { get; set; }

    [MessageHeader(Namespace = "http://blah.co.uk/contracts", Name = "Label")]
    public string Label { get; set; }

    [MessageBodyMember(Namespace = "http://blah.co.uk/contracts", Name = "Payload")]
    public T Payload { get; set; }

    [MessageBodyMember(Namespace = "http://blah.co.uk/contracts", Name = "MonitoringResults")]
    public MessageTimestamp MessageTimestamp { get; set; }


}

[DataContract]
public class MessageTimestamp
{
    private ICollection<Timestamp> timestamps = new List<Timestamp>();

    [DataMember]
    public ICollection<Timestamp> GetAllTimestamps
    {
        get
        {
            return timestamps.ToList();
        }

        private set
        {
            timestamps = new List<Timestamp>(value);
        }
    }        
}

public class Timestamp
{
    public Operation Operation { get; set; }
    public DateTime StartTime { get; set; }
    public DateTime EndTime { get; set; }

    public TimeSpan TimeTaken
    {
        get
        {
            return EndTime - StartTime;
        }
    }
}

public enum Operation
{
    OverallProcessing
}

抛出的错误是:

反序列化类型对象时出错SerialisationIssue.Message1[[System.Xml.Linq.XElement, System.Xml.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]`.输入源格式不正确.

There was an error deserializing the object of type SerialisationIssue.Message1[[System.Xml.Linq.XElement, System.Xml.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]`. The input source is not correctly formatted.

我已经尝试序列化大量的 XML(即没有 Message 包装器)并且工作正常,所以我确定它实际上与 XML 的大小无关,但是始终如一地让它崩溃.

I have tried serialising large amounts of just XML (ie no Message<XElement> wrapper) and that works ok, so I'm sure its not actually related to the size of the XML, but that consistently make it break.

我已经反映了在 ServiceBus SDK 客户端库中使用的实际类,并尝试使用在那里找到的反序列化器 (DataContractBinarySerializer) 但这没有任何区别,似乎基本上和我在做同样的事情无论如何手动.

I've reflected the actual class that is used in the ServiceBus SDK client libraries and tried to use the deserialiser found in there (DataContractBinarySerializer) but that has made no difference and seems to basically do the same thing that I'm doing manually anyway.

关于如何找到实际问题的任何想法?我该如何修复它?

Any ideas on how I can find what the actual problem is? And how I might go about fixing it?

推荐答案

所以这个问题确实与 XmlBinaryReader 中的一些明显错误有关,如本 连接问题

So the issue is indeed related to some apparent bug in the XmlBinaryReader as outlined in this connect issue

这可以通过在序列化数据的末尾写入一些空格来解决,如 这篇文章

which can be worked around by writing some whitespace at the end of the serialized data, as suggested in this post

这篇关于如果它包含的 xml 变得稍大,为什么我不能反序列化我的对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆