.net core signalR 全局异常处理
Hub的异常拦截
{ }
{ }
*:first-child { }
*:last-child { }
{ }
{ }
{ }
{ }
{ }
{ }
{ }
{ }
{ }
h6:first-child { }
{ }
{ }
{ }
{ }
{ }
{ }
{ }
{ }
{ }
{ }
:first-child { }
:last-child { }
{ }
:first-child { }
:last-child { }
{ }
{ }
code { }
{ }
{ }
{ }
{ }
:first-child { }
:last-child { }
{ }
{ }
{ }
{ }
{ }
{ }
{ color: rgba(255, 255, 255, 1); padding: 5px; background-color: rgba(43, 102, 149, 1); border: 1px solid rgba(255, 255, 255, 1); border-radius: 5px; font-size: 24px; margin-top: 15px; margin-bottom: 15px }
environment
.net core 5.0
主题
对于hub中的方法执行 实现一个全局的异常处理
食用方法
1.实现自定义拦截类:
Microsoft.AspNetCore.SignalR.IHubFilter
public class HubMethodFilter : IHubFilter
{
public async ValueTask<object?> InvokeMethodAsync(HubInvocationContext invocationContext, Func<HubInvocationContext, ValueTask<object?>> next)
{
try
{
return await next(invocationContext);
}
catch(Exception e)
{
do something
// write log,send notice....
}
}
}
2.注册拦截器
services.AddSignalR(hubOptions =>
{
hubOptions.AddFilter<HubMethodFilter>();
})
扩展
在自定义拦截类中可使用 .net core 的依赖注入
文档
可忽略的源码
扩展
首先从注册的地方查找:Microsoft.Extensions.DependencyInjection.SignalRDependencyInjectionExtensions:
public static ISignalRServerBuilder AddSignalR(this IServiceCollection services, Action<HubOptions> configure)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
if (services == null)
{
throw new ArgumentNullException("services");
}
ISignalRServerBuilder result = services.AddSignalR();
services.Configure<HubOptions>(configure);
return result;
} public static ISignalRServerBuilder AddSignalR(this IServiceCollection services)
{
if (services == null)
{
throw new ArgumentNullException("services");
}
services.AddConnections();
services.Configure(delegate(WebSocketOptions o)
{
o.KeepAliveInterval = TimeSpan.Zero;
});
services.TryAddSingleton<SignalRMarkerService>();
services.TryAddEnumerable(ServiceDescriptor.Singleton<IConfigureOptions<HubOptions>, HubOptionsSetup>());
return services.AddSignalRCore();
}public static ISignalRServerBuilder AddSignalRCore(this IServiceCollection services)
{
services.TryAddSingleton<SignalRCoreMarkerService>();
services.TryAddSingleton(typeof(HubLifetimeManager<>), typeof(DefaultHubLifetimeManager<>));
services.TryAddSingleton(typeof(IHubProtocolResolver), typeof(DefaultHubProtocolResolver));
services.TryAddSingleton(typeof(IHubContext<>), typeof(HubContext<>));
services.TryAddSingleton(typeof(IHubContext<, >), typeof(HubContext<, >));
services.TryAddSingleton(typeof(HubConnectionHandler<>), typeof(HubConnectionHandler<>));
services.TryAddSingleton(typeof(IUserIdProvider), typeof(DefaultUserIdProvider));
services.TryAddSingleton(typeof(HubDispatcher<>), typeof(DefaultHubDispatcher<>));
services.TryAddScoped(typeof(IHubActivator<>), typeof(DefaultHubActivator<>));
services.AddAuthorization();
SignalRServerBuilder signalRServerBuilder = new SignalRServerBuilder(services);
signalRServerBuilder.AddJsonProtocol();
return signalRServerBuilder;
}
看完后你就能发现,在默认注册的类中,没有一个是符合需要的其中HubDispatcher<>最为迷惑,里面有提供异常处理,但类是internal的,只好当场离去
既然默认配置都没有,只好从参数上上手还好就一个参数,找到其对应的扩展类Microsoft.AspNetCore.SignalR.HubOptionsExtensions:
ps:你可能会问为啥直接找扩展类,->HubOptions类的公开属性你看一下就能明白了
/// <summary>
/// Methods to add <see cref="IHubFilter"/>'s to Hubs.
/// </summary>
public static class HubOptionsExtensions
{
/// <summary>
/// Adds an instance of an <see cref="IHubFilter"/> to the <see cref="HubOptions"/>.
/// </summary>
/// <param name="options">The options to add a filter to.</param>
/// <param name="hubFilter">The filter instance to add to the options.</param>
public static void AddFilter(this HubOptions options, IHubFilter hubFilter)
{
_ = options ?? throw new ArgumentNullException(nameof(options));
_ = hubFilter ?? throw new ArgumentNullException(nameof(hubFilter));if (options.HubFilters == null)
{
options.HubFilters = new List<IHubFilter>();
} options.HubFilters.Add(hubFilter);
} /// <summary>
/// Adds an <see cref="IHubFilter"/> type to the <see cref="HubOptions"/> that will be resolved via DI or type activated.
/// </summary>
/// <typeparam name="TFilter">The <see cref="IHubFilter"/> type that will be added to the options.</typeparam>
/// <param name="options">The options to add a filter to.</param>
public static void AddFilter<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]TFilter>(this HubOptions options) where TFilter : IHubFilter
{
_ = options ?? throw new ArgumentNullException(nameof(options)); options.AddFilter(typeof(TFilter));
} /// <summary>
/// Adds an <see cref="IHubFilter"/> type to the <see cref="HubOptions"/> that will be resolved via DI or type activated.
/// </summary>
/// <param name="options">The options to add a filter to.</param>
/// <param name="filterType">The <see cref="IHubFilter"/> type that will be added to the options.</param>
public static void AddFilter(this HubOptions options, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type filterType)
{
_ = options ?? throw new ArgumentNullException(nameof(options));
_ = filterType ?? throw new ArgumentNullException(nameof(filterType)); options.AddFilter(new HubFilterFactory(filterType));
}
}
/// <summary>
/// The filter abstraction for hub method invocations.
/// </summary>
public interface IHubFilter
{
/// <summary>
/// Allows handling of all Hub method invocations.
/// </summary>
/// <param name="invocationContext">The context for the method invocation that holds all the important information about the invoke.</param>
/// <param name="next">The next filter to run, and for the final one, the Hub invocation.</param>
/// <returns>Returns the result of the Hub method invoke.</returns>
ValueTask<object?> InvokeMethodAsync(HubInvocationContext invocationContext, Func<HubInvocationContext, ValueTask<object?>> next) => next(invocationContext);/// <summary>
/// Allows handling of the <see cref="Hub.OnConnectedAsync"/> method.
/// </summary>
/// <param name="context">The context for OnConnectedAsync.</param>
/// <param name="next">The next filter to run, and for the final one, the Hub invocation.</param>
/// <returns></returns>
Task OnConnectedAsync(HubLifetimeContext context, Func<HubLifetimeContext, Task> next) => next(context); /// <summary>
/// Allows handling of the <see cref="Hub.OnDisconnectedAsync(Exception)"/> method.
/// </summary>
/// <param name="context">The context for OnDisconnectedAsync.</param>
/// <param name="exception">The exception, if any, for the connection closing.</param>
/// <param name="next">The next filter to run, and for the final one, the Hub invocation.</param>
/// <returns></returns>
Task OnDisconnectedAsync(HubLifetimeContext context, Exception? exception, Func<HubLifetimeContext, Exception?, Task> next) => next(context, exception);
}
看到这里,瞬间就明白了,就这个了
不过将HubOptions设为**internal,又弄个扩展类来维护此属性也是绝了为了防止使用者乱来真是费尽了心思...直呼一流,有需要的可以学习一下~
到此也差不多结束了,最后贴一下IHubFilter的使用位置:Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher 好巧不巧就是HubDispatcher<>,据说是HubDispatcher<>中的信息太多了,不想直接公开...
private readonly Func<HubInvocationContext, ValueTask<object>> _invokeMiddleware;
private readonly Func<HubLifetimeContext, Task> _onConnectedMiddleware;
private readonly Func<HubLifetimeContext, Exception, Task> _onDisconnectedMiddleware; public DefaultHubDispatcher(IServiceScopeFactory serviceScopeFactory, IHubContext<THub> hubContext, bool enableDetailedErrors,
ILogger<DefaultHubDispatcher<THub>> logger, List<IHubFilter> hubFilters)
{
_serviceScopeFactory = serviceScopeFactory;
_hubContext = hubContext;
_enableDetailedErrors = enableDetailedErrors;
_logger = logger;
DiscoverHubMethods();var count = hubFilters?.Count ?? 0;
if (count != 0)
{
_invokeMiddleware = (invocationContext) =>
{
var arguments = invocationContext.HubMethodArguments as object[] ?? invocationContext.HubMethodArguments.ToArray();
if (invocationContext.ObjectMethodExecutor != null)
{
return ExecuteMethod(invocationContext.ObjectMethodExecutor, invocationContext.Hub, arguments);
}
return ExecuteMethod(invocationContext.HubMethod.Name, invocationContext.Hub, arguments);
}; _onConnectedMiddleware = (context) => context.Hub.OnConnectedAsync();
_onDisconnectedMiddleware = (context, exception) => context.Hub.OnDisconnectedAsync(exception); for (var i = count - 1; i > -1; i--)
{
var resolvedFilter = hubFilters[i];
var nextFilter = _invokeMiddleware;
_invokeMiddleware = (context) => resolvedFilter.InvokeMethodAsync(context, nextFilter); var connectedFilter = _onConnectedMiddleware;
_onConnectedMiddleware = (context) => resolvedFilter.OnConnectedAsync(context, connectedFilter); var disconnectedFilter = _onDisconnectedMiddleware;
_onDisconnectedMiddleware = (context, exception) => resolvedFilter.OnDisconnectedAsync(context, exception, disconnectedFilter);
}
}
}
说明:在构造函数中将filter注册到委托中,委托的调用就不看了,有兴趣的自己去翻翻吧
.net core signalR 全局异常处理的更多相关文章
- asp.net core添加全局异常处理及log4net、Nlog应用
0.目录 整体架构目录:ASP.NET Core分布式项目实战-目录 一.介绍 此篇文章将会介绍项目的全局异常收集以及采用log4net或者NLog记录. 众所周知,一旦自己的项目报错,如果没有进行处 ...
- ASP.NET Core 中间件自定义全局异常处理
目录 背景 ASP.NET Core过滤器(Filter) ASP.NET Core 中间件(Middleware) 自定义全局异常处理 .Net Core中使用ExceptionFilter .Ne ...
- 在.NET Core程序中设置全局异常处理
以前我们想设置全局异常处理只需要这样的代码: AppDomain currentDomain = AppDomain.CurrentDomain; currentDomain.UnhandledExc ...
- ASP.NET Core 中间件的使用(三):全局异常处理机制
前言 我们经常听到"秒修复秒上线",觉得很厉害的样子. 其实不然,这只是一个调侃而已,出现问题的方式很多(逻辑漏洞.代码异常.操作方式不正确等). 我们今天来说代码异常问题怎么快速 ...
- NET MVC全局异常处理(一) 【转载】网站遭遇DDoS攻击怎么办 使用 HttpRequester 更方便的发起 HTTP 请求 C#文件流。 Url的Base64编码以及解码 C#计算字符串长度,汉字算两个字符 2019周笔记(2.18-2.23) Mysql语句中当前时间不能直接使用C#中的Date.Now传输 Mysql中Count函数的正确使用
NET MVC全局异常处理(一) 目录 .NET MVC全局异常处理 IIS配置 静态错误页配置 .NET错误页配置 程序设置 全局异常配置 .NET MVC全局异常处理 一直知道有.NET有相关 ...
- Net Core SignalR 测试,可以用于unity、Layair、白鹭引擎、大数据分析平台等高可用消息实时通信器。
SignalR介绍 SignalR介绍来源于微软文档,不过多解释.https://docs.microsoft.com/zh-cn/aspnet/core/signalr/introduction?v ...
- aspnetcore配置log4net并添加全局异常处理
第一步:在NuGet中引用log4net 第二步:创建log4net.config <?xml version="1.0" encoding="utf-8" ...
- 全栈项目|小书架|服务器开发-Koa2 全局异常处理
什么是异常 做开发的基本都知道异常,像Android开发中常见的ANR异常.空指针异常,服务器开发中经常遇到的异常404,500异常,还有一些其他常见的异常,具体可见HTTP状态码. 基本上这些异常可 ...
- Spring Cloud Gateway的全局异常处理
Spring Cloud Gateway中的全局异常处理不能直接用@ControllerAdvice来处理,通过跟踪异常信息的抛出,找到对应的源码,自定义一些处理逻辑来符合业务的需求. 网关都是给接口 ...
随机推荐
- SHELL 变量引用
shell变量的引用非常重要,运用技巧灵活多变 变量的引用主要包含四类:双引号引用.单引号引用.反引号引用.反斜线引用 " " 双引号 屏蔽除美元符号$.反引号( ` )和反斜线( ...
- [刘阳Java]_easyui-panel组件入门级_第3讲
EasyUI中的panel组件在前面一节中我们简单告诉了大家代码如何写.这一节我们会从panel的入门级开始讲起走,重点包括它的事件监听,属性tool介绍 1. 事件监听-通过data-options ...
- 从代码生成说起,带你深入理解 mybatis generator 源码
枯燥的任务 这一切都要从多年前说起. 那时候刚入职一家新公司,项目经理给我分配了一个比较简单的工作,为所有的数据库字段整理一张元数据表. 因为很多接手的项目文档都不全,所以需要统一整理一份基本的字典表 ...
- OpenGL学习笔记(二)画三角形
目录 渲染管线(Graphics Pipeline) 编码实现 顶点数据 顶点缓冲对象(VBO) 顶点着色器 编译着色器 片段着色器 着色器程序 链接顶点属性 顶点数组对象 最终绘制三角形 索引缓冲对 ...
- 小程序中多个echarts折线图在同一个页面的使用
最近做小程序的业务中遇到一个页面要同时显示几个echarts图,刚开始遇到各种冲突,死数据可以,动态数据就报错的问题,折磨了一天,仔细看了官网和查在各种资料之后,终于解决了. 直接上代码: commi ...
- DDD随谈
前言 最近再次拜读了Eric的奠基之作[Domain-Driven Design –Tackling Complexity in the Heart of Software],还有Vernon的[In ...
- 多次面试被拒,‘宅家苦修’30天,终获美团offer(含字节跳动/阿里/腾讯等大厂面试题整理)
背景:双非渣本. 今年由于疫情,上半年一直在家里.2月份本来无忧无虑,呆在家里不给国家添乱的时候,发现身边的同学找到了大厂的offer.心里开始有点慌张.本来想在3月份如果能回到学校,就开始考研之路, ...
- TCP实现聊天
TCP实现聊天 IO流关闭是简写的,正常写要判断是否为null 客户端:(最好捕获异常) 1.连接服务器Socket 2.发送消息 package net.TCPChat; import java.i ...
- Notes about BSD
FreeBSD: mainly for web server; OpenBSD: mainly for security concerned server;
- 基于ivy的源代码调试方法
项目PORJ_TEST是项目PROJ的测试项目.在它的ivy中引用了PROJ的jar包.由于PROJ正处于开发阶段,源代码更改频繁, 在运行PROJ_TEST中的测试时,需要进入PROJ的jar包内部 ...