WCF:数据合同转换为消息协定协定、转换为、合同、消息

2023-09-04 00:35:19 作者:失而复得的都旧了

我的WCF服务出口的单一操作,标有包罗万象的动作和回复动作,使其重新presents一个共同的切入点,以服务:

My WCF service exports a single operation, marked with the catch-all action and reply action so that it represents a common entry point to the service:

[ServiceContract]
public interface IService
{
    [OperationContract (Action="*", ReplyAction="*")]
    Message MyMethod (Message msg);
}

客户端代理仍生成为数据的合同。

什么我发现,但问题在于,尽管客户端发送的数据合同,当信息序列化,身体似乎是等同的消息合同数据契约,而不是数据的合同本身。

What I'm finding, however, is that despite the client sending a data contract, when msg is serialized, the body appears to be the equivalent message contract to the data contract, not the data contract itself.

即使这是好的,但里面提取数据合同涉及做传入的XML的手工解析。服务本身不具备实际 MessageContract 键入要使用,所以存取主体装置提取节点,重新标记元素,等等。这是一个手动过程的东西,presumably,WCF已经在幕后操作时露出操作不消息为基础的。

Even this is fine, except that extracting the data contract inside involves doing a manual parsing of the incoming XML. The service itself does not have an actual MessageContract type to use, so accessing the body means extracting nodes, relabeling elements, and so on. It's a manual process for something that, presumably, WCF is already handling under the covers when the exposed operations are not Message-based.

如何WCF做到这一点时,它的数据的合同到数据的合同?有没有我可以使用相同的过程办法?

How does WCF do this when it's data contract-to-data contract? Is there a way that I can use that same process?

推荐答案

这是正确的默认行为。每个时间的请求或响应的数据是发送它们自动包装在缠绕元件。它也被称为裹参数样式。如果你不想使用它,而是要使用裸参数风格,你必须定义消息的合同,并设置其IsWrapped属性设置为false。像这样简单的例子:

That is the correct default behavior. Each time a request or a response data are send they are automatically wrapped in the wrapping element. It is also known as Wrapped parameter style. If you don't want to use it and instead you want to use Bare parameter style you have to define message contract and set its IsWrapped property to false. Like this simple example:

[ServiceContract]
public interface IService
{
    [OperationContract]
    GetMessageResponse GetMessage(GetMessageRequest request);
}

[MessageContract(IsWrapped = false)]
public class GetMessageResponse
{
    [MessageBodyMember]
    public string Result { get; set; }
}

[MessageContract(IsWrapped = false)]
public class GetMessageRequest
{
    [MessageBodyMember]
    public string Data { get; set; }
}

在请求和响应

GetMessage函数的操作将不使用包装。

GetMessage operation will not use wrapping in request and response.

限制是,操作具有为仅接受单一MessageContract作为参数的,总是返回MessageContract(即使它返回void)。因此,要实现你的要求,最简单的方法就是通过更换属性将所有的数据合同信息的合同。

Limitation is that operation has to accept only single MessageContract as the parameter and always has to return MessageContract (even if it returns void). So the easiest way to achieve your requirement is to convert all your data contracts to message contracts by replacing attributes.

另一种方法是创建为数据的合同类型的每个请求和响应,并使用特性作为消息体分开的消息的合同。如果由于某种原因你不喜欢为每个操作创建两个额外的消息,合同的想法,你还是希望可以使用的黑客工具preserve旧数据合同(我看不出有任何理由使用它,但它作品)。加入MessageContract属性数据合同和MessageBodyMember属性为所有的数据成员。

Another way is to create separate message contract for each request and response and use properties of your data contracts types as message body. If for any reason you don't like the idea of creating two additional message contracts for each operation and you still want to preserve old data contracts you can use little hack (I don't see any reason for using it but it works). Add MessageContract attribute to your data contracts and MessageBodyMember attribute to all your data members.

[DataContract, MessageContract(IsWrapped = false)]
public class MyData
{ 
    [DataMember, MessageBodyMember]
    public string Data { get; set; }
}