Exporter (0) Imprimer
Développer tout
Cet article a fait l'objet d'une traduction manuelle. Déplacez votre pointeur sur les phrases de l'article pour voir la version originale de ce texte.
Traduction
Source

Création de filtres d'action personnalisés

Les utilisations possibles des filtres d'action sont aussi variées que les actions auxquelles ils peuvent s'appliquer. Les filtres d'action peuvent notamment servir aux activités suivantes :

  • Journalisation permettant le suivi des interventions de l'utilisateur.

  • Protection contre le pillage d'image ("image-leeching") visant à empêcher le chargement d'images dans des pages qui ne figurent pas sur votre site.

  • Fonctions de filtrage des robots d'indexation permettant de modifier le comportement d'une application en fonction de l'agent utilisateur du navigateur.

  • Localisation permettant de définir les paramètres régionaux.

  • Actions dynamiques permettant d'injecter une action dans un contrôleur.

Un filtre d'action est implémenté sous la forme d'une classe d'attributs héritant de ActionFilterAttribute. ActionFilterAttribute est une classe abstraite comportant quatre méthodes virtuelles que vous pouvez substituer : OnActionExecuting, OnActionExecuted, OnResultExecuting et OnResultExecuted. Pour implémenter un filtre d'action, vous devez substituer au moins l'une de ces méthodes.

L'infrastructure ASP.NET MVC appellera la méthode OnActionExecuting de votre filtre d'action avant toute méthode d'action marquée avec votre attribut de filtre d'action. De la même façon, l'infrastructure appellera la méthode OnActionExecuted une fois l'exécution de la méthode d'action terminée.

La méthode OnResultExecuting est appelée juste avant que l'instance ActionResult retournée par votre action ne soit appelée. La méthode OnResultExecuted est appelée juste après l'exécution du résultat. Ces méthodes sont utiles pour exécuter des actions telles que la journalisation, la mise en cache de sortie, etc.

L'exemple suivant présente un filtre d'action simple qui journalise des messages de trace avant et après l'appel d'une méthode d'action.


public class LoggingFilterAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        filterContext.HttpContext.Trace.Write("(Logging Filter)Action Executing: " +
            filterContext.ActionDescriptor.ActionName);

        base.OnActionExecuting(filterContext);
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        if (filterContext.Exception != null)
            filterContext.HttpContext.Trace.Write("(Logging Filter)Exception thrown");

        base.OnActionExecuted(filterContext);
    }
}


Chacun des gestionnaires d'événements de contrôleur utilisés pour le filtrage d'actions accepte un objet de contexte en tant que paramètre. La liste suivante répertorie les gestionnaires d'événements de filtre et le type de contexte accepté par chacun d'eux.

Toutes les classes de contexte héritent de la classe ControllerContext et incluent une propriété ActionDescriptor. Vous pouvez utiliser la propriété ActionDescriptor pour identifier l'action à laquelle le filtre est actuellement appliqué.

Les classes ActionExecutingContext et ResultExecutingContext contiennent une propriété Cancel qui vous permet d'annuler l'action.

Les classes ActionExecutedContent et ResultExecutedContext contiennent une propriété Exception et une propriété ExceptionHandled. Si la propriété Exception est null, elle indique qu'aucune erreur n'est survenue lors de l'exécution de la méthode d'action. Si la propriété Exception n'est pas null et que le filtre est en mesure de gérer l'exception, il peut la gérer, puis signaler qu'il a effectué cette opération en affectant à la propriété ExceptionHandled la valeur true. Même si la propriété ExceptionHandled est true, la méthode OnActionExecuted ou OnResultExecuted de tous les autres filtres d'action de la pile sera appelée et les informations sur l'exception leur seront passées. Des scénarios où, par exemple, un filtre de journalisation consigne une exception même si celle-ci a été gérée sont ainsi possibles. En général, un filtre d'action ne doit pas gérer d'exception à moins que l'erreur ne lui soit spécifique.

Vous pouvez appliquer un filtre d'action à un nombre illimité de méthodes d'action. L'exemple suivant présente un contrôleur contenant des méthodes d'action marquées avec un attribut de filtre d'action. Dans ce cas, toutes les méthodes d'action du contrôleur appellent le même filtre d'action.


[HandleError]
public class HomeController : Controller
{
    [LoggingFilter]
    public ActionResult Index()
    {
        ViewData["Message"] = "Welcome to ASP.NET MVC!";

        if (TempData.ContainsKey("Clicked"))
        {
            ViewData["Clicked"] = true;
        }
        else ViewData["Clicked"] = false;

        if ((Boolean)ViewData["Clicked"] == true)
        {
            ViewData["ClickMessage"] = "You clicked this button.";
            ViewData["Clicked"] = false;
        }

        return View();
    }

    [LoggingFilter]
    public ActionResult About()
    {
        return View();
    }

    [LoggingFilter]
    public ActionResult ClickMe()
    {
        TempData["Clicked"] = true;

        return RedirectToAction("Index");
    }
}


La classe Controller ASP.NET MVC définit des méthodes OnActionExecuting et OnActionExecuted que vous pouvez substituer. Lorsque vous substituez l'une de ces méthodes ou les deux, votre logique s'exécutera avant ou après toutes les méthodes d'action de ce contrôleur. Cette fonctionnalité est semblable aux filtres d'action, mais la portée des méthodes est limitée au contrôleur.

L'exemple suivant présente des méthodes OnActionExecuting et OnActionExecuted de niveau contrôleur qui s'appliquent à toutes les méthodes d'action du contrôleur.


[HandleError]
public class HomeController : Controller
{
    public ActionResult Index()
    {
        ViewData["Message"] = "Welcome to ASP.NET MVC!";

        if (TempData.ContainsKey("Clicked"))
        {
            ViewData["Clicked"] = true;
        }
        else ViewData["Clicked"] = false;

        if ((Boolean)ViewData["Clicked"] == true)
        {
            ViewData["ClickMessage"] = "You clicked this button.";
            ViewData["Clicked"] = false;
        }

        return View();
    }

    public ActionResult About()
    {
        ViewData["Title"] = "About Page";

        return View();
    }

     public ActionResult ClickMe()
    {
        TempData["Clicked"] = true;

        return RedirectToAction("Index");
    }

    [NonAction]
    protected override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        filterContext.HttpContext.Trace.Write("(Controller)Action Executing: " +
            filterContext.ActionDescriptor.ActionName);

        base.OnActionExecuting(filterContext);
    }

    [NonAction]
    protected override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        if (filterContext.Exception != null)
            filterContext.HttpContext.Trace.Write("(Controller)Exception thrown");

        base.OnActionExecuted(filterContext);
    }
}


Vous pouvez non seulement marquer des méthodes d'action individuelles avec un filtre d'action, mais également une classe de contrôleur complète. Dans ce cas, le filtre s'applique à toutes les méthodes d'action de ce contrôleur.

En outre, si votre contrôleur dérive d'un autre contrôleur, le contrôleur de base peut disposer de ses propres attributs de filtre d'action. De plus, si votre contrôleur substitue une méthode d'action d'un contrôleur de base, la méthode peut disposer de ses propres attributs de filtre d'action et d'attributs hérités de la méthode d'action substituée.

Pour qu'il soit plus facile de comprendre comment les filtres d'action fonctionnent conjointement, les méthodes d'action sont regroupées en portées. Une portée définit l'élément auquel l'attribut s'applique et détermine notamment s'il marque une classe ou une méthode, ou bien une classe de base ou une classe dérivée.

Chaque filtre d'action a une propriété Order qui est utilisée pour déterminer l'ordre d'exécution des filtres dans la portée du filtre. La propriété Order accepte une valeur entière qui doit être égale à 0 (valeur par défaut) ou supérieure (avec une exception). Si la propriété Order est omise, la valeur d'ordre -1 est attribuée au filtre ; elle indique qu'aucun ordre n'est spécifié. Tout filtre d'action d'une portée dont la propriété Order a la valeur -1 sera exécuté dans un ordre indéterminé, mais avant les filtres pour lesquels un ordre est spécifié.

Lorsqu'une propriété Order d'un filtre est spécifiée, elle doit avoir une valeur unique dans une portée. Si plusieurs filtres d'action d'une portée ont la même valeur de propriété Order, une exception est levée.

Les filtres d'action sont exécutés dans un ordre respectant les contraintes suivantes. Si plusieurs ordres respectent toutes ces contraintes, l'ordre est indéterminé.

  1. L'implémentation des méthodes OnActionExecuting et OnActionExecuted sur le contrôleur est toujours effectuée en premier. Pour plus d'informations, consultez Exécution du code avant et après une action à partir d'un contrôleur.

  2. À moins que la propriété Order ne soit définie explicitement, un filtre d'action a une valeur d'ordre implicite égale à -1.

  3. Si la propriété Order de plusieurs filtres d'action est définie explicitement, le filtre ayant la valeur la plus faible s'exécute avant ceux ayant des valeurs supérieures, comme indiqué dans l'exemple suivant :

    <Filter1(Order = 2)> _ 
    <Filter2(Order = 3)> _ 
    <Filter3(Order = 1)> _ 
    Public Sub Index()
        View("Index")
    End Sub
    

    [Filter1(Order = 2)]
    [Filter2(Order = 3)]
    [Filter3(Order = 1)]
    public void Index()
    {
        View("Index");
    }
    

    Dans cet exemple, les filtres d'action s'exécutent dans l'ordre suivant : Filter3, Filter1, puis Filter2.

  4. Si deux filtres d'action ont la même valeur de propriété Order et qu'un filtre d'action est défini sur un type, tandis que l'autre est défini sur une méthode, le filtre d'action défini sur le type s'exécute en premier. L'exemple suivant présente un filtre d'action défini sur un type et un autre défini sur une méthode.

    <FilterType(Order = 1)> _ 
    Public Class MyController
        <FilterMethod(Order = 1)> _ 
        Public  Sub Index()
            View("Index")
        End Sub
    End Class
    

    [FilterType(Order = 1)]
    public class MyController
    {
        [FilterMethod(Order = 1)]
        public void Index()
        {
            View("Index");
        }
    }
    

    Dans cet exemple, FilterType s'exécute avant FilterMethod.

Ajouts de la communauté

AJOUTER
Afficher:
© 2014 Microsoft