2012-10-02 8 views
8

Sto creando un'API utilizzando la versione di Asp.Net Web Api. Sto cercando di restituire il codice di risposta corretto (404) se non vengono trovati risultati.Asp.Net Web Api - Restituzione di 404 per IEnumerable <T> Get When null

Prima Acquista (tiri errore di enumerazione multipla):

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

Seconda Acquista (risultato non è mai nullo, quindi restituisce sempre 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(); 
} 

come si fa Passo un 404 se non vengono trovati risultati? So che potrei usare una lista, ma ho un formattatore di tipo di supporto csv personalizzato che funziona solo con tipi IEnumerable, quindi preferirei restare fedele a questo.

risposta

4

è probabilmente più semplice per convertire solo i risultati a un elenco, che può ovviamente essere enumerato più volte:

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

Naturalmente questo significa materializzare l'intera query ... ma presumibilmente ci si finisce per fare che comunque ad un certo punto.

+0

1. credo usando 'result.Count = 0 'dovrebbe essere più veloce in quanto non utilizzerà il' Any' metodo di estensione 'di Enumerable' che! crea un blocco iteratore ma un li la proprietà di st 2. Con web API v2 e OData probabilmente vorrai restituire IQueryable e non List (o IEnumerable). – gdoron

+2

@gdoron: Credo che 'Any()' sia ottimizzato per le implementazioni di 'ICollection ', ma è potenzialmente * molto * più efficiente dell'uso di 'Count()' nei casi in cui si tratta di una sequenza filtrata. –

25

Meglio approccio è quello di catturare null a un'azione a livello di filtro, definire un filtro azione con portata globale, e gettare un'eccezione 404 da questo:

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 questo modo, non è necessario utilizzare Any nella vostra azione, il codice sarebbe più semplice:

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