2014-10-18 59 views
4

如何限制web api &實體框架返回的列? 因爲我仍然是一個新手,我希望儘可能多的信息成爲可能;)如何限制web api返回的列?

我的控制器:

  //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"}] 

回答

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

+0

我一直在玩odata&看起來不錯..它和webapi一樣快嗎?你知道它是否會在vnext中得到支持嗎? – MWD 2014-10-21 15:06:06

+0

我不確定,但我期望。團隊在此頁面發表的評論(http://blogs.msdn.com/b/webdev/archive/2014/09/11/announcing-the-release-of-web-api-odata-5-3.aspx )表示當vNext處於「穩定」狀態時,他們會查看「如何啓用它」。那是在9月11日,所以事情可能會繼續。它正在積極發展,所以我會想象它們將會移植。至於速度,我還沒有看到任何速度問題。事實上,事實上正好相反,因爲我已經設法對數據庫進行更有針對性的查詢了。 – 2014-10-21 16:00:19

+0

感謝Josh ..我在玩了一天的odata後覺得很印象深刻,並且認爲我會盡我所能開始使用它;) – MWD 2014-10-21 20:14:12

1

這可以通過使用投影來完成,這裏使用匿名類型示例:

db.Creditors 
    .Select(x => new { 
     x.CreditorID, 
     x.BusinessName, 
    }) 
    .ToArray() 

這將導致查詢數據庫,將只得到兩個字段你需要的包裹在匿名課上。您可以直接從您的WebAPI控制器以JSON結果返回它。

如果你需要傳遞的結果(這是SomeAnonymousClassICanNotReference[]型)層之間,您可以使用dymanic關鍵字(實際上不是一個很好的選擇),或者使用自定義類像Select(x => new MyClass { Id = x.CreditorID ...

+0

我仍然是一個新手&將需要看看你的回答更多..謝謝你的幫助:) – MWD 2014-10-21 15:12:08

+0

你能解釋更多嗎?我寧願不使用odata。你的方法看起來像它應該工作,但它不適合我。 – 2015-08-14 22:27:11

+0

@ConnieDeCinko你有更具體的問題嗎?你有什麼嘗試,什麼不適合你,你有哪些問題? – Lanorkin 2015-08-17 11:57:04

1

在沒有OData的情況下,有幾種不同的方法可以處理這種需求。我傾向於使用投影查詢(正如Lanorkin在他的回答中提到的)。這裏有些例子。

1.返回一個動態類型從您的WebAPI控制器:

這是最快和最簡單的方法。有人會認爲動態返回類型是sl,不馴的,但他們完成了工作。

[HttpGet] 
public dynamic GetCreditors() { 
    return db.Creditors 
     .Select(x => new { 
     x.CreditorID, 
     x.BusinessName, 
    }).ToArray() 
} 

2.使用顯式的返回類型在你的控制器:

除的WebAPI,這種方法適用於WCF不允許動態返回類型。如果您的標準做法是使用靜態返回類型,這是一個「更好」的方法。

您的返回類型創建一個類:

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要包含或忽略哪些屬性。

如果您使用實體框架的代碼優先方法,那麼您可以直接將屬性添加到您的類。如果您使用數據庫優先方法(代碼生成),那麼將您的屬性放入Metadata類是最安全的。 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瞭解更多詳情。