Невозможно десериализовать сообщение SOAP программно - PullRequest
4 голосов
/ 26 мая 2011

Я получаю следующее исключение при попытке десериализации сообщения мыла.Я делаю это так, потому что у меня есть файлы ответов, которые я хочу использовать в тестировании.Я не могу использовать реальный сервис или тому подобное, так как он не соответствует архитектуре для имеющейся у нас инфраструктуры тестирования.

    Test 'MyUnitTestMethod' failed: System.InvalidOperationException : There is an error in XML document (1, 2).
----> System.InvalidOperationException : <MySpecialResponse xmlns='http://xsd.com/msgs/v1'> was not expected. 
at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events) 
at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle) 
at System.Xml.Serialization.XmlSerializer.Deserialize(Stream stream)


private const string _content =
@"<soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"">
  <soapenv:Body>
    <ns3:MySpecialResponse xmlns:ns3=""http://xsd.com/msgs/v1"" >
      <header>
        <status>0</status>
      </header>
      <ns3:Payload>
        <ns3:CustomerName>name</ns3:CustomerName>
        <ns3:EmailAddress>test1@mail.com</ns3:EmailAddress>
      </ns3:Payload>
    </ns3:MySpecialResponse>
  </soapenv:Body>
</soapenv:Envelope>";

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "2.0.50727.3082")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://xsd.com/msgs/v1")]
public partial class MySpecialResponse : BaseResponse {

    private MySpecialPayload payloadField;

    /// <remarks/>
    public MySpecialPayload Payload {
        get {
            return this.payloadField;
        }
        set {
            this.payloadField;= value;
        }
    }
}

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "2.0.50727.3082")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://xsd.com/msgs/v1")]
public partial class MySpecialPayload {

    private string customerNameField;

    private string emailAddressField;

    /// <remarks/>
    public string CustomerName {
        get {
            return this.customerNameField;
        }
        set {
            this.customerNameField = value;
        }
    }

    /// <remarks/>
    public string EmailAddress {
        get {
            return this.emailAddressField;
        }
        set {
            this.emailAddressField = value;
        }
    } 
}

//The code I am using - might not be right?
  var serialiser = new System.Xml.Serialization.XmlSerializer(typeof(MySpecialResponse));


  using (var stream = new MemoryStream(Encoding.ASCII.GetBytes(_content))
  { 
      var doc = new System.Xml.XmlDocument();
      doc.Load(stream);

      var nsManager = new System.Xml.XmlNamespaceManager(doc.NameTable);
      nsManager.AddNamespace("soapenv", "http://schemas.xmlsoap.org/soap/envelope/");

      //so I can get the actual response and not the soap body
      var node = doc.SelectSingleNode("//soapenv:Body", nsManager);

      if (node != null)
      {
           byte[] xml = Encoding.UTF8.GetBytes(node.InnerXml);
           using (var memStream = new System.IO.MemoryStream(xml))
           {
                memStream.Position = 0;
                var resp = (MySpecialResponse)serialiser.Deserialize(memStream);  //Throws exception here
            }
      }
  }

(BaseResponse имеет поле заголовка)

Любые идеи, за исключением случаев, когда я получаю, и как я могу получить мыльное сообщение для десериализации сообщения в объект, будь то исправление моегокод или применение другой технологии.

Примечание: у меня есть много файлов, которые я хочу использовать универсальный метод для десериализации, поэтому я не буду знать заранее все пространства имен xml, только корневой тип ответа.

Спасибо

1 Ответ

8 голосов
/ 26 мая 2011

Хорошо, я решил это для себя.

Мне нужно было добавить XmlRootAttribute для XmlSerializer

var xRoot = new System.Xml.Serialization.XmlRootAttribute();
xRoot.ElementName = "MySpecialResponse";
xRoot.IsNullable = true;
xRoot.Namespace = rootResponseNamespace;

var serialiser = new System.Xml.Serialization.XmlSerializer(typeof(MySpecialResponse), xRoot);
...