How do I get access to the Controller from ExceptionFilterAttribute

113 Views Asked by At

I am converting a project from a Framework 4.7.2 into a Net (Core) 6. The framework used a ExceptionFilterAttribute to call a method on the controller that caused the exception. Im just trying to port across and then refactor new ways later.

I want to get access to a method on the controller that the exception occurred on.

In the framework version the code looked like:

        public override void OnException(HttpActionExecutedContext actionExecutedContext)
    {

        LoggingController = actionExecutedContext.ActionContext.ControllerContext.Controller as ILoggingController;

        if (LoggingController == null)
        {
            throw new InvalidOperationException($"{GetType().Name} can can only be used on controllers that implement ILoggingController");
        }

        LoggingController.MethodToCall()

        ....
    }

but when using Net 6.0 things have changed and I can't see where to get access to the Controller which called it. I can get the descriptor but don't know how that helps.

using Microsoft.AspNetCore.Mvc.Filters;

public class ExcFilterAttribuite: ExceptionFilterAttribute
{
    public override void OnException(ExceptionContext context)
    {

        var controller = context.ControllerContext.Controller; // Doesnt work
        var endpoint = context.HttpContext.GetEndpoint();
        var controllerActionDescriptor = endpoint?.Metadata.GetMetadata<ControllerActionDescriptor>();
        
        base.OnException(context);
    }
}

How can I get to the controller from the ExceptionFilterAttribute in Net 6 ?

1

There are 1 best solutions below

0
Rena On

Here is a whole working demo below for how to invoke the controller action in custom ExceptionFilterAttribute:

public class ExcFilterAttribuite : ExceptionFilterAttribute
{
     public override void OnException(ExceptionContext context)
     {
         var controllerDescriptor = context.ActionDescriptor as ControllerActionDescriptor;

         if (controllerDescriptor == null)
         {
             throw new InvalidOperationException($"{GetType().Name} can only be used on controllers");
         }
         var controllerType = controllerDescriptor.ControllerTypeInfo.AsType();
         var serviceProvider = context.HttpContext.RequestServices;

         // Create an instance of the controller
         var controller = ActivatorUtilities.CreateInstance(serviceProvider, controllerType);
         
         if (controller != null)
         {
             // Get the method name the exception occured on the controller
             var actionName = controllerDescriptor.ActionName;                
             var methodInfo = controllerType.GetMethod(actionName, BindingFlags.Instance | BindingFlags.Public);

             if (methodInfo != null)
             {
                 //object[] parameters = new object[] { /* parameters here */ };

                 // Invoke the method on the controller instance
                 methodInfo.Invoke(controller, null); // You can pass parameters if needed

                 // Optionally, you can set the result to the ExceptionContext
                 // context.Result = result;

                 // Mark the exception as handled
                 //context.ExceptionHandled = true;
             }
         }                
         base.OnException(context);
     }
 }