Search code examples
c#.netasp.net-coremiddlewareactioncontext

IActionContextAccessor Is Null


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.


Solution

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