应用于所有操作的ActionMethodSelectorAttribute?

时间:2012-02-29 10:02:52

标签: c# asp.net-mvc asp.net-mvc-3

我希望我的选择器应用于所有操作,但我不想将它复制并粘贴到任何地方。

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public abstract class ActionMethodSelectorAttribute : Attribute

public class VersionAttribute : ActionMethodSelectorAttribute
{
    public override bool IsValidForRequest(ControllerContext controllerContext, System.Reflection.MethodInfo methodInfo)
    {
        //my logic here
    }
}

GlobalFilterCollection.Add在这种情况下不起作用,因为它不是FilterAttribute。有什么想法吗?

2 个答案:

答案 0 :(得分:2)

我认为这是一种挑战 - 尝试将自定义ActionMethodSelector注入现有列表中。 虽然我没有找到任何防弹方法来做到这一点,但我会分享我的想法

1.创建自定义ActionInvoker并尝试注入选择器。我使用了默认的ReflectedActionDescriptor,因为它已经包含MethodInfo来测试MyActionMethodSelector

public class MyActionInvoker : ControllerActionInvoker
{
    protected override ActionDescriptor FindAction(ControllerContext controllerContext, ControllerDescriptor controllerDescriptor, string actionName)
    {
        var action = base.FindAction(controllerContext, controllerDescriptor, actionName);

        if (action != null)
        {
            var reflectedActionDecsriptor = action as ReflectedActionDescriptor;
            if (reflectedActionDecsriptor != null)
            {
                if (new MyActionMethodSelectorAttribute().IsValidForRequest(controllerContext, reflectedActionDecsriptor.MethodInfo))
                {
                    return null;
                }
            }
        }

        return action;
    }
}

2.将MyActionInvoker注入控制器。为此,从MyBaseController派生所有控制器,实现为

public class MyBaseController : Controller
{
    protected override IActionInvoker CreateActionInvoker()
    {
        return new MyActionInvoker();
    }
}

现在就是这样:)

答案 1 :(得分:1)

您可以将其更改为以下内容:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class VersionAttribute : FilterAttribute, IActionFilter
{
    private bool IsValidForRequest(ActionExecutingContext filterContext)
    {
        //my logic here
        return true; //for testing
    }

    public void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (!IsValidForRequest(filterContext))
        {
            filterContext.Result = new HttpNotFoundResult();  //Or whatever other logic you require?
        }
    }

    public void  OnActionExecuted(ActionExecutedContext filterContext)
    {
        //left blank intentionally
    }
}

然后将其注册为全局过滤器:

filters.Add(new VersionAttribute());