返回 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&lt;MyItem&gt; / IQueryable&lt;MyItem&gt;

【问题讨论】:

如果您的操作方法不包括使用await 关键字,那么您不应返回Task。相反,您应该简单地返回IHttpActionResultIEnumerable&lt;MyItem&gt;IQueryable&lt;MyItem&gt;。请参阅问题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);

IEnumerableIQueryable只会将您的数据解析为输出格式,您将没有正确的方法来处理异常。这是最重要的区别。

【讨论】:

鉴于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 发送

创建新的 IHttpActionResult 操作结果方法

[使用C#使用IHttpActionResult将请求类型发送为XML

使用具有匿名类型的 OkNegotiatedContentResult 对 IHttpActionResult 进行单元测试