2012-10-02 26 views
8

Estoy creando una API con la versión de lanzamiento de Asp.Net Web Api. Estoy tratando de devolver el código de respuesta correcto (404) si no se encuentran resultados.Asp.Net Web Api - Devolver 404 para IEnumerable <T> Obtener cuando nulo

Primera Comprar (tiros de error múltiple enumeración):

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); 
} 

Segunda Comprar (resultado nunca es nula, por lo que siempre devuelve 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(); 
} 

¿Cómo ¿Devuelvo un 404 si no se encuentran resultados? Sé que podría usar una lista, pero tengo un formateador de tipo de medios CSV personalizado que solo funciona con tipos de IEnumerables, por lo que preferiría seguir con eso.

Respuesta

4

es probable que sea más simple de convertir sólo los resultados de una lista, que, obviamente, se pueden enumerar varias veces:

var result = db.pr_ApiSelectMyObjectType(store, id, format).ToList(); 
if (!result.Any()) 
{ 
    ... 
} 

Por supuesto que significa materializar toda la consulta ... pero se supone que iba a terminar haciendo eso de todos modos en algún momento.

+0

1. creo que el uso de 'result.Count = 0' debe ser más rápido, ya que no utilizará el método de extensión' 'Any' de Enumerable' cual! crea un bloque iterador pero un li propiedad de st. 2. Con web API v2 y OData, es probable que desee devolver IQueryable y no List (o IEnumerable). – gdoron

+2

@gdoron: Creo que 'Any()' está optimizado para las implementaciones 'ICollection ' de todos modos, pero es potencialmente * mucho * más eficiente que usar 'Count()' en los casos en que se trata de una secuencia filtrada. –

25

mejor enfoque consiste en atrapar al nullnivel del filtro acción, definir un filtro de acción con alcance global, y lanzar una excepción 404 de esta:

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); 
    } 
} 

Con esta manera, no es necesario utilizar Any en su acción, el código sería más simple:

public IEnumerable<MyObjectType> Get(int id, string format) 
{ 
    using (db = new DbEntities()) 
    { 
     return db.pr_ApiSelectMyObjectType(store, id, format) 
       .AsEnumerable(); 
    } 
} 
Cuestiones relacionadas