前言
在增删改查中的增和改操作中,我们经常需要更新数据流的创建人和修改人,无论我们项目是基于DDD,抑或是简单仅有服务层,此时我们都需要获取用户信息,那么我们只能将用户标识从控制器层层传递到服务或仓储层?鉴于如上场景很常见,难道我们没发觉这样做很是繁琐吗?于是乎,我们想要解放生产力,下面咱们来聊聊我个人的想法
全局获取用户信息
既然是全局获取用户信息,难道是定义静态变量?怎么可能,当然是基于请求而获取,基于静态变量必然存在多个用户请求覆盖信息的情况,那我们到底应该怎么全局获取?首先我们想到的过滤器比如ActionFilter...等等,但要是我们需要进行异步操作呢?貌似又不可行,根据我查询官方文档,没搞错的话,应该是从1.0开始就给出了异步过滤器,那就是IAsyncActionFilter,此方法不同于ActionFilter的是,它能够处理异步操作,同时它是在模型绑定完成之后执行,也就是只有一个异步方法
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
await next();
}
接下来我们定义全局用户会话类,如下:
public class Session
{
/// <summary>
/// 用户id
/// </summary>
public string UserId { get; set; }
/// <summary>
/// 用户名
/// </summary>
public string UserName { get; set; }
}
紧接着,比如项目我们使用JWT,则拿到声明中用户标识和用户账号,那么我们接下来我们只需要实现上述异步action过滤器接口即可,如下:
public class AsyncSessionFilter : IAsyncActionFilter
{
private readonly Session _session; public AsyncSessionFilter(Session session)
{
_session = session;
} public async Task OnActionExecutionAsync(
ActionExecutingContext context,
ActionExecutionDelegate next)
{
var user = context.HttpContext.User; _session.UserId = user.FindFirst(JwtRegisteredClaimNames.Sub)?.Value; _session.UserName = user.FindFirst(JwtRegisteredClaimNames.UniqueName)?.Value; await next();
}
}
最后,则很简单的进行上述接口实现和会话注入,如下:
//注册用户会话
services.AddScoped<Session>(); //注册全局过滤器
services.AddControllers(options =>
{
options.Filters.Add<AsyncSessionFilter>();
})
在实际使用中,我们只需要在仓储或服务层构造函数使用Session,即可拿到用户名和用户id,从而最终解决对于新增和更改操作处理操作人信息
总结
在.NET Core中借助实现异步IAsyncActionFilter接口而实现全局获取用户信息