【问题标题】:WCF: Use JSON to encode a SOAP Message BodyWCF:使用 JSON 对 SOAP 消息体进行编码
【发布时间】:2009-05-18 07:04:12
【问题描述】:

我们有我们的服务的 SOAP 实现,到目前为止,我们有一些遗留代码包装我们的 args 并返回另一个对象,以绕过 RPC 方法上的一些序列化/泛型。

经过优化,我们实现了这个类,使其Json序列化(DataContractJsonSerializer)并GZipped我们复杂的请求参数和响应对象。

我现在想将这些东西下推到 WCF 堆栈中。我真正想要的是在标准 SOAP 服务上将消息体编码为 GZipped Json 的能力。我们需要事务支持和安全等,因此我们需要能够支持标准绑定。

我已经设法实现 Json 序列化的操作行为,以便消息信息集将包含 json 兼容的 XML。然后我想添加一个 MessageEncoder 将 xml 转换为消息正文中的 json。这是我有问题的地方。我无法序列化整个消息,因为我们仍然有标准的肥皂头等,并且 s:body 在 json 兼容的 xml 之前仍然包含根请求或响应对象。我想我可以使用 JsonReaderWriterFactory 只是不确定如何应用于消息的正确部分。

我知道如果我能弄清楚读写这个 Json 部分,我以后可以做 GZIP。

有什么想法吗? 皮特

好的。所以澄清一下。

我的服务是这样的

[ServiceContract]
public interface IMyService {
  [OperationContract]
  Person SavePerson(Person personToSave);

  [OperationContract]
  Person GetPersons();
}

GetPersons() 方法的输出如下所示:

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
  <s:Header>
    <a:Action s:mustUnderstand="1">http://www.petegoo.com/wcf/MyService/IMyService/GetPersonsResponse</a:Action>
    <a:RelatesTo>urn:uuid:a18ccf1c-0793-4240-ba6f-9e86b6f2fdf6</a:RelatesTo>
  </s:Header>
  <s:Body>[{"DateOfBirth":"\/Date(286801200000+1300)\/","FirstName":"Foo","Id":1,"LastName":"Bar"},{"DateOfBirth":"\/Date(333720000000+1200)\/","FirstName":"Foo","Id":1,"LastName":"Bar"}]</s:Body>
</s:Envelope>

注意:以上内容是临时的,因此在语法或语义上可能不正确。

【问题讨论】:

  • 您解决过这个问题吗?我正在开发一个项目,其中使用服务的客户端希望消息采用 JSON 格式,但内部要求需要(或强烈建议)SOAP。谢谢。

标签: c# .net wcf json soap


【解决方案1】:

我的理解是你喜欢将 JSON 嵌入到 SOAP 中的 XML 信息集中吗? 编写一些您想要实现的示例请求和响应会更容易。

我看不出将 JSON 信息集与 XML 信息集共存的充分理由。但是,您可以将 JSON 数据作为 SOAP 中 XML 元素/属性的字符串值返回。

【讨论】:

  • 我应该详细说明一下,我们已将在线消息大小优化为 JSON+GZip。这就是我想要保持这种格式的原因。我现在很高兴只分离为 JSON,我可以稍后添加压缩,因为有很多示例。至于 xml 中的字符串值作为属性或元素,我还是希望有一个明确的服务契约。我希望能够仅使用配置将其全部换掉。如果它可以像这样隐藏在 WCF 堆栈中,那就太好了,但不确定如何。
  • 如果您真的关心消息的大小,您可以让整个服务返回纯 JSON,但是,您的 soap 标头中不会支持这些功能。通过查看 GetPersons() 的输出,我不知道混合 JSON 和 XML 的 WSDL 应该是什么样子。如果你真的想这样做,我还是觉得把整个 JSON 作为 SOAP 响应的字符串值。
  • 您知道如何在不更改代码合同的情况下将 JSON 作为 SOAP 响应的字符串值。换句话说,实现这一点的 WCF 扩展点是什么?
  • 这是我能想到的唯一方法,[DataContract] public class Person { // 现有属性放在这里 public string PersonJosnString {get;set;} }
  • 谢谢。这对我来说真的不起作用。我不想用实现细节污染数据合约。我宁愿把它埋在 WCF 堆栈中,这样我对数据就没有这个要求了。不过谢谢你的帮助。
【解决方案2】:

啊!!才知道这是多少岁。会离开这里,以防它对其他人有用。

我自己对这一切都很陌生,但作为建议,您是否尝试过查看MessageInspectors?您可以将这些添加到clientRuntimedispatchRuntime,以便在 WCF 发送 SOAP 消息之前和之后“播放”它们。

通过实现IDispatchMessageInspector 和/或IClientMessageInspector,您可以在发送消息之前收到一个调用,读取当前的soap 消息xml,更改body 元素的内容以包含您的压缩内容(也许将其添加为新的子节点),然后重新构建消息并将其传递回 WCF 以发送出去。在接收端,您再次在AfterReceiveRequest 中获取消息并反转该过程。

不知道这是否对您有用,但希望对您有所帮助。 W

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-16
    • 1970-01-01
    • 2011-07-20
    • 2012-01-08
    • 1970-01-01
    相关资源
    最近更新 更多