C# 如何在ASP.NET MVC 2中向自定义ActionFilter传递参数?
我正在尝试创建一个自定义ActionFilter,它对从控制器传递给它的一组参数进行操作 到目前为止,我的客户ActionFilter如下所示:C# 如何在ASP.NET MVC 2中向自定义ActionFilter传递参数?,c#,asp.net,asp.net-mvc,action-filter,C#,Asp.net,Asp.net Mvc,Action Filter,我正在尝试创建一个自定义ActionFilter,它对从控制器传递给它的一组参数进行操作 到目前为止,我的客户ActionFilter如下所示: public class CheckLoggedIn : ActionFilterAttribute { public IGenesisRepository gr { get; set; } public Guid memberGuid { get; set; } public override void OnActionEx
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);
}
}
[CheckLoggedIn(gr = genesisRepository, memberGuid = md.memberGUID)]
public ActionResult Home(MemberData md)
{
return View(md);
}
genesisRepository
和md
正在控制器的构造函数中设置
我无法编译这个。我得到的错误是:
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
我仔细检查了gr
和memberGuid
是否与genesreport
和md.memberGuid
的类型相同,是什么导致了这些错误
解决方案
感谢jfar提供的解决方案
以下是我最终使用的过滤器:
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);
}
}
只能对属性属性使用常量值;有关完整解释,请参见。属性本质上是添加到类型中的元数据。它们只能使用
const
值,而不能使用实例变量。在您的情况下,您需要传入genisisRepository
等的实例变量。这将无法编译,因为它们不是编译时常量
为了实现这一点,您应该研究操作过滤器的依赖项注入,通常使用IoC容器
此外,如果您的ActionFilter正在执行post ActionResult操作,例如OnActionExecuted
,则您可能不需要在路由数据中存储某些内容:
public ActionResult Index()
{
ControllerContext.RouteData.DataTokens.Add("name", "value");
return View();
}
这是一个使这项工作的方法。您可以从ActionFilter对象访问ControllerContext,从而访问控制器。您只需将控制器强制转换为该类型,就可以访问任何公共成员 鉴于此控制器:
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);
}
}
公共类CheckLoggedIn:ActionFilterAttribute
{
公共IGenesisRespository gr{get;set;}
公共Guid成员Guid{get;set;}
公共覆盖无效OnActionExecuting(ActionExecutingContext filterContext)
{
/*如何获取控制器*/
var controllerUsingThisAttribute=((GenesisController)filterContext.Controller);
/*现在,您可以使用控制器中的公共属性*/
gr=controllerUsingThisAttribute.genesisRepository;
memberGuid=(controllerUsingThisAttribute.memberGuid;
成员thisMember=gr.GetActiveMember(memberGuid);
Member bottomMember=gr.GetMemberOnBottom();
如果(thisMember.Role.Tier+1)提供进一步的指导…依赖注入是这种情况下的理想解决方案;服务位置是另一个(更简单)也可以考虑。嗯……我不确定这是可能的。<代码> M.MeMyGuIDID<代码>绑定到会话,并且不能是const,因为站点需要访问更新登录数据。因为我不想对特定的会话密钥创建依赖项。我宁愿检查GULAL..ASPX.CS会显示绑定和未来的开发人员可以很容易地进行更改将不在URL中的内容添加到路由数据中是一种非常可怕的数据存储方式。这会导致难以发现的错误。--依赖项注入并不能真正帮助解决此问题。任何为ActionFilter提供存储库的技术都会起作用。现在当然DI最好帮助停止服务位置问题,但这不是解决方案,只是启用解决方案的一种方法。关于如何实现这一点的好文章:您不需要IoC来注入它,但IoC可能会使它更容易。您可以在筛选器配置中声明筛选器,将其依赖项注入构造函数,然后注册筛选器。好吧,这让我明白了离解决方案更近了。谢谢jfar。不过actionFilter将在多个控制器之间使用。我在获取控制器时遇到很多问题。var thisController=((MemberController)ControllerContext.controller)
返回错误:非静态字段、方法或属性'System.Web.Mvc.ControllerContext.Controller.get'
@quakkels-Oops需要对象引用,请在我的头顶上执行。您可以通过filterContext.Controller
获取控制器。也更新答案。[CheckLoggedIn](gr=genesisRepository,memberGuid=md.memberGuid)]
???它是如何工作的?正如@DanP所说,您只能对属性属性使用常量值。我也注意到了这一点。18票赞成一个无法编译的答案。我想知道这是否是一个记录。您的问题很好,但解决方案比问题更棒。我正在寻找一个将参数发送到全局筛选器属性的解决方案但是,这对我来说就像是止痛药:)