2015-02-24 7 views
11

ho scritto semplice server usando Owin Self-hosting e WebAPI:Come sovrascrivere l'output di eccezione non gestito di default in Owin?

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<Startup>(ADDRESS)) 
        { 
         resetEvent.WaitOne(Timeout.Infinite, true); 
        } 
       }); 
      thread.Start(); 
     } 

     public void Stop() 
     { 
      resetEvent.Set(); 
     } 
    } 

} 

Quando c'è eccezione nel controllore, poi Owin restituisce risposta XML come questo:

<Error> 
    <Message>An error has occurred.</Message> 
    <ExceptionMessage>Attempted to divide by zero.</ExceptionMessage> 
    <ExceptionType>System.DivideByZeroException</ExceptionType> 
    <StackTrace> 
     ... 
    </StackTrace> 
</Error> 

Ma voglio output diverso - Allora, come posso ignorare questo?

+1

Che tipo di uscita stai cercando? – abatishchev

risposta

8

lo fa creando un OWIN middleware e agganciandolo nella 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 
     } 
    } 
} 

ed agganciarlo 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<CustomExceptionMiddleware>().UseWebApi(config); 
    } 
} 

In questo modo qualsiasi eccezioni non gestite vengono catturati dal middleware e ti permettono di personalizzare il risultato di output.

Una cosa importante da notare: se la cosa ospitata ha una logica di gestione di essa la propria eccezione, come fa WebAPI, eccezioni non si propagano. Questo gestore è pensato per qualsiasi eccezione che va da non gestito dal servizio sottostante ospitato.

+0

@DarthVader: cosa non funziona esattamente? –

+7

Btw che non funziona. Alla chiamata di Next.Invoke() il blocco catch non viene mai attivato. Inciampato su questo sulla mia ricerca sarebbe bello sapere come fare questo. L'eccezione è ingerita non appare il contesto o il dizionario. –

+0

@DrSchizo Bene, se la tua eccezione è gestita da WebAPI, ovviamente non la vedrai colpire qui, poiché è già gestita e contenuta all'interno del suddetto framework. –

2

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

Così, con questa modifica alla soluzione fornita da @ Yuval-itzchakov sarete in grado di catturare eccezioni sottostanti:

var subtask = Next.Invoke(context); 

await subtask; 

if (subtask.Exception != null) 
{ 
    // log subtask.Exception here 
} 
+1

Se un 'Task' o un' Task 'lancia un'eccezione, si propagherà definitivamente al punto' await'. Perché pensi che non lo sarebbe? –

Problemi correlati