简体   繁体   中英

C# Deserialization problem

I have the following class:

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="urn:eu.emsa.ssn")]
public partial class SSN_ReceiptType {

    private Header1Type headerField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Order=0)]
    public Header1Type Header {
        get {
            return this.headerField;
        }
        set {
            this.headerField = value;
        }
    }
}

And the following XML:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <SSN_Receipt xmlns="urn:eu.emsa.ssn">
        <Header StatusMessage="SomethingSomething" StatusCode="Blabla" SSNRefId="N/A" MSRefId="2674762" Version="2.0" To="NCANOHAU1" SentAt="2010-11-12T14:48:44Z" From="SSN"/>
    </SSN_Receipt>

And I use this typed method to deserialize (by calling Deserialize<SSN_ReceiptType>(xmlGoesHere)):

    /// <summary>
    /// Deserialize xml string to object of type T
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="xml"></param>
    /// <returns></returns>
    public static T Deserialize<T>(string xml)
    {
        try
        {

            // Create serializer
            var xs = new XmlSerializer(typeof(T));

            // Deserialize
            T t = (T)xs.Deserialize(new StringReader(xml));

            return t;
        }
        catch (Exception e)
        {
            log.Error(string.Format("Unable to deserialize XML: {0}", xml), e);

            return default(T);
        }
    }

Now here's the kicker. This used to work. But recently we received a new version of the XSD used to generate the classes, and after generating the new code (which is unchanged for this class, and seen above) I receive the following exception when trying to deserialize:

System.SystemException: "There is an error in XML document (1, 57)"

And furthermore:

System.InnerException: <SSN_Receipt xmlns='urn:eu.emsa.ssn'> was not expected.

What the hell? :SI tried adding an XmlRootAttribute specifying "SSN_Receipt", that did not help one bit. Anyone know what's going on?

Update: relevant sections from the XSD:

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns:ssn="urn:eu.emsa.ssn" 
    attributeFormDefault="unqualified" 
    elementFormDefault="qualified" 
    targetNamespace="urn:eu.emsa.ssn">
[...]
<xsd:element name="SSN_Receipt" type="ssn:SSN_ReceiptType"/>
[...]
<xsd:complexType name="SSN_ReceiptType">
    <xsd:annotation>
        <xsd:documentation xml:lang="en"/>
    </xsd:annotation>
    <xsd:sequence>
        <xsd:element name="Header" type="ssn:Header1Type"/>
    </xsd:sequence>
</xsd:complexType>

For future reference for other poor souls, here is the solution I came up with.

As mentioned in my question, my classes are generated from an XSD. I tested the previous version of our classes, and they work just fine still. Additionally, SOAP services which utilize the same classes also works. Inspecting the trace log, I can't see anything revealing in particular.

But I found a concrete solution. I added the following attribute to my class:

[System.Xml.Serialization.XmlRoot(Namespace = "urn:eu.emsa.ssn", 
                                  ElementName = "SSN_Receipt")]

Now, I don't want to litter my generated classes with custom code, so I added a partial class:

[System.Xml.Serialization.XmlRoot(Namespace = "urn:eu.emsa.ssn", 
                                  ElementName = "SSN_Receipt")]
public partial class SSN_ReceiptType {}

This fixes my problem completely. But I still don't understand why this broke in the first place.

If anyone can come up with a good testable answer to why it broke, I will make that the proper answer.

Thank you for your time guys! This has been an educational experience, to some extent :)

I'm pretty sure your xml should read

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<ssn:SSN_Receipt xmlns="urn:eu.emsa.ssn"> 
    <ssn:Header StatusMessage="SomethingSomething" StatusCode="Blabla" SSNRefId="N/A" MSRefId="2674762" Version="2.0" To="NCANOHAU1" SentAt="2010-11-12T14:48:44Z" From="SSN"/> 
</ssn:SSN_Receipt> 

You should have a SSN_Receipt class generated. You need to use that class when passing it to the deserialization method.

IE:

Deserialize<SSN_Receipt>(xmlGoesHere);

and not the SSN_ReceiptType

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM