XML deserialization ignores properties out of alph

2020-04-18 00:42发布

问题:

I have small problem - XML deserialization completely ignores items, which are out of alphabetic order. In example object (description in end of question), Birthday node is after FirstName node, and it is ignored and assigned default value after deserialization. Same for any other types and names (I had node CaseId of Guid type after node Patient of PatientInfo type, and after deserialization it had default value).

I'm serializing it in one application, using next code:

public static string SerializeToString(object data)
{
    if (data == null) return null;
    XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
    ns.Add("", "");

    // what should the XmlWriter do?
    var settings = new XmlWriterSettings
    {
        OmitXmlDeclaration = true,
        NewLineChars = ""
    };

    using (var stringwriter = new System.IO.StringWriter())
    {
        // Use an XmlWriter to wrap the StringWriter
        using (var xmlWriter = XmlWriter.Create(stringwriter, settings))
        {
            var serializer = new XmlSerializer(data.GetType(), "");
            // serialize to the XmlWriter instance
            serializer.Serialize(xmlWriter, data, ns);
            return stringwriter.ToString();
        }
    }
}

Such approach was used to get proper result as argument for WebMethod (full problem described here). Results are something like this:

<PatientInfo><FirstName>Foo</FirstName><Birthday>2015-12-19T16:21:48.4009949+01:00</Birthday><RequestedClientID>00000000-0000-0000-0000-000000000000</RequestedClientID>00000000-0000-0000-0000-000000000000</patientId></PatientInfo>

Also I'm deserializing it in another application in simple manner

public static T Deserialize<T>(string xmlText)
{
    if (String.IsNullOrEmpty(xmlText)) return default(T);
    using (var stringReader = new StringReader(xmlText))
    {
        var serializer = new XmlSerializer(typeof(T));
        return (T)serializer.Deserialize(stringReader);
    }
}

Example object:

[XmlRoot("PatientInfo")]
public class PatientInfo
{
    [XmlElement("FirstName")]
    public string FirstName { get; set; }
    [XmlElement("LastName")]
    public string LastName { get; set; }
    [XmlElement("SSN")]
    public string SSN { get; set; }
    [XmlElement("Birthday")]
    public DateTime? Birthday { get; set; }
    [XmlElement("RequestedClientID")]
    public Guid RequestedClientID { get; set; }
    [XmlElement("patientId")]
    public Guid patientId { get; set; }
}

So, I'd like to have answer for one of two questions - 1) How can I adjust my serialization to have all items in alphabetical order? 2) How can I adjust my deserialization, so it won't ignore items out of alphabetical order?

Any help is appreciated.

Update:

Just figured out, that deserialization method I'm using is not actually used at all in my problem, since I'm using serialized info as data with WebMethod, and it is deserialized with some internal mechanism of WCF.

回答1:

WCF uses DataContractSerializer. This serializer is sensitive to XML element order, see Data Member Order. There's no quick way to disable this, instead you need to replace the serializer with XmlSerializer.

To do this, see Using the XmlSerializer Class, then and apply [XmlSerializerFormat] to your service, for instance:

[ServiceContract]
[XmlSerializerFormat]
public interface IPatientInfoService
{
    [OperationContract]
    public void ProcessPatientInfo(PatientInfo patient)
    {
        // Code not shown.
    }
}

[XmlRoot("PatientInfo")]
public class PatientInfo
{
    [XmlElement("FirstName")]
    public string FirstName { get; set; }
    [XmlElement("LastName")]
    public string LastName { get; set; }
    [XmlElement("SSN")]
    public string SSN { get; set; }
    [XmlElement("Birthday")]
    public DateTime? Birthday { get; set; }
    [XmlElement("RequestedClientID")]
    public Guid RequestedClientID { get; set; }
    [XmlElement("patientId")]
    public Guid patientId { get; set; }
}