How can I access MethodInfo.ReturnType for an ActionDescriptor in an ActionExecutingContext?

I have an ActionFilterAttribute application in my application that is used to redirect users when it detects that the user is not authenticated. Inside the filter, I would like to determine when the ReturnType for the action is JsonResult.

As a workaround, I initially created a custom IsJsonResult attribute and decorated the JsonResult methods in my solution with this attribute. This works and is implemented in the action filter as follows:

public class CheckUser : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext actionExecutingContext)
    {
        base.OnActionExecuting(actionExecutingContext);
        object[] customAttributes = actionExecutingContext.ActionDescriptor.GetCustomAttributes(true);
        bool isJsonResult = customAttributes.FirstOrDefault(a => a.GetType() == typeof(IsJsonResult)) != null;

        if (isJsonResult)
        {
            return; // Don't perform any additional checks on JsonResult requests.
        }

        // Additional checking code omitted.
    }
}

This works, but I don't like the idea of ​​decorating all the JsonResult actions in this project. This can easily fail if a new JsonResult project is added to the project and we forget to decorate it accordingly.

, , ReturnType "JsonResult" actionExecutingContext. , :

actionExecutingContext > ActionDescriptor > [System.Web.Mvc.ReflectedActionDescriptor] > MethodInfo > ReturnType > FullName

FullName "System.Web.Mvc.JsonResult".

, , actionExecutingContext bool. , , .

    private bool isReturnTypeJson(ActionExecutingContext actionExecutingContext)
    {
        string actionName = actionExecutingContext.ActionDescriptor.ActionName;
        string controllerName = actionExecutingContext.ActionDescriptor.ControllerDescriptor.ControllerName;
        Type controllerType = actionExecutingContext.Controller.GetType();
        try
        {
            // Only effective when the actionName is not duplicated in the controller.
            Type returnType = controllerType.GetMethod(actionName).ReturnType;
            return (returnType.Name == "JsonResult");
        }
        catch (AmbiguousMatchException)
        {
            // Using LINQ, can I filter this collection to isolate just the methods
            // that have the same name as the "actionName" variable above?
            MethodInfo[] methodsInfoCollection = controllerType.GetMethods(BindingFlags.Public | BindingFlags.Instance);

            // Attempted code from /questions/1467840/net-mvc-counting-action-methods-in-web-application
            //var info = typeof(controllerType)
            //        .Assembly.GetTypes()
            //        .Where(t => typeof(Controller).IsAssignableFrom(t))
            //        .Where(t => t.Namespace.StartsWith("AwesomeProduct.Web"))
            //        .SelectMany(t => t.GetMethods(BindingFlags.Public | BindingFlags.Instance))
            //        .Where(m => typeof(ActionResult).IsAssignableFrom(m.ReturnType))
            //        .Where(m => !m.IsAbstract)
            //        .Where(m => m.GetCustomAttribute<NonActionAttribute>() == null);

        }
        return false;
    }

returnType try-block , . , AmbiguousMatchException. catch . LINQ, methodsInfoCollection , ActionExecutingContext?

, , . .

.

==============

. , .

private bool isReturnTypeJson(ActionExecutingContext actionExecutingContext)
{
    string actionName = actionExecutingContext.ActionDescriptor.ActionName;
    string controllerName = actionExecutingContext.ActionDescriptor.ControllerDescriptor.ControllerName;
    Type controllerType = actionExecutingContext.Controller.GetType();
    try
    {
        // Only effective when the actionName is not duplicated in the controller.
        Type returnType = controllerType.GetMethod(actionName).ReturnType;
        return (returnType.Name == "JsonResult");
    }
    catch (AmbiguousMatchException)
    {
        // Using LINQ, can I filter this collection to isolate just the methods with a name of actionName.
        MethodInfo[] methodInfoCollection = controllerType.GetMethods(BindingFlags.Public | BindingFlags.Instance);
        foreach (MethodInfo methodInfo in methodInfoCollection)
        {
            if (methodInfo.ReturnType != null) {
                if (methodInfo.ReturnType == typeof(ActionResult))
                {
                    return false;
                }
                if (methodInfo.ReturnType == typeof(JsonResult))
                {
                    return true;
                }
            }
        }
    }
    return false;
}

. Reza Aghaei . .

+7
1

((ReflectedActionDescriptor)filterContext.ActionDescriptor).MethodInfo.ReturnType 

, JsonResult:

((ReflectedActionDescriptor)filterContext.ActionDescriptor).MethodInfo.ReturnType == typeof(JsonResult)

true :

public JsonResult Index()
{
    return Json(new { });
}
+13

Source: https://habr.com/ru/post/1611333/


All Articles