【问题标题】:Adding dynamic datamembers to DataContract将动态数据成员添加到 DataContract
【发布时间】:2011-12-05 21:01:39
【问题描述】:

我有返回 Json 的 WCF 服务。

下面定义的数据合约

  [DataContract]
    public class OptionData
    {
        [DataMember]
        public string Book { get; set; }
        [DataMember]
        public string Id { get; set; }
        [DataMember]
        public string DealId { get; set; }
        [DataMember]
        public string DeliveryDate { get; set; }
        [DataMember]
        public string ExpiryDate { get; set; }
   }

而Operation Contract定义如下

[Description("Returns List of Options by user id")]
        [WebGet(UriTemplate = "{sessionId}/Application/{applicationId}?start={start}&limit={limit}&page={page}", ResponseFormat = WebMessageFormat.Json)]
        public List<OptionData> GetAllTask(string sessionId, string applicationId)

我需要向 OptionData 类动态添加新的 DataMember 字段。

最好的做法是什么?

【问题讨论】:

    标签: wcf json


    【解决方案1】:

    只要接收 json 的客户端知道如何处理动态添加的类成员,您就可以使用此@987654321 的已接受答案中概述的 Expando 对象策略@ 它使用 ServiceStack 库,但您可以提取必要的代码来做您想做的事。来自 ExpandoObject 的简单键/值对方法记录在 this code snippet.

    编辑:我应该指出,这种方法不依赖于 WCF,因此考虑到问题的上下文,它可能不是您所需要的。

    【讨论】:

    • 看起来还是很危险的事情。
    • 非常正确。我会推荐一种更 RESTful 的方法,它依赖于 links 在应用程序中实现此功能。客户端将使用这些链接来访问所需的任何特殊情况类结构。当然,这不是格雷戈里要问的问题:)
    【解决方案2】:

    如果您知道自己需要 JSON,您可以随时自己控制序列化(请参阅 this post) - 只需使用现有库返回一串 JSON。

    如果您知道所有可能的字段名称,另一种选择是只给我们IsRequired = false

    最后的替代方法是使用 WCF 用于 Forward-Compatible Contracts 的相同模式 - 只需将所有未知属性附加到单个集合对象 (ExtensionData)。 ExtensionData 只是根据this post 的键/值对字典。不幸的是 - ExtensionData 不能直接写。这将是我模拟IExtensibleDataObject 正在做什么的方法......

    [DataContract]
    public class OptionData 
    {
        [DataMember]
        public string Book { get; set; }
        [DataMember]
        public string Id { get; set; }
        [DataMember]
        public string DealId { get; set; }
        [DataMember]
        public string DeliveryDate { get; set; }
        [DataMember]
        public string ExpiryDate { get; set; }
        [DataMember]
        public Dictionary<string, string> Metadata { get; set;}
    } 
    

    【讨论】:

      【解决方案3】:

      我认为这是不可能的。

      让我们暂时考虑一下您的 DataContract 是什么:它是您的服务定义它所知道的内容的方式 - 作为输入或输出。客户端必须通过元数据交换发现或从您提供的静态代理类(可能在 dll 中)找到这一点。

      如果您即时更改合同,则您的服务无法让其客户知道合同已更改。无法即时更改该合同。

      即使您即时更改了类的定义,包括正确的属性等,客户也无法找到它,因为之前已经发布了合同。

      我无法想象需要什么样的机制来与客户即时传达此类更改。

      我能想到的唯一解决方法是有一个参数,它接受一个字符串并允许客户端传入 XML 或类似的东西,这可能是任何东西。不过,这是一个非常讨厌的 hack……

      【讨论】:

      • 根据他使用 REST 的代码示例,因此不会有元数据交换或代理类。
      【解决方案4】:

      正如我最近在这里发布的那样,我刚刚遇到了这个确切的问题: Configuring WCF data contract for proper JSON response

      我的解决方案是使用 ExpandoObject。但是,我必须使用 Newtsoft.json 进行 JSON 序列化,然后我必须让我的 web 服务返回原始文本(而不是依赖 WCF 序列化)。如果您愿意,我很乐意发布我的代码。可能有一种方法可以进行动态数据合同,但我无法弄清楚。但我的解决方案可以完成这项工作。

      【讨论】:

      【解决方案5】:

      如果您需要动态控制 RESTful 服务返回的数据结构,我认为您唯一的选择是返回 XDocument 之类的东西。您的服务操作可以创建任意结构的 XDocument 并将其返回。话虽如此,我不确定当 WCF 尝试将 XDocument 序列化为 JSON 时会发生什么。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-01-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-05
        • 2012-10-30
        • 2022-11-29
        • 1970-01-01
        相关资源
        最近更新 更多