【问题标题】:ASP.NET WebApi - How to set a controller's property from ActionFilter?ASP.NET Web Api - 如何从动作过滤器设置控制器属性?
【发布时间】:2021-08-25 07:19:56
【问题描述】:

我有一个这样的控制器:

public class MyController : System.Web.Http.ApiController
{
    private ILogger logger;

    public MyController(ILogger logger)
    {
        this.logger = logger;
    }
    
    ...Methods...
}

记录器需要来自经过身份验证的用户的用户 ID,或者只是一个空的 guid。 据我了解,授权过程是在创建控制器之后执行的,但在执行方法之前。所以在控制器构建过程中,还没有包含UserName、ID、Token等的“用户”。

我可以在这样的任何方法中为 logger 提供它所需的 ID:

var claim = this.ActionContext.RequestContext.Principal.Identity as System.Security.Claims.ClaimsIdentity;
var userId = claim.IsAuthenticated ? new Guid(claim.GetUserId()) : Guid.Empty;
logger.SetUserID(userId);

但不是在每个方法中都这样做,我想在 动作过滤器 中编写此一次,然后用它装饰整个控制器。

问题: 有没有办法在动作过滤器中访问 MyController 的记录器? 像这样的:

public class LoggerFilter : ActionFilterAttribute 
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        base.OnActionExecuting(actionContext);
???---> Check if controller that is currently working has a logger property;
        If it has, then ThatController.logger.SetUserID(...); 
    }
}

【问题讨论】:

    标签: c# asp.net controller asp.net-web-api2


    【解决方案1】:

    您可以在过滤器中使用您的记录器,然后在那里记录您想要的任何内容。

    之后,您可以使用过滤器装饰您的控制器。过滤器会变魔术。无需将 ILogger 注入到控制器中,如果您的控制器中需要 ILogger,您也可以将其注入到您的控制器中。

        public override void OnActionExecuted(ActionExecutedContext context)
        {
            base.OnActionExecuted(context);
    
            
            var actionName = string.Empty;
            var controllerName = string.Empty;
            var userId = Guid.Empty;
            if (context.HttpContext.User.Identity.IsAuthenticated)
                userId = context.HttpContext.User.GetId();
    
            if (userId == Guid.Empty)
                return;
    
            if (context?.ActionDescriptor is ControllerActionDescriptor descriptor)
            {
                actionName = descriptor.ActionName;
                controllerName = descriptor.ControllerName;
            }
    
            var logger = context.HttpContext.RequestServices.GetService(typeof(ICustomLogger));
            logger.Log($"{actionName} - {controllerName} - {userId}");
        }
    

    【讨论】:

    • 如果我需要控制器内部的记录器(我想在方法内部使用 logger.log),我如何将它从 ActionFilter 注入控制器本身?能详细点吗?
    • 如果您需要在控制器类中记录更多数据,您可以将ILogger<ControllerName> 注入您的控制器ctor,或者您可以只使用过滤器记录器
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-09
    • 1970-01-01
    • 2011-09-24
    • 2015-01-03
    • 2016-11-21
    相关资源
    最近更新 更多