使用DataContractSerializer在WCF中序列化和反序列化XmlDocument

时间:2009-05-18 20:51:19

标签: .net xml wcf

我有一个WCF服务,它接受一个字符串作为其一个操作契约的参数。但是该字符串中包含xml内容。

我需要将其转换为标记为DataContract的类,但不会暴露给外界。

我需要使用DataContractSerializer,因为类成员将[DataMember]属性设置为其他名称。例如:属性Phone的DataMember名称设置为"Telephone",所以当我使用普通的序列化程序反序列化xmldocument时,我得到一个错误,因为反序列化器会查找Phone元素不存在。

如何使用XmlDocument反序列化DataContractSerializer?但有一个限制是我无法将xmldocument保存到文件中。

编辑:使用DataContractSerializer here.

找到一篇关于序列化和反序列化的优秀文章

我的客户代码:

string xmldata = "<Customer> + 
                System.Environment.NewLine+ 
                "<Age>1</Age>"+
                System.Environment.NewLine+
                "<BirthDate>1900-01-01T01:01:01.0000000-05:00</BirthDate>" + 
                System.Environment.NewLine+
                "<FistName>John</FistName>"+
                System.Environment.NewLine +
                "<LastName>Doe</LastName>" +
                System.Environment.NewLine +
                "</Customer>";

doc.LoadXml(xmldata); 
Service1Client a = new Service1Client();
a.GetData(doc.OuterXml.ToString());

我的服务代码:

public string GetData(string per)
{
    string xmldata = per;
    XmlDocument xmlDoc = new XmlDocument();
    xmlDoc.LoadXml(xmldata);
    XmlDemo.Person a = Person.Create();

    DataContractSerializer ser = new DataContractSerializer(a.GetType());
    StringWriter stringWriter = new StringWriter();
    XmlTextWriter xmlWriter = new XmlTextWriter(stringWriter);
    xmlDoc.WriteTo(xmlWriter);

    MemoryStream stream = new MemoryStream(Encoding.ASCII.GetBytes(stringWriter.ToString()));
    stream.Position = 0;
    XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(stream, new XmlDictionaryReaderQuotas());
    Person myContact = (Person)ser.ReadObject(reader, true);

    return string.Empty; 

}

我的DataContract:

[Serializable]
[DataContract(Name = "Customer")]
public class Person
{
    private Person() {}
    [DataMember(Name = "FistName")]
    public string FName { get; set; }
    [DataMember(Name = "LastName")]
    public string LName { get; set; }
    [DataMember(Name = "Age")]
    public int Age { get; set; }
    [DataMember(Name = "BirthDate")]
    public DateTime DOB { get; set; }

    public static Person Create()
    {
        return new Person();
    }
}

我在Person myContact =(Person)ser.ReadObject(reader,true)中收到此错误;

Error in line 1 position 11. Expecting element 'Customer' from namespace 'http://schemas.datacontract.org/2004/07/XmlDemo'.. Encountered 'Element'  with name 'Customer', namespace ''.

2 个答案:

答案 0 :(得分:3)

从字符串直接反序列化

MemoryStream stream = new MemoryStream(Encoding.ASCII.GetBytes("<myXml />"));
stream.Position = 0;
XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(stream, new XmlDictionaryReaderQuotas());
MyContact myContact = (MyContact)ser.ReadObject(reader, true);

从XmlDocument反序列化

StringWriter stringWriter = new StringWriter();
XmlTextWriter xmlWriter = new XmlTextWriter(stringWriter);
xmlDoc.WriteTo(xmlWriter);

MemoryStream stream = new MemoryStream(Encoding.ASCII.GetBytes(stringWriter.ToString()));
stream.Position = 0;
XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(stream, new XmlDictionaryReaderQuotas());
MyContact myContact = (MyContact)ser.ReadObject(reader, true);

答案 1 :(得分:1)

这是你的服务吗?如果是这样,那么不要在 string 参数中发送或接收XML,因为它们不是同一个东西。

此外,虽然您尚未将要将此XML反序列化到其中的DataContract公开,但您几乎已经通过公开XML来完成此操作。这在很大程度上是同样的效果。因此,您应该创建一个没有与之关联的行为的DataContract类,然后在ServiceContract中公开它。如果您需要在内部将其用作具有行为的类中的数据,则将数据复制到您从未公开的内部类的新实例中。


我仍然建议你通过将XML复制到字符串中来阻止这种愚蠢。仍然,根据您发布的代码和例外情况:

为什么这样做

XmlDemo.Person a = Person.Create();

然后在反序列化时将其擦除?

XmlDemo.Person a;

就足够了。然后使用typeof(XmlDemo.Person)而不是a.GetType()。

另外,你发布的Person类与“XmlDemo.Person”类完全相同吗?我非常想知道命名空间的来源。要消除我的不确定性,请尝试将[DataContract]属性更改为Namespace = String.Empty(或者Namespace = null)。

最后,你有没有听说过那个没有在实现IDisposable的类实例上调用Dispose的开发人员?