Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to parse a soap message loaded from a file?

I need to parse a SOAP message I load from the disk, to the type of the generated proxy. WCF does it when it receives the message from the http server, so I should be able to do it from the disk.

I consume a webservice with WCF, I generated the proxy client from the remote WSDL.

Here is the XML structure I received from the network (it was logged with System.ServiceModel.MessageLogging) that I want to parse to the generated class CRResponse.:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns1="urn:PourtuIntf" xmlns:ns2="ns2:PourtuIntf-IPourtu">
   <SOAP-ENV:Header/>
   <SOAP-ENV:Body SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
      <ns2:GetCRResponse>
         <return>
            <ResultCode>0</ResultCode>
            <CR>
               <Theme SOAP-ENC:arrayType="ns1:ItemType[5]">
                  <item>
                     <Key/>
                     <Section SOAP-ENC:arrayType="ns1:Section[3]">
...

When I call the operation 'GetCR' of the web service, the message is correctly converted to the WCF generated proxy client type GetCRResponse, but I don't knwo how WCF works and I need to parse the file from the disk.

I tried to parse the message that way:

  GetCRResponse body;
  using (var xmlReader =  XmlReader.Create("Requests\\CR.xml"))
  {
      Message m = Message.CreateMessage(xmlReader, int.MaxValue, MessageVersion.Soap11);
      body = m.GetBody<GetCRResponse>();
  }

In the GeyBody method this exception is raised:

Expected element 'ActGetCRResponse' from namespace 'http://schemas.datacontract.org/2004/07/Pourtu.PourtuClient'.. Detecting 'Element' with name 'ActGetCRResponse', namespace 'urn:PourtuIntf-IPourtu'.

I tried using the SoapFormatter:

using ( FileStream fs = new FileStream("Requests\\CR.xml", FileMode.Open) )
{
    SoapFormatter formatter = new SoapFormatter();
    body = (ActGetCRResponse)formatter.Deserialize(fs);
}

..the Deserialize throws the following exception: Analysis error, no assembly associated to the xml key 'ns2 GetCRResponse'.

I cannot use the xml serializer to deserialize to GetCRResponse beceause of the attributes SOAP-ENC:arrayType that need to be interpreted by the soap serializer.

like image 363
Anthony Brenelière Avatar asked Apr 28 '17 13:04

Anthony Brenelière


2 Answers

You should be able to use XmlSerializer to accomplish this with help of SoapReflectionImporter.

var importer = new SoapReflectionImporter("ns2:PourtuIntf-IPourtu");
var mapping = importer.ImportTypeMapping(typeof(GetCRResponse));
var serializer = new XmlSerializer(mapping);
var response = serializer.Deserialize(reader) as GetCRResponse;

The SoapReflectionImporter class provides type mappings to SOAP-encoded message parts, as defined in a Web Services Description Language (WSDL) document. It is used only when a Web service or client specifies SOAP encoding, as described in Section 5 of the SOAP 1.1 specification.

The following command was used to generate your client contracts from WSDL

SvcUtil.exe IPlotiservice.wsdl /t:code /serviceContract
like image 126
Eugene Komisarenko Avatar answered Oct 01 '22 16:10

Eugene Komisarenko


Updated:

Message m = Message.CreateMessage(XmlReader.Create("C:\\testSvc\\login.xml"), int.MaxValue, MessageVersion.Soap11);
            SoapReflectionImporter importer = new SoapReflectionImporter(new SoapAttributeOverrides(), "urn:PlotiIntf-IPloti");
            XmlTypeMapping mapp = importer.ImportTypeMapping(typeof(ActGetCRResponse));
            XmlSerializer xmlSerializer = new XmlSerializer(mapp); 
            var o = (ActGetCRResponse)xmlSerializer.Deserialize(m.GetReaderAtBodyContents());

reference

like image 1
Popo Avatar answered Oct 01 '22 16:10

Popo