svcutilsoap 命名空间故障问题
我正在使用 svcutil 生成客户端 Web 服务代码。 我正在使用的 wsdl 合约包含肥皂错误。 当代码生成时,错误似乎被包装在合同中定义的名称空间中。
谁能解释为什么?
我只是运行 svcutil [filename]
示例 WSDL:
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tns="http://tempuri.org/" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://tempuri.org/">
<wsdl:types>
<s:schema elementFormDefault="qualified" targetNamespace="http://tempuri.org/">
<s:element name="HelloFault">
<s:complexType/>
</s:element>
<s:element name="HelloWorld">
<s:complexType/>
</s:element>
<s:element name="HelloWorldResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="HelloWorldResult" type="s:string"/>
</s:sequence>
</s:complexType>
</s:element>
</s:schema>
</wsdl:types>
<wsdl:message name="HelloWorldSoapIn">
<wsdl:part name="parameters" element="tns:HelloWorld"/>
</wsdl:message>
<wsdl:message name="HelloWorldSoapOut">
<wsdl:part name="parameters" element="tns:HelloWorldResponse"/>
</wsdl:message>
<wsdl:message name="NewMessage">
<wsdl:part name="detail" element="tns:HelloFault"/>
</wsdl:message>
<wsdl:portType name="Service1Soap">
<wsdl:operation name="HelloWorld">
<wsdl:input message="tns:HelloWorldSoapIn"/>
<wsdl:output message="tns:HelloWorldSoapOut"/>
<wsdl:fault name="FaultName" message="tns:NewMessage"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="Service1Soap12" type="tns:Service1Soap">
<soap12:binding transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="HelloWorld">
<soap12:operation soapAction="http://tempuri.org/HelloWorld" soapActionRequired="" style="document"/>
<wsdl:input>
<soap12:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap12:body use="literal"/>
</wsdl:output>
<wsdl:fault name="FaultName">
<soap12:fault name="FaultName" use="literal"/>
</wsdl:fault>
</wsdl:operation>
</wsdl:binding>
?
namespace tempuri.org
{
using System.Runtime.Serialization;
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "3.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute(Name="HelloFault", Namespace="http://tempuri.org/")]
public partial class HelloFault : object, System.Runtime.Serialization.IExtensibleDataObject
{
private System.Runtime.Serialization.ExtensionDataObject extensionDataField;
public System.Runtime.Serialization.ExtensionDataObject ExtensionData
{
get
{
return this.extensionDataField;
}
set
{
this.extensionDataField = value;
}
}
}
但是
合约中声明的其他类型是在没有命名空间的情况下声明的吗
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.MessageContractAttribute(IsWrapped=false)]
public partial class HelloWorldRequest
{
...
I'm generating client side web service code using svcutil. The wsdl contract I'm using contains a soap fault. When the code is generated the fault seems to be wrapped in the namespace it was defined in the contract.
Can anyone explain why?
I'm simply running svcutil [filename]
Example WSDL:
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tns="http://tempuri.org/" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://tempuri.org/">
<wsdl:types>
<s:schema elementFormDefault="qualified" targetNamespace="http://tempuri.org/">
<s:element name="HelloFault">
<s:complexType/>
</s:element>
<s:element name="HelloWorld">
<s:complexType/>
</s:element>
<s:element name="HelloWorldResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="HelloWorldResult" type="s:string"/>
</s:sequence>
</s:complexType>
</s:element>
</s:schema>
</wsdl:types>
<wsdl:message name="HelloWorldSoapIn">
<wsdl:part name="parameters" element="tns:HelloWorld"/>
</wsdl:message>
<wsdl:message name="HelloWorldSoapOut">
<wsdl:part name="parameters" element="tns:HelloWorldResponse"/>
</wsdl:message>
<wsdl:message name="NewMessage">
<wsdl:part name="detail" element="tns:HelloFault"/>
</wsdl:message>
<wsdl:portType name="Service1Soap">
<wsdl:operation name="HelloWorld">
<wsdl:input message="tns:HelloWorldSoapIn"/>
<wsdl:output message="tns:HelloWorldSoapOut"/>
<wsdl:fault name="FaultName" message="tns:NewMessage"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="Service1Soap12" type="tns:Service1Soap">
<soap12:binding transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="HelloWorld">
<soap12:operation soapAction="http://tempuri.org/HelloWorld" soapActionRequired="" style="document"/>
<wsdl:input>
<soap12:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap12:body use="literal"/>
</wsdl:output>
<wsdl:fault name="FaultName">
<soap12:fault name="FaultName" use="literal"/>
</wsdl:fault>
</wsdl:operation>
</wsdl:binding>
Generates:
namespace tempuri.org
{
using System.Runtime.Serialization;
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "3.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute(Name="HelloFault", Namespace="http://tempuri.org/")]
public partial class HelloFault : object, System.Runtime.Serialization.IExtensibleDataObject
{
private System.Runtime.Serialization.ExtensionDataObject extensionDataField;
public System.Runtime.Serialization.ExtensionDataObject ExtensionData
{
get
{
return this.extensionDataField;
}
set
{
this.extensionDataField = value;
}
}
}
}
But other types declared in the contract are declared without a namespace?
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.MessageContractAttribute(IsWrapped=false)]
public partial class HelloWorldRequest
{
...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您必须在 svcutil 上使用 /UseSerializerForFaults 属性,这将导致 XmlSerializer 用于读取和写入错误(但仅限这些错误),而不是默认的 DataContractSerializer(仍将用于读取和写入错误)其余的东西)。
这似乎是一个真正的错误 - 有关我的 博客文章的更多信息。
You have to use the /UseSerializerForFaults attribute on svcutil, this will cause the XmlSerializer to be used for reading and writing faults (but only those), instead of the default DataContractSerializer (which will still be used for the rest of the stuff).
This seems to be a genuine bug - more info on my blog post.
我不确定我明白问题是什么......你能澄清一下吗?
从表面上看,WCF 似乎正在做正确的事情...根据您显示的 WSDL 片段中的架构,生成的类在 [DataContract] 属性中具有正确的命名空间 URI。
你在期待什么?
更新:好的,我明白你在说什么,但在这个特定的情况下,这也并不意外。 如果仔细观察,请注意您提到的另一个类 (HelloWorldRequest) 是消息契约,而不是数据契约。 消息契约本身没有命名空间,但它们可以为消息正文周围的包装元素指定命名空间(请参阅 WrapperNamespace 属性)。
在您的情况下,消息契约指定它没有被包装,因此 WrapperNamespace 无论如何都不会应用。
更新#2:关于 CLR 命名空间(而不是 XML 命名空间 URI),SvcUtil 确实为您提供了一种控制它的方法; 查看文档中的 /namespace: 参数。
I'm not sure I understand what the problem is... can you clarify?
From the looks of it, it would seem WCF is doing the right thing... the generated class has the right namespace URI in the [DataContract] attribute according to the schema in the WSDL fragment you showed.
What were you expecting?
Update: OK, I see what you're saying, but in this specific case, it's not unexpected either. If you look closely, notice that the other class you mention (HelloWorldRequest) is a Message Contract, not a DataContract. Message Contracts don't have namespaces themselves, though they can specify a namespace for the wrapper element around the message body (see the WrapperNamespace property).
In your case, the message contract specifies that it is not wrapped, so the WrapperNamespace wouldn't apply anyway.
Update #2: Regarding the CLR namespace (and not the XML namespace URI), SvcUtil does give you a way to control that; check out the /namespace: argument in the documentation.