无法使用DataContractSerializer反序列化xml

问题描述

我无法将此XML反序列化为对象,我不知道这是怎么回事:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
    <ProcessOneWayEvent xmlns="http://schemas.microsoft.com/sharepoint/remoteapp/">
        <properties xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
            <CultureLCID>1033</CultureLCID>
        </properties>
    </ProcessOneWayEvent>
</s:Body>
</s:Envelope>

这里已经准备好sample,是否有任何解决方法,因为我无法在请求中进行修改,所以我的模型有什么问题吗?是否有任何解决方案可以在不使用XmlSerializer

的情况下反序列化XML

https://dotnetfiddle.net/RfQMSD

解决方法

BodySPRemoteEventProperties必须位于"http://schemas.microsoft.com/sharepoint/remoteapp/"命名空间中:

[DataContract(Name = "Body",Namespace = "http://schemas.microsoft.com/sharepoint/remoteapp/")]
public class Body
{
    [DataMember(Name = "ProcessOneWayEvent")]
    public ProcessOneWayEvent ProcessOneWayEvent;
}

[DataContract(Name = "properties",Namespace = "http://schemas.microsoft.com/sharepoint/remoteapp/")]
public class SPRemoteEventProperties
{
    [DataMember(Name = "CultureLCID") ]
    public int CultureLCID { get; set; }
}

DataContractAttribute.Namespace控制数据协定对象的数据成员元素序列化到的名称空间,以及当数据协定对象是根元素时控制根元素的名称空间。由于元素<ProcessOneWayEvent xmlns="http://schemas.microsoft.com/sharepoint/remoteapp/">声明了新的默认XML名称空间,因此元素本身及其子元素都在此名称空间中。因此,包含的数据协定对象Body必须相应地设置其数据成员名称空间。对于<properties xmlns:i="http://www.w3.org/2001/XMLSchema-instance">i:名称空间不是默认名称空间,因此实际上没有元素被分配给该名称空间,并且SPRemoteEventProperties类型不应为其自身分配。

修复了小提琴here

,

我暂时不知道为什么它不起作用,但是一种替代方法是使用System.Xml.Serialization.XmlSerializer

首先通过将XML复制到新类中来创建适当的信封类(编辑→选择性粘贴→将XML作为类粘贴)

然后以这个为例反序列化:

byte[] byteArray = System.Text.Encoding.UTF8.GetBytes(request);
using (var stream = new MemoryStream(byteArray))
{
    var serializer = new XmlSerializer(typeof(Envelope));
    Envelope response = (Envelope)serializer.Deserialize(stream);
    Console.WriteLine(JsonConvert.SerializeObject(response));
}
,

尝试以下操作:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
namespace ConsoleApplication1
{

    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            string xml = File.ReadAllText(FILENAME);
            StringReader sReader = new StringReader(xml);
            XmlReader reader = XmlReader.Create(sReader);

            XmlSerializer serializer = new XmlSerializer(typeof(Envelope));
            Envelope envelope = (Envelope)serializer.Deserialize(reader);

        }
    }
    [XmlRoot(ElementName = "Envelope",Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
    public class Envelope
    {
        [XmlElement(ElementName = "Body",Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
        public Body Body { get; set; }
    }
    public class Body
    {
        [XmlElement(ElementName = "ProcessOneWayEvent",Namespace = "http://schemas.microsoft.com/sharepoint/remoteapp/")]
        public ProcessOneWayEvent ProcessOneWayEvent { get; set; }
    }
    public class ProcessOneWayEvent
    {
        public Properties properties { get; set; } 
    }
    public class Properties
    {
        public string CultureLCID { get; set; }
    }
}

使用Xml Linq

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.IO;
namespace ConsoleApplication1
{

    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            string xml = File.ReadAllText(FILENAME);
            XDocument doc = XDocument.Parse(xml);
            string CultureLCID = (string)doc.Descendants().Where(x => x.Name.LocalName == "CultureLCID").FirstOrDefault();


        }
    }

}