When I call a web service operation, WCF deserializes the message to the proxy class with the DataContractSerializer: why couldn't I do the same ?
Here is the soap message in the file ActLoginResponse.xml:
<SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="urn:PlotiIntf" xmlns:ns2="urn:PlotiIntf-IPloti" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<s:Header xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"/>
<SOAP-ENV:Body SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<ns2:ActLoginResponse>
<return>
<ResultCode>0</ResultCode>
<ResultMessage>Login et password correct.</ResultMessage>
<Acteur>
<Id>IMT_706</Id>
<Nom>IMA PROTECT</Nom>
<Prenom/>
<nbFI>0</nbFI>
<FonctionActeur>TS</FonctionActeur>
<Timeout>30</Timeout>
</Acteur>
<ZneGeoList xsi:nil="true"/>
</return>
</ns2:ActLoginResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
The WCF proxy code for the corresponding ActLoginResponse class is :
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
[System.ServiceModel.MessageContractAttribute(WrapperName="ActLoginResponse", WrapperNamespace="urn:PlotiIntf-IPloti", IsWrapped=true)]
public partial class ActLoginResponse {
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="", Order=0)]
public Ploti.PlotiClient.LoginResponseType @return;
public ActLoginResponse() {
}
public ActLoginResponse(Ploti.PlotiClient.LoginResponseType @return) {
this.@return = @return;
}
}
So I need to parse the XML to an object instance of type ActLoginResponse.
Here is how I perform the parsing:
ActLoginResponse body;
FileStream stream = new FileStream("Requests\\ActLoginResponse.xml", FileMode.Open);
XmlReader xmlReader = XmlReader.Create(stream);
xmlReader.MoveToContent();
xmlReader.ReadStartElement();
xmlReader.MoveToContent();
xmlReader.ReadStartElement();
xmlReader.MoveToContent();
xmlReader.ReadStartElement();
xmlReader.MoveToContent();
// the the reader is on the element ActLoginResponse (that is confirmed by a Log.Debug( xmlReader.ReadOuterXml());
// I create The DataContractSerializer: exception if nampespace is not specified
DataContractSerializer dataContract = new `DataContractSerializer`(typeof(ActLoginResponse), "ActLoginResponse", "urn:PlotiIntf-IPloti");
ActLoginResponse actLogin = dataContract.ReadObject(xmlReader, true);
The actLogin object is created, but the content actLogin.return is allways NULL ! Did I miss something ?
This is an old one, but it came up as my first search on Google for how to deserialize an object, so I thought it would be worthwhile to post the solution that worked for me in .NET Core.
In our case, we generated the code from the WSDL using the svcutil tool, and then used XmlSerializer
, but it was throwing an invalid operation exception. The fix was to add the XmlRoot
attribute to our object (that is, the first element of the Soap Envelope).
So we had to decorate the object like this:
[System.Xml.Serialization.XmlRoot(ElementName = "Foo", Namespace = "ns")]
public partial class FooType
{
}
And then we could deserialize like so:
using var stream = new MemoryStream(Encoding.UTF8.GetBytes(/* stream object */));
using var message = Message.CreateMessage(XmlReader.Create(stream), int.MaxValue, MessageVersion.Soap11);
using var xmlStream = message.GetReaderAtBodyContents();
var serializer = new XmlSerializer(typeof(FooType));
var obj = serializer.Deserialize(xmlStream);
Hopefully this helps others :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With