Failed deserializing xml due to namespaces

I have the following xml that i want to deserialize to a c# class:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tns="http://www.s1.com/info/" xmlns:types="http://www.s1.com/info/" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Header>
    <tns:SessionInfo>
      <SessionId xsi:type="xsd:string">string</SessionId>
    </tns:SessionInfo>
  </soap:Header>
  <soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
    <tns:LoginResponse>
      <Result xsi:type="xsd:boolean">boolean</Result>
    </tns:LoginResponse>
  </soap:Body>
</soap:Envelope>

I am using the following classes in order to deserialize the xml:

        public class SessionId
        {

            [XmlAttribute(AttributeName = "type", Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
            public string Type { get; set; }

            [XmlText]
            public string Text { get; set; }
        }

        [XmlRoot(ElementName = "SessionInfo", Namespace = "http://www.s1.com/info/")]
        public class SessionInfo
        {

            [XmlElement(ElementName = "SessionId")]
            public SessionId SessionId { get; set; }

            [XmlAttribute(AttributeName = "id", Namespace = "")]
            public string Id { get; set; }

            [XmlText]
            public string Text { get; set; }
        }

        [XmlRoot(ElementName = "Header", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
        public class Header
        {

            [XmlElement(ElementName = "SessionInfo", Namespace = "http://www.s1.com/info/")]
            public SessionInfo SessionInfo { get; set; }
        }


        [XmlRoot(ElementName = "Result", Namespace = "")]
        public class Result
        {

            [XmlAttribute(AttributeName = "type", Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
            public string Type { get; set; }

            [XmlText]
            public string Text { get; set; }
        }

        [XmlRoot(ElementName = "LoginResponse", Namespace = "http://www.s1.com/info/")]
        public class LoginResponse
        {

            [XmlElement(ElementName = "Result")]
            public Result Result { get; set; }
        }

        [XmlRoot(ElementName = "Body", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
        public class Body
        {

            [XmlElement(ElementName = "LoginResponse", Namespace = "http://www.s1.com/info/")]
            public LoginResponse LoginResponse { get; set; }

            [XmlAttribute(AttributeName = "encodingStyle", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
            public string EncodingStyle { get; set; }

            [XmlText]
            public string Text { get; set; }
        }

        [XmlRoot(ElementName = "Envelope", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
        public class Envelope
        {

            [XmlElement(ElementName = "Header", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
            public Header Header { get; set; }

            [XmlElement(ElementName = "Body", Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
            public Body Body { get; set; }

            [XmlAttribute(AttributeName = "xsi", Namespace = "http://www.w3.org/2000/xmlns/")]
            public string Xsi { get; set; }

            [XmlAttribute(AttributeName = "xsd", Namespace = "http://www.w3.org/2000/xmlns/")]
            public string Xsd { get; set; }

            [XmlAttribute(AttributeName = "soapenc", Namespace = "http://www.w3.org/2000/xmlns/")]
            public string Soapenc { get; set; }

            [XmlAttribute(AttributeName = "tns", Namespace = "http://www.w3.org/2000/xmlns/")]
            public string Tns { get; set; }

            [XmlAttribute(AttributeName = "types", Namespace = "http://www.w3.org/2000/xmlns/")]
            public string Types { get; set; }

            [XmlAttribute(AttributeName = "soap", Namespace = "http://www.w3.org/2000/xmlns/")]
            public string Soap { get; set; }

            [XmlText]
            public string Text { get; set; }
        }

The problem is that the SessionId element is not getting deserialized, I am assuming due to the namespaces mismatch. I tried using an empty string as the namespace but that doesn't work either as it doesn't get recognized during deserialization.

Any insight on the problem is very much appreciated. Thank you!

Upvotes: 0

Views: 95

Answers (1)

Charles Mager
Charles Mager

Reputation: 26213

First, SessionId has the wrong namespace. It inherits this from the parent, you need to explicitly specify that it doesn't have one by setting it to an empty string.

Secondly, the xsi:type has a special meaning, you shouldn't try to deserialise this. It's used to indicate the content type of an element - in this case, string - and will be used by the serialiser. The implication is that this is one of many acceptable types. The simplest way to define this is using object.

Putting those together, this should work:

[XmlElement(ElementName = "SessionId", Namespace = "")]
public object SessionId { get; set; }

SessionId should contain a string object with value string.

I'd also note various other minor things:

  • You shouldn't specify all the namespace bindings (e.g. Xsd) as part of the model. This is lower level than this model and will be handled by the serialiser.
  • You only need XmlRoot on the root
  • You don't need XmlText properties where there isn't any text
  • You need to make a similar change to above to deserialise Result
  • ElementName and AttributeName will default to the name of the property, so you don't have to specify these if that's what you want

Taking that into account, this model should work:

public class SessionInfo
{
    [XmlElement(Namespace = "")]
    public object SessionId { get; set; }
}

public class Header
{
    [XmlElement(Namespace = "http://www.s1.com/info/")]
    public SessionInfo SessionInfo { get; set; }
}

public class LoginResponse
{
    [XmlElement(Namespace = "")]
    public object Result { get; set; }
}

public class Body
{
    [XmlElement(Namespace = "http://www.s1.com/info/")]
    public LoginResponse LoginResponse { get; set; }

    [XmlAttribute("encodingStyle", Namespace = "http://schemas.xmlsoap.org/soap/envelope/", Form = XmlSchemaForm.Qualified)]
    public string EncodingStyle { get; set; }
}

[XmlRoot(Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public class Envelope
{
    [XmlElement]
    public Header Header { get; set; }

    [XmlElement]
    public Body Body { get; set; }
}

You can see a working demo here. I've made one change to the source XML - I changed the Result value from boolean to true, else you'll get an exception because boolean isn't a valid value for that type.

Upvotes: 1

Related Questions