C# 应用于所有操作的ActionMethodSelectorAttribute?

C# 应用于所有操作的ActionMethodSelectorAttribute?,c#,asp.net-mvc,asp.net-mvc-3,C#,Asp.net Mvc,Asp.net Mvc 3,我希望我的选择器应用于所有操作,但我不希望复制并粘贴到任何地方 [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)] public abstract class ActionMethodSelectorAttribute : Attribute public class VersionAttribute : ActionMethodSelectorAttribute { pu

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

[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
。有什么想法吗?

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

[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());

我认为这是一种挑战——试图将定制的
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();
    }
}

现在就这样:)

我也考虑过这个解决方案,我认为它应该有效。只是想知道是否有更简单的方法…
base.FindAction
可能会在这里抛出一个
模糊的MatchException
异常,因为我在控制器中有几个同名的操作,这就是为什么我需要一个选择器。无法更改它们的名称,因为旧客户端仍在使用它们。我目前正在对它们进行版本控制。@DannyChen哦,如果是这样的话,你是对的,解决方案对你不起作用。你有没有想出一个更好的方法来解决这个问题?@nfplee:最后我用另一个解决方案来绕过这个问题……你的解决方案能帮助解决我的问题?如果是这样的话,我会很感激你的反馈,即使这只是为了给我指出正确的方向。Thanks@nfplee:对不起,我没有解决这个问题,我只是应用了另一个解决方案,这样我就不会再为这个问题头疼了…谢谢,这看起来像是我必须要做的。