2010-03-09 28 views
5

我有這樣的多個合同的服務。WCF具有重複方法名稱的多個合同

[ServiceContract] 
public partial interface IBusinessFunctionDAO { 

    [OperationContract] 
    BusinessFunction GetBusinessFunction(Int32 businessFunctionRefID); 

    [OperationContract] 
    IEnumerable<Project> GetProjects(Int32 businessFunctionRefID); 
} 

[ServiceContract] 
public partial interface IBusinessUnitDAO { 

    [OperationContract] 
    BusinessUnit GetBusinessUnit(Int32 businessUnitRefID); 

    [OperationContract] 
    IEnumerable<Project> GetProjects(Int32 businessUnitRefID); 
} 

然後,我明確地實現了每個接口像這樣。

public class TrackingTool : IBusinessFunctionDAO, IBusinessUnitDAO { 

    BusinessFunction IBusinessFunctionDAO.GetBusinessFunction(Int32 businessFunctionRefID) { 
     // implementation 
    } 
    IEnumerable<Project> IBusinessFunctionDAO.GetProjects(Int32 businessFunctionRefID) { 
     // implementation 
    } 

    BusinessUnit IBusinessUnitDAO.GetBusinessUnit(Int32 businessUnitRefID) { 
     // implementation 
    } 
    IEnumerable<Project> IBusinessUnitDAO.GetProjects(Int32 businessUnitRefID) { 
     // implementation 
    } 
} 

正如你可以看到我有兩個GetProjects(int)的方法,但每一個明確的實現,因此這個編譯就好了,是完全有效的。當我真正開始這項服務時,問題就出現了。它給我一個錯誤,認爲TrackingTool已經包含一個定義GetProject。雖然這是事實,但它是不同服務合同的一部分。生成方法名稱時,WCF是否不區分服務合同? 有沒有辦法讓它區分服務合同?

我App.Config中看起來像這樣

<service name="TrackingTool"> 
    <endpoint address="BusinessUnit" contract="IBusinessUnitDAO" /> 
    <endpoint address="BusinessFunction" contract="IBusinessFunctionDAO" /> 
</service> 

任何幫助,將不勝感激。

謝謝,勞爾

+0

as @monO在他的回答中提到 - 實際的單個方法名稱在服務類中必須是唯一的。 WSDL不知道你的接口和所有的東西,它不允許用不同的參數重載方法;您需要使這些方法名在整個服務類中都是唯一的! – 2010-03-09 18:07:02

+0

啊,我想我應該讀一下WSDL是如何創建的。我認爲每個合約都有自己的WSDL內的命名空間。 – HaxElit 2010-03-09 18:49:43

+0

......實際上我也覺得很困惑。 @marc_s:WSDL確實知道不同的接口。它們被暴露爲專用端口和專用綁定。 – Alex 2010-03-09 22:51:16

回答

10

我想我找到了它的原因。 WSDL中的功能被曝光,如下所示:

<wsdl:message name="IBusinessUnitDAO_GetBusinessUnitProjects_InputMessage"> 
    <wsdl:part name="parameters" element="tns:GetBusinessUnitProjects" /> 
</wsdl:message> 
<wsdl:message name="IBusinessFunctionDAO_GetBusinessFunctionProjects_InputMessage"> 
    <wsdl:part name="parameters" element="tns:GetBusinessFunctionProjects" /> 
</wsdl:message> 

然後在定義TNS的XSD:命名空間,我們有以下幾點:

<xs:element name="GetBusinessUnitProjects"> 
    <xs:complexType> 
    <xs:sequence> 
     <xs:element minOccurs="0" name="businessUnitRefID" type="xs:int" /> 
    </xs:sequence> 
    </xs:complexType> 
</xs:element> 

<xs:element name="GetBusinessFunctionProjects"> 
    <xs:complexType> 
    <xs:sequence> 
     <xs:element minOccurs="0" name="businessFunctionRefID" type="xs:int" /> 
    </xs:sequence> 
    </xs:complexType> 
</xs:element> 

所以對於碰撞,即使原因的服務公開兩個不同的合同是因爲所有wsdl部件元素都在相同的名稱空間中。因此,當您創建兩個相同的函數名稱時,您會得到重複的元素,並且會導致問題。所以問題的解決方案是爲每個服務合約添加一個名稱空間屬性。如果我們拿出我們原來的服務合同並像這樣修改它。

[ServiceContract(Namespace="Tracking/BusinessFunction")] 
public partial interface IBusinessFunctionDAO { 

    [OperationContract] 
    BusinessFunction GetBusinessFunction(Int32 businessFunctionRefID); 

    [OperationContract] 
    IEnumerable<Project> GetProjects(Int32 businessFunctionRefID); 
} 

[ServiceContract(Namespace="Tracking/BusinessUnit")] 
public partial interface IBusinessUnitDAO { 

    [OperationContract] 
    BusinessUnit GetBusinessUnit(Int32 businessUnitRefID); 

    [OperationContract] 
    IEnumerable<Project> GetProjects(Int32 businessUnitRefID); 
} 

當我們生成WSDL時,我們爲我們創建的每個名稱空間獲取一個WSDL。該名稱空間具有用其所有操作和元素標識的每個端口。所以裏面我們每個單獨的WSDL的,我們得到如下:

//File: Tracking.BusinessFunction.wsdl 
<wsdl:message name="IBusinessFunctionDAO_GetProjects_InputMessage"> 
    <wsdl:part name="parameters" element="tns:GetProjects" /> 
</wsdl:message> 

//File: Tracking.BusinessUnit.wsdl 
<wsdl:message name="IBusinessUnitDAO_GetProjects_InputMessage"> 
    <wsdl:part name="parameters" element="tns:GetProjects" /> 
</wsdl:message> 

你可以看到它們都具有相同的元素名稱,而是因爲他們在不同的命名空間中的元素不再互相沖突。如果我們看一看在XSD他們現在已經定義了相同的元素,但使用不同的參數:

//File: Tracking.BusinessFunction.xsd 
<xs:element name="GetProjects"> 
    <xs:complexType> 
    <xs:sequence> 
     <xs:element minOccurs="0" name="businessFunctionRefID" type="xs:int" /> 
    </xs:sequence> 
    </xs:complexType> 
</xs:element> 

//File: Tracking.BusinessUnit.xsd 
<xs:element name="GetProjects"> 
    <xs:complexType> 
    <xs:sequence> 
     <xs:element minOccurs="0" name="businessUnitRefID" type="xs:int" /> 
    </xs:sequence> 
    </xs:complexType> 
</xs:element> 

所以答案我原來的問題是使每一個服務合同,住在不同的命名空間,所以你不要有衝突的港口元素。這也使您可以靈活地將您的合約放在單獨的WSDL中,如果您分發其中的一部分,這些WSDL更易於管理。

+0

只是跟進,我認爲它應該工作的方式是,如果明確定義了接口,則生成的元素名稱應爲。這將消除與消息部分元素的衝突。有什麼想法嗎 ? – HaxElit 2010-03-10 16:49:30

+0

不錯的一個!感謝您分享這些細節! – Alex 2010-03-10 18:17:03

0

嘗試了兩種方法具有相同的名稱,以消除該衝突,像這樣的設置在OperationContract的屬性Action屬性:

[ServiceContract] 
public partial interface IBusinessFunctionDAO { 

[OperationContract] 
BusinessFunction GetBusinessFunction(Int32 businessFunctionRefID); 

[OperationContract(Action="GetBusinessFunctionProjects")] 
IEnumerable<Project> GetProjects(Int32 businessFunctionRefID); 
} 

[ServiceContract] 
public partial interface IBusinessUnitDAO { 

[OperationContract] 
BusinessUnit GetBusinessUnit(Int32 businessUnitRefID); 

[OperationContract(Action="GetBusinessUnitProjects")] 
IEnumerable<Project> GetProjects(Int32 businessUnitRefID); 
} 
相關問題