您可以使用filter,特别是动作过滤器,它可以:
- 在调用操作方法之前和之后立即运行代码。
- 可以更改传递给操作的参数。
- 可以更改操作返回的结果。
- 在 Razor 页面中不受支持。
一个例子是
public class MySampleActionFilter : IActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
{
// Do something before the action executes.
MyDebug.Write(MethodBase.GetCurrentMethod(), context.HttpContext.Request.Path);
}
public void OnActionExecuted(ActionExecutedContext context)
{
// Do something after the action executes.
MyDebug.Write(MethodBase.GetCurrentMethod(), context.HttpContext.Request.Path);
}
}
在这里,您可以准备一个范围服务,根据该服务加载用户,然后在需要该数据的任何服务中重用它。
即使没有过滤器,您也可以简单地创建一个具有作用域生命周期的 UserService,在其中加载用户并在您的服务中的任何位置使用它。
在我们的系统中,我们正在做类似的事情:
加载会话数据的服务:
public class ClientTokenService
{
private readonly IHttpContextAccessor _httpContextAccessor;
public ClientTokenService(
IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public Profile LoadProfile()
{
if (_httpContextAccessor.HttpContext.User == null)
{
throw new Exception("No user claims found to load Profile");
}
var user = _httpContextAccessor.HttpContext.User;
var numberType = (NumberType)int.Parse(user.FindFirst("numberType").Value);
var profileType = (PackagePlan)int.Parse(user.FindFirst("profileType").Value);
var lineOfBusiness = (LineOfBusiness)int.Parse(user.FindFirst("lineOfBusiness").Value);
// More stuff
// Prepare the profile data
return new Profile(
user.FindFirst("number").Value,
user.FindFirst("contractId").Value,
numberType,
profileType,
user.FindFirst("cc")?.Value,
user.FindFirst("app").Value,
user.FindFirst("clickId")?.Value,
user.FindFirst("wifi") != null,
lineOfBusiness
);
}
}
此服务可以是暂时的,然后是保存数据的范围服务
public class ClientSessionContext
{
public Profile Profile { get; }
public ClientSessionContext(
ClientTokenService sessionService)
{
Profile = sessionService.LoadProfile();
}
}
将此服务声明为作用域,因此此类仅在每个请求中初始化一次
Statup.cs
services.AddScoped<ClientSessionContext>();
然后只需在您需要访问用户数据的任何地方注入此服务。