Asp.Net Web Api - 为IEnumerable <T>返回404返回null

Luk*_*ins 11 c# asp.net asp.net-web-api

我正在使用Asp.Net Web Api的发行版创建API.如果没有找到结果,我试图传回正确的响应代码(404).

首先获取版本(抛出多个枚举错误):

public IEnumerable<MyObjectType> Get(int id, string format)
{
    var db = new DbEntities();

    var result = db.pr_ApiSelectMyObjectType(store, id, format).AsEnumerable();
    if (result.Any())
    {
        return result;
    }
    var response = new HttpResponseMessage(HttpStatusCode.NotFound) 
        { Content = new StringContent("Unable to find any results") };
    throw new HttpResponseException(response);
}
Run Code Online (Sandbox Code Playgroud)

第二次获取版本(结果永远不为null,因此它总是返回200):

public IEnumerable<MyObject> Get(int id, string format)
{
    var db = new DbEntities();

    var result = db.pr_ApiSelectMyObjectType(store, id, format);
    if (result == null)
    {
        var response = new HttpResponseMessage(HttpStatusCode.NoContent) 
            { Content = new StringContent("Unable to find any results") };
        throw new HttpResponseException(response);
    }
    return result.AsEnumerable();
}
Run Code Online (Sandbox Code Playgroud)

如果没有找到结果,如何传回404?我知道我可以使用列表,但我有一个自定义的csv媒体类型格式化程序,只适用于IEnumerable类型,所以我宁愿坚持下去.

cuo*_*gle 28

更好的办法是抓null行动过滤级别,定义与全球范围内的行为过滤,并从此引发异常404:

public class NullFilter : ActionFilterAttribute
{
    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        var response = actionExecutedContext.Response;

        object responseValue;
        bool hasContent = response.TryGetContentValue(out responseValue);

        if (!hasContent)
            throw new HttpResponseException(HttpStatusCode.NotFound);
    }
}
Run Code Online (Sandbox Code Playgroud)

通过这种方式,您不需要Any在您的操作中使用,代码会更简单:

public IEnumerable<MyObjectType> Get(int id, string format)
{
    using (db = new DbEntities())
    {
       return db.pr_ApiSelectMyObjectType(store, id, format)
                .AsEnumerable();
    }
}
Run Code Online (Sandbox Code Playgroud)


Jon*_*eet 5

将结果转换为列表可能是最简单的,显然可以多次枚举:

var result = db.pr_ApiSelectMyObjectType(store, id, format).ToList();
if (!result.Any())
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

当然,这意味着将整个查询具体化……但大概你最终会在某个时候这样做。

  • @gdoron:我相信 `Any()` 无论如何都针对 `ICollection&lt;T&gt;` 实现进行了优化,但在它是一个过滤序列的情况下,它可能比使用 `Count()` 更有效率。 (3认同)