【问题标题】:How to have a WCF DataContract with a json dynamic member如何拥有一个带有 json 动态成员的 WCF DataContract
【发布时间】: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"}
}

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

  1. 使用 Stream 作为请求正文的合同参数。工作,但把工作放在我们这边,而不是使用框架。
  2. 将“json”定义为动态对象。不工作。无法正确写入属性。
  3. 使用 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 吗?

标签: c# json wcf serialization


【解决方案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”}}
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多