如何将参数传递给ASP.NET MVC 2中的自定义ActionFilter?

我正在尝试创建一个自定义ActionFilter,它操作一组参数,这些参数将从控制器传递给它。

到目前为止,我的客户ActionFilter看起来像这样:

public class CheckLoggedIn : ActionFilterAttribute { public IGenesisRepository gr { get; set; } public Guid memberGuid { get; set; } public override void OnActionExecuting(ActionExecutingContext filterContext) { Member thisMember = gr.GetActiveMember(memberGuid); Member bottomMember = gr.GetMemberOnBottom(); if (thisMember.Role.Tier <= bottomMember.Role.Tier) { filterContext .HttpContext .Response .RedirectToRoute(new { controller = "Member", action = "Login" }); } base.OnActionExecuting(filterContext); } } 

我知道我仍然需要检查空值等,但我无法弄清楚为什么没有成功传递grmemberGuid 。 我这样称为filter:

  [CheckLoggedIn(gr = genesisRepository, memberGuid = md.memberGUID)] public ActionResult Home(MemberData md) { return View(md); } 

genesisRepositorymd正在控制器的构造函数中设置。

我无法将其编译。 我得到的错误是:

 Error 1 'gr' is not a valid named attribute argument because it is not a valid attribute parameter type Error 2 'memberGuid' is not a valid named attribute argument because it is not a valid attribute parameter type 

我仔细检查了grmemberGuidgenesisReporitymd.memberGUID类型相同,是什么导致了这些错误?

感谢jfar提供解决方案。

这是我最终使用的filter:

 public class CheckLoggedIn : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext filterContext) { var thisController = ((MemberController)filterContext.Controller); IGenesisRepository gr = thisController.GenesisRepository; Guid memberGuid = ((MemberData)filterContext.HttpContext.Session[thisController.MemberKey]).MemberGUID; Member thisMember = gr.GetActiveMember(memberGuid); Member bottomMember = gr.GetMemberOnBottom(); if (thisMember.Role.Tier >= bottomMember.Role.Tier) { filterContext.Result = new RedirectToRouteResult( new RouteValueDictionary( new { controller = "Member", action = "Login" })); } base.OnActionExecuting(filterContext); } } 

这是一种使这项工作的方法。 您可以从ActionFilter对象访问ControllerContext,从而访问Controller。 您需要做的就是将控制器转换为类型,您可以访问任何公共成员。

鉴于此控制器:

 public GenesisController : Controller { [CheckLoggedIn()] public ActionResult Home(MemberData md) { return View(md); } } 

ActionFilter看起来像

 public class CheckLoggedIn : ActionFilterAttribute { public IGenesisRepository gr { get; set; } public Guid memberGuid { get; set; } public override void OnActionExecuting(ActionExecutingContext filterContext) { /* how to get the controller*/ var controllerUsingThisAttribute = ((GenesisController)filterContext.Controller); /* now you can use the public properties from the controller */ gr = controllerUsingThisAttribute .genesisRepository; memberGuid = (controllerUsingThisAttribute .memberGuid; Member thisMember = gr.GetActiveMember(memberGuid); Member bottomMember = gr.GetMemberOnBottom(); if (thisMember.Role.Tier <= bottomMember.Role.Tier) { filterContext .HttpContext .Response .RedirectToRoute(new { controller = "Member", action = "Login" }); } base.OnActionExecuting(filterContext); } } 

当然这是假设ActionFilter不是跨多个控制器使用的,你可以使用耦合。 另一个选项是使用共享属性创建ICheckedLoggedInController接口,然后简单地转换为该接口。

您只能对属性属性使用常量值; 请参阅此页面以获取完整说明。

属性本质上是添加到类型的元数据。 它们只能使用const值,而不是实例变量。 在你的情况下,你想要传递genisisRepository等的实例变量。这将无法编译,因为它们不是编译时常量。

您应该查看动态filter的dependency injection以实现此目的,通常使用IoC容器。

此外,如果您的ActionFilter正在执行PostResult操作,例如OnActionExecuted ,您可能会在路径数据中存储一些内容:

 public ActionResult Index() { ControllerContext.RouteData.DataTokens.Add("name", "value"); return View(); } 

在这种情况下,dependency injection是理想的解决方案; 服务地点是另一个(更简单)的选择。

嗯……我不确定这是否可行。 md.memberGUID绑定到会话,不能是const,因为站点需要访问权限才能更新登录数据。

因为我不想创建对特定会话密钥的依赖项。 我宁愿检查global.aspx.cs会显示绑定,未来的开发人员可以轻松地进行更改

将内容添加到不在URL中的路由数据中是存储数据的一种非常可怕的方式。 这导致很难找到错误。 – dependency injection并不能真正帮助解决这个问题。 任何为ActionFilter提供存储库的技术都可以使用。 当然,DI更好地帮助停止服务位置问题,但它不是解决方案,只是启用解决方案的一种方式。 关于如何实现这一目标的好文章:lostechies.com/blogs/jimmy_bogard/archive/2010/05/03 / …