WCF服务端点接受不同的请求/响应

WCF服务端点接受不同的请求/响应,wcf,Wcf,我使用的是Framework 3.5,希望有一个ServiceContract,可以接收不同类型的请求/响应对象,可以吗?是的,如果您真的愿意,您可以将通用的消息类型作为参数和/或返回值处理 [ServiceContract] public interface IMyService { [OperationContract] Message GetData(); [OperationContract] void PutData(Message m); } 有关

我使用的是Framework 3.5,希望有一个ServiceContract,可以接收不同类型的请求/响应对象,可以吗?

是的,如果您真的愿意,您可以将通用的
消息
类型作为参数和/或返回值处理

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

    [OperationContract]
    void PutData(Message m);
}
有关详细信息,请参见

但是,这意味着您必须手动执行大量XML操作巫术,并自己处理大量内容,如果您使用强类型
[DataContract]
类型,这些内容将免费处理

你能做到吗?对你应该这样做吗?好吧,这取决于你到底想要多少!:-)


Marc

正如Marc所说,您有一个接受消息参数的服务合同。但是您不必手工构建XML,相反,您可以在共享DLL中共享接口和消息契约,这对于服务器和客户端都是通用的

例如,我有一个软件,它接收消息,因为规范说它必须这样做。我有一个公共程序集,其中包含接口、所有潜在的请求和响应消息以及命名空间的公共静态字符串。因此,对于其中一个操作,它如下所示

[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();
} 
我有一些类似于

[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();
} 
需要注意的一点是,在客户端不会抛出错误,当消息对象作为响应返回时,您必须手动检查它,并按照示例中所示进行相应的操作

在服务器端,我用TypedMessageConverter做了很多相同的事情

// 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,您还可以传递一个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>

....
....

服务端代码simple需要确定存在哪些“选择”对象,以确定如何处理参数。

不同类型的请求/响应对象是什么意思?您可以根据自己的喜好定义服务接口,所以这不应该是一个问题。我希望有一个名为DoSomeThing的服务方法,每个客户端都将调用它,但传递不同的请求/响应对象。有趣的方法-感谢分享!然而,我不知道这在OP的场景中是否会起作用,在这个场景中,我们基本上想要传递“任何东西”。。。。。如果您传入任何内容,您可能不得不求助于手动对XML进行模糊处理……是的,这是真的,但任何内容通常都不是人们想要的,即使他们认为这是开始。以上也是您开始编写消息路由器的方式(尽管它将内置于4.0/都柏林)