2014-02-15 6 views
12

Я разработал приложение образец signalR на основе ASP.NET 4.5 & Owin,SignalR, Owin и обработка исключений

и я принимал, что приложение на IIS 7.5

Все работает отлично, но как я могу обрабатывать исключения в Owin?

Рассмотрим следующие коды:

[HubName("SampleHub")] 
public class SampleHub : Hub 
{ 
    public SampleHub() 
    { 
     throw new InvalidOperationException("?!"); 
    } 
} 

Это исключение не будет называть Application_Error (и это моя проблема)

Где я могу получить все исключения из Owin для протоколирования и отладки похожи как

Application_Error?

Я не заинтересован в чем-то вроде этого:

 app.UseErrorPage(new ErrorPageOptions() 
     { 
      ShowCookies = true, 
      ShowEnvironment = true, 
      ShowExceptionDetails = true, 
      ShowHeaders = true, 
      ShowQuery = true, 
      ShowSourceCode = true 
     }); 

Это совершенно бесполезно для сложных сценариев, что-то вроде asp.net Web API & ASP.NET MVC

фильтров действий с OnException методом для переопределения целей намного лучше.

Заранее спасибо.

ответ

19

Если вы хотите обработать исключение специально для концентраторов SignalR, промежуточное ПО OWIN - это не путь.

Чтобы проиллюстрировать только одну причину, предположим, что SignalR использует свой транспорт WebSocket, когда исключение выбрасывается из метода Hub. В этом случае SignalR не закрывает соединение WebSocket. Вместо этого SignalR будет записывать JSON-кодированное сообщение непосредственно в сокет, чтобы указать клиенту, что было создано исключение. Нет простого способа использования промежуточного программного обеспечения OWIN для запуска любого события, когда это происходит за пределами возможной упаковки всего OWIN WebSocket Extension, о котором я бы настоятельно советовал.

К счастью, SignalR предлагает свой собственный Hub Pipeline, который идеально подходит для вашего сценария.

using System; 
using System.Diagnostics; 
using Microsoft.AspNet.SignalR.Hubs; 

public class MyErrorModule : HubPipelineModule 
{ 
    protected override void OnIncomingError(ExceptionContext exceptionContext, IHubIncomingInvokerContext invokerContext) 
    { 
     MethodDescriptor method = invokerContext.MethodDescriptor; 

     Debug.WriteLine("{0}.{1}({2}) threw the following uncaught exception: {3}", 
      method.Hub.Name, 
      method.Name, 
      String.Join(", ", invokerContext.Args), 
      exceptionContext.Error); 
    } 
} 

Вы можете использовать ExceptionContext для более чем простого ведения журнала. Например, вы можете установить ExceptionContext.Error в другое исключение, которое изменит исключение, которое получает клиент.

Вы можете даже исключить исключение, установив ExceptionContext.Error в значение null или установив ExceptonContext.Result. Если вы это сделаете, клиенту появится, что метод Hub вернет значение, найденное вами в ExceptonContext.Result вместо метания.

Некоторое время назад написал другой SO ответ на вопрос о том, как вы можете вызвать одного клиента обратного вызова для каждого исключения, брошенным методом Hub: SignalR exception logging?

Существует также MSDN документация HubPipelineModules: http://msdn.microsoft.com/en-us/library/microsoft.aspnet.signalr.hubs.hubpipelinemodule(v=vs.118).aspx

+2

Большое спасибо для вашего хорошего решения. Но этот модуль не может регистрировать исключения, такие как «Исключения провайдера дескриптора концентратора» и «активатор концентратора» в SignalR Модуль signalR не будет регистрировать конструкторские исключения концентраторов. Ваш модуль полезен, и я собираюсь использовать его в качестве регистратора SignalR. Но процесс создания и запуска SignalR выполняется самим «Owin». Где я могу получить эти исключения. Временно я применил все точки расширяемости SignalR, такие как IHubDescriptorProvider, IHubActivator и т. Д., Чтобы сделать возможной регистрацию, что, на мой взгляд, явно неверно. Есть идеи? –

+0

@ halter73 он не работает для исключений, которые генерируются другими методами HubPipeLineModules или другими методами текущего модуля. –

+1

Спасибо за ответ. Тем не менее я не могу получить 'OnIncomingError', когда я бросаю исключение в свой метод hub, вызываемый клиентом. Он зарегистрирован через 'GlobalHost.HubPipeline.AddModule()'. Почему мой 'HubPipelineModule' не вызван? – Artyom

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