Filtros en ASP.NET CoreFilters in ASP.NET Core

Por Kirk Larkin, Rick Anderson, Tom Dykstra y Steve SmithBy Kirk Larkin, Rick Anderson, Tom Dykstra, and Steve Smith

Los filtros en ASP.NET Core permiten que se ejecute el código antes o después de determinadas fases de la canalización del procesamiento de la solicitud.Filters in ASP.NET Core allow code to be run before or after specific stages in the request processing pipeline.

Los filtros integrados se encargan de tareas como las siguientes:Built-in filters handle tasks such as:

  • Autorización (impedir el acceso a los recursos a un usuario que no está autorizado).Authorization (preventing access to resources a user isn't authorized for).
  • Almacenamiento en caché de respuestas (cortocircuitar la canalización de solicitud para devolver una respuesta almacenada en caché).Response caching (short-circuiting the request pipeline to return a cached response).

Se pueden crear filtros personalizados que se encarguen de cuestiones transversales.Custom filters can be created to handle cross-cutting concerns. Entre los ejemplos de cuestiones transversales se incluyen el control de errores, el almacenamiento en caché, la configuración, la autorización y el registro.Examples of cross-cutting concerns include error handling, caching, configuration, authorization, and logging. Los filtros evitan la duplicación de código.Filters avoid duplicating code. Así, por ejemplo, un filtro de excepción de control de errores puede consolidar el control de errores.For example, an error handling exception filter could consolidate error handling.

Este documento se aplica a Razor Pages, a los controladores de API y a los controladores con vistas.This document applies to Razor Pages, API controllers, and controllers with views.

Vea o descargue el ejemplo (cómo descargarlo).View or download sample (how to download).

Funcionamiento de los filtrosHow filters work

Los filtros se ejecutan dentro de la canalización de invocación de acciones de ASP.NET Core, a veces denominada canalización de filtro.Filters run within the ASP.NET Core action invocation pipeline, sometimes referred to as the filter pipeline. La canalización de filtro se ejecuta después de que ASP.NET Core seleccione la acción que se va a ejecutar.The filter pipeline runs after ASP.NET Core selects the action to execute.

La solicitud se procesa a través de las fases de otro middleware, del middleware de enrutamiento, de la selección de acción y de la canalización de invocación de acciones de ASP.NET Core.

Tipos de filtroFilter types

Cada tipo de filtro se ejecuta en una fase diferente dentro de la canalización de filtro:Each filter type is executed at a different stage in the filter pipeline:

  • Los filtros de autorización se ejecutan en primer lugar y sirven para averiguar si el usuario está autorizado para realizar la solicitud.Authorization filters run first and are used to determine whether the user is authorized for the request. Los filtros de autorización pueden cortocircuitar la canalización si una solicitud no está autorizada.Authorization filters short-circuit the pipeline if the request is unauthorized.

  • Filtros de recursos:Resource filters:

    • Se ejecutan después de la autorización.Run after authorization.
    • OnResourceExecuting puede ejecutar código antes que el resto de la canalización del filtro.OnResourceExecuting can run code before the rest of the filter pipeline. Por ejemplo, OnResourceExecuting puede ejecutar código antes que el enlace de modelos.For example, OnResourceExecuting can run code before model binding.
    • OnResourceExecuted puede ejecutar el código una vez que el resto de la canalización se haya completado.OnResourceExecuted can run code after the rest of the pipeline has completed.
  • Los filtros de acciones pueden ejecutar código inmediatamente antes y después de llamar a un método de acción individual.Action filters can run code immediately before and after an individual action method is called. Se pueden usar para manipular los argumentos pasados a una acción y el resultado obtenido de la acción.They can be used to manipulate the arguments passed into an action and the result returned from the action. Los filtros de acciones no se admiten en Razor Pages.Action filters are not supported in Razor Pages.

  • Los filtros de excepciones sirven para aplicar directivas globales a las excepciones no controladas que se producen antes de que se escriba algo en el cuerpo de respuesta.Exception filters are used to apply global policies to unhandled exceptions that occur before anything has been written to the response body.

  • Los filtros de resultados pueden ejecutar código inmediatamente antes y después de la ejecución de resultados de acción individuales.Result filters can run code immediately before and after the execution of individual action results. Se ejecutan solo cuando el método de acción se ha ejecutado correctamente.They run only when the action method has executed successfully. Son útiles para la lógica que debe regir la ejecución de la vista o el formateador.They are useful for logic that must surround view or formatter execution.

En el siguiente diagrama se muestra cómo interactúan los tipos de filtro en la canalización de filtro.The following diagram shows how filter types interact in the filter pipeline.

La solicitud se procesa a través de las fases Filtros de autorización, Filtros de recursos, Enlace de modelos, Filtros de acciones, Ejecución de acciones/Conversión del resultado de acción, Filtros de excepción, Filtros de resultados y Ejecución del resultado.

ImplementaciónImplementation

Los filtros admiten implementaciones tanto sincrónicas como asincrónicas a través de diferentes definiciones de interfaz.Filters support both synchronous and asynchronous implementations through different interface definitions.

Los filtros sincrónicos pueden ejecutar código antes (On-Stage-Executing) y después (On-Stage-Executed) de la fase de canalización.Synchronous filters can run code before (On-Stage-Executing) and after (On-Stage-Executed) their pipeline stage. Por ejemplo, OnActionExecuting se llama antes de llamar al método de acción.For example, OnActionExecuting is called before the action method is called. OnActionExecuted se llama después de devolver el método de acción.OnActionExecuted is called after the action method returns.

public class MySampleActionFilter : IActionFilter
{
    public void OnActionExecuting(ActionExecutingContext context)
    {
        // Do something before the action executes.
    }

    public void OnActionExecuted(ActionExecutedContext context)
    {
        // Do something after the action executes.
    }
}

Los filtros asincrónicos definen un método On-Stage-ExecutionAsync:Asynchronous filters define an On-Stage-ExecutionAsync method:

public class SampleAsyncActionFilter : IAsyncActionFilter
{
    public async Task OnActionExecutionAsync(
        ActionExecutingContext context,
        ActionExecutionDelegate next)
    {
        // Do something before the action executes.

        // next() calls the action method.
        var resultContext = await next();
        // resultContext.Result is set.
        // Do something after the action executes.
    }
}

En el código anterior, SampleAsyncActionFilter tiene un delegado ActionExecutionDelegate (next) que ejecuta el método de acción.In the preceding code, the SampleAsyncActionFilter has an ActionExecutionDelegate (next) that executes the action method. Cada uno de los métodos On-Stage-ExecutionAsync toman un FilterType-ExecutionDelegate que ejecuta la fase de canalización del filtro.Each of the On-Stage-ExecutionAsync methods take a FilterType-ExecutionDelegate that executes the filter's pipeline stage.

Varias fases de filtroMultiple filter stages

Se pueden implementar interfaces para varias fases de filtro en una sola clase.Interfaces for multiple filter stages can be implemented in a single class. Por ejemplo, la clase ActionFilterAttribute implementa IActionFilter, IResultFilter y sus equivalentes asincrónicos.For example, the ActionFilterAttribute class implements IActionFilter, IResultFilter, and their async equivalents.

Implemente la versión sincrónica o la versión asincrónica de una interfaz de filtro, pero no ambas.Implement either the synchronous or the async version of a filter interface, not both. El entorno de ejecución comprueba primero si el filtro implementa la interfaz asincrónica y, si es así, llama a la interfaz.The runtime checks first to see if the filter implements the async interface, and if so, it calls that. De lo contrario, llamará a métodos de interfaz sincrónicos.If not, it calls the synchronous interface's method(s). Si se implementan las interfaces asincrónicas y sincrónicas en una clase, solo se llama al método asincrónico.If both asynchronous and synchronous interfaces are implemented in one class, only the async method is called. Cuando se usan clases abstractas como ActionFilterAttribute, se invalidan solo los métodos sincrónicos o el método asincrónico de cada tipo de filtro.When using abstract classes like ActionFilterAttribute override only the synchronous methods or the async method for each filter type.

Atributos de filtros integradosBuilt-in filter attributes

ASP.NET Core incluye filtros integrados basados en atributos que se pueden personalizar y a partir de los cuales crear subclases.ASP.NET Core includes built-in attribute-based filters that can be subclassed and customized. Por ejemplo, el siguiente filtro de resultados agrega un encabezado a la respuesta:For example, the following result filter adds a header to the response:

public class AddHeaderAttribute : ResultFilterAttribute
{
    private readonly string _name;
    private readonly string _value;

    public AddHeaderAttribute(string name, string value)
    {
        _name = name;
        _value = value;
    }

    public override void OnResultExecuting(ResultExecutingContext context)
    {
        context.HttpContext.Response.Headers.Add( _name, new string[] { _value });
        base.OnResultExecuting(context);
    }
}

Los atributos permiten a los filtros aceptar argumentos, como se muestra en el ejemplo anterior.Attributes allow filters to accept arguments, as shown in the preceding example. Aplique el AddHeaderAttribute a un método de acción o controlador y especifique el nombre y el valor del encabezado HTTP:Apply the AddHeaderAttribute to a controller or action method and specify the name and value of the HTTP header:

[AddHeader("Author", "Joe Smith")]
public class SampleController : Controller
{
    public IActionResult Index()
    {
        return Content("Examine the headers using the F12 developer tools.");
    }

    [ShortCircuitingResourceFilter]
    public IActionResult SomeResource()
    {
        return Content("Successful access to resource - header is set.");
    }

Algunas de las interfaces de filtro tienen atributos correspondientes que se pueden usar como clases base en las implementaciones personalizadas.Several of the filter interfaces have corresponding attributes that can be used as base classes for custom implementations.

Atributos de filtro:Filter attributes:

Ámbitos del filtro y orden de ejecuciónFilter scopes and order of execution

Un filtro se puede agregar a la canalización en uno de tres ámbitos posibles:A filter can be added to the pipeline at one of three scopes:

  • Mediante un atributo en una acción.Using an attribute on an action.
  • Mediante un atributo en un controlador.Using an attribute on a controller.
  • Globalmente para todos los controladores y las acciones, tal como se muestra en el siguiente código:Globally for all controllers and actions as shown in the following code:
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(options =>
    {
        options.Filters.Add(new AddHeaderAttribute("GlobalAddHeader",
            "Result filter added to MvcOptions.Filters"));         // An instance
        options.Filters.Add(typeof(MySampleActionFilter));         // By type
        options.Filters.Add(new SampleGlobalActionFilter());       // An instance
    }).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

El código anterior agrega tres filtros globalmente mediante la colección MvcOptions.Filters.The preceding code adds three filters globally using the MvcOptions.Filters collection.

Orden de ejecución predeterminadoDefault order of execution

Cuando hay varios filtros en una determinada fase de la canalización, el ámbito determina el orden predeterminado en el que esos filtros se van a ejecutar.When there are multiple filters for a particular stage of the pipeline, scope determines the default order of filter execution. Los filtros globales abarcan a los filtros de clase, que a su vez engloban a los filtros de método.Global filters surround class filters, which in turn surround method filters.

Como resultado de este anidamiento de filtros, el código de filtros posterior se ejecuta en el orden inverso al código anterior.As a result of filter nesting, the after code of filters runs in the reverse order of the before code. La secuencia de filtro:The filter sequence:

  • El código anterior de los filtros globales.The before code of global filters.
    • El código anterior de los filtros de controlador.The before code of controller filters.
      • El código anterior de los filtros de métodos de acción.The before code of action method filters.
      • El código posterior de los filtros de métodos de acción.The after code of action method filters.
    • El código posterior de los filtros de controlador.The after code of controller filters.
  • El código posterior de los filtros globales.The after code of global filters.

El ejemplo siguiente que ilustra el orden en el que se llama a los métodos de filtro relativos a filtros de acciones sincrónicos.The following example that illustrates the order in which filter methods are called for synchronous action filters.

SecuenciaSequence Ámbito del filtroFilter scope Método de filtroFilter method
11 GlobalGlobal OnActionExecuting
22 ControladorController OnActionExecuting
33 MétodoMethod OnActionExecuting
44 MétodoMethod OnActionExecuted
55 ControladorController OnActionExecuted
66 GlobalGlobal OnActionExecuted

Esta secuencia pone de manifiesto lo siguiente:This sequence shows:

  • El filtro de método está anidado en el filtro de controlador.The method filter is nested within the controller filter.
  • El filtro de controlador está anidado en el filtro global.The controller filter is nested within the global filter.

Filtros de nivel de controlador y de páginas de RazorController and Razor Page level filters

Cada controlador que hereda de la clase base Controller incluye los métodos Controller.OnActionExecuting, Controller.OnActionExecutionAsync y Controller.OnActionExecuted OnActionExecuted.Every controller that inherits from the Controller base class includes Controller.OnActionExecuting, Controller.OnActionExecutionAsync, and Controller.OnActionExecuted OnActionExecuted methods. Estos métodos:These methods:

  • Encapsulan los filtros que se ejecutan para una acción determinada.Wrap the filters that run for a given action.
  • OnActionExecuting se llama antes de cualquiera de los filtros de acciones.OnActionExecuting is called before any of the action's filters.
  • OnActionExecuted se llama después de todos los filtros de acciones.OnActionExecuted is called after all of the action filters.
  • OnActionExecutionAsync se llama antes de cualquiera de los filtros de acciones.OnActionExecutionAsync is called before any of the action's filters. El código del filtro después de next se ejecuta después del método de acción.Code in the filter after next runs after the action method.

Por ejemplo, en el ejemplo de descarga, se aplica MySampleActionFilter globalmente al inicio.For example, in the download sample, MySampleActionFilter is applied globally in startup.

El TestController:The TestController:

  • Aplica SampleActionFilterAttribute ([SampleActionFilter]) a la acción FilterTest2:Applies the SampleActionFilterAttribute ([SampleActionFilter]) to the FilterTest2 action:
  • Invalida OnActionExecuting y OnActionExecuted.Overrides OnActionExecuting and OnActionExecuted.
public class TestController : Controller
{
    [SampleActionFilter]
    public IActionResult FilterTest2()
    {
        return Content($"From FilterTest2");
    }

    public override void OnActionExecuting(ActionExecutingContext context)
    {
        // Do something before the action executes.
        base.OnActionExecuting(context);
    }

    public override void OnActionExecuted(ActionExecutedContext context)
    {
        // Do something after the action executes.
        base.OnActionExecuted(context);
    }
}

Si se dirige a https://localhost:5001/Test/FilterTest2, se ejecuta el código siguiente:Navigating to https://localhost:5001/Test/FilterTest2 runs the following code:

  • TestController.OnActionExecuting
    • MySampleActionFilter.OnActionExecuting
      • SampleActionFilterAttribute.OnActionExecuting
        • TestController.FilterTest2
      • SampleActionFilterAttribute.OnActionExecuted
    • MySampleActionFilter.OnActionExecuted
  • TestController.OnActionExecuted

Para Razor Pages, consulte Implementar filtros de páginas de Razor globalmente.For Razor Pages, see Implement Razor Page filters by overriding filter methods.

Invalidación del orden predeterminadoOverriding the default order

La secuencia de ejecución predeterminada se puede invalidar con la implementación de IOrderedFilter.The default sequence of execution can be overridden by implementing IOrderedFilter. Order expone la propiedad IOrderedFilter que tiene prioridad sobre el ámbito a la hora de determinar el orden de ejecución.IOrderedFilter exposes the Order property that takes precedence over scope to determine the order of execution. Un filtro con un valor Order menor:A filter with a lower Order value:

  • Ejecuta el código anterior antes que el de un filtro con un valor mayor de Order.Runs the before code before that of a filter with a higher value of Order.
  • Ejecuta el código posterior después que el de un filtro con un valor mayor de Order.Runs the after code after that of a filter with a higher Order value.

La propiedad Order se puede establecer con un parámetro de constructor:The Order property can be set with a constructor parameter:

[MyFilter(Name = "Controller Level Attribute", Order=1)]

Considere los mismos tres filtros de acción que se muestran en el ejemplo anterior.Consider the same 3 action filters shown in the preceding example. Si la propiedad Order del controlador y de los filtros globales está establecida en 1 y 2 respectivamente, el orden de ejecución se invierte.If the Order property of the controller and global filters is set to 1 and 2 respectively, the order of execution is reversed.

SecuenciaSequence Ámbito del filtroFilter scope PropiedadOrder Order property Método de filtroFilter method
11 MétodoMethod 00 OnActionExecuting
22 ControladorController 11 OnActionExecuting
33 GlobalGlobal 22 OnActionExecuting
44 GlobalGlobal 22 OnActionExecuted
55 ControladorController 11 OnActionExecuted
66 MétodoMethod 00 OnActionExecuted

La propiedad Order invalida el ámbito al determinar el orden en el que se ejecutarán los filtros.The Order property overrides scope when determining the order in which filters run. Los filtros se clasifican por orden en primer lugar y, después, se usa el ámbito para priorizar en caso de igualdad.Filters are sorted first by order, then scope is used to break ties. Todos los filtros integrados implementan IOrderedFilter y establecen el valor predeterminado de Order en 0.All of the built-in filters implement IOrderedFilter and set the default Order value to 0. En los filtros integrados, el ámbito determina el orden, a menos que Order se establezca en un valor distinto de cero.For built-in filters, scope determines order unless Order is set to a non-zero value.

Cancelación y cortocircuitoCancellation and short-circuiting

La canalización de filtro se puede cortocircuitar en cualquier momento mediante el establecimiento de la propiedad Result en el parámetro ResourceExecutingContext que se ha proporcionado al método de filtro.The filter pipeline can be short-circuited by setting the Result property on the ResourceExecutingContext parameter provided to the filter method. Por ejemplo, el siguiente filtro de recursos impide que el resto de la canalización se ejecute:For instance, the following Resource filter prevents the rest of the pipeline from executing:

public class ShortCircuitingResourceFilterAttribute : Attribute, IResourceFilter
{
    public void OnResourceExecuting(ResourceExecutingContext context)
    {
        context.Result = new ContentResult()
        {
            Content = "Resource unavailable - header not set."
        };
    }

    public void OnResourceExecuted(ResourceExecutedContext context)
    {
    }
}

En el siguiente código, tanto el filtro ShortCircuitingResourceFilter como el filtro AddHeader tienen como destino el método de acción SomeResource.In the following code, both the ShortCircuitingResourceFilter and the AddHeader filter target the SomeResource action method. El ShortCircuitingResourceFilter:The ShortCircuitingResourceFilter:

  • Se ejecuta en primer lugar, porque es un filtro de recursos y AddHeader es un filtro de acciones.Runs first, because it's a Resource Filter and AddHeader is an Action Filter.
  • Cortocircuita el resto de la canalización.Short-circuits the rest of the pipeline.

Por tanto, el filtro AddHeader nunca se ejecuta en relación con la acción SomeResource.Therefore the AddHeader filter never runs for the SomeResource action. Este comportamiento sería el mismo si ambos filtros se aplicaran en el nivel de método de acción, siempre y cuando ShortCircuitingResourceFilter se haya ejecutado primero.This behavior would be the same if both filters were applied at the action method level, provided the ShortCircuitingResourceFilter ran first. ShortCircuitingResourceFilter se ejecuta primero debido a su tipo de filtro o al uso explícito de la propiedad Order.The ShortCircuitingResourceFilter runs first because of its filter type, or by explicit use of Order property.

[AddHeader("Author", "Joe Smith")]
public class SampleController : Controller
{
    public IActionResult Index()
    {
        return Content("Examine the headers using the F12 developer tools.");
    }

    [ShortCircuitingResourceFilter]
    public IActionResult SomeResource()
    {
        return Content("Successful access to resource - header is set.");
    }

Inserción de dependenciasDependency injection

Los filtros se pueden agregar por tipo o por instancia.Filters can be added by type or by instance. Si se agrega una instancia, esta se utiliza para todas las solicitudes.If an instance is added, that instance is used for every request. Si se agrega un tipo, se activa por tipo.If a type is added, it's type-activated. Un filtro activado por tipo significa:A type-activated filter means:

  • Se crea una instancia para cada solicitud.An instance is created for each request.
  • Las dependencias de constructor se rellenan mediante la inserción de dependencias.Any constructor dependencies are populated by dependency injection (DI).

Los filtros que se implementan como atributos y se agregan directamente a las clases de controlador o a los métodos de acción no pueden tener dependencias de constructor proporcionadas por la inserción de dependencias.Filters that are implemented as attributes and added directly to controller classes or action methods cannot have constructor dependencies provided by dependency injection (DI). Las dependencias de constructor no pueden proporcionarse mediante la inserción de dependencias porque:Constructor dependencies cannot be provided by DI because:

  • Los atributos deben tener los parámetros de constructor proporcionados allá donde se apliquen.Attributes must have their constructor parameters supplied where they're applied.
  • Se trata de una limitación de cómo funcionan los atributos.This is a limitation of how attributes work.

Los filtros siguientes admiten dependencias de constructor proporcionadas en la inserción de dependencias:The following filters support constructor dependencies provided from DI:

Los filtros anteriores se pueden aplicar a un método de controlador o de acción:The preceding filters can be applied to a controller or action method:

Los registradores están disponibles en la inserción de dependencias.Loggers are available from DI. Sin embargo, evite crear y utilizar filtros únicamente con fines de registro.However, avoid creating and using filters purely for logging purposes. El registro del marco integrado proporciona normalmente lo que se necesita para el registro.The built-in framework logging typically provides what's needed for logging. Registro agregado a los filtros:Logging added to filters:

  • Debe centrarse en cuestiones de dominio empresarial o en el comportamiento específico del filtro.Should focus on business domain concerns or behavior specific to the filter.
  • No debe registrar acciones u otros eventos del marco.Should not log actions or other framework events. Los filtros integrados registran acciones y eventos del marco.The built in filters log actions and framework events.

ServiceFilterAttributeServiceFilterAttribute

Los tipos de implementación de filtro de servicio se registran en ConfigureServices.Service filter implementation types are registered in ConfigureServices. ServiceFilterAttribute recupera una instancia del filtro de la inserción de dependencias.A ServiceFilterAttribute retrieves an instance of the filter from DI.

El código siguiente muestra AddHeaderResultServiceFilter:The following code shows the AddHeaderResultServiceFilter:

public class AddHeaderResultServiceFilter : IResultFilter
{
    private ILogger _logger;
    public AddHeaderResultServiceFilter(ILoggerFactory loggerFactory)
    {
        _logger = loggerFactory.CreateLogger<AddHeaderResultServiceFilter>();
    }

    public void OnResultExecuting(ResultExecutingContext context)
    {
        var headerName = "OnResultExecuting";
        context.HttpContext.Response.Headers.Add(
            headerName, new string[] { "ResultExecutingSuccessfully" });
        _logger.LogInformation($"Header added: {headerName}");
    }

    public void OnResultExecuted(ResultExecutedContext context)
    {
        // Can't add to headers here because response has started.
    }
}

En el código siguiente, AddHeaderResultServiceFilter se agrega al contenedor de inserción de dependencias:In the following code, AddHeaderResultServiceFilter is added to the DI container:

public void ConfigureServices(IServiceCollection services)
{
    // Add service filters.
    services.AddScoped<AddHeaderResultServiceFilter>();
    services.AddScoped<SampleActionFilterAttribute>();

    services.AddMvc(options =>
    {
        options.Filters.Add(new AddHeaderAttribute("GlobalAddHeader",
            "Result filter added to MvcOptions.Filters"));         // An instance
        options.Filters.Add(typeof(MySampleActionFilter));         // By type
        options.Filters.Add(new SampleGlobalActionFilter());       // An instance
    }).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

En el código siguiente, el atributo ServiceFilter recupera una instancia del filtro AddHeaderResultServiceFilter desde la inserción de dependencias:In the following code, the ServiceFilter attribute retrieves an instance of the AddHeaderResultServiceFilter filter from DI:

[ServiceFilter(typeof(AddHeaderResultServiceFilter))]
public IActionResult Index()
{
    return View();
}

ServiceFilterAttribute.IsReusable:ServiceFilterAttribute.IsReusable:

  • Proporciona una sugerencia que la instancia de filtro podría reutilizarse fuera del ámbito de la solicitud en la que se creó.Provides a hint that the filter instance may be reused outside of the request scope it was created within. El entorno de ejecución de ASP.NET Core no garantiza:The ASP.NET Core runtime doesn't guarantee:

    • Que se creará una única instancia del filtro.That a single instance of the filter will be created.
    • El filtro no volverá a solicitarse desde el contenedor de inserción de dependencias en algún momento posterior.The filter will not be re-requested from the DI container at some later point.
  • No debe usarse con un filtro que depende de servicios con una duración distinta de singleton.Should not be used with a filter that depends on services with a lifetime other than singleton.

ServiceFilterAttribute implementa IFilterFactory.ServiceFilterAttribute implements IFilterFactory. IFilterFactory expone el método CreateInstance para crear una instancia de IFilterMetadata.IFilterFactory exposes the CreateInstance method for creating an IFilterMetadata instance. CreateInstance carga el tipo especificado desde la inserción de dependencias.CreateInstance loads the specified type from DI.

TypeFilterAttributeTypeFilterAttribute

TypeFilterAttribute es similar a ServiceFilterAttribute, pero su tipo no se resuelve directamente desde el contenedor de inserción de dependencias,TypeFilterAttribute is similar to ServiceFilterAttribute, but its type isn't resolved directly from the DI container. sino que crea una instancia del tipo usando el elemento Microsoft.Extensions.DependencyInjection.ObjectFactory.It instantiates the type by using Microsoft.Extensions.DependencyInjection.ObjectFactory.

Dado que los tipos TypeFilterAttribute no se resuelven directamente desde el contenedor de inserción de dependencias:Because TypeFilterAttribute types aren't resolved directly from the DI container:

  • Los tipos a los que se hace referencia con TypeFilterAttribute no tienen que estar registrados con el contenedor de inserción de dependencias.Types that are referenced using the TypeFilterAttribute don't need to be registered with the DI container. Sus dependencias se completan a través del contenedor de inserción de dependencias.They do have their dependencies fulfilled by the DI container.
  • TypeFilterAttribute puede aceptar opcionalmente argumentos de constructor del tipo en cuestión.TypeFilterAttribute can optionally accept constructor arguments for the type.

Al usar TypeFilterAttribute, el valor IsReusable es una sugerencia de que la instancia de filtro podría reutilizarse fuera del ámbito de la solicitud en la que se creó.When using TypeFilterAttribute, setting IsReusable is a hint that the filter instance may be reused outside of the request scope it was created within. El entorno de ejecución de ASP.NET Core no ofrece ninguna garantía de que se vaya a crear una única instancia del filtro.The ASP.NET Core runtime provides no guarantees that a single instance of the filter will be created. IsReusable no debe usarse con un filtro que dependa de servicios con una duración distinta de singleton.IsReusable should not be used with a filter that depends on services with a lifetime other than singleton.

En el siguiente ejemplo se muestra cómo pasar argumentos a un tipo mediante TypeFilterAttribute:The following example shows how to pass arguments to a type using TypeFilterAttribute:

[TypeFilter(typeof(LogConstantFilter),
    Arguments = new object[] { "Method 'Hi' called" })]
public IActionResult Hi(string name)
{
    return Content($"Hi {name}");
}
public class LogConstantFilter : IActionFilter
{
    private readonly string _value;
    private readonly ILogger<LogConstantFilter> _logger;

    public LogConstantFilter(string value, ILogger<LogConstantFilter> logger)
    {
        _logger = logger;
        _value = value;
    }

    public void OnActionExecuting(ActionExecutingContext context)
    {
        _logger.LogInformation(_value);
    }

    public void OnActionExecuted(ActionExecutedContext context)
    { }
}

Filtros de autorizaciónAuthorization filters

Filtros de autorización:Authorization filters:

  • Son los primeros filtros que se ejecutan en la canalización del filtro.Are the first filters run in the filter pipeline.
  • Controlan el acceso a los métodos de acción.Control access to action methods.
  • Tienen un método anterior, pero no uno posterior.Have a before method, but no after method.

Los filtros de autorización personalizados requieren un marco de autorización personalizado.Custom authorization filters require a custom authorization framework. Es preferible configurar directivas de autorización o escribir una directiva de autorización personalizada a escribir un filtro personalizado.Prefer configuring the authorization policies or writing a custom authorization policy over writing a custom filter. El filtro de autorización integrado:The built-in authorization filter:

  • Llama a la autorización del sistema.Calls the authorization system.
  • No autoriza las solicitudes.Does not authorize requests.

No inicie excepciones dentro de los filtros de autorización:Do not throw exceptions within authorization filters:

  • La excepción no se controlará.The exception will not be handled.
  • Los filtros de excepciones no controlarán la excepción.Exception filters will not handle the exception.

Considere la posibilidad de emitir un desafío cuando se produzca una excepción en un filtro de autorizaciones.Consider issuing a challenge when an exception occurs in an authorization filter.

Aquí encontrará más información sobre la autorización.Learn more about Authorization.

Filtros de recursosResource filters

Filtros de recursos:Resource filters:

Los filtros de recursos son útiles para cortocircuitar la mayor parte de la canalización.Resource filters are useful to short-circuit most of the pipeline. Por ejemplo, un filtro de almacenamiento en caché puede evitar que se ejecute el resto de la canalización en un acierto de caché.For example, a caching filter can avoid the rest of the pipeline on a cache hit.

Ejemplos de filtros de recursos:Resource filter examples:

Filtros de accionesAction filters

Importante

Los filtros de acción no se aplican a Razor Pages.Action filters do not apply to Razor Pages. Razor Pages admite IPageFilter y IAsyncPageFilter.Razor Pages supports IPageFilter and IAsyncPageFilter . Para más información, vea Filter methods for Razor Pages (Métodos de filtrado para páginas de Razor).For more information, see Filter methods for Razor Pages.

Filtros de acciones:Action filters:

El código siguiente muestra un ejemplo de filtro de acciones:The following code shows a sample action filter:

public class MySampleActionFilter : IActionFilter
{
    public void OnActionExecuting(ActionExecutingContext context)
    {
        // Do something before the action executes.
    }

    public void OnActionExecuted(ActionExecutedContext context)
    {
        // Do something after the action executes.
    }
}

ActionExecutingContext ofrece las siguientes propiedades:The ActionExecutingContext provides the following properties:

  • ActionArguments: permite leer las entradas de un método de acción.ActionArguments - enables the inputs to an action method be read.
  • Controller: permite manipular la instancia del controlador.Controller - enables manipulating the controller instance.
  • Result: si se establece Result, se cortocircuita la ejecución del método de acción y de los filtros de acciones posteriores.Result - setting Result short-circuits execution of the action method and subsequent action filters.

Inicio de una excepción en un método de acción:Throwing an exception in an action method:

  • Impide la ejecución de los filtros subsiguientes.Prevents running of subsequent filters.
  • A diferencia del establecimiento de Result, se trata como un error en lugar de como un resultado correcto.Unlike setting Result, is treated as a failure instead of a successful result.

ActionExecutedContext proporciona Controller y Result, además de las siguientes propiedades:The ActionExecutedContext provides Controller and Result plus the following properties:

  • Canceled: es true si otro filtro ha cortocircuitado la ejecución de la acción.Canceled - True if the action execution was short-circuited by another filter.

  • Exception: es un valor distinto de NULL si la acción o un filtro de acción de ejecución anterior han producido una excepción.Exception - Non-null if the action or a previously run action filter threw an exception. Si se establece esta propiedad en un valor NULL:Setting this property to null:

    • Controla la excepción eficazmente.Effectively handles the exception.
    • Result se ejecuta como si se devolviera desde el método de acción.Result is executed as if it was returned from the action method.

En un IAsyncActionFilter, una llamada a ActionExecutionDelegate:For an IAsyncActionFilter, a call to the ActionExecutionDelegate:

  • Ejecuta cualquier filtro de acciones posterior y el método de acción.Executes any subsequent action filters and the action method.
  • Devuelve ActionExecutedContext.Returns ActionExecutedContext.

Para cortocircuitar esto, asigne Microsoft.AspNetCore.Mvc.Filters.ActionExecutingContext.Result a una instancia de resultado y no llame a next (la clase ActionExecutionDelegate).To short-circuit, assign Microsoft.AspNetCore.Mvc.Filters.ActionExecutingContext.Result to a result instance and don't call next (the ActionExecutionDelegate).

El marco proporciona una clase ActionFilterAttribute abstracta de la que se pueden crear subclases.The framework provides an abstract ActionFilterAttribute that can be subclassed.

Se puede usar el filtro de acción OnActionExecuting para:The OnActionExecuting action filter can be used to:

  • Validar el estado del modelo.Validate model state.
  • Devolver un error si el estado no es válido.Return an error if the state is invalid.
public class ValidateModelAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        if (!context.ModelState.IsValid)
        {
            context.Result = new BadRequestObjectResult(context.ModelState);
        }
    }

El método OnActionExecuted se ejecuta después del método de acción:The OnActionExecuted method runs after the action method:

  • Y puede ver y manipular los resultados de la acción a través de la propiedad Result.And can see and manipulate the results of the action through the Result property.

  • Canceled se establece en true si otro filtro ha cortocircuitado la ejecución de la acción.Canceled is set to true if the action execution was short-circuited by another filter.

  • Exception se establece en un valor distinto de NULL si la acción o un filtro de acción posterior han producido una excepción.Exception is set to a non-null value if the action or a subsequent action filter threw an exception. Si Exception se establece como nulo:Setting Exception to null:

    • Controla una excepción eficazmente.Effectively handles an exception.
    • ActionExecutedContext.Result se ejecuta como si se devolviera con normalidad desde el método de acción.ActionExecutedContext.Result is executed as if it were returned normally from the action method.
public class ValidateModelAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        if (!context.ModelState.IsValid)
        {
            context.Result = new BadRequestObjectResult(context.ModelState);
        }
    }


    public override void OnActionExecuted(ActionExecutedContext context)
    {
        var result = context.Result;
        // Do something with Result.
        if (context.Canceled == true)
        {
            // Action execution was short-circuited by another filter.
        }

        if(context.Exception != null)
        {
            // Exception thrown by action or action filter.
            // Set to null to handle the exception.
            context.Exception = null;
        }
        base.OnActionExecuted(context);
    }
}

Filtros de excepcionesException filters

Los filtros de excepciones:Exception filters:

En el siguiente filtro de excepciones de ejemplo se usa una vista de error personalizada para mostrar los detalles sobre las excepciones que se producen cuando la aplicación está en fase de desarrollo:The following sample exception filter uses a custom error view to display details about exceptions that occur when the app is in development:

public class CustomExceptionFilterAttribute : ExceptionFilterAttribute
{
    private readonly IHostingEnvironment _hostingEnvironment;
    private readonly IModelMetadataProvider _modelMetadataProvider;

    public CustomExceptionFilterAttribute(
        IHostingEnvironment hostingEnvironment,
        IModelMetadataProvider modelMetadataProvider)
    {
        _hostingEnvironment = hostingEnvironment;
        _modelMetadataProvider = modelMetadataProvider;
    }

    public override void OnException(ExceptionContext context)
    {
        if (!_hostingEnvironment.IsDevelopment())
        {
            return;
        }
        var result = new ViewResult {ViewName = "CustomError"};
        result.ViewData = new ViewDataDictionary(_modelMetadataProvider,
                                                    context.ModelState);
        result.ViewData.Add("Exception", context.Exception);
        // TODO: Pass additional detailed data via ViewData
        context.Result = result;
    }
}

Los filtros de excepciones:Exception filters:

  • No tienen eventos anteriores ni posteriores.Don't have before and after events.
  • Implementan OnException o OnExceptionAsync.Implement OnException or OnExceptionAsync.
  • Controlan las excepciones sin controlar que se producen en Razor Pages, al crear controladores, en el enlace de modelos, en los filtros de acciones o en los métodos de acción.Handle unhandled exceptions that occur in Razor Page or controller creation, model binding, action filters, or action methods.
  • No detectan aquellas excepciones que se produzcan en los filtros de recursos, en los filtros de resultados o en la ejecución de resultados de MVC.Do not catch exceptions that occur in resource filters, result filters, or MVC result execution.

Para controlar una excepción, establezca la propiedad ExceptionHandled en true o escriba una respuesta.To handle an exception, set the ExceptionHandled property to true or write a response. Esto detiene la propagación de la excepción.This stops propagation of the exception. Un filtro de excepciones no tiene capacidad para convertir una excepción en un proceso "correcto".An exception filter can't turn an exception into a "success". Eso solo lo pueden hacer los filtros de acciones.Only an action filter can do that.

Los filtros de excepciones:Exception filters:

  • Son adecuados para interceptar las excepciones que se producen en las acciones.Are good for trapping exceptions that occur within actions.
  • No son tan flexibles como el middleware de control de errores.Are not as flexible as error handling middleware.

Es preferible usar middleware de control de excepciones.Prefer middleware for exception handling. Utilice los filtros de excepciones solo cuando el control de errores es diferente en función del método de acción que se llama.Use exception filters only where error handling differs based on which action method is called. Por ejemplo, puede que una aplicación tenga métodos de acción tanto para los puntos de conexión de API como para las vistas/HTML.For example, an app might have action methods for both API endpoints and for views/HTML. Los puntos de conexión de API podrían devolver información sobre errores como JSON, mientras que las acciones basadas en vistas podrían devolver una página de error como HTML.The API endpoints could return error information as JSON, while the view-based actions could return an error page as HTML.

Filtros de resultadosResult filters

Filtros de resultados:Result filters:

IResultFilter e IAsyncResultFilterIResultFilter and IAsyncResultFilter

El código siguiente muestra un filtro de resultados que agrega un encabezado HTTP:The following code shows a result filter that adds an HTTP header:

public class AddHeaderResultServiceFilter : IResultFilter
{
    private ILogger _logger;
    public AddHeaderResultServiceFilter(ILoggerFactory loggerFactory)
    {
        _logger = loggerFactory.CreateLogger<AddHeaderResultServiceFilter>();
    }

    public void OnResultExecuting(ResultExecutingContext context)
    {
        var headerName = "OnResultExecuting";
        context.HttpContext.Response.Headers.Add(
            headerName, new string[] { "ResultExecutingSuccessfully" });
        _logger.LogInformation($"Header added: {headerName}");
    }

    public void OnResultExecuted(ResultExecutedContext context)
    {
        // Can't add to headers here because response has started.
    }
}

El tipo de resultado que se ejecute dependerá de la acción.The kind of result being executed depends on the action. Una acción que devuelve una vista incluye todo el procesamiento de Razor como parte del elemento ViewResult que se está ejecutando.An action returning a view would include all razor processing as part of the ViewResult being executed. Un método API puede llevar a cabo algunas funciones de serialización como parte de la ejecución del resultado.An API method might perform some serialization as part of the execution of the result. Aquí encontrará más información sobre los resultados de acciones.Learn more about action results

Los filtros de resultados solo se ejecutan cuando los resultados son correctos; es decir, cuando la acción o los filtros de acciones generan un resultado de acción.Result filters are only executed for successful results - when the action or action filters produce an action result. Los filtros de resultados no se ejecutan si hay filtros de excepciones que controlan una excepción.Result filters are not executed when exception filters handle an exception.

El método Microsoft.AspNetCore.Mvc.Filters.IResultFilter.OnResultExecuting puede cortocircuitar la ejecución del resultado de la acción y de los filtros de resultados posteriores mediante el establecimiento de Microsoft.AspNetCore.Mvc.Filters.ResultExecutingContext.Cancel en true.The Microsoft.AspNetCore.Mvc.Filters.IResultFilter.OnResultExecuting method can short-circuit execution of the action result and subsequent result filters by setting Microsoft.AspNetCore.Mvc.Filters.ResultExecutingContext.Cancel to true. Escriba en el objeto de respuesta cuando el proceso se cortocircuite, ya que así evitará que se genere una respuesta vacía.Write to the response object when short-circuiting to avoid generating an empty response. Si se inicia una excepción en IResultFilter.OnResultExecuting, sucederá lo siguiente:Throwing an exception in IResultFilter.OnResultExecuting will:

  • Se impedirá la ejecución del resultado de la acción y de los filtros subsiguientes.Prevent execution of the action result and subsequent filters.
  • Se tratará como un error en lugar de como un resultado correcto.Be treated as a failure instead of a successful result.

Cuando se ejecuta el método Microsoft.AspNetCore.Mvc.Filters.IResultFilter.OnResultExecuted:When the Microsoft.AspNetCore.Mvc.Filters.IResultFilter.OnResultExecuted method runs:

  • Es probable que la respuesta se haya enviado al cliente y no se pueda cambiar.The response has likely been sent to the client and cannot be changed.
  • Si se inicia una excepción, no se envía el cuerpo de respuesta.If an exception was thrown, the response body is not sent.

ResultExecutedContext.Canceled se establece en true si otro filtro ha cortocircuitado la ejecución del resultado de la acción.ResultExecutedContext.Canceled is set to true if the action result execution was short-circuited by another filter.

ResultExecutedContext.Exception se establece en un valor distinto de NULL si el resultado de la acción o un filtro de resultado posterior ha producido una excepción.ResultExecutedContext.Exception is set to a non-null value if the action result or a subsequent result filter threw an exception. Establecer Exception en un valor NULL hace que una excepción se "controle" de forma eficaz y evita que ASP.NET Core vuelva a producir dicha excepción más adelante en la canalización.Setting Exception to null effectively handles an exception and prevents the exception from being rethrown by ASP.NET Core later in the pipeline. No hay una forma confiable de escribir datos en una respuesta cuando se controla una excepción en un filtro de resultados.There is no reliable way to write data to a response when handling an exception in a result filter. Si los encabezados ya se han vaciado en el cliente si el resultado de una acción inicia una excepción, no hay ningún mecanismo confiable que permita enviar un código de error.If the headers have been flushed to the client when an action result throws an exception, there's no reliable mechanism to send a failure code.

En un elemento IAsyncResultFilter, una llamada a await next en ResultExecutionDelegate ejecuta cualquier filtro de resultados posterior y el resultado de la acción.For an IAsyncResultFilter, a call to await next on the ResultExecutionDelegate executes any subsequent result filters and the action result. Para cortocircuitarlo, establezca ResultExecutingContext.Cancel en true y no llame a ResultExecutionDelegate:To short-circuit, set ResultExecutingContext.Cancel to true and don't call the ResultExecutionDelegate:

public class MyAsyncResponseFilter : IAsyncResultFilter
{
    public async Task OnResultExecutionAsync(ResultExecutingContext context,
                                             ResultExecutionDelegate next)
    {
        if (!(context.Result is EmptyResult))
        {
            await next();
        }
        else
        {
            context.Cancel = true;
        }

    }
}

El marco proporciona una clase abstracta ResultFilterAttribute de la que se pueden crear subclases.The framework provides an abstract ResultFilterAttribute that can be subclassed. La clase AddHeaderAttribute mostrada anteriormente es un ejemplo de un atributo de filtro de resultados.The AddHeaderAttribute class shown previously is an example of a result filter attribute.

IAlwaysRunResultFilter e IAsyncAlwaysRunResultFilterIAlwaysRunResultFilter and IAsyncAlwaysRunResultFilter

Las interfaces IAlwaysRunResultFilter e IAsyncAlwaysRunResultFilter declaran una implementación IResultFilter que se ejecuta para obtener todos los resultados de la acción.The IAlwaysRunResultFilter and IAsyncAlwaysRunResultFilter interfaces declare an IResultFilter implementation that runs for all action results. El filtro se aplica a todos los resultados de la acción a menos que:The filter is applied to all action results unless:

Los filtros distintos de IExceptionFilter e IAuthorizationFilter no cortocircuitan IAlwaysRunResultFilter y IAsyncAlwaysRunResultFilter.Filters other than IExceptionFilter and IAuthorizationFilter don't short-circuit IAlwaysRunResultFilter and IAsyncAlwaysRunResultFilter.

Por ejemplo, el siguiente filtro siempre ejecuta y establece un resultado de la acción (ObjectResult) con un código de estado 422 - Entidad no procesable cuando se produce un error en la negociación de contenido:For example, the following filter always runs and sets an action result (ObjectResult) with a 422 Unprocessable Entity status code when content negotiation fails:

public class UnprocessableResultFilter : Attribute, IAlwaysRunResultFilter
{
    public void OnResultExecuting(ResultExecutingContext context)
    {
        if (context.Result is StatusCodeResult statusCodeResult &&
            statusCodeResult.StatusCode == 415)
        {
            context.Result = new ObjectResult("Can't process this!")
            {
                StatusCode = 422,
            };
        }
    }

    public void OnResultExecuted(ResultExecutedContext context)
    {
    }
}

IFilterFactoryIFilterFactory

IFilterFactory implementa IFilterMetadata.IFilterFactory implements IFilterMetadata. Por tanto, una instancia de IFilterFactory se puede usar como una instancia de IFilterMetadata en cualquier parte de la canalización de filtro.Therefore, an IFilterFactory instance can be used as an IFilterMetadata instance anywhere in the filter pipeline. Cuando el entorno de ejecución se prepara para invocar el filtro, intenta convertirlo a un IFilterFactory.When the runtime prepares to invoke the filter, it attempts to cast it to an IFilterFactory. Si esa conversión se realiza correctamente, se llama al método CreateInstance para crear la instancia IFilterMetadata que se va a invocar.If that cast succeeds, the CreateInstance method is called to create the IFilterMetadata instance that is invoked. Esto proporciona un diseño flexible, dado que no hay que establecer la canalización de filtro exacta de forma explícita cuando la aplicación se inicia.This provides a flexible design, since the precise filter pipeline doesn't need to be set explicitly when the app starts.

Puede implementar IFilterFactory con las implementaciones de atributos personalizados como método alternativo para crear filtros:IFilterFactory can be implemented using custom attribute implementations as another approach to creating filters:

public class AddHeaderWithFactoryAttribute : Attribute, IFilterFactory
{
    // Implement IFilterFactory
    public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
    {
        return new InternalAddHeaderFilter();
    }

    private class InternalAddHeaderFilter : IResultFilter
    {
        public void OnResultExecuting(ResultExecutingContext context)
        {
            context.HttpContext.Response.Headers.Add(
                "Internal", new string[] { "My header" });
        }

        public void OnResultExecuted(ResultExecutedContext context)
        {
        }
    }

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
}

El código anterior se puede probar mediante la ejecución del ejemplo de descargar:The preceding code can be tested by running the download sample:

  • Invoque las herramientas de desarrollador de F12.Invoke the F12 developer tools.
  • Navegue a https://localhost:5001/Sample/HeaderWithFactory.Navigate to https://localhost:5001/Sample/HeaderWithFactory

Las herramientas de desarrollador F12 muestran los siguientes encabezados de respuesta agregados por el código de ejemplo:The F12 developer tools display the following response headers added by the sample code:

  • author: Joe Smithauthor: Joe Smith
  • globaladdheader: Result filter added to MvcOptions.Filtersglobaladdheader: Result filter added to MvcOptions.Filters
  • internal: My headerinternal: My header

El código anterior crea el encabezado de respuesta internal: My header.The preceding code creates the internal: My header response header.

IFilterFactory implementado en un atributoIFilterFactory implemented on an attribute

Los filtros que implementan IFilterFactory son útiles para los filtros que:Filters that implement IFilterFactory are useful for filters that:

  • No requieren pasar parámetros.Don't require passing parameters.
  • Tienen dependencias de constructor que deben completarse por medio de la inserción de dependencias.Have constructor dependencies that need to be filled by DI.

TypeFilterAttribute implementa IFilterFactory.TypeFilterAttribute implements IFilterFactory. IFilterFactory expone el método CreateInstance para crear una instancia de IFilterMetadata.IFilterFactory exposes the CreateInstance method for creating an IFilterMetadata instance. CreateInstance carga el tipo especificado desde el contenedor de servicios (inserción de dependencias).CreateInstance loads the specified type from the services container (DI).

public class SampleActionFilterAttribute : TypeFilterAttribute
{
    public SampleActionFilterAttribute():base(typeof(SampleActionFilterImpl))
    {
    }

    private class SampleActionFilterImpl : IActionFilter
    {
        private readonly ILogger _logger;
        public SampleActionFilterImpl(ILoggerFactory loggerFactory)
        {
            _logger = loggerFactory.CreateLogger<SampleActionFilterAttribute>();
        }

        public void OnActionExecuting(ActionExecutingContext context)
        {
            _logger.LogInformation("Business action starting...");
            // perform some business logic work

        }

        public void OnActionExecuted(ActionExecutedContext context)
        {
            // perform some business logic work
            _logger.LogInformation("Business action completed.");
        }
    }
}

El código siguiente muestra tres métodos para aplicar [SampleActionFilter]:The following code shows three approaches to applying the [SampleActionFilter]:

[SampleActionFilter]
public IActionResult FilterTest()
{
    return Content($"From FilterTest");
}

[TypeFilter(typeof(SampleActionFilterAttribute))]
public IActionResult TypeFilterTest()
{
    return Content($"From ServiceFilterTest");
}

// ServiceFilter must be registered in ConfigureServices or
// System.InvalidOperationException: No service for type '<filter>' has been registered.
// Is thrown.
[ServiceFilter(typeof(SampleActionFilterAttribute))]
public IActionResult ServiceFilterTest()
{
    return Content($"From ServiceFilterTest");
}

En el código anterior, decorar el método con [SampleActionFilter] es el enfoque preferido para aplicar SampleActionFilter.In the preceding code, decorating the method with [SampleActionFilter] is the preferred approach to applying the SampleActionFilter.

Uso de middleware en la canalización de filtroUsing middleware in the filter pipeline

Los filtros de recursos funcionan como el middleware, en el sentido de que se encargan de la ejecución de todo lo que viene después en la canalización.Resource filters work like middleware in that they surround the execution of everything that comes later in the pipeline. Pero los filtros se diferencian del middleware en que forman parte del entorno de ejecución de ASP.NET Core, lo que significa que tienen acceso al contexto y las construcciones de ASP.NET Core.But filters differ from middleware in that they're part of the ASP.NET Core runtime, which means that they have access to ASP.NET Core context and constructs.

Para usar middleware como un filtro, cree un tipo con un método Configure en el que se especifique el middleware para insertar en la canalización de filtro.To use middleware as a filter, create a type with a Configure method that specifies the middleware to inject into the filter pipeline. El ejemplo siguiente usa el middleware de localización para establecer la referencia cultural actual de una solicitud:The following example uses the localization middleware to establish the current culture for a request:

public class LocalizationPipeline
{
    public void Configure(IApplicationBuilder applicationBuilder)
    {
        var supportedCultures = new[]
        {
            new CultureInfo("en-US"),
            new CultureInfo("fr")
        };

        var options = new RequestLocalizationOptions
        {

            DefaultRequestCulture = new RequestCulture(culture: "en-US", 
                                                     uiCulture: "en-US"),
            SupportedCultures = supportedCultures,
            SupportedUICultures = supportedCultures
        };
        options.RequestCultureProviders = new[] 
            { new RouteDataRequestCultureProvider() { Options = options } };

        applicationBuilder.UseRequestLocalization(options);
    }
}

Use MiddlewareFilterAttribute para ejecutar el middleware:Use the MiddlewareFilterAttribute to run the middleware:

[Route("{culture}/[controller]/[action]")]
[MiddlewareFilter(typeof(LocalizationPipeline))]
public IActionResult CultureFromRouteData()
{
    return Content($"CurrentCulture:{CultureInfo.CurrentCulture.Name},"
        + $"CurrentUICulture:{CultureInfo.CurrentUICulture.Name}");
}

Los filtros de middleware se ejecutan en la misma fase de la canalización de filtro que los filtros de recursos, antes del enlace de modelos y después del resto de la canalización.Middleware filters run at the same stage of the filter pipeline as Resource filters, before model binding and after the rest of the pipeline.

Siguientes accionesNext actions