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:对不起,我没有解决这个问题,我只是应用了另一个解决方案,这样我就不会再为这个问题头疼了…谢谢,这看起来像是我必须要做的。