2014-04-21 2 views
29

В ASP.NET Web API 2 в чем разница между следующими?Возврат IHttpActionResult против IEnumerable <Item> vs IQueryable <Item>

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

и

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

и

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

Должен ли я вернуть IHttpActionResult или IEnumerable<MyItem>/IQueryable<MyItem>?

+0

Если ваш метод действия не включает использование ключевого слова 'await', вы не должны возвращать' Task'.Вместо этого вы должны просто вернуть 'IHttpActionResult',' IEnumerable 'или' IQueryable '. См. Вопрос [IHttpActionResult vs async Task ] (https://stackoverflow.com/q/29100732/1497596). Также см. Вопрос [Эффективно использовать async/wait с ASP.NET Web API] (https://stackoverflow.com/q/31185072/1497596). – DavidRR

ответ

24

Вы должны вернуть IHttpActionResult, потому что вы можете быть более конкретным для клиента. Вы можете создавать более удобные веб-приложения. В основном вы можете возвращать разные сообщения статуса HTML для разных ситуаций.

Например:

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

IEnumerable и IQueryable просто разобрать ваши данные в формат вывода и вы не будете иметь надлежащий способ обработки исключений. Это самое важное различие.

+0

Учитывая, что 'await' не используется в' GetMyItems() ', его подпись должна просто быть« public IHttpActionResult GetMyItems() ». Из вопроса [IHttpActionResult vs async Task ] (https://stackoverflow.com/q/29100732/1497596) см. [Этот ответ] (https://stackoverflow.com/a/38699810/1497596), который гласит: : «Если ваш код действия контроллера не использует' await', вы можете вернуться к более простой подписи. Однако результат, который вы вернете, будет по-прежнему асинхронным ». – DavidRR

6

Я бы выбрал между IEnumerable и IHttpActionResult, вы можете сделать почти то же самое с обоими из них только несколько разными способами. IQueryable обычно используется для задач доступа к данным более низкого уровня и отложенного выполнения sql-запросов, поэтому я бы сохранил его инкапсулированным в ваших классах доступа к данным и не подвергал его веб-ави.

Вот резюме от http://www.asp.net/web-api/overview/web-api-routing-and-actions/action-results:

IHttpActionResult

Интерфейс IHttpActionResult был Введены в Web API 2. По существу, он определяет HttpResponseMessage завод. Вот некоторые преимущества использования интерфейса IHttpActionResult (по классу HttpResponseMessage):

  • Упрощает модульное тестирование контроллеров.
  • Перемещает общую логику для создания ответов HTTP на отдельные классы.
  • Делает намерение действия контроллера более ясным, скрывая детали низкого уровня построения ответа.

IEnumerable <Item>

Для всех других типов возврата, Web API использует медиа форматировщик для сериализации возвращаемого значения. Web API записывает сериализованное значение в тело ответа. Код состояния ответа - 200 (OK).

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

Недостатком этого подхода является то, что вы не можете напрямую возвращать код ошибки, например, 404. Тем не менее, вы можете бросить HttpResponseException коды ошибок. Чтобы получить больше информации.

+2

-1 «IQueryable обычно используется для задач доступа к данным более низкого уровня и отложенного выполнения запросов sql, поэтому я бы сохранил его в ваших классах доступа к данным и не подвергал его веб-ави». Это совершенно неправильно. Без раскрытия IQueryable трудно использовать запросы запросов OData. http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/odata-v4/create-an-odata-v4-endpoint – Aron

+1

@Aron Я согласен, что это не примените к OData, но многие люди не согласятся с вами о том, чтобы выставлять IQueryable вне уровня репозитория: http://codetunnel.com/should-you-return-iqueryablet-from-your-repositories/, http: // программисты .stackexchange.com/questions/192044/should-repositories-return-iqueryable, http://mikehadlow.blogspot.com.au/2009/01/should-my-repository-expose-iqueryable.html. И некоторые люди даже описывают OData как анти-шаблон https://github.com/ServiceStack/ServiceStack/wiki/Auto-Query#why-not-odata – Jason

+0

Это те же люди, которых я бы утвердил, что внутренняя платформа является анти- шаблон. – Aron