[英]How to pass parameters to a custom ActionFilter in ASP.NET MVC 2?
I'm trying to create a custom ActionFilter which operates on a set of parameters that would be passed to it from the controller. 我正在尝试创建一个自定义ActionFilter,它操作一组参数,这些参数将从控制器传递给它。
So far, my customer ActionFilter looks like this: 到目前为止,我的客户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);
}
}
I know I still need to check for nulls, etc. but I can't figure out why gr
and memberGuid
aren't successfully being passed. 我知道我仍然需要检查空值等,但我无法弄清楚为什么没有成功传递
gr
和memberGuid
。 I'm calling this Filter like this: 我这样称为过滤器:
[CheckLoggedIn(gr = genesisRepository, memberGuid = md.memberGUID)]
public ActionResult Home(MemberData md)
{
return View(md);
}
genesisRepository
and md
are being set in the controller's constructor. genesisRepository
和md
正在控制器的构造函数中设置。
I'm not able to get this to compile. 我无法将其编译。 The error I get is:
我得到的错误是:
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
I double checked that gr
and memberGuid
were the same types as genesisRepority
and md.memberGUID
, What is causing these errors? 我仔细检查了
gr
和memberGuid
与genesisRepority
和md.memberGUID
类型相同,是什么导致了这些错误?
Thanks to jfar for offering a solution. 感谢jfar提供解决方案。
Here's the Filter I ended up using: 这是我最终使用的过滤器:
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);
}
}
This is a way to make this work. 这是一种使这项工作的方法。 You have access to the ControllerContext and therefore Controller from the ActionFilter object.
您可以从ActionFilter对象访问ControllerContext,从而访问Controller。 All you need to do is cast your controller to the type and you can access any public members.
您需要做的就是将控制器转换为类型,您可以访问任何公共成员。
Given this controller: 鉴于此控制器:
public GenesisController : Controller
{
[CheckLoggedIn()]
public ActionResult Home(MemberData md)
{
return View(md);
}
}
ActionFilter looks something like 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);
}
}
Of course this is assuming the ActionFilter isn't used across multiple controllers and you're ok with the coupling. 当然这是假设ActionFilter没有在多个控制器上使用,你可以使用耦合。 Another Option is to make a ICheckedLoggedInController interface with the shared properties and simply cast to that instead.
另一个选项是使用共享属性创建ICheckedLoggedInController接口,然后简单地转换为该接口。
Attributes are essentially metadata added to a type. 属性本质上是添加到类型的元数据。 They can only use
const
values, instead of instance variables. 它们只能使用
const
值,而不是实例变量。 In your case you are tying to pass in your instance variables of genisisRepository
, etc. This will fail to compile as they are not compile time constants. 在你的情况下,你想要传递
genisisRepository
等的实例变量。这将无法编译,因为它们不是编译时常量。
You should look into Dependency Injection for Action Filters to achieve this, typically using an IoC container. 您应该查看动态过滤器的依赖注入以实现此目的,通常使用IoC容器。
Also, if your ActionFilter is performing a post ActionResult action, such as OnActionExecuted
, you could probably get away with storing something in the route data: 此外,如果您的ActionFilter正在执行PostResult操作,例如
OnActionExecuted
,您可能会在路径数据中存储一些内容:
public ActionResult Index()
{
ControllerContext.RouteData.DataTokens.Add("name", "value");
return View();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.