如何拥有一个带有 json 动态成员的 WCF DataContract

Posted

技术标签:

【中文标题】如何拥有一个带有 json 动态成员的 WCF DataContract【英文标题】:How to have a WCF DataContract with a json dynamic member 【发布时间】:2012-10-06 16:20:19 【问题描述】:

在我正在进行的项目中,我们需要有一个可以包含一些未定义 JSON 的 DataContract。

DataMember 是一些仅对客户端有意义的 JSON。我们希望允许客户端向我们发送我们不知道的 json。

例子:

public class Contract

    [DataMember]
    public int clientId;
    [DataMember]
    public string json;

显然,定义这样的合同需要客户端像这样转义 json:


    "clientId":1,
    "json": "\"test\":\"json\""

显然,这不是我们需要的。客户端应该发送给我们的 json 应该是这样的:


    "clientId":1,
    "json": "test":"json"

我们调查的可能解决方案:

    使用 Stream 作为请求正文的合同参数。工作,但把工作放在我们这边,而不是使用框架。 将“json”定义为动态对象。不工作。无法正确写入属性。 使用 Newtonsoft 库,更改 WCF 端点中的默认合同序列化程序,以将所有输入序列化为 JObject。我们还需要处理请求的序列化,这会导致我们的应用程序出现问题。我们宁愿避免这种方式。

有没有人可以解决这个问题?

编辑

该服务提供其他 json 资源。它使用 webHttpBinding 定义了一个端点。 操作是这样定义的(为了简单起见):

[WebInvoke(Method = "POST", UriTemplate = "...", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)]
[OperationContract]
Stream Create(Contract c);

此外,该服务使用以下属性进行装饰:

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]

谢谢。 杰夫

【问题讨论】:

听起来您的客户端正在将您的服务输出作为soap/XML 使用,并且您正试图通过soap 消息传输JSON 字符串。您是否考虑过为soap/XML 和JSON 响应保留单独的端点。您可以将标准 DataContact 端点按原样保留在当前绑定中,并添加一个新的 WebHttpBinding 端点以使用 JSON 字符串进行响应。是的,它增加了一个调用,但它会简化你的合同。 @Sixto Saez:我们不提供肥皂。我们有 1 个带有 webHttpBinding 的端点,仅支持 REST json。 您会使用客户端在请求中发送的未定义 JSON 吗? 【参考方案1】:

WCF(从 4.5 开始)不支持将任意 JSON 作为数据协定的一部分进行反序列化。您需要使用另一个序列化程序来执行此操作 - JSON.NET 是我个人喜欢的一个。为了能够更改序列化程序,您可以使用不同的消息格式化程序,在https://github.com/microsoftarchive/msdn-code-gallery-community-s-z/tree/master/Supporting%20different%20data%20and%20serialization%20formats%20in%20WCF 的帖子中,我有一个完全可以做到这一点的示例 - 将 WCF 使用的默认序列化替换为 JSON.NET。

请注意,要使用该库接收任意 JSON,您需要将“json”属性的类型更改为 JSON.NET 中的任意 JSON,JToken:

public class Contract 
 
    [DataMember] 
    public int clientId; 
    [DataMember] 
    public Newtonsoft.Json.Linq.JToken json; 
 

【讨论】:

嗨,Carlos,在问这个问题之前,我已经在你的博客上看了很多关于我的问题。 ;) 我已经尝试过这条路线,实现了我自己的消息格式化程序,但它在我们的应用程序中暗示了一些问题。如果可能的话,我想找到另一种方法。否则,我最终会更改格式化程序。顺便说一句,感谢您的博客,在过去的几个月里,我阅读了很多关于 WCF 可扩展性的帖子。 链接失效了我把它改成微软官方 GitHub 存档的 Msdn 博客存档。在这种情况下,它比 Web 存档链接更好,因为它也提供了整个代码解决方案【参考方案2】:

你用这些标签配置了类和方法吗? 类实施前

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class xxx ...

方法实现之前

[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Json)]
public Contract getContract() ...

【讨论】:

AspNetCompatibilityRequirements 属性在我们的合约实例上,操作使用 [OperationContract] 和 [WebInvoke(Method = "POST" UriTemplate="....", ResponseFormat = WebMessageFormat.Json , RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare 往返可以将名为“json”的类属性声明为对象而不是字符串。该对象必须是包含一个唯一属性的类: public string test get;set;【参考方案3】:

你试过了吗?

public class Contract 
 
    [DataMember] 
    public int clientId; 
    [DataMember] 
    public Dictionary<string,string> DynamicProperties; 

【讨论】:

这只会给出平面对象...想想students:[name:"john", grade:54,name:"michelle", grade:95], class:"Eco 1o1"【参考方案4】:

更改签名以接受流。 例如:

public String ProcessJson(Stream jsondata)

//play with jsondata


要作为流接收,请覆盖 WebContentTypeMapper 方法。

 public class RawWebContentTypeMapper : WebContentTypeMapper 
    
        public override WebContentFormat GetMessageFormatForContentType(string contentType)
                    
                return WebContentFormat.Raw;       
           
    

【讨论】:

【参考方案5】:

您不希望“json”属性包含字符串,而是希望它包含对象。像这样:

public class Contract

    [DataMember]
    public int clientId;
    [DataMember]
    public JsonObj json;

public class JsonObj

    [DataMember]
    public string test;

这样 json 解析器就会输出你需要的东西。 我希望我说清楚了。

干杯!

【讨论】:

不幸的是,这行不通。对于客户端它可以工作,但另一个可能会发布一些完全不同的 json。一些像:“clientId”:1,“json”:“id”:13,“ref”:“theOther”

以上是关于如何拥有一个带有 json 动态成员的 WCF DataContract的主要内容,如果未能解决你的问题,请参考以下文章

如何在 WCF 自定义行为中动态更改 URL

使用 JSON 实现带有 WCF 服务 (wshttpBinding) 的 c# asp.net 应用程序

WCF POST 通过 JQuery。如何在 JSON 中发送数组?

在 WCF Azure 服务总线中动态分配 json 响应内容类型

始终在 WCF 服务中返回带有 Json 的 XML 字符串

双继承和多态。如何从一个基类中拥有两个独立的成员?