2014-02-15 187 views
12

我已经开发了基于ASP.NET 4.5 & Owin样本signalR应用,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网页API & asp.net的MVC

操作筛选与onException的方法完全无用为了覆盖的目的要好得多。

在此先感谢。

回答

19

如果你想专门为SignalR Hubs提供异常处理,OWIN中间件是而不是要走的路。

为了说明一个理由,假设SignalR在Hub方法内引发异常时使用WebSocket传输。在这种情况下,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回答了如何可以调用一个客户端回调由集线器方法抛出每一个例外:SignalR exception logging?

还为HubPipelineModules MSDN文档: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”。它通过'GlobalHost.HubPipeline.AddModule()'注册。为什么我的'HubPipelineModule'没有被调用? – Artyom