Exportar (0) Imprimir
Expandir todo
Este artículo se tradujo de forma manual. Mueva el puntero sobre las frases del artículo para ver el texto original.
Traducción
Original

Crear filtros de acción personalizada

Los posibles usos de los filtros de acción son tan variados como las acciones a las que se pueden aplicar. Algunos usos posibles de los filtros de acción incluyen:

  • Iniciar sesión para realizar el seguimiento de las interacciones del usuario.

  • "Anti-leeching de imágenes" para evitar que las imágenes se carguen en páginas que no se hallan en su sitio web.

  • Filtrado de rastreadores (crawler) web, para cambiar el comportamiento de la aplicación basado en el agente de usuario del explorador.

  • Localización para establecer la configuración regional.

  • Acciones dinámicas para insertar una acción en un controlador.

Un filtro de acción se implementa como una clase de atributos que hereda de la clase ActionFilterAttribute. ActionFilterAttribute es una clase abstracta que tiene cuatro métodos virtuales que se pueden reemplazar: OnActionExecuting, OnActionExecuted, OnResultExecuting y OnResultExecuted. Para implementar un filtro de acción, debe reemplazar uno de estos métodos por lo menos.

El marco de ASP.NET MVC llamará al método OnActionExecuting de su filtro de acción antes de llamar a cualquier método de acción que esté marcado con su atributo de filtro de acción. De igual forma, el marco llamará al método OnActionExecuted cuando el método de acción haya finalizado.

Se llama al método OnResultExecuting inmediatamente antes de que se invoque la instancia ActionResult que devuelve su acción. Se llama al método OnResultExecuted justo después de que se ejecute el resultado. Estos métodos son útiles para realizar acciones como registro, almacenamiento en la caché de resultados, etc.

En el ejemplo siguiente se muestra un filtro de acción simple que registra los mensajes de seguimiento antes y después de que se llame a un método de acción.


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


Cada uno de los controladores de eventos de controlador para el filtrado de acciones toma un objeto de contexto como parámetro. La lista siguiente muestra los controladores de eventos de filtro y el tipo de contexto que toma cada uno.

Todas las clases de contexto heredan de la clase ControllerContext e incluyen una propiedad ActionDescriptor. Puede utilizar la propiedad ActionDescriptor para identificar a qué acción se aplica actualmente el filtro.

Las clases ResultExecutingContext y ActionExecutingContext contienen una propiedad Cancel que permite cancelar la acción.

Las clases ActionExecutedContent y ResultExecutedContext contienen una propiedad Exception y otra ExceptionHandled. Si la propiedad Exception es null, indica que no se produjo ningún error cuando el método de acción se ejecutó. Si la propiedad Exception no es null y el filtro sabe cómo administrar la excepción, el filtro puede administrarla y, a continuación, señalar que lo ha hecho estableciendo la propiedad ExceptionHandled en true. Aun cuando la propiedad ExceptionHandled sea true, se llamará al método OnResultExecuted u OnActionExecuted de cualquier filtro de acción adicional en la pila y se les pasará información de la excepción. Esto habilita escenarios como permitir que un filtro de registro registre una excepción aunque ésta se haya administrado. En general, un filtro de acción no debería administrar una excepción a menos que el error sea específico de ese filtro.

Puede aplicar un filtro de acción a tantos métodos de acción como necesite. En el ejemplo siguiente se muestra un controlador que contiene métodos de acción que se marcan con un atributo de filtro de acción. En este caso, todos los métodos de acción del controlador invocarán al mismo filtro de acción.


[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 clase de ASP.NET MVC Controller define los métodos OnActionExecuted y OnActionExecuting que se pueden reemplazar. Al reemplazar uno o ambos de estos métodos, su lógica se ejecutará antes o después de todos los métodos de acción de ese controlador. Esta funcionalidad es como los filtros de acción, aunque el ámbito de los métodos lo establece el controlador.

En el ejemplo siguiente se muestran los métodos OnActionExecuted y OnActionExecuting de nivel de controlador que se aplican a todos los métodos de acción en el controlador.


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


Además de marcar los métodos de acción individuales con un filtro de acción, puede marcar una clase de controlador en su totalidad con un filtro de acción. En ese caso, el filtro se aplica a todos los métodos de acción de ese controlador.

Además, si su controlador deriva de otro controlador, el controlador base podría tener sus propios atributos de filtro de acción. Igualmente, si su controlador reemplaza un método de acción de un controlador base, el método podría tener sus propios atributos de filtro de acción y aquellos que hereda del método de acción reemplazado.

Para que sea más fácil comprender cómo funcionan conjuntamente los filtros de acción, los métodos de acción están agrupados en ámbitos. Un ámbito define dónde se aplica el atributo, por ejemplo, si marca una clase o un método, y si marca una clase base o una clase derivada.

Cada filtro de acción tiene una propiedad Order, que se utiliza para determinar el orden en que los filtros se ejecutan en el ámbito del filtro. La propiedad Order toma un valor entero que debe ser 0 (valor predeterminado) o mayor (con una excepción). Omitir la propiedad Order da al filtro un valor de orden de -1, que indica un orden no especificado. Cualquier filtro de acción en un ámbito cuya propiedad Order esté establecida en -1 se ejecutará en un orden indeterminado, pero antes que los filtros que tienen un orden especificado.

Cuando se especifica una propiedad Order de un filtro, debe estar establecida en un valor único en un ámbito. Si dos o más filtros de acción en un ámbito tienen el mismo valor de la propiedad Order, se produce una excepción.

Los filtros de acción se ejecutan en un orden que cumple las restricciones siguientes. Si todas estas restricciones se cumplen en más de una clasificación, el orden es indeterminado.

  1. La implementación de los métodos OnActionExecuted y OnActionExecuting en el controlador siempre va primero. Para obtener más información, vea Ejecutar código antes y después de una acción desde dentro un controlador.

  2. A menos que se establezca explícitamente la propiedad Order, un filtro de acción tiene un orden implícito de -1.

  3. Si se establece explícitamente la propiedad Order de varios filtros de acción, el filtro con el valor mínimo se ejecuta antes que aquellos con valores mayores, como se muestra en el ejemplo siguiente:

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

    En este ejemplo, los filtros de acción se ejecutarían en el orden siguiente: Filter3, Filter1 y Filter2.

  4. Si dos filtros de acción tienen el mismo valor de la propiedad Order, y si un filtro de acción se define en función de un tipo y el otro en función de un método, el filtro de acción definido para un tipo se ejecuta primero. En el ejemplo siguiente se muestra un filtro de acción definido para un tipo y otro definido para un método.

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

    En este ejemplo, FilterType se ejecuta antes que FilterMethod.

Adiciones de comunidad

AGREGAR
Mostrar:
© 2015 Microsoft