Alex
Alex

Reputation: 423

ASP.NET WebApi - How to set a controller's property from ActionFilter?

I have a controller like this:

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

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

The logger needs a user id from authenticated user or just an empty guid. As I understand it, the authorization process is carried out after the controller is created, but before the method is executed. So the "User" with UserName, ID, Token, etc. does not exist yet during the controller construction process.

I can give logger the ID it needs inside any method like this:

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);

But instead of doing this inside every method, I want to write this once inside an action filter and decorate the entire controller with it.

The question: Is there a way to access MyController's logger inside an action filter? Something like this:

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(...); 
    }
}

Upvotes: 1

Views: 1180

Answers (1)

mohammadreza
mohammadreza

Reputation: 158

You can just user your logger inside filter then log anything you want there.

after that you can decorate your controllers with your filter. filter will do the magic. no need to inject ILogger to controller, if you need ILogger in your controller, you can inject it o your controller too.

    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}");
    }

Upvotes: 1

Related Questions