1

如果这篇文章感觉太长,我提前道歉。但是 1)这是我的第一篇文章,2)我真的已经过了河,穿过树林试图弄清楚这一点。

Visual Studio 2012 中的添加服务引用功能会生成一个代理,该代理(显然)会生成无效的 SOAP 消息。我怀疑它与序列化或代理类型的装饰方式有关,但我似乎无法弄清楚。非常感谢您的帮助。

详细信息 1. 我的环境是 Visual Studio 2012,我创建了一个 .NET 4.5 类库,其中包含对https://sandbox-api.bancbox.com/v1/BBXPort?wsdl的服务引用。我正在尝试调用 getClient() 函数;这是在这里定义的。( http://www.bancbox.com/api/view/45 )

代码如下所示:

public void GetClient()

{
    // create an instance of the service reference proxy class
    var bbx=newBBXClient();
    bbx.ChannelFactory.Endpoint.Behaviors.Remove<System.ServiceModel.Description.ClientCredentials>();
    bbx.ChannelFactory.Endpoint.Behaviors.Add(new CustomCredentials());

    bbx.ClientCredentials.UserName.UserName="MY_USERNAME";
    bbx.ClientCredentials.UserName.Password="MY_PASSWORD";

    var customerId=newid {
            subscriberReferenceId="44XX33YY"
    };

    var request=newgetClientRequest {
            subscriberId=MY_SUBSCRIBER_ID,
            clientId=customerId
    };

    var response=bbx.getClient(request);
}

细节 2. 我通过 SoapUI 成功调用了 Web 服务。成功的 SoapUI 生成的 SOAP 消息如下所示

<soapenv:Envelope xmlns:sch="schema.bancbox.com" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
    <wsse:Security soapenv:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
        <wsse:UsernameToken wsu:Id="UsernameToken-11">
            <wsse:Username>MY_USERNAME</wsse:Username>
            <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">MY_PASSWORD</wsse:Password>
            <wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">tRLo6AlRKl+/rULiKq6A6g==</wsse:Nonce>
            <wsu:Created>2013-02-22T18:32:02.204Z</wsu:Created>
        </wsse:UsernameToken>
    </wsse:Security>
</soapenv:Header>
<soapenv:Body>
    <sch:getClient>
        <getClientRequest>
            <subscriberId>MY_SUBSCRIBER_ID</subscriberId>
                <clientId>
                    <!--Optional:-->
                    <subscriberReferenceId>44XX33YY</subscriberReferenceId>
                </clientId>
        </getClientRequest>
    </sch:getClient>
</soapenv:Body>
</soapenv:Envelope>

细节 3.每个 Fiddler,我失败的 SOAP 消息看起来像这样

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<s:Header>
<VsDebuggerCausalityData xmlns="http://schemas.microsoft.com/vstudio/diagnostics/servicemodelsink">uIDPozcAgEH0QhJHloqMBWUf3mAAAAAA5wy3enJkDUGU8IaMUCFyEjzfL+1Uez1HhAvEeFpJ+30ACQAA</VsDebuggerCausalityData>
    <o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
        <o:UsernameToken u:Id="uuid-6e1c9f81-0651-41f7-b659-26b191bf7e13-1" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
            <o:Username>MY_USERNAME</o:Username>
            <o:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">MY_PASSWORD</o:Password>
            <o:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">hGggJkxurSkHQ3MKoeBK6AmEHNs=</o:Nonce>
            <u:Created>2013-02-23T11:24:47.663Z</u:Created>
        </o:UsernameToken>
    </o:Security>
</s:Header>
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <getClient xmlns="schema.bancbox.com">
        <getClientRequest xmlns="">
            <subscriberId>MY_SUBSCRIBER_ID</subscriberId>
            <clientId>
                <subscriberReferenceId>XX55YY22</subscriberReferenceId>
            </clientId>
        </getClientRequest>
    </getClient>
</s:Body>
</s:Envelope>

上面的 SOAP 消息是在运行 GetClient() 方法时产生的。GetClient 引发以下异常。

System.ServiceModel.FaultException
Unmarshalling Error: cvc-elt.4.2: Cannot resolve 'getClientRequest' to a type definition for element 'getClientRequest'.

当我使用 SoapUI 重播相同的失败消息时,我得到以下响应:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
    <soap:Fault>
        <faultcode>soap:Client</faultcode>
        <faultstring>Unmarshalling Error: cvc-elt.4.2: Cannot resolve 'getClientRequest' to a type definition for element 'getClientRequest'. </faultstring>
    </soap:Fault>
</soap:Body>
</soap:Envelope>

细节 4.根据我的研究,这表明另一端的服务器是 Apache CXS。我的 SOAP 请求令人窒息。所以我开始玩弄我的 SOAP 消息并通过 SoapUI 提交它。

成功消息和我的失败消息中的第一个明显距离是这些行

成功

<sch:getClient>
    <getClientRequest>

失败

<getClient xmlns="schema.bancbox.com">
    <getClientRequest xmlns="">

所以我做的第一件事就是让我的 getClientRequest 标记与成功的标记相同。

<getClient xmlns="schema.bancbox.com">
    <getClientRequest>

这产生了以下响应。

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
    <soap:Fault>
        <faultcode>soap:Server</faultcode>
        <faultstring>Found element {schema.bancbox.com}getClientRequest but could not find matching RPC/Literal part</faultstring>
    </soap:Fault>
</soap:Body>
</soap:Envelope>

我做的下一件事是更改为 getClient 标记分配模式的方式。

<getClient xmlns="schema.bancbox.com">

<s:Envelope xmlns:bb="schema.bancbox.com" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
. . .
    <bb:getClient>
        <getClientRequest>
. . .
    </bb:getClient>

生成的 SOAP 消息如下所示,并且它是成功的。

<s:Envelope xmlns:bb="schema.bancbox.com" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<s:Header>
<VsDebuggerCausalityData xmlns="http://schemas.microsoft.com/vstudio/diagnostics/servicemodelsink">uIDPozcAgEH0QhJHloqMBWUf3mAAAAAA5wy3enJkDUGU8IaMUCFyEjzfL+1Uez1HhAvEeFpJ+30ACQAA</VsDebuggerCausalityData>
    <o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
        <o:UsernameToken u:Id="uuid-6e1c9f81-0651-41f7-b659-26b191bf7e13-1" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
            <o:Username>MY_USERNAME</o:Username>
            <o:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">MY_PASSWORD</o:Password>
            <o:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">hGggJkxurSkHQ3MKoeBK6AmEHNs=</o:Nonce>
            <u:Created>2013-02-23T11:24:47.663Z</u:Created>
        </o:UsernameToken>
    </o:Security>
</s:Header>
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <bb:getClient>
        <getClientRequest>
            <subscriberId>MY_SUBSCRIBER_ID</subscriberId>
            <clientId>
                <subscriberReferenceId>XX55YY22</subscriberReferenceId>
            </clientId>
        </getClientRequest>
    </bb:getClient>
</s:Body>
</s:Envelope>

所以百万美元的问题是为什么和如何。

*为什么 .NET 代理类以它的方式序列化 SOAP 消息?

*我如何解决它?我怎样才能将我的代理序列化为上面的 SOAP 消息?如何强制序列化程序为信封中的消息命名空间定义简写,然后在消息标签中使用简写?

仅供参考,为了达到这一点,我必须克服许多 WCF WSE 问题,并最终实施 Rich Stahls 博客上慷慨提供的解决方案。我会发布链接,但显然我没有足够的代表。

4

1 回答 1

0

据我了解,WCF 生成的 SOAP 消息在语法上是正确的。但是,Java CXF Web 服务对于它们将接受的 SOAP 消息非常严格。

在 WCF 代理生成的 SOAP 消息的操作节点中为 xml 命名空间定义设置别名的特定问题的解决方案涉及实现自定义消息检查器,此处详细介绍: 强制 WCF 在客户端代理中创建 xml 命名空间别名

这完全解决了我的问题。

于 2013-02-25T16:08:53.907 回答