如何使用DataContractSerializer从文件反序列化WCF soap响应消息?

时间:2017-05-02 15:22:17

标签: c# wcf soap datacontractserializer

当我调用Web服务操作时,WCF使用DataContractSerializer将消息反序列化到代理类:为什么我不能这样做?

以下是ActLoginResponse.xml文件中的soap消息:

<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>

相应的ActLoginResponse类的WCF代理代码为:

[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;
    }
}

所以我需要将XML解析为ActLoginResponse类型的对象实例。

以下是我执行解析的方法:

        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);

创建了actLogin对象,但内容actLogin.return总是为NULL!我错过了什么吗?

3 个答案:

答案 0 :(得分:4)

我使用了您从其他问题提供的WSDL并从中创建了一个代理类。

使用上面的XML,我似乎没有问题通过以下方式反序列化到ActLoginResponse

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(ActLoginResponse));
XmlSerializer xmlSerializer = new XmlSerializer(mapp); //typeof(T), xr
var o = (ActLoginResponse)xmlSerializer.Deserialize(m.GetReaderAtBodyContents());

reference

答案 1 :(得分:2)

您应该可以使用rpois(1,lab)SoapReflectionImporter的帮助下完成此操作。

XmlSerializer
  

SoapReflectionImporter类提供类型映射   SOAP编码的消息部分,在Web服务描述中定义   语言(WSDL)文档。它仅在Web服务或客户端时使用   指定SOAP编码,如SOAP 1.1的第5节中所述   说明书

以下命令用于从WSDL生成客户端合同

var importer = new SoapReflectionImporter("urn:PlotiIntf-IPloti");
var mapping = importer.ImportTypeMapping(typeof(ActLoginResponse));
var serializer = new XmlSerializer(mapping);
var response = serializer.Deserialize(reader) as ActLoginResponse;

答案 2 :(得分:2)

这是一个古老的版本,但它是我在Google上首次搜索如何反序列化对象时出现的,因此,我认为有必要在.NET Core中发布适用于我的解决方案。

在我们的例子中,我们使用svcutil工具从WSDL生成了代码,然后使用了XmlSerializer,但是它抛出了无效的操作异常。解决方法是将XmlRoot属性添加到我们的对象(即Soap Envelope的第一个元素)。

所以我们必须像这样装饰对象:

    [System.Xml.Serialization.XmlRoot(ElementName = "Foo", Namespace = "ns")]
    public partial class FooType
    {
    }

然后我们可以像这样反序列化:

            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);

希望这对其他人有帮助:)