web-dev-qa-db-fra.com

Comment passer des paramètres à un ActionFilter personnalisé dans ASP.NET MVC 2?

J'essaie de créer un ActionFilter personnalisé qui fonctionne sur un ensemble de paramètres qui lui seraient transmis depuis le contrôleur.

Jusqu'à présent, mon client ActionFilter ressemble à ceci:

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);
    }
}

Je sais que je dois encore vérifier les valeurs nulles, etc., mais je ne peux pas comprendre pourquoi gr et memberGuid ne sont pas passés avec succès. J'appelle ce filtre comme ceci:

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

genesisRepository et md sont définis dans le constructeur du contrôleur.

Je ne parviens pas à faire compiler cela. L'erreur que j'obtiens est:

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

J'ai revérifié que gr et memberGuid étaient du même type que genesisRepority et md.memberGUID, Quelle est la cause de ces erreurs?

Solution

Merci à jfar d'avoir proposé une solution.

Voici le filtre que j'ai fini par utiliser:

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);
    }
}
31
quakkels

Vous ne pouvez utiliser que des valeurs constantes pour les propriétés d'attribut; voir un cette page pour une explication complète.

8
DanP

Les attributs sont essentiellement des métadonnées ajoutées à un type. Ils ne peuvent utiliser que des valeurs const, au lieu de variables d'instance. Dans votre cas, vous tentez de passer vos variables d'instance de genisisRepository, etc. Cela ne pourra pas être compilé car ce ne sont pas des constantes de temps de compilation.

Vous devez examiner l'injection de dépendances pour les filtres d'action pour y parvenir, en utilisant généralement un conteneur IoC.

De plus, si votre ActionFilter effectue une action après ActionResult, telle que OnActionExecuted, vous pourriez probablement vous en sortir en stockant quelque chose dans les données de l'itinéraire:

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