IActionContextAccessor Is Null
Asked Answered
I

1

6

I am setting up a custom Middleware for my .NET Core Application to log exception errors and have the following in the Startup.cs to register my contexts:

   services.AddHttpContextAccessor();
   services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();

And in my Configure I have added the following to use a custom middleware:

   app.UseMiddleware<CustomMiddleware>();

My custom Middleware class is the following:

 public class CustomMiddleware
 {
    private readonly RequestDelegate next;

    public CustomMiddleware(RequestDelegate next)
    {
        this.next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        try
        {
            this.BeginInvoke(context);
            await this.next.Invoke(context);
            this.EndInvoke(context);
        }
        catch(Exception ex)
        {
            //Capture the exception.
            string hostName = Environment.MachineName;
            string url = StringFunctions.getCurrentUrl(context);
            string userName = string.Empty;
            string controllerName = string.Empty;
            string actionName = string.Empty;

            //THIS IS NULL BELOW.
            IActionContextAccessor contextAccessor = context.RequestServices.GetService(typeof(IActionContextAccessor)) as IActionContextAccessor;
            RouteData routeData = contextAccessor.ActionContext.RouteData;

            if (context.User != null)
            {
                userName = context.User.Identity.Name;
            }

            if (routeData != null && routeData.Values != null)
            {
                controllerName = routeData.Values["controller"].ToString();
                actionName = routeData.Values["action"].ToString();
            }

            EventLogging.LogApplicationError(hostName, controllerName, actionName, url, userName, ex);
        }
    }

    private void BeginInvoke(HttpContext context)
    {
        //custom work here
    }

    private void EndInvoke(HttpContext context)
    {
        // Do custom work after controller execution
    }
}

It seems that the 'contextAccessor' that I am trying to get the ActionContext.RouteData values from is Null.

What am I doing wrong? Thank you.

Intervene answered 26/9, 2019 at 13:47 Comment(2)
Have you made sure that IActionContextAccessor is registered in Startup.cs?Xebec
I have services.AddSingleton<IActionContextAccessor, ActionContextAccessor>(); in my ConfigureServices function in my Startup.csIntervene
C
3

IActionContextAccessor.ActionContext is null outside the scope of mvc middleware.

If all you care about in your exception handler is MVC actions, you create an action filter instead of middleware to capture and log exceptions.

public class CustomExceptionFilterAttribute : ExceptionFilterAttribute
{
    public override void OnException(ExceptionContext context)
    {
        //Capture the exception.
        string hostName = Environment.MachineName;
        string url = StringFunctions.getCurrentUrl(context.HttpContext);
        string userName = string.Empty;
        string controllerName = string.Empty;
        string actionName = string.Empty;

        if (context.HttpContext.User != null)
        {
            userName = context.HttpContext.User.Identity.Name;
        }

        controllerName = context.RouteData.Values["controller"].ToString();
        actionName = context.RouteData.Values["action"].ToString();

        EventLogging.LogApplicationError(hostName, controllerName, actionName, url, userName, ex);
    }
}
Cisterna answered 26/9, 2019 at 14:32 Comment(3)
GetCurrentUrl takes HttpContext not ExceptionContext, so guessing I will have to inject the IHttpAccessorContext in for that?Intervene
You can access it via context.HttpContext. I updated the codeCisterna
Thank you. I have registered it in my services using services.AddMvc(config => config.Filters.Add(new CustomExceptionFilter())).SetCompatibilityVersion(CompatibilityVersion.Version_2_2); and it working fine in all controllers.Intervene

© 2022 - 2024 — McMap. All rights reserved.