2014-04-21 15 views
29

W ASP.NET Web API 2, jaka jest różnica między następującymi?Powracanie IHttpActionResult vs IEnumerable <Item> vs IQueryable <Item>

public async Task<IEnumerable<MyItem>> GetMyItems() 
{ 
    //... code ..., var myItems = await ... 
    return myItems; 
} 

i

public async Task<IQueryable<MyItem>> GetMyItems() 
{ 
    //... code ..., var myItems = await ... 
    return myItems; 
} 

i

public async Task<IHttpActionResult> GetMyItems() 
{ 
    //... code ..., var myItems = await ... 
    return Ok(myItems); 
} 

powinienem wrócić IHttpActionResult lub IEnumerable<MyItem>/IQueryable<MyItem>?

+0

Jeśli twoja metoda działania nie uwzględnia użycia słowa kluczowego 'await', nie powinieneś zwracać' zadania'.Zamiast tego powinieneś po prostu zwrócić 'IHttpActionResult',' IEnumerable 'lub' IQueryable '. Zobacz pytanie [IHttpActionResult vs async Task ] (https://stackoverflow.com/q/29100732/1497596). Zobacz także pytanie [Skutecznie korzystaj z asynchronizacji/poczekaj z ASP.NET Web API] (https://stackoverflow.com/q/31185072/1497596). – DavidRR

Odpowiedz

24

Powinieneś zwrócić IHttpActionResult, ponieważ możesz być bardziej konkretny dla klienta. Możesz tworzyć bardziej przyjazne dla użytkownika aplikacje internetowe. Zasadniczo możesz zwrócić różne komunikaty o stanie HTML dla różnych sytuacji.

Na przykład:

public async Task<IHttpActionResult> GetMyItems() 
{ 
    if(!authorized) 
     return Unauthorized(); 
    if(myItems.Count == 0) 
     return NotFound(); 
    //... code ..., var myItems = await ... 
    return Ok(myItems); 
} 

IEnumerable i IQueryable po prostu analizować dane do formatu wyjściowego i nie będzie mieć odpowiednią drogę do obsługi wyjątków. To jest najważniejsza różnica.

+0

Ponieważ 'await' nie jest używany w' GetMyItems() ', jego sygnatura powinna po prostu być' public IHttpActionResult GetMyItems() '. Od pytania [IHttpActionResult vs async Zadanie ] (https://stackoverflow.com/q/29100732/1497596), zobacz [ta odpowiedź] (https://stackoverflow.com/a/38699810/1497596) która stwierdza : "Jeśli twój kod akcji kontrolera nie używa' Czekaj', możesz przełączyć się na prostszy podpis, jednak wynik, który zwrócisz, będzie nadal asynchroniczny. " – DavidRR

6

Wybieram między IEnumerable i IHttpActionResult, możesz zrobić prawie to samo z obiema z nich w nieco inny sposób. IQueryable jest zwykle używany do zadań dostępu do niższego poziomu i odroczonego wykonywania kwerend sql, więc powinienem przechowywać go w swoich klasach dostępu do danych i nie ujawniać go za pomocą interfejsu API.

Oto podsumowanie z http://www.asp.net/web-api/overview/web-api-routing-and-actions/action-results:

IHttpActionResult

Interfejs IHttpActionResult został introducted w Web API 2. Zasadniczo definiuje fabrykę HttpResponseMessage. Oto niektóre zalety korzystania z interfejsu IHttpActionResult (nad klasą HttpResponseMessage):

  • Upraszcza jednostka testowania kontrolerów.
  • Przenosi wspólną logikę do tworzenia odpowiedzi HTTP na oddzielne klasy.
  • Uczyni działanie kontrolera bardziej przejrzystym, ukrywając szczegóły niskiego poziomu dotyczące konstruowania odpowiedzi.

IEnumerable <Przedmiot>

Dla wszystkich innych rodzajów powrotów, Web API używa formatowania mediów do serializacji zwracanej wartości. Web API zapisuje serializowaną wartość w treści odpowiedzi. Kod statusu odpowiedzi to 200 (OK).

public class ProductsController : ApiController 
{ 
    public IEnumerable<Product> Get() 
    { 
     return GetAllProductsFromDB(); 
    } 
} 

Wadą tego podejścia jest to, że nie można bezpośrednio zwracają kod błędu, takich jak 404. Można jednak rzucić HttpResponseException dla kodów błędów. Po więcej informacji.

+2

-1 "IQueryable jest zwykle używany do zadań dostępu na poziomie niższego poziomu i odroczonego wykonywania kwerend sql, więc powinienem przechowywać go w swoich klasach dostępu do danych i nie ujawniać go za pomocą interfejsu API." To jest całkowicie błędne. Bez narażania IQueryable trudno jest używać adresów URL zapytań "OData". http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/odata-v4/create-an-odata-v4-endpoint – Aron

+1

@Aron Zgadzam się, że to nie stosuje się do OData, ale wiele osób nie zgodziłoby się z tobą o ujawnieniu IQueryable poza warstwą repozytorium: http://codetunnel.com/should-you-return-iqueryablet-from-your-repositories/, http: // programming .stackexchange.com/questions/192044/should-reositories-return-iqueryable, http://mikehadlow.blogspot.com.au/2009/01/should-my-repository-expose-iqueryable.html. A niektórzy nawet opisują OData jako anty-wzór https://github.com/ServiceStack/ServiceStack/wiki/Auto-Query#why-not-odata – Jason

+0

To są ci sami ludzie, którzy twierdzą, że wewnętrzna platforma jest anty wzór. – Aron