.net WCF:数据协定正在转换为消息协定

.net WCF:数据协定正在转换为消息协定,.net,wcf,datacontract,messagecontract,.net,Wcf,Datacontract,Messagecontract,我的WCF服务导出单个操作,该操作标记为“捕获所有操作”和“回复”操作,因此它表示服务的公共入口点: [ServiceContract] public interface IService { [OperationContract (Action="*", ReplyAction="*")] Message MyMethod (Message msg); } 客户代理仍然作为数据合同生成 然而,我发现,尽管客户机发送了一个数据契约,但当序列化msg时,主体似乎是与数据契约等价的

我的WCF服务导出单个操作,该操作标记为“捕获所有操作”和“回复”操作,因此它表示服务的公共入口点:

[ServiceContract]
public interface IService
{
    [OperationContract (Action="*", ReplyAction="*")]
    Message MyMethod (Message msg);
}
客户代理仍然作为数据合同生成

然而,我发现,尽管客户机发送了一个数据契约,但当序列化
msg
时,主体似乎是与数据契约等价的消息契约,而不是数据契约本身

即使这样也没问题,只是提取内部的数据契约需要手动解析传入的XML。服务本身没有实际使用的
MessageContract
类型,因此访问主体意味着提取节点、重新标记元素等等。这是一个手动过程,大概是WCF在公开操作不是基于
消息时已经在幕后处理的事情


当WCF是数据契约到数据契约时,它是如何做到这一点的?有没有一种方法可以使用相同的流程?

这是正确的默认行为。每次发送请求或响应数据时,它们都自动包装在包装元素中。它也称为包裹参数样式。如果您不想使用它,而是想使用裸参数样式,则必须定义消息约定并将其IsWrapped属性设置为false。就像这个简单的例子:

[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操作不会在请求和响应中使用包装

限制是操作必须只接受单个MessageContract作为参数,并且始终必须返回MessageContract(即使它返回void)。因此,实现需求的最简单方法是通过替换属性将所有数据契约转换为消息契约

另一种方法是为每个请求和响应创建单独的消息约定,并将数据约定类型的属性用作消息体。如果出于任何原因,您不喜欢为每个操作创建两个额外的消息契约,并且您仍然希望保留旧的数据契约,那么您可以使用little hack(我看不出有任何理由使用它,但它是有效的)。将MessageContract属性添加到数据契约中,并将MessageBodyMember属性添加到所有数据成员中

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

我同意拉迪斯拉夫的观点,你看到的是正确的行为。MSDN上有一个很棒的文档,描述了WCF接收和发送消息时发生的情况:

与您的问题相关的关键段落如下:

阅读信息主要用于 由服务框架在 接收消息。例如,当 DataContractSerializer正在使用中, 服务框架将获得一个XML 读卡器在身体上方,并将其传递给 反序列化引擎,它将 然后开始阅读信息 逐元素和构造 相应的对象图

因此,框架使用
DataContractSerializer
在收到有效负载(一个XML信息集)时将其反序列化为适当的类。您可以尝试使用相同的逻辑—通过提取有效负载(可能使用返回XmlReader的
Message.getReaderAtombodyContents()
),然后使用DataContractSerializer将XML反序列化为要使用返回的
XmlReader
的对象


希望这有帮助

这是有道理的,但是对于默认的
消息
类型,是否有任何方法可以抑制这种情况,而不是定义自定义数据/消息契约?本质上,此服务是动态服务加载器的包装器。客户机向其抛出数据契约;服务查看操作,查找需要调用的服务和操作,加载程序集并调用操作。“问题”是后端服务都是用数据契约编写的。包装器服务必须从
消息
转换为数据契约。有没有一种不用手动解析XML就能做到这一点的方法?