我使用框架3.5,並希望有一個ServiceContract,可以採取不同類型的請求/響應對象,是否有可能?WCF服務端點採取不同的請求/響應
回答
是的,如果你真的想,你可以處理一個通用的Message
類型作爲參數和/或返回值。
[ServiceContract]
public interface IMyService
{
[OperationContract]
Message GetData();
[OperationContract]
void PutData(Message m);
}
在MSDN documentation中查看詳細信息。
但是,這意味着如果您使用強類型[DataContract]
類型,則必須手動執行大量XML操作voodoo並自行處理大量內容,這將免費處理。
你能做到嗎?是。你應該這樣做嗎?那麼,取決於你真正想要它多少! :-)
Marc
正如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
有趣的方法 - 感謝分享!然而,我不知道這是否會在OP的場景中起作用,我們希望基本上通過它「任何事情」......如果你傳遞任何東西,你可能不得不訴諸手動繞開XML。 ... –
嗯,是真的,但任何事情往往都不是人們想要的,即使他們認爲它是開始的。以上內容也是您開始編寫消息路由器的方式(儘管它將內置於4.0/Dublin中) – blowdart
你也可以傳遞一個的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>
您的服務端代碼很簡單,需要確定哪個「選擇」對象存在以確定如何處理參數。
- 1. WCF服務 - HTTP請求和響應
- 2. 節點服務器未響應請求
- 3. FTP服務器不響應USER請求
- 4. 記錄客戶端請求而不等待服務器響應
- 5. WCF - (504)服務器沒有返回此請求的響應
- 6. WCF - (504)服務器沒有返回此請求的響應
- 7. 用於請求 - 響應的WCF或服務總線會話
- 8. 記錄WCF REST服務中的請求/響應
- 9. 在服務器上記錄WCF請求的請求和響應值
- 10. 取消WCF服務器到客戶端的流請求
- 11. Silverlight的WCF服務對服務請求
- 12. 試圖採取服務器響應
- 13. 相同的請求不同的響應
- 14. WCF:服務器響應錯誤請求(400)
- 15. 限制WCF服務只響應一個域請求?
- 16. 如何捕獲WCF數據服務請求/響應消息
- 17. WCF多點服務端點
- 18. 服務器不同時響應多個AJAX請求
- 19. 更改根節點(響應)wcf服務
- 20. 基於PHP服務器端請求/響應的AngularJS過濾器
- 21. 來自服務器的Android客戶端請求和響應
- 22. 簡單的服務器和客戶端請求/響應在C#
- 23. 在WCF服務端編輯來自客戶端的SOAP請求
- 24. 如何更改不影響客戶端的WCF服務合同?
- 25. Web服務 - HTTP GET請求和響應
- 26. Java Web服務請求響應問題
- 27. Web服務 - 相關請求和響應
- 28. 請求與服務器響應DUPLICATE_REQUEST_ID
- 29. 來自同一WCF服務主機中不同服務的多個端點
- 30. WCF服務在兩個不同的服務合同上暴露2個端點
你是什麼意思的不同類型的請求/響應對象?你可以根據需要定義你的服務接口,所以這不應該是一個問題。 –
我想要一個名爲DoSomeThing的服務方法,每個客戶端都會調用,但傳入不同的請求/響應對象。 – Hetal