2013-05-14 10 views
10

Possiedo un servizio Web API Web ASP.NET che genera una SerializationException in determinate circostanze. Il problema è che non sono in grado di intercettare e registrare questa eccezione sul lato server: l'unico posto in cui si trova è nel corpo della risposta HTTP al client.Come intrappolare un SerializationException in Web API?

Ho registrato un ExceptionFilterAttribute come descritto in e verificato che funzioni correttamente quando lancio un'eccezione nel mio controller. Sfortunatamente la SerializationException viene lanciata durante la risposta (dopo il controller) e sembra essere completamente inghiottita da ASP.NET. Ho anche provato ad agganciare Application_Error() in Global.asax.cs ma non è nemmeno apparso lì.

Come posso rilevare eccezioni SerializationException durante la risposta dell'API Web?

risposta

8

Se, invece di restituire un oggetto, si utilizza il metodo ApiController.CreateResponse() e restituire un HttpResponseMessage si può poi fare response.Content.LoadIntoBufferAsync().Wait() e che costringerà la serializzazione per accadere mentre siete ancora in azione e quindi in grado di intercettare l'eccezione.

+1

Perfetto! Leggera ottimizzazione, ho reso la mia azione asincrona e atteso LoadIntoBufferAsync in modo da non bloccare il thread. – Mike

+0

@Mike È probabile che LoadIntoBufferAsync stia spostando solo byte in memoria durante il processo di serializzazione, quindi probabilmente non stai facendo alcun IO. Pertanto, rendendolo asincrono si sta semplicemente passando da un thread pool di thread a un altro thread pool thread, che sarà effettivamente dannoso per il perf. Tuttavia, se sai che il tuo formattatore verrà bloccato in attesa di I/O, allora async potrebbe essere d'aiuto. –

+1

Non sono sicuramente un esperto di Wait vs Wait, ma la mia comprensione è che Wait() blocca il thread corrente mentre Task viene eseguito su un altro thread. attendi inoltre blocca il thread corrente ma lo fa in modo asincrono, liberando il thread per fare altre cose e quindi riprendere al termine dell'attività. Entrambi i casi prevedono un cambio di thread, quindi penso che le prestazioni saranno simili, ma l'approccio asincrono consente (leggermente) una maggiore scalabilità. Come ho detto, le mie conoscenze su questo sono approssimative, quindi dovremmo probabilmente chiedere a Stephen Toub. :) – Mike

1

proposito, serializzazione di risposte effettivamente accade negli strati ospitanti (in HttpControllerHandler, quando ospitato in IIS e in HttpSelfhostServer, quando ospitato in SelfHost) che è ben al di sotto della pila e non immediatamente dopo la risposta viene restituita da un'azione.

WebAPI Stack Poster: http://www.asp.net/posters/web-api/ASP.NET-Web-API-Poster-grayscale.pdf

Detto questo, io non sono in grado di trovare un modo dritto in avanti per raggiungere questo obiettivo. Questo è ingombrante, ma potrebbe sovrascrivere i metodi WriteToStreamAsync di formattazione Xml e Json predefiniti e try-catch-logg eventuali eccezioni?

In alternativa, è possibile abilitare Traccia API Web che registra le eccezioni che si verificano durante la serializzazione. Ma sì, se non sai per le richieste che causano gli errori di serializzazione, allora potresti voler abilitare la traccia tutto il tempo che non sono sicuro sia qualcosa che potresti voler fare.

2

È possibile rilevare tutte le eccezioni Web Api registrando un'implementazione di IExceptionHandler.

Vedi Web API Global Error Handling

ci sono una serie di casi che i filtri di eccezione non può gestire. Ad esempio:

  • Eccezioni generate dai costruttori di controller.
  • Eccezioni generate dai gestori di messaggi.
  • Eccezioni generate durante il routing.
  • Eccezioni generate durante la serializzazione del contenuto della risposta.

Una cosa non menzionata in tale articolo è che il vostro IExceptionHandler dovranno essere inviate tramite ci sono una serie di casi che i filtri di eccezione non può gestire. Per esempio:

Exceptions thrown from controller constructors. 
Exceptions thrown from message handlers. 
Exceptions thrown during routing. 
Exceptions thrown during response content serialization . 

Una cosa non menzionata in tale articolo è che il vostro IExceptionHandler devono essere registrati, sia per GlobalConfiguration.Configuration.Services.Add(...) o tramite un contenitore CIO configurato per essere usato da DependencyResolver.