0

I am having a very hard time trying to deserialize the soap response below. I assume its because of the multiple namespaces or maybe because of the complex type (Serialization Array)

Soapformatter throws an Object reference exception and other more manual deserializations are returning an empty object. At this point I can only assume that I am not tagging my object correctly. What is the correct way to build out the BatchResponse object below so that it can deserialize from this response?

    <?xml version="1.0" encoding="UTF-8"?>
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
   <s:Header>
      <a:Action s:mustUnderstand="1">https://example.com/operations/fetch/BatchResponse</a:Action>
   </s:Header>
   <s:Body>
      <BatchResponse xmlns="https://example.com/operations">
         <BatchResult xmlns:b="https://example.com/responses" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
            <b:FailureMessages xmlns:c="http://schemas.microsoft.com/2003/10/Serialization/Arrays" i:nil="true" />
            <b:FailureType i:nil="true" />
            <b:ProcessedSuccessfully>true</b:ProcessedSuccessfully>
            <b:SessionId>1961810</b:SessionId>
            <b:TotalPages>38</b:TotalPages>
         </BatchResult>
      </BatchResponse>
   </s:Body>
</s:Envelope>

Also assuming Soapformatter continues to throw exceptions - what is the correct way to "xpath" to the BatchResponse object so that I can extract and deserialize?

Thanks

Gotts
  • 2,274
  • 3
  • 23
  • 32
  • The solution below works but NOT when the namespace contains two periods and a dash - for eg example.test-site.com - no idea why! – Gotts Sep 10 '19 at 17:58

2 Answers2

2

Try following :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

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

            XmlSerializer serializer = new XmlSerializer(typeof(Envelope));
            Envelope envelope = (Envelope)serializer.Deserialize(reader);
        }
    }
    [XmlRoot(ElementName = "Envelope", Namespace = "http://www.w3.org/2003/05/soap-envelope")]
    public class Envelope
    {
        [XmlElement(ElementName = "Header", Namespace = "http://www.w3.org/2003/05/soap-envelope")]
        public Header header { get; set; }

        [XmlElement(ElementName = "Body", Namespace = "http://www.w3.org/2003/05/soap-envelope")]
        public Body body { get; set; }
    }
    [XmlRoot(ElementName = "Header", Namespace = "http://www.w3.org/2003/05/soap-envelope")]
    public class Header
    {
        [XmlElement(ElementName = "Action", Namespace = "http://www.w3.org/2005/08/addressing")]
        public Action action { get; set; }
    }
    [XmlRoot(ElementName = "Action", Namespace = "http://www.w3.org/2005/08/addressing")]
    public class Action
    {
        [XmlAttribute(AttributeName = "mustUnderstand", Namespace = "http://www.w3.org/2003/05/soap-envelope")]
        public int mustUnderstand { get; set;}
        [XmlText]
        public string value { get;set;}
    }
    [XmlRoot(ElementName = "Body", Namespace = "")]
    public class Body
    {
        [XmlElement(ElementName = "BatchResponse", Namespace = "https://example.com/operations")]
        public BatchResponse batchResponse { get; set; }
    }
    [XmlRoot(ElementName = "BatchResponse", Namespace = "https://example.com/operations")]
    public class BatchResponse
    {
        [XmlElement(ElementName = "BatchResult", Namespace = "https://example.com/operations")]
        public BatchResult batchResult { get; set; }
    }
    [XmlRoot(ElementName = "BatchResult", Namespace = "https://example.com/operations")]
    public class BatchResult
    {
        [XmlElement(ElementName = "FailureMessages", Namespace = "https://example.com/responses")]
        public string failureMessages { get; set; }

        [XmlElement(ElementName = "FailureType", Namespace = "https://example.com/responses")]
        public string failureType { get; set; }

        [XmlElement(ElementName = "ProcessedSuccessfully", Namespace = "https://example.com/responses")]
        public Boolean  processedSuccessfully { get; set; }

        [XmlElement(ElementName = "SessionId", Namespace = "https://example.com/responses")]
        public string sessionId { get; set; }

        [XmlElement(ElementName = "TotalPages", Namespace = "https://example.com/responses")]
        public int totalPages { get; set; }

    }
}
jdweng
  • 33,250
  • 2
  • 15
  • 20
  • amazing that worked! Thank you. Is there a way I can deserialize just from the Body (ie the actual object itself) without dealing with the whole envelope? – Gotts Sep 10 '19 at 11:56
  • XML Serialization does not require all properties to work. Just public properties are serialized and deserialized. You need all the parents to the body, but not all the properties in each parent. – jdweng Sep 10 '19 at 12:05
  • thanks for clarifying. I was going to ask if that was necessary. However I have discovered that its still not working for me. I had modified the namespace domain name in the example for privacy reasons. With my domain name its not working. It seems to have to do with having a more complex domain name. I rebuilt the whole example and when https://example.com/operations is used (as per above ) it works. But if I switch that with https://example.test-site.com/operations it serializes to a NULL on the BatchResponse object!! Why would that be? What can i do? – Gotts Sep 10 '19 at 12:36
  • It looks like its the "subdomain" that makes problems. test-site.com works. example.test-site.com does not work – Gotts Sep 10 '19 at 12:49
  • I cannot see the link you provide because I'm blocked. Will not be able to look at links until later. Five reasons for not getting object 1) Namespace is wrong. 2) Element name is wrong. It is uppercase/lowercase sensitive 3) Properties are not public. 4) You are using wrong type Element/Attribute 5) You have arrays. – jdweng Sep 10 '19 at 12:52
  • Does xml contain a schema? The XmlReader will check the schema. I would check the xml against the schema. You can use VS. From menu : Project : Add New Item : Xml File. Paste your xml into view. Any error will show up on the error list like compiler errors. – jdweng Sep 10 '19 at 13:02
  • no there is no schema. Bottom line when the namespace has a dash and a subdomain it wont work :( – Gotts Sep 10 '19 at 13:25
  • The code I tested had dashes in namespace and worked. Why? – jdweng Sep 10 '19 at 13:56
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/199255/discussion-between-gotts-and-jdweng). – Gotts Sep 10 '19 at 16:15
0

you can use local-name() to ignore the namespace in xpath

//*[local-name()='Envelope']/*[local-name()='Body']/*[local-name()='BatchResponse']
Ed Bangga
  • 12,879
  • 4
  • 16
  • 30