1

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

1 Answer 1

1

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}");
    }
Sign up to request clarification or add additional context in comments.

2 Comments

If I need the logger inside controller (i want to use logger.log inside methods), how do I inject it from ActionFilter to the controller itself? Can you please elaborate?
you can just inject ILogger<ControllerName> to your controller ctor if u need log more data inside controller class, or you can just use the filter logger

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.