2009-08-25 34 views
0

我使用框架3.5,並希望有一個ServiceContract,可以採取不同類型的請求/響應對象,是否有可能?WCF服務端點採取不同的請求/響應

+0

你是什麼意思的不同類型的請求/響應對象?你可以根據需要定義你的服務接口,所以這不應該是一個問題。 –

+0

我想要一個名爲DoSomeThing的服務方法,每個客戶端都會調用,但傳入不同的請求/響應對象。 – Hetal

回答

0

是的,如果你真的想,你可以處理一個通用的Message類型作爲參數和/或返回值。

[ServiceContract] 
public interface IMyService 
{ 
    [OperationContract] 
    Message GetData(); 

    [OperationContract] 
    void PutData(Message m); 
} 

MSDN documentation中查看詳細信息。

但是,這意味着如果您使用強類型[DataContract]類型,則必須手動執行大量XML操作voodoo並自行處理大量內容,這將免費處理。

你能做到嗎?是。你應該這樣做嗎?那麼,取決於你真正想要它多少! :-)

Marc

0

正如Marc所說,你有一個需要消息參數的服務契約。但是,您不必手動構建XML,而是可以在服務器和客戶端共有的共享DLL中共享接口和消息協定。

例如我有一個軟件需要消息,因爲規範說明它必須。我有一個通用程序集,它包含接口,所有可能的請求和響應消息以及名稱空間的公共靜態字符串。所以,這看起來像

[MessageContract(IsWrapped = true, 
       WrapperNamespace = Constants.Messages.Namespace.Location)] 
public sealed class GetTasksRequest 
{ 
    .... 
} 

要到服務的連接進行

[ServiceContract(
    Namespace = Constants.Service.Namespace.Location, 
    Name = "ServiceMonitorContract")] 
public interface IMonitor 
{ 
    [OperationContract(
     Action = Constants.Service.Actions.GetTasksRequest, 
     ReplyAction = Constants.Service.Actions.GetTasksResponse)] 
    Message GetTasks(Message request); 
} 

,我有消息合約的操作之一,我做了以下

private static IMonitor GetChannelToWebService() 
{ 
    EndpointAddress endpoint = new EndpointAddress("http://example/service.svc"); 
    ChannelFactory<IMonitor> channelFactory = 
     new ChannelFactory<IMonitor>(new BasicHttpBinding(), endpoint); 

    return channelFactory.CreateChannel(); 
} 

然後我可以執行以下操作,使用共享郵件合同

IMonitor channel = GetChannelToWebService(); 

// Create the GetTasksRequest message 
GetTasksRequest getTasksRequest = new GetTasksRequest(); 
// Set the various properties on the message 

// Convert it to a strongly type message 
TypedMessageConverter requestMessageConverter = TypedMessageConverter.Create(
    typeof(GetTasksRequest), 
    Constants.Service.Actions.GetTasksRequest, 
    Constants.Service.Namespace.Location); 
Message request = requestMessageConverter.ToMessage(
         getTasksRequest, 
         MessageVersion.Soap11); 

// Send it and get the response. 
Message response = channel.GetTasks(request); 

// Check for SOAP faults 
if (response.IsFault) 
{ 
    MessageFault fault = MessageFault.CreateFault(response, int.MaxValue); 
    // React accordingly   
} 

TypedMessageConverter responseMessageConverter = TypedMessageConverter.Create(
    typeof(GetTasksResponse), 
    Constants.Service.Actions.GetTasksResponse, 
    Constants.Service.Namespace.Location); 
GetTasksResponse getTasksResponse = 
    responseMessageConverter.FromMessage(response) as GetTasksResponse; 

((IClientChannel)channel).Close(); 

有一點需要注意的是,故障不會被拋出客戶端,您必須手動檢查Message對象作爲響應,並按照您從樣本中看到的方式採取相應措施。

服務器端我做的同樣的事情用TypedMessageConvertor

// Convert the inbound message to a GetTasksRequest. 
TypedMessageConverter getTasksMessageConverter = TypedMessageConverter.Create(
    typeof(GetTasksRequest), 
    Constants.Service.Actions.GetTasksRequest, 
    Constants.Service.Namespace.Location); 
GetTasksRequest getTasksMessage = 
    getTasksMessageConverter.FromMessage(request) as GetTasksRequest; 

// Validate the message is the correct type. 
if (getTasksMessage == null) 
{ 
    throw FaultHelper.UnknownMessageTypeFault(); 
} 

// Do my thing 

GetTasksResponse responseMessage = new GetTasksResponse(); 

// Set appropriate response bits in the responseMessage 

TypedMessageConverter responseConverter = TypedMessageConverter.Create(
    typeof(GetTasksResponse), 
    Constants.Service.Actions.GetTasksResponse, 
    Constants.Service.Namespace.Location); 
Message response = responseConverter.ToMessage(responseMessage, request.Version); 
response.Headers.RelatesTo = request.Headers.MessageId; 

return response; 

只是不要忘記設置RelatesTo頭是從請求頭中的MessageId

+0

有趣的方法 - 感謝分享!然而,我不知道這是否會在OP的場景中起作用,我們希望基本上通過它「任何事情」......如果你傳遞任何東西,你可能不得不訴諸手動繞開XML。 ... –

+0

嗯,是真的,但任何事情往往都不是人們想要的,即使他們認爲它是開始的。以上內容也是您開始編寫消息路由器的方式(儘管它將內置於4.0/Dublin中) – blowdart

0

你也可以傳遞一個的XElement 。這使請求對象能夠靈活地包含您選擇的任何內容。

您會理想地指定一個XSD,其中包含多個'choice'元素,每個元素指定不同的請求類型之一。

<xs:element name="request"> 
    <xs:complexType> 
    <xs:choice> 
     <xs:element name="requestType1"/> 
      .... 
     </xs:element> 
     <xs:element name="requestType2"/> 
      .... 
     </xs:element> 
    </xs:choice> 
    </xs:complexType> 
</xs:element> 

您的服務端代碼很簡單,需要確定哪個「選擇」對象存在以確定如何處理參數。