返回 IHttpActionResult vs IEnumerable<Item> vs IQueryable<Item>
Posted
技术标签:
【中文标题】返回 IHttpActionResult vs IEnumerable<Item> vs IQueryable<Item>【英文标题】:Returning IHttpActionResult vs IEnumerable<Item> vs IQueryable<Item> 【发布时间】:2014-06-05 11:45:56 【问题描述】:在 ASP.NET Web API 2 中,以下有什么区别?
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>
?
【问题讨论】:
如果您的操作方法不包括使用await
关键字,那么您不应返回Task
。相反,您应该简单地返回IHttpActionResult
、IEnumerable<MyItem>
或IQueryable<MyItem>
。请参阅问题IHttpActionResult vs async Task<IHttpActionResult>。另见问题Effectively use async/await with ASP.NET Web API。
【参考方案1】:
我会在 IEnumerable 和 IHttpActionResult 之间进行选择,你可以用它们做几乎相同的事情,只是方式略有不同。 IQueryable 通常用于较低级别的数据访问任务和延迟执行 sql 查询,因此我会将其封装在您的数据访问类中,而不是通过 web api 公开它。
这是来自http://www.asp.net/web-api/overview/web-api-routing-and-actions/action-results的摘要:
IHttpActionResult
IHttpActionResult 接口是在 Web API 2 中引入的。本质上,它定义了一个 HttpResponseMessage 工厂。以下是使用 IHttpActionResult 接口的一些优点(相对于 HttpResponseMessage 类):
简化对控制器的单元测试。 将用于创建 HTTP 响应的通用逻辑移到单独的类中。 通过隐藏构造响应的低级细节,使控制器操作的意图更加清晰。IEnumerable
对于所有其他返回类型,Web API 使用媒体格式化程序来序列化返回值。 Web API 将序列化值写入响应正文。响应状态码为 200(OK)。
public class ProductsController : ApiController
public IEnumerable<Product> Get()
return GetAllProductsFromDB();
这种方法的一个缺点是不能直接返回错误代码,例如 404。但是,对于错误代码,您可以抛出 HttpResponseException。了解更多信息。
【讨论】:
-1 “IQueryable 通常用于较低级别的数据访问任务和延迟执行 sql 查询,因此我会将其封装在您的数据访问类中,而不是通过 web api 公开它。”这是完全错误的。在不暴露 IQueryable 的情况下,很难使用OData
查询 url。 asp.net/web-api/overview/odata-support-in-aspnet-web-api/…
@Aron 我同意这不适用于 OData,但很多人会不同意您将 IQueryable 暴露在存储库层之外:codetunnel.com/…、programmers.stackexchange.com/questions/192044/…、mikehadlow.blogspot.com.au/2009/01/…。甚至有人将 OData 本身描述为反模式github.com/ServiceStack/ServiceStack/wiki/…
+1 我希望实现 OData url,您的回答引导我走上正确的错误处理路径。 HttpResponseException 是我需要的。谢谢!
如果您有异常过滤器neovolve.com/2013/02/20/…,我不会使用 IEnumerable
我在这里说“...抛出一个 HttpResponseException ...”是我所需要的。谢谢@Jason【参考方案2】:
您应该返回IHttpActionResult
,因为您可以更具体地针对客户。您可以创建更多用户友好的 Web 应用程序。基本上你可以针对不同的情况返回不同的 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
只会将您的数据解析为输出格式,您将没有正确的方法来处理异常。这是最重要的区别。
【讨论】:
鉴于await
未在GetMyItems()
中使用,其签名应为public IHttpActionResult GetMyItems()
。从问题IHttpActionResult vs async Task<IHttpActionResult>,请参阅this answer,其中指出:“如果您的控制器操作代码不使用await
,那么您可以切换回更简单的签名。但是,您返回的结果仍然是异步的。”
以上是关于返回 IHttpActionResult vs IEnumerable<Item> vs IQueryable<Item>的主要内容,如果未能解决你的问题,请参考以下文章
使用 IHttpActionResult 为非 OK 响应返回内容
返回 IHttpActionResult 时如何对 Web api 操作方法进行单元测试?
使用 c# 使用 IHttpActionResult 将请求类型作为 XML 发送
[使用C#使用IHttpActionResult将请求类型发送为XML
使用具有匿名类型的 OkNegotiatedContentResult 对 IHttpActionResult 进行单元测试