我从原始帖子中获得了更多信息,并且能够在非常简单的文件>新建项目> WCF服务应用程序解决方案中重新创建问题.因此,我正在大量编辑这篇文章的原始内容,以摆脱一些多余的信息并简化示例:
我们的消息合同定义如下.
[MessageContract( WrapperName = "SingleTypeResponse", WrapperNamespace = "urn:WcfService1" )]
public class SingleTypeResponse<T>
{
[MessageBodyMember( Name = "ReturnValue" )]
public T ReturnValue { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
服务接口具有以下内容:
[OperationContract]
SingleTypeResponse<string> GetStringData();
[OperationContract]
SingleTypeResponse<int> GetIntData();
Run Code Online (Sandbox Code Playgroud)
当我运行项目并导航到.svc文件时,我得到以下内容:
调用WSDL导出扩展时抛出异常:System.ServiceModel.Description.DataContractSerializerOperationBehavior contract:http://tempuri.org/:IService1 ----> System.InvalidOperationException:WcfService1.IService1.GetIntData操作引用a已从WcfService1.IService1.GetStringData操作导出的message元素[urn:WcfService1:SingleTypeResponse].您可以通过更改方法名称或使用OperationContractAttribute的Name属性来更改其中一个操作的名称.或者,您可以使用MessageContract编程模型更详细地控制元素名称.
如果我在界面上注释掉GetIntData并使用WCF测试客户端测试服务,并且设置了WrapperName属性,我会得到以下响应XML:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header />
<s:Body>
<SingleTypeResponse xmlns="urn:WcfService1">
<ReturnValue xmlns="http://tempuri.org/">foo</ReturnValue>
</SingleTypeResponse>
</s:Body>
</s:Envelope>
Run Code Online (Sandbox Code Playgroud)
我猜这个元素是问题的根源,它看到了同一个元素的两个版本,一个是字符串,另一个是int.
然后我取消注释了GetIntData并从MessageContract中删除了WrapperName属性:
[MessageContract( WrapperNamespace = "urn:WcfService1" )]
public class SingleTypeResponse<T>
{
[MessageBodyMember( Name = "ReturnValue" )]
public T ReturnValue { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我收到相同的错误消息,但它所抱怨的消息元素是合同的ReturnValue属性而不是消息合同名称.
再次注释掉GetIntData并使用WCF测试客户端进行测试我得到:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header />
<s:Body>
<SingleTypeResponseOf_String xmlns="urn:WcfService1">
<ReturnValue xmlns="http://tempuri.org/">foo</ReturnValue>
</SingleTypeResponseOf_String>
</s:Body>
</s:Envelope>
Run Code Online (Sandbox Code Playgroud)
所以我能够让它为包装器创建一个唯一的名称,但SingleTypeResponseOf_String和SingleTypeResponseOf_Int32都具有ReturnValue属性的事实继续导致它的大脑爆发.
我以前从未考虑过这个问题,但需要将泛型类型定义为 WSDL 的具体类型是有道理的。从这个角度来看,似乎是的 - 您正在定义SingleTypeResponse服务中的两种“类型”。WSDL 不允许两个具有相同名称和名称空间的元素定义共存(出于显而易见的原因 - 它们需要唯一可识别)。
这里有一些潜在的冲突。SingleTypeResponse我认为您已经确定了第一个 - 在命名空间内命名的元素urn:WcfService1。当您关闭消息契约的命名(允许它由序列化程序命名)时,您会看到以下内容:
<!-- Setting wrapper name & wrapper namespace -->
<wsdl:message name="SingleTypeResponseOf_String">
<wsdl:part name="parameters" element="q1:SingleTypeResponse"
xmlns:q1="urn:WcfService1" />
</wsdl:message>
<!-- Setting wrapper namespace only -->
<wsdl:message name="SingleTypeResponseOf_String">
<wsdl:part name="parameters" element="q1:SingleTypeResponseOf_String"
xmlns:q1="urn:WcfService1" />
</wsdl:message>
Run Code Online (Sandbox Code Playgroud)
这应该避免第一个冲突,因为运行两个操作意味着您将能够拥有两种类型的元素(SingleTypeResponseOf_String和SingleTypeResponseOf_Int)。
我相信你的第二个冲突来自属性MessageBodyMember。因为这两个操作都在同一命名空间中定义消息,并且两个返回类型都包含一个 element ReturnValue,所以您会遇到冲突,该urn:ReturnValue元素被定义两次,一次作为 int ,一次作为 string 。
为了演示,请参阅以下内容,将GetIntData操作注释掉,请参阅ReturnValue定义的元素:
<!-- from the XSD http://localhost/Service1.svc?xsd=xsd0 -->
<xs:element name="SingleTypeResponseOf_String">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" ref="q1:ReturnValue"
xmlns:q1="http://tempuri.org/" />
</xs:sequence>
</xs:complexType>
</xs:element>
<!-- from the XSD http://localhost/Service1.svc?xsd=xsd2 -->
<xs:schema elementFormDefault="qualified"
targetNamespace="http://tempuri.org/"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://tempuri.org/">
<xs:element name="ReturnValue"
nillable="true"
type="xs:string" />
</xs:schema>
Run Code Online (Sandbox Code Playgroud)
你怎么能允许他们MessageContract重命名ReturnValue财产呢?我认为 DataContractSerializer 不能。
解决办法是什么?嗯,我认为没有使用[MessageBodyMember]. 如果你使用[DataMember]它会很好地工作。您之前提到您正在使用 net.tcp,所以我假设您的 .NET 到 .NET。您是否需要对 SOAP 信封进行这种级别的控制?
通常我会DataContract尽可能多地使用,并且只MessageContract在必要时才冒险使用 - 与旧的 SOAP 风格平台交互。
| 归档时间: |
|
| 查看次数: |
3404 次 |
| 最近记录: |