Come sovrascrivere l’output di eccezione non gestita di default in Owin?

Ho scritto server semplice usando Owin Self-hosting e WebApi:

namespace OwinSelfHostingTest { using System.Threading; using System.Web.Http; using Microsoft.Owin.Hosting; using Owin; public class Startup { public void Configuration(IAppBuilder builder) { var config = new HttpConfiguration(); config.Routes.MapHttpRoute( "Default", "{controller}/{id}", new { id = RouteParameter.Optional } ); builder.UseWebApi(config); } } public class Server { private ManualResetEvent resetEvent = new ManualResetEvent(false); private Thread thread; private const string ADDRESS = "http://localhost:9000/"; public void Start() { this.thread = new Thread(() => { using (var host = WebApp.Start(ADDRESS)) { resetEvent.WaitOne(Timeout.Infinite, true); } }); thread.Start(); } public void Stop() { resetEvent.Set(); } } } 

Quando c’è un’eccezione nel controller, quindi Owin restituisce la risposta XML in questo modo:

  An error has occurred. Attempted to divide by zero. System.DivideByZeroException  ...   

Ma voglio un output diverso, quindi come posso ignorarlo?

Puoi farlo creando OWIN MiddleWare e collegandolo alla pipeline:

 public class CustomExceptionMiddleware : OwinMiddleware { public CustomExceptionMiddleware(OwinMiddleware next) : base(next) {} public override async Task Invoke(IOwinContext context) { try { await Next.Invoke(context); } catch(Exception ex) { // Custom stuff here } } } 

E collegalo all’avvio:

 public class Startup { public void Configuration(IAppBuilder builder) { var config = new HttpConfiguration(); config.Routes.MapHttpRoute( "Default", "{controller}/{id}", new { id = RouteParameter.Optional } ); builder.Use().UseWebApi(config); } } 

In questo modo qualsiasi eccezione non gestita verrà catturata dal tuo middleware e ti consentirà di personalizzare il risultato di output.

Una cosa importante da notare : se la cosa ospitata ha una propria logica di gestione delle eccezioni, come fa WebAPI, le eccezioni non si propagheranno . Questo gestore è destinato a qualsiasi eccezione che non sia gestita dal servizio sottostante ospitato .

Quando si attende un metodo asincrono, un’eccezione non verrà gettata nel contesto del chiamante, ma sarà disponibile controllando l’attività restituita al chiamante.

Quindi, con questa modifica alla soluzione fornita da @ yuval-itzchakov sarete in grado di catturare le eccezioni sottostanti:

 var subtask = Next.Invoke(context); await subtask; if (subtask.Exception != null) { // log subtask.Exception here }