zoukankan      html  css  js  c++  java
  • WCF和Delphi通信时序列化的问题

    起因:

    WCF序列化的对象Delphi可以正确的接收,但是Delphi序列化的对象WCF端接收就会因反序列化错误,导致接收到的对象为NULL。

    还未找到解决办法,现在用的是传递XML字符串的方法而不是直接序列化对象的方式来暂时解决这个问题。但是这样就会很繁琐,毕竟要拼凑XML是一件挺繁琐的事情。

    下面两段式用tcp trace抓到的soap

    C#:
    <MessageLogTraceRecord>
    <HttpRequest xmlns="http://schemas.microsoft.com/2004/06/ServiceModel/Management/MessageTrace">
    <Method>POST</Method>
    <QueryString></QueryString>
    <WebHeaders>
    <Connection>Keep-Alive</Connection>
    <Content-Length>385</Content-Length>
    <Content-Type>text/xml; charset=utf-8</Content-Type>
    <Expect>100-continue</Expect>
    <Host>pc-201007021201:8099</Host>
    <VsDebuggerCausalityData>uIDPozhfWXopshZDtHDngP/FfEwAAAAABlnI7S7LLE+3UhFI/NQahmUvtiY6tpBBkfIU7zTLAMsACQAA</VsDebuggerCausalityData>
    <SOAPAction>"http://tempuri.org/IService1/GetDataUsingDataContract"</SOAPAction>
    </WebHeaders>
    </HttpRequest>
    <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
    <s:Header>
    <To s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://pc-201007021201:8099/wcf/WcfServiceLibrary1.Service1.svc</To>
    <Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://tempuri.org/IService1/GetDataUsingDataContract</Action>
    </s:Header>
    <s:Body>
    <GetDataUsingDataContract xmlns="http://tempuri.org/">
    <composite xmlns:a="http://schemas.datacontract.org/2004/07/WcfServiceLibrary1" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <a:BoolValue>true</a:BoolValue>
    <a:StringValue>test</a:StringValue>
    </composite>
    </GetDataUsingDataContract>
    </s:Body>
    </s:Envelope>
    </MessageLogTraceRecord>

    Delphi:
    <MessageLogTraceRecord>
    <HttpRequest xmlns="http://schemas.microsoft.com/2004/06/ServiceModel/Management/MessageTrace">
    <Method>POST</Method>
    <QueryString></QueryString>
    <WebHeaders>
    <Cache-Control>no-cache</Cache-Control>
    <Connection>Keep-Alive</Connection>
    <Content-Length>482</Content-Length>
    <Content-Type>text/xml</Content-Type>
    <Host>pc-201007021201:8099</Host>
    <User-Agent>Borland SOAP 1.2</User-Agent>
    <SOAPAction>"http://tempuri.org/IService1/GetDataUsingDataContract"</SOAPAction>
    </WebHeaders>
    </HttpRequest>
    <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 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/">
    <To s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://pc-201007021201:8099/wcf/WcfServiceLibrary1.Service1.svc</To>
    <Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://tempuri.org/IService1/GetDataUsingDataContract</Action>
    </s:Header>
    <SOAP-ENV:Body>
    <GetDataUsingDataContract xmlns="http://tempuri.org/">
    <composite xmlns="http://schemas.datacontract.org/2004/07/WcfServiceLibrary1">
    <BoolValue>true</BoolValue>
    <StringValue>test</StringValue>
    </composite>
    </GetDataUsingDataContract>
    </SOAP-ENV:Body>
    </SOAP-ENV:Envelope>
    </MessageLogTraceRecord>

     


    我原以为因为C#中定义了2个“有名称命名空间,分别是a和i”,所以需要名称来区别命名空间。而Delphi中定义的是“无名称命名空间”,所以不要前缀才是正确的,没有前缀的都属于"无名称命名空间"
    现在不知道问题出在哪了,难道是
    <User-Agent>Borland SOAP 1.2</User-Agent>
    指定了是1.2,但是里面用的命名空间又是1.1的,所以冲突?(后面证实是错误的理解)

    SOAP 1.2 uses "http://www.w3.org/2003/05/soap-envelope"
    SOAP 1.1 uses "http://schemas.xmlsoap.org/soap/envelope/"

    最后察觉问题所在:

    还是命名空间冲突的问题
    <composite xmlns:a="http://schemas.datacontract.org/2004/07/WcfServiceLibrary1" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <a:BoolValue>true</a:BoolValue>
    <a:StringValue>test</a:StringValue>
    </composite>

    在上面所示的这种情况下,composite这个元素的命名空间仍然是为空的,也就是说.NET这边要求就是composite这个元素命名空间为空

    测试代码如下,因为WCF默认调用的是DataContractSerializer

            static void Serialize<T>(string filePath,object graph)
    {
    DataContractSerializer serializer = new DataContractSerializer(typeof(T));

    using (XmlWriter writer = new XmlTextWriter(filePath, Encoding.UTF8))
    {
    serializer.WriteObject(writer, graph);
    }

    }

        [DataContract(Namespace = "http://schemas.datacontract.org/2004/07/WcfServiceLibrary1")]
    public class CompositeType
    {
    bool boolValue = true;
    string stringValue = "Hello ";

    [DataMember]
    public bool BoolValue
    {
    get { return boolValue; }
    set { boolValue = value; }
    }

    [DataMember]
    public string StringValue
    {
    get { return stringValue; }
    set { stringValue = value; }
    }
    }


    我自己给CompositeType添加上了命名空间前缀,反序列化成功

    <a:CompositeType xmlns:a="http://schemas.datacontract.org/2004/07/WcfServiceLibrary1">
    <a:BoolValue>true</a:BoolValue>
    <a:StringValue>test</a:StringValue>
    </a:CompositeType>




    所以说反序列化丢失了相应的值,这样的话就会OK

    <composite xmlns:a="http://schemas.datacontract.org/2004/07/WcfServiceLibrary1" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <a:BoolValue>true</a:BoolValue>
    <a:StringValue>test</a:StringValue>

    <BoolValue>true<BoolValue>
    <StringValue>test<StringValue>
    </composite>


    或者这样

    <a:CompositeType xmlns:a="http://schemas.datacontract.org/2004/07/WcfServiceLibrary1">
        <a:BoolValue>true</a:BoolValue>
        <a:StringValue>test</a:StringValue>
    </a:CompositeType>


    问题结症找到了,但是解决方案只有把命名空间设置为空才行。很奇怪为什么会莫名其妙有个a:的前缀导致命名空间错误。我如何调整WCF序列化的行为呢?

  • 相关阅读:
    Golang结构体序列化与反序列化时默认值的问题
    Golang在函数中给结构体对象赋值的一个坑
    Go出现panic的场景
    Redis内存使用率增长的一些解决思路
    「转」50个Go新手容易犯的错误
    关系型数据库跨时区查询简介
    Golang中append与copy内置函数介绍
    实践案例1利用低代码开发平台Odoo快速构建律师事务所管理系统
    自助分析工具Power BI的简介和应用
    一个开源免费高颜值的轻量级商业智能BI平台Superset 介绍
  • 原文地址:https://www.cnblogs.com/lwzz/p/1947365.html
Copyright © 2011-2022 走看看