2015-02-24 5 views
11

Я написал простой сервер с помощью Owin Self-хостинг и WebAPI:Как переопределить вывод необработанных исключений по умолчанию в 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(); 
     } 
    } 

} 

Когда есть исключение в контроллере, а затем Owin возвращает ответ XML, как это:

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

Но я хочу другой вывод - так как я могу переопределить это?

+1

Какой выход вы ищете? – abatishchev

ответ

8

Вы сделать это путем создания Owin ППО и закреплять его в магистральный трубопровод:

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

и повесьте его на старте:

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

Таким образом, любое необработанное исключение будет поймано вашего промежуточного слоя и вы можете настроить результат вывода.

Важная вещь, чтобы отметить: если вещь приютили есть исключение обработки логики его собственной, как это делает WebAPI, исключения не будут распространяться. Этот обработчик предназначен для любого исключения, которое отправляется , которое не используется в базовой службе, размещенной.

+0

@DarthVader - Что именно не работает? –

+7

Btw, что не работает. При вызове Next.Invoke() блок catch никогда не запускается. Наткнувшись на это при моем поиске, было бы хорошо знать, как это сделать. Исключение проглатывается, не отображается контекст или словарь. –

+0

@DrSchizo Хорошо, если ваше исключение handeled с помощью WebAPI, вы, конечно, не увидите его здесь, поскольку оно уже обработано и содержится внутри указанной структуры. –

2

Когда вы ожидаете метода async, исключение не будет передано в контекст вызывающего, но будет доступно путем проверки задачи, возвращенной вызывающему.

Таким образом, с этой модификацией решения представленной @ Юваль-itzchakov вы будете в состоянии захватить, лежащие в основе исключения:

var subtask = Next.Invoke(context); 

await subtask; 

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

Если задача 'Task' или' Task 'выдает исключение, она определенно будет распространяться в точке' await'. Почему вы думаете, что это не так? –

Смежные вопросы