使用自定义WSDL和引用的模式,为什么不能正确地从对象序列化SOAP方法返回的Xml?

时间:2012-03-01 13:23:10

标签: c# asp.net soap wsdl linq-to-xsd

阅读本文后:

Improve Web Service Interoperability with XML Message Design

我决定将我们现有的消息设计模式导入到新的SOAP服务的WSDL中。

这完全在VS2008和.NET 3.5中,Altova XMLSpy 2009用于架构和wsdl设计。

所以我做了以下事情:

  1. 编写自定义WSDL,导入我们的XSD接口规范。
  2. 使用WSDL.EXE生成服务器存根代码
  3. 在Web服务项目中包含XSD
  4. 使用Linq To Xsd生成我们使用的强类型XDocument包装器
  5. 手动编辑生成的存根代码以删除冗余的自动生成的包装类
  6. 手动编辑存根代码以将WSDL中的类型映射到Linq2Xsd生成的包装器
  7. 禁用WSDL生成并使用WebServiceBindingAttribute
  8. 显式引用自定义WSDL
  9. 使用常规网络参考创建一个win form测试装备
  10. 好的,这是问题:

    SOAP请求工作正常,参数的序列化和反序列化工作正常。 问题中的SOAP响应,序列化正在创建错误形成的Xml,并且客户端反序列化无法正常工作。

    这是SOAP响应:

    <?xml version="1.0" encoding="utf-8"?>
    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <soap:Body>
            <GetCameraLocationsTableResponse xmlns="http://blah">
                <GetCameraLocationsTableResponse Version="1.0rc2">
                    <Response>
                        <Success>true</Success>
                    </Response>
                    <CameraLocationsTable/>
                </GetCameraLocationsTableResponse>
            </GetCameraLocationsTableResponse>
        </soap:Body>
    </soap:Envelope>
    

    注意嵌套的GetCameraLocationsTableResponse元素,这是错误的。 我已经确认我们的XDocument包装器创建了内部GetCameraLocationsTableResponse,并且SOAP消息生成器的内部工作中添加了外部GetCameraLocationsTableResponse 它应该是:

    <?xml version="1.0" encoding="utf-8"?>
    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <soap:Body>
            <GetCameraLocationsTableResponse Version="1.0rc2" xmlns="http://blah">
                <Response>
                    <Success>true</Success>
                </Response>
                <CameraLocationsTable/>
            </GetCameraLocationsTableResponse>
        </soap:Body>
    </soap:Envelope>
    

    所以我很难过,客户端代理代码正确序列化,但服务器代理代码没有。当然,这是我用的服务器代码!

    名称已更改为Blah以保护无辜者。

    作为参考,这是我编辑的服务器端代理代码:

    [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")]
    [System.Web.Services.WebServiceBindingAttribute(Name = "Blah", Namespace = "http://Blah", Location = @"http://localhost:57264/wsdl/Blah.wsdl")]
    public interface IBlah
    {
    
        [System.Web.Services.WebMethodAttribute()]
        [SoapLogger]
        [System.Web.Services.Protocols.SoapDocumentMethodAttribute("", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Bare)]
        [return: System.Xml.Serialization.XmlElementAttribute("GetCameraLocationsTableResponse", Namespace="http://Blah")]
        GetCameraLocationsTableResponse GetCameraLocationsTable([System.Xml.Serialization.XmlElementAttribute(Namespace="http://Blah")] NativeCaseInterfaceDelegateRequest NativeCaseInterfaceDelegateRequest);
    }
    

    以下是为实现上述Web服务而编写的代码:

    [WebService(Namespace = "http://blah")]
    public class Blah : WebService, IBlah
    {
        #region IBlah Members
    
        public GetCameraLocationsTableResponse GetCameraLocationsTable(Blah BlahRequest)
        {
            return BlahTools.GetCameraLocationsTable(BlahRequest);
        }
    
        #endregion
    }
    

    使用here中的system.diagnostics开关,我设法提取自动生成的序列化代码:

        protected override void Serialize(object objectToSerialize, System.Xml.Serialization.XmlSerializationWriter writer) {
            ((XmlSerializationWriter1)writer).Write3_Item((object[])objectToSerialize);
        }
    
        public void Write3_Item(object[] p) {
            WriteStartDocument();
            TopLevelElement();
            int pLength = p.Length;
            if (pLength > 0) {
                WriteSerializable((System.Xml.Serialization.IXmlSerializable)((global::blah.GetCameraLocationsTableResponse)p[0]), @"GetCameraLocationsTableResponse", @"http://blah", false, true);
            }
        }
    

    这是自定义WSDL

    <?xml version="1.0" encoding="UTF-8"?>
    <wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:sis="http://Blah" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" targetNamespace="http://Blah">
        <wsdl:import namespace="http://Blah" location="Blah.xsd"/>
        <wsdl:message name="BlahRequestMessage">
            <wsdl:part name="in" element="sis:BlahRequest"/>
        </wsdl:message>
        <wsdl:message name="GetCameraLocationsTableResponseMessage">
            <wsdl:part name="out" element="sis:GetCameraLocationsTableResponse"/>
        </wsdl:message>
        <wsdl:portType name="BlahPort">
            <wsdl:operation name="GetCameraLocationsTable">
                <wsdl:input message="sis:BlahRequestMessage"/>
                <wsdl:output message="sis:GetCameraLocationsTableResponseMessage"/>
            </wsdl:operation>
        </wsdl:portType>
        <wsdl:binding name="Blah" type="sis:BlahPort">
            <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
            <wsdl:operation name="GetCameraLocationsTable">
                <soap:operation soapAction="" style="document"/>
                <wsdl:input>
                    <soap:body use="literal"/>
                </wsdl:input>
                <wsdl:output>
                    <soap:body use="literal"/>
                </wsdl:output>
            </wsdl:operation>
        </wsdl:binding>
    </wsdl:definitions>
    

    感谢阅读,

    詹姆斯。

0 个答案:

没有答案