SignalR,Owin和异常处理

Yas*_*adi 14 asp.net signalr owin

我开发了一个基于ASP.NET 4.5和Owin的示例signalR应用程序,

我在IIS 7.5上托管了该应用程序

一切都很好,但我怎么能处理Owin的异常?

请考虑以下代码:

[HubName("SampleHub")]
public class SampleHub : Hub
{
    public SampleHub()
    {
        throw new InvalidOperationException("?!");
    }
}
Run Code Online (Sandbox Code Playgroud)

这个异常不会调用Application_Error(这是我的问题)

我在哪里可以获得owin的所有异常用于日志记录和调试目的

应用程序错误 ?

我对这样的事情不感兴趣:

app.UseErrorPage(new ErrorPageOptions()
{
    ShowCookies = true,
    ShowEnvironment = true,
    ShowExceptionDetails = true,
    ShowHeaders = true,
    ShowQuery = true,
    ShowSourceCode = true
});
Run Code Online (Sandbox Code Playgroud)

这对于高级场景来说完全没用,比如asp.net web api和asp.net mvc

用于覆盖目的的OnException方法的动作过滤器要好得多.

提前致谢.

hal*_*r73 22

如果您希望专门针对SignalR Hub进行异常处理,那么OWIN中间件就不是您的选择.

为了说明原因之一,假设当从Hub方法内部抛出异常时,SignalR正在使用其WebSocket传输.在这种情况下,SignalR不会关闭WebSocket连接.相反,SignalR会将JSON编码消息直接写入套接字,以向客户端指示抛出异常.没有简单的方法使用OWIN中间件来触发任何类型的事件,当这可能包装整个OWIN WebSocket扩展之外,我强烈建议不要这样做.

幸运的是,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);
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以使用ExceptionContext而不仅仅是记录.例如,您可以将ExceptionContext.Error设置为另一个异常,该异常将更改客户端接收的异常.

您甚至可以通过将ExceptionContext.Error设置为null或通过设置ExceptonContext.Result来抑制异常.如果你这样做,客户端会发现Hub方法返回你在ExceptonContext.Result中找到的值而不是throw.

前一段时间写了另一个SO答案,关于如何为Hub方法抛出的每个异常调用单个客户端回调:SignalR异常记录?

还有HubPipelineModules的MSDN文档:http://msdn.microsoft.com/en-us/library/microsoft.aspnet.signalr.hubs.hubpipelinemodule (v=vs.118) .aspx

  • 非常感谢您的良好解决方案.但是这个模块不能记录例如SignalR的"集线器描述符提供者的例外"和"集线器激活器"部分的异常信号.RingR模块不会记录集线器的构造函数异常.您的模块很有用,我将把它用作SignalR记录器.但是,SignalR的创建和启动过程由'Owin'本身执行.我在哪里可以获得这些例外.暂时,我已经实现了SignalR的所有扩展点,例如IHubDescriptorProvider,IHubActivator等,以使日志记录成为可能,这在我看来显然是错误的.任何的想法? (2认同)