使用命名空间前缀调用 SOAP 方法

发布于 2024-10-08 07:43:14 字数 5814 浏览 0 评论 0原文

我的 C# Web 服务客户端向基于 Java 的 Web 服务发送以下肥皂消息:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<getData>
<request>
<requestParameters xmlns="http://b...">
<equals>
...
</equals>
</requestParameters>
</request>
</getData>
</soap:Body>
</soap:Envelope> 

并且基于 Java 的 Web 服务返回错误:

500 内部服务器错误
...
找不到 {}getData 的调度方法
...

用 Java 编写的客户端可以正常工作,发送以下消息:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<ns2:getData xmlns:ns2="http://a...">
<ns2:request>
<ns3:requestParameters xmlns:ns3="http://b...">
<ns3:equals>
...
</ns3:equals>
</ns3:requestParameters>
</ns2:request>
</ns2:getData>
</soap:Body>
</soap:Envelope> 

在 C# 中是否有一种简单的方法可以像 Java 客户端发送的方式一样发送 SOAP 消息:使用命名空间前缀?

以下是发送消息的 C# 代码:

// class MyService is auto-generated using wsdl.exe tool
MyService service = new MyService();

RequestMessage request = new RequestMessage();
...

ResponseMessage response = service.getData(request);
...

更新:

这里是 RequestMessage 类:

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("svcutil", "3.0.4506.2152")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://uri.etsi.org/02657/v1.5.1#/RetainedData")]
public partial class RequestMessage
{

    private byte[] requestPriorityField;

    private RequestConstraints requestParametersField;

    private string deliveryPointHIBField;

    private string maxHitsField;

    private NationalRequestParameters nationalRequestParametersField;

    private System.Xml.XmlElement anyField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(DataType="hexBinary", Order=0)]
    public byte[] requestPriority
    {
        get
        {
            return this.requestPriorityField;
        }
        set
        {
            this.requestPriorityField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Order=1)]
    public RequestConstraints requestParameters
    {
        get
        {
            return this.requestParametersField;
        }
        set
        {
            this.requestParametersField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Order=2)]
    public string deliveryPointHIB
    {
        get
        {
            return this.deliveryPointHIBField;
        }
        set
        {
            this.deliveryPointHIBField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(DataType="integer", Order=3)]
    public string maxHits
    {
        get
        {
            return this.maxHitsField;
        }
        set
        {
            this.maxHitsField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Order=4)]
    public NationalRequestParameters nationalRequestParameters
    {
        get
        {
            return this.nationalRequestParametersField;
        }
        set
        {
            this.nationalRequestParametersField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlAnyElementAttribute(Order=5)]
    public System.Xml.XmlElement Any
    {
        get
        {
            return this.anyField;
        }
        set
        {
            this.anyField = value;
        }
    }
}

更新#2:

基于 Java 的 Web 服务不喜欢我的 C# 客户端生成 SOAP 消息的原因不是省略名称空间前缀,而只是因为省略getData 元素中的 xmlns,所以如果我的消息如下所示:

...
<getData xmlns="http://a...">
...
</getData>
...

它有效!

我通过在 wsdl.exe 生成的源代码中手动编辑 SoapRpcMethodAttribute 设法将 xmlns 放入 getData 中。以下是摘录:

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Web.Services.WebServiceBindingAttribute(
    Name="AxxxPortTypeBinding", Namespace="http://a...")]
public partial class AxxxService 
    : System.Web.Services.Protocols.SoapHttpClientProtocol {

    ...

    /// <remarks/>
    [System.Web.Services.Protocols.SoapRpcMethodAttribute(
        "http://a.../getData", 
        RequestNamespace = "http://a...", 
        ResponseNamespace = "http://a...",
        Use = System.Web.Services.Description.SoapBindingUse.Literal)]
    [return: System.Xml.Serialization.XmlElementAttribute("response")]
    public ResponseMessage getData(RequestMessage request) {
        object[] results = this.Invoke("getData", new object[] {
                    request});
        return ((ResponseMessage)(results[0]));
    }

    ...
}

在我进行更改之前,SoapRpcMethodAttribute 有以下构造函数:

[System.Web.Services.Protocols.SoapRpcMethodAttribute(
    "", RequestNamespace = "", ResponseNamespace = "",
    Use = System.Web.Services.Description.SoapBindingUse.Literal)]

现在,问题是:在 WSDL 文件中放入什么内容,以便 SoapRpcMethodAttribute 首先在构造函数中包含这些字符串(由 wsdl.exe 工具填充)?

My C# web service client sends following soap message to Java-based web service:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<getData>
<request>
<requestParameters xmlns="http://b...">
<equals>
...
</equals>
</requestParameters>
</request>
</getData>
</soap:Body>
</soap:Envelope> 

and Java-based web service returns error:

500 Internal Server Error
...
Cannot find dispatch method for {}getData
...

Client written in Java, which works, sends the following message:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<ns2:getData xmlns:ns2="http://a...">
<ns2:request>
<ns3:requestParameters xmlns:ns3="http://b...">
<ns3:equals>
...
</ns3:equals>
</ns3:requestParameters>
</ns2:request>
</ns2:getData>
</soap:Body>
</soap:Envelope> 

Is there an easy way in C# to send SOAP messages the same way Java client sends: with namespace prefixes?

Following is C# code that sends message:

// class MyService is auto-generated using wsdl.exe tool
MyService service = new MyService();

RequestMessage request = new RequestMessage();
...

ResponseMessage response = service.getData(request);
...

UPDATE:

Here is RequestMessage class:

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("svcutil", "3.0.4506.2152")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://uri.etsi.org/02657/v1.5.1#/RetainedData")]
public partial class RequestMessage
{

    private byte[] requestPriorityField;

    private RequestConstraints requestParametersField;

    private string deliveryPointHIBField;

    private string maxHitsField;

    private NationalRequestParameters nationalRequestParametersField;

    private System.Xml.XmlElement anyField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(DataType="hexBinary", Order=0)]
    public byte[] requestPriority
    {
        get
        {
            return this.requestPriorityField;
        }
        set
        {
            this.requestPriorityField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Order=1)]
    public RequestConstraints requestParameters
    {
        get
        {
            return this.requestParametersField;
        }
        set
        {
            this.requestParametersField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Order=2)]
    public string deliveryPointHIB
    {
        get
        {
            return this.deliveryPointHIBField;
        }
        set
        {
            this.deliveryPointHIBField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(DataType="integer", Order=3)]
    public string maxHits
    {
        get
        {
            return this.maxHitsField;
        }
        set
        {
            this.maxHitsField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Order=4)]
    public NationalRequestParameters nationalRequestParameters
    {
        get
        {
            return this.nationalRequestParametersField;
        }
        set
        {
            this.nationalRequestParametersField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlAnyElementAttribute(Order=5)]
    public System.Xml.XmlElement Any
    {
        get
        {
            return this.anyField;
        }
        set
        {
            this.anyField = value;
        }
    }
}

UPDATE #2:

The reason why Java-based web service didn't like my C# client produced SOAP message is not omission of namespace prefixes, but only because of omission of xmlns in getData element, so if my message looks like this:

...
<getData xmlns="http://a...">
...
</getData>
...

it works!

I managed to put xmlns inside getData by manually editing SoapRpcMethodAttribute in wsdl.exe-produced source code. Here is excerpt:

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Web.Services.WebServiceBindingAttribute(
    Name="AxxxPortTypeBinding", Namespace="http://a...")]
public partial class AxxxService 
    : System.Web.Services.Protocols.SoapHttpClientProtocol {

    ...

    /// <remarks/>
    [System.Web.Services.Protocols.SoapRpcMethodAttribute(
        "http://a.../getData", 
        RequestNamespace = "http://a...", 
        ResponseNamespace = "http://a...",
        Use = System.Web.Services.Description.SoapBindingUse.Literal)]
    [return: System.Xml.Serialization.XmlElementAttribute("response")]
    public ResponseMessage getData(RequestMessage request) {
        object[] results = this.Invoke("getData", new object[] {
                    request});
        return ((ResponseMessage)(results[0]));
    }

    ...
}

Before my change, SoapRpcMethodAttribute had following constructor:

[System.Web.Services.Protocols.SoapRpcMethodAttribute(
    "", RequestNamespace = "", ResponseNamespace = "",
    Use = System.Web.Services.Description.SoapBindingUse.Literal)]

Now, the question is: what to put in WSDL file so that SoapRpcMethodAttribute have those strings in constructor (filled by the wsdl.exe tool) in the first place?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

太傻旳人生 2024-10-15 07:43:14

我以前见过这个问题,WSDL.exe 工具在生成服务代码时没有正确提取命名空间。检查生成的代码中的 request 对象定义。我的猜测是,在 request 对象的类定义中没有定义 XmlRootAttribute 属性。

将属性 [XmlRootAttribute(Namespace "http://a...")] 添加到 request 对象的类定义中应该可以解决此问题。

作为旁注,我建议使用部分类定义在单独的代码文件中添加此附加属性。在单独的文件中定义属性将允许您在必要时使用 WSDL.exe 重新生成 Web 服务代码,而无需覆盖修复程序以正确设置根元素的命名空间。

I've seen this problem before where the WSDL.exe tool did not properly pull in the namespace when generating the service code. Check the request object definition in your generated code. My guess is that there is no XmlRootAttribute attribute defined on the class definition for the request object.

Adding the attribute [XmlRootAttribute(Namespace "http://a...")] to the class definition for the request object should fix this issue.

As a side note, I recommend adding this additional attribute in a separate code file using a partial class definition. Defining the attribute in a separate file will allow you to regenerate the web service code using WSDL.exe whenever neccessary without overwriting the fix to set the root element's namespace properly.

无远思近则忧 2024-10-15 07:43:14

生成的代理类应该具有正确的命名空间。我建议两件事:

1) 从命令行运行 WSDL.EXE 并注意是否有任何错误或警告。如果是这样,请编辑您的问题以包含它们。

2) 除非您无法使用 .NET 2.0,否则您应该尝试使用“添加服务引用”或等效的“SVCUTIL.EXE”来创建代理类,这些类将在客户端使用现代的 WCF 基础结构,这比更有可能已修复以解决此问题。

The generated proxy class should have had the correct namespace in it. I recommend two things:

1) Run WSDL.EXE from the command line and note whether there are any errors or warnings. If so, please edit your question to include them.

2) Unless you are stuck using .NET 2.0, you should try to create your proxy classes using either "Add Service Reference" or the equivalent "SVCUTIL.EXE" these will use the modern, WCF infrastructure on the client side, which is much more likely to have been fixed to resolve this problem.

瑾兮 2024-10-15 07:43:14

我遇到了同样的问题,并通过更改与每个 Web 服务方法对应的 System.Web.Services.Protocols.SoapDocumentMethodAttribute 属性中的属性 Use 的值来解决它。
System.Web.Services.Description.SoapBindingUse.Literal 默认值已替换为 System.Web.Services.Description.SoapBindingUse.Encoded

I had the same issue and solved it changing the value of the property Use in System.Web.Services.Protocols.SoapDocumentMethodAttribute attribute corrisponding to each web service method.
The System.Web.Services.Description.SoapBindingUse.Literal default value was replaced with System.Web.Services.Description.SoapBindingUse.Encoded.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文