简体   繁体   English

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

[英]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. 我知道我仍然需要检查空值等,但我无法弄清楚为什么没有成功传递grmemberGuid 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. genesisRepositorymd正在控制器的构造函数中设置。

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? 我仔细检查了grmemberGuidgenesisReporitymd.memberGUID类型相同,是什么导致了这些错误?

Solution

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接口,然后简单地转换为该接口。

You can only use constant values for attribute properties; 您只能对属性属性使用常量值; see a this page for a full explanation. 请参阅此页面以获取完整说明。

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.

相关问题 Asp.Net核心ActionFilter-如何传递不同数量的参数 - Asp.Net core ActionFilter - how to pass varying number of parameters ASP.NET MVC ActionFilter - ASP.NET MVC ActionFilter ASP.NET MVC OnActionExecuted ActionFilter - ASP.NET MVC OnActionExecuted ActionFilter ASP.NET MVC-如何将参数传递给其他控制器上的操作 - ASP.NET MVC - how to pass parameters to actions on a different controller 如何将两个参数传递给 ASP.NET Core MVC 中的 controller? - How to pass two parameters to a controller in ASP.NET Core MVC? ASP.NET MVC:为什么我的自定义 ActionFilter 会更改我的 HTTP 响应代码? - ASP.NET MVC: Why my custom ActionFilter changes my HTTP response code? ASP.NET MVC ActionFilter不会阻止其他过滤器运行 - ASP.NET MVC ActionFilter is not preventing other filters from running ASP.NET Core MVC ActionFilter 在 AuthorizationFilter 之前执行 - ASP.NET Core MVC ActionFilter execute before AuthorizationFilter 在OnAuthorization之前执行的ASP.NET MVC Global或BaseController ActionFilter - ASP.NET MVC Global or BaseController ActionFilter to Execute Before OnAuthorization 在 ASP.NET Core MVC 中将其用于 ActionFilter 时出现 DbContext 错误 - DbContext error when using it for ActionFilter in ASP.NET Core MVC
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM