我从原始帖子中获得了更多信息,并且能够在一个非常简单的文件中重新创建问题>新项目> WCF服务应用解决方案。因此,我正在大量编辑这篇文章的原始内容,以摆脱一些多余的信息并简化示例:
我们的消息合约定义如下。
[MessageContract( WrapperName = "SingleTypeResponse", WrapperNamespace = "urn:WcfService1" )]
public class SingleTypeResponse<T>
{
[MessageBodyMember( Name = "ReturnValue" )]
public T ReturnValue { get; set; }
}
服务界面具有以下内容:
[OperationContract]
SingleTypeResponse<string> GetStringData();
[OperationContract]
SingleTypeResponse<int> GetIntData();
当我运行项目并导航到.svc文件时,我得到以下内容:
调用WSDL导出扩展时抛出异常:System.ServiceModel.Description.DataContractSerializerOperationBehavior 合同:http://tempuri.org/:IService1 ----&gt; System.InvalidOperationException:WcfService1.IService1.GetIntData操作引用已从WcfService1.IService1.GetStringData操作导出的消息元素[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>
我猜这个元素是问题的根源,它看到同一个元素的两个版本,一个带字符串,一个带有int。
然后我取消注释GetIntData并从MessageContract中删除了WrapperName属性:
[MessageContract( WrapperNamespace = "urn:WcfService1" )]
public class SingleTypeResponse<T>
{
[MessageBodyMember( Name = "ReturnValue" )]
public T ReturnValue { get; set; }
}
我收到与相同的错误消息,它抱怨的消息元素是合约的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>
所以我能够让它为包装器创建一个唯一的名称,但SingleTypeResponseOf_String和SingleTypeResponseOf_Int32都具有ReturnValue属性这一事实继续导致它的大脑爆发。
答案 0 :(得分:3)
我以前从未考虑过它,但是有必要将泛型类型定义为WSDL的具体类型。从这个角度来看,似乎是 - 您在服务中定义了SingleTypeResponse
的两种“类型”。 WSDL不允许同名的两个元素定义&amp;命名空间共存(出于显而易见的原因 - 它们需要是唯一可识别的)。
这里有几个潜在的冲突。我想你已经确定了第一个 - 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>
这应避免第一次冲突,因为运行两项操作意味着您将能够拥有两种类型的元素(SingleTypeResponseOf_String
和SingleTypeResponseOf_Int
)。
我相信你的第二个冲突来自MessageBodyMember
属性。因为两个操作都在同一名称空间中定义消息,并且两个返回类型都包含元素ReturnValue
,所以在urn:ReturnValue
元素定义两次时会出现冲突,一次为一个int和一个字符串。
要演示请参阅以下内容,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>
如何允许MessageContract
重命名ReturnValue
属性?我不认为你可以使用DataContractSerializer。
解决方案是什么?好吧,我认为没有使用[MessageBodyMember]
的解决方案。如果您使用[DataMember]
,它将正常工作。你之前提到过你正在使用net.tcp,所以我假设你的.NET为.NET。您是否需要对SOAP信封进行这种级别的控制?
通常情况下,我尽可能使用DataContract
,并且只在必要时冒险进入MessageContract
- 与旧的SOAP风格平台接口。