2009-05-29 6 views
4

Depuis asp.net mvc a beaucoup changé depuis Novembre, quelqu'un at-il une solution à cette question:Comment faire ActionFilter sur la méthode d'action ont préséance sur le même contrôleur ActionFilter

Resolve FilterAttributes On Controller And Action

Phil dit un ActionFilter sur un contrôleur est juste un raccourci pour appliquer l'attribut à toutes les méthodes d'action du contrôleur, et c'est vrai, si je mets le même attribut ActionFilter sur le contrôleur et sur une méthode d'action, il s'exécutera deux fois. Mais cela ne semble pas être un comportement naturel puisque le compilateur ne vous laissera même pas placer le même attribut directement sur une méthode plusieurs fois.

Répondre

7

Un filtre peut avoir la priorité sur un autre filtre en spécifiant la propriété Order sur chaque filtre. Par exemple ...

[MyFilter(Order=2)] 
public class MyController : Controller 
{ 
    [MyFilter(Order=1)] 
    public ActionResult MyAction() 
    { 
     //... 
    } 
} 

Dans cet exemple, le filtre sur la méthode d'action serait exécuter avant le déposant sur le contrôleur.

HTH

+0

Un filtre d'action peut-il remplacer un filtre du contrôleur afin qu'un filtre puisse être appliqué à toutes les exceptions d'actions pour 1 action spécifique? – David

+0

Oui, un filtre d'action permet de remplacer un filtre du contrôleur. Si vous commandez les filtres, vous pouvez faire exécuter votre filtre Action avant le filtre de votre contrôleur et annuler l'action. L'annulation d'une action peut être effectuée en définissant ActionExecutingContext.Result sur une valeur non nulle. (Note: ActionExecutingContext.Cancel a été déprécié) – robertz

+1

Il semble que la définition du résultat de ActionExecutingContext empêche tous les autres événements OnActionExecuting de se déclencher, pas seulement ceux du même ActionFilter. – JeremyWeir

1

J'ai trouvé une façon de le faire par « tricher » un peu avec l'ordre, l'héritage et le paramètre AttributeUsage

D'abord, définir votre ActionFilter pour le contrôleur

[AttributeUsage(AttributeTargets.Class)] 
public class FilterController : ActionFilterAttribute 
{ 
    public FilterController() 
    { 
     this.Order = 2; 
    } 

    public override void OnActionExecuted(ActionExecutedContext filterContext) 
    { 
     if (!filterContext.HttpContext.Items.Contains("WeAlreadyWentThroughThis")) 
     { 
       // do our thing 
      filterContext.HttpContext.Items.Add("WeAlreadyWentThroughThis", "yep"); 
      base.OnActionExecuted(filterContext); 
     } 
    } 
} 

Héritez ensuite la classe de votre attribut d'action

[AttributeUsage(AttributeTargets.Method)] 
public class FilterAction : FilterController 
{ 
    public FilterAction() 
    { 
     this.Order = 1; 
    } 
} 

C'est loin d'être parfait puisque vous devez vous fier à HttpContext et à deux classes (bien que vous puissiez utiliser des espaces de noms pour nommer les deux classes de la même manière). Mais vous obtenez une vérification imposée par le compilateur de la portée de l'attribut pour la classe ou l'action et vous n'oublierez pas un paramètre d'ordre lorsque vous tapez le code.

Questions connexes