如何限制web api&amp ;;返回的列数实体框架? 我会尽可能多地欣赏信息,因为我还是新手;)
我的控制器:
//GET: api/Creditors
public IQueryable<Creditor> GetCreditors()
{
return db.Creditors;
}
我的班级:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
namespace PurchaseOrders.Models
{
public class Creditor
{
[Key]
public int CreditorID { get; set; }
[MaxLength(10, ErrorMessage = "Maximum of 10 characters")]
public string CRKEY { get; set; }
[Display(Name = "Business Name")]
[MaxLength(40, ErrorMessage = "Maximum of 40 characters")]
public string BusinessName { get; set; }
[MaxLength(40, ErrorMessage = "Maximum of 40 characters")]
public string Address { get; set; }
[MaxLength(40, ErrorMessage = "Maximum of 40 characters")]
public string City { get; set; }
[MaxLength(4, ErrorMessage = "Maximum of 4 characters")]
public string State { get; set; }
[MaxLength(4, ErrorMessage = "Maximum of 4 characters")]
public string Postcode { get; set; }
[MaxLength(15, ErrorMessage = "Maximum of 15 characters")]
public string Phone { get; set; }
[MaxLength(15, ErrorMessage = "Maximum of 15 characters")]
public string Fax { get; set; }
[MaxLength(60, ErrorMessage = "Maximum of 60 characters")]
public string Email { get; set; }
[MaxLength(60, ErrorMessage = "Maximum of 60 characters")]
public string Website { get; set; }
[MaxLength(30, ErrorMessage = "Maximum of 30 characters")]
public string ContactName { get; set; }
[MaxLength(15, ErrorMessage = "Maximum of 15 characters")]
public string ABN { get; set; }
[Display(Name = "Registered for GST")]
public bool RegisteredForGST { get; set; }
}
}
目前返回:
[{"CreditorID":1,"CRKEY":"test1","BusinessName":"test1","Address":"7 Smith Street","City":"Melbourne","State":"VIC","Postcode":"3000","Phone":null,"Fax":null,"Email":null,"Website":null,"ContactName":null,"ABN":"null","RegisteredForGST":true},{"CreditorID":2,"CRKEY":"test2","BusinessName":"test2","Address":"10 Smith Street","City":"SYDNEY","State":"NSW","Postcode":"2000","Phone":null,"Fax":null,"Email":null,"Website":null,"ContactName":null,"ABN":"null","RegisteredForGST":true}]
这是我想要的结果(只有“CreditorID”和“BusinessName”):
[{"CreditorID":1,"BusinessName":"test1"},{"CreditorID":2,"BusinessName":"test2"}]
答案 0 :(得分:1)
这可以使用投影来完成,这里是使用匿名类型的示例:
db.Creditors
.Select(x => new {
x.CreditorID,
x.BusinessName,
})
.ToArray()
这将导致对数据库的查询,这将只需要包含在匿名类中的两个字段。您可以使用JSON结果直接从WebAPI控制器返回它。
如果您需要在图层之间传递结果(类型为SomeAnonymousClassICanNotReference[]
),您可以使用dymanic
关键字(实际上不是一个好的选项),也可以使用自定义类{{1 }}
答案 1 :(得分:1)
在您的问题中,您显示了查询的json输出,因此我假设您正在从Javascript发出GET请求。当您使用IQueryable
作为API方法的返回值类型时,您应该能够利用WebApi提供的OData支持,以便您可以发出OData查询以仅选择你想要的列。有关OData支持的更多详细信息,请this article。
首先,javascript方面,假设jQuery易于回答:
$.get('api/Creditors?$select=CreditorId,BusinessName', onSuccess)
您想要的列名在$select
参数的逗号分隔列表中指定。 (onSuccess
是一个回调函数,您将定义哪个函数将传递从API返回的数据。有关详细信息,请参阅jQuery documentation。)
在服务器端,您可能需要从ODataController
而不是ApiController
派生您的控制器,您需要添加[Queryable]
或[EnableQuery]
属性您的GetCreditors()
方法取决于您使用的WebApi版本。
如果您发现需要继承ODataController
以使其正常工作,那么您必须添加另一部分配置,即配置OData端点。为此,您需要类似以下的代码:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
ODataModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<Creditor>("Creditors");
config.MapODataServiceRoute(
routeName: "ODataRoute",
routePrefix: null, // or "api" ?
model: builder.GetEdmModel());
}
}
在您的网络启动代码中的某处(例如Application_Start
),您需要按以下方式调用此方法:
GlobalConfiguration.Configure(WebApiConfig.Register);
根据您设置项目的方式,后一种配置中的一些可能不是必需的,因为它已经完成,但我认为我已经提到它了。有关详细信息,请查看this page。
答案 2 :(得分:1)
在没有OData的情况下,有几种不同的方法可以处理此要求。我倾向于使用投影查询(正如Lanorkin在他的回答中提到的)。以下是一些例子。
<强> 1。从WebAPI控制器返回动态类型:
这是最快捷,最简单的方法。有些人认为动态回报类型是草率的,但他们完成了工作。
[HttpGet]
public dynamic GetCreditors() {
return db.Creditors
.Select(x => new {
x.CreditorID,
x.BusinessName,
}).ToArray()
}
<强> 2。在控制器中使用显式返回类型:
这适用于WebAPI以及不允许动态返回类型的WCF。这是一个更好的&#34;如果你的标准做法是使用静态回报类型,那就接近。
为您的返回类型创建一个类:
public class CreditorResult {
public int CreditorID { get; set; }
public string BusinessName { get; set; }
}
然后您的API方法如下所示:
[HttpGet]
public CreditorResult[] GetCreditors() {
return db.Creditors
.Select(x => new CreditorResult() {
x.CreditorID,
x.BusinessName,
}).ToArray()
}
第3。使用模型属性来控制输出字段:
当前版本的WebAPI使用JSON.NET作为其序列化程序,旧版本也可以设置为使用它。您可以在模型上指定数据属性,以告知JSON.NET要包含或忽略哪些属性。
如果您使用实体框架的代码优先方法,则可以将属性直接添加到您的类中。如果您正在使用数据库优先方法(代码生成),那么将您的属性放在元数据类中是最安全的。 http://www.ozkary.com/2015/01/add-data-annotations-to-entity.html
如果您只想包含几个字段,则应将[DataContract]
添加到类中,并将[DataMember]
添加到属性中。只有[DataMember]
的属性才会包含在输出中。例如,以下内容仅返回CreditorID和BusinessName:
[DataContract]
public class Creditor
{
[DataMember]
[Key]
public int CreditorID { get; set; }
[DataMember]
[Display(Name = "Business Name")]
[MaxLength(40, ErrorMessage = "Maximum of 40 characters")]
public string BusinessName { get; set; }
...
如果您想要包含大部分字段并忽略一些字段,则更容易的选择是将[JsonIgnore]
添加到您要隐藏的属性中。
public class Creditor
{
[Key]
public int CreditorID { get; set; }
[JsonIgnore]
[MaxLength(10, ErrorMessage = "Maximum of 10 characters")]
public string CRKEY { get; set; }
[Display(Name = "Business Name")]
[MaxLength(40, ErrorMessage = "Maximum of 40 characters")]
public string BusinessName { get; set; }
...
还有很多其他方法可以微调输出。查看http://james.newtonking.com/archive/2009/10/23/efficient-json-with-json-net-reducing-serialized-json-size了解详情。