【问题标题】:How to only return a subset of specific fields from Model in REST APIController using .NET MVC4如何使用 .NET MVC 4 仅从 REST API 控制器中的模型返回特定字段的子集
【发布时间】:2013-09-25 16:22:45
【问题描述】:

我正在编写一个 Web API,客户端可以请求以 XML 格式返回数据。我正在使用 Enterprise Foundation 和 MVC4 在 .NET 中实现这一点。

我正在为如何仅从我的控制器中的模型返回某些字段的子集而苦苦挣扎。

为了论证,假设我有一个 Product 模型,其中包含属性“Id”、“Name”、“Price”和“Actual Cost”(我使用的是来自 http://www.asp.net/web-api/overview/creating-web-apis/using-web-api-with-entity-framework/using-web-api-with-entity-framework,-part-6 的示例)

我需要公开一个 Web API 供客户端查询特定产品以获取其名称和价格,但在此响应中我不想返回“实际成本”属性(因为这是我们的秘密)。

现在在我提供的链接中,这正是他们试图通过使用 DTO 来解决的问题(他们定义了一个名为 ProductDTO 的 DTO,它只包含我想要返回的子集)。我已经实现了这个解决方案,我现在确实能够只返回我在 DTO 中指定的字段。

问题是用于在 XML 中返回的实体的命名现在是 ProductDTO 而不是 Product,即返回的 XML 是

{"ProductDTO":[{"Id":1,"Name":"Tomato Soup","Price":1.39}, {"Id":3,"Name":"Yo yo","Price":6.99]}

而不是

{"Product":[{"Id":1,"Name":"Tomato Soup","Price":1.39}, {"Id":3,"Name":"Yo yo","Price":6.99]}

这意味着我们所有当前使用我们的 API 并期望返回“产品”的客户现在都将返回“ProductDTO”,这意味着他们将不得不对其代码进行更改,这是不可接受的。我需要为他们提供一个“产品”,其中只有他们目前获得的相关子字段集。我如何实现这一目标?我不能像prevent property from being serialized in web api 中建议的那样简单地“忽略”一个数据成员,因为我也有一些 API 案例,我确实需要返回所有属性而不仅仅是一个子集。

只是一些背景知识:我们有一个现有的 API 服务器接口,它是用 Ruby on Rails 编写的,现在我们正在将其转移到 C# 和 .NET MVC4。我们还有一堆客户端应用程序已经连接到我们现有的、较旧的 Ruby on Rails API 服务器,我们不希望客户端对其代码进行任何更改。我们只是将 API 服务器代码从 Ruby on Rails 转移到 C#。在 Ruby on Rails 中,当我只需要在某些调用上返回属性的子集时,我可以简单地对 XML 序列化器应用过滤器。

【问题讨论】:

    标签: asp.net-mvc dto asp.net-apicontroller


    【解决方案1】:

    假设你有一个类似的类

    public class product
    {
    public string Name{get; set;}
    ..
    }
    

    并且您不想在响应中出现它,您可以使用 [XMLIgnore] 属性

    [XMLIgnore]
    public string Name{get; set;}
    

    希望这会有所帮助。

    【讨论】:

    • 您错过了我提到忽略属性不是一种选择的问题部分,因为在某些情况下我确实需要使用它。 (我问题中的第二个链接实际上显示了类似的建议。)只有当我总是想阻止该属性显示时,您的建议才有效。奥拉夫的回答描述了我希望实现的目标。
    【解决方案2】:

    如果你想继续你已经开始的 DTO 路线,恕我直言,这是一个好主意,因为它可以让你控制你导出的内容,而不用导出特定的东西污染你的内部类,你可以添加一个 DataContract 属性到你的ProductDTO 类。

    [DataContract(Name="Product")]
    public class ProductDTO
    {
        [DataMember]
        public int Id {get;set;}
        [DataMember]
        public string Name {get;set;}
    }
    

    Web API 中使用的默认 XML 格式化程序是 DataContractSerializer。 你可以阅读更多关于这个here

    【讨论】:

    • 我还要提一下(尽管在您提供的链接中提到了),如果您使用 DataContract,则必须在每个属性之前添加 [DataMember],因为 DataContract “使序列化选择加入”。感谢您的帮助!
    • 你说得对,我已经用 DataMember 属性更新了答案
    • 知道使用 XMLSerializer 而不是 DataContractSerializer 时这将如何工作吗?
    • @Stanley XmlRoot 属性来控制元素名称。有关属性的完整列表,请参阅此链接:msdn.microsoft.com/en-us/library/83y7df3e.aspx
    • [XmlRoot(ElementName = "Product")] 在 xml 中仅返回一个对象时工作正常。但是,当我返回产品集合时,它会将其序列化为包含“ProductDTO”元素的“ArrayOfProductDTO”。
    猜你喜欢
    • 2015-08-14
    • 2021-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-10
    • 2020-01-05
    • 1970-01-01
    相关资源
    最近更新 更多