Filtros no ASP.NET CoreFilters in ASP.NET Core

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

Os Filtros no ASP.NET Core permitem a execução de código antes ou depois de determinados estágios do pipeline de processamento de solicitações.Filters in ASP.NET Core allow code to be run before or after specific stages in the request processing pipeline.

O filtros internos lidam com tarefas como:Built-in filters handle tasks such as:

  • Autorização (impedir o acesso a recursos aos quais o usuário não está autorizado).Authorization (preventing access to resources a user isn't authorized for).
  • Cache de resposta (causar um curto-circuito do pipeline de solicitação para retornar uma resposta armazenada em cache).Response caching (short-circuiting the request pipeline to return a cached response).

É possível criar filtros personalizados para lidar com interesses paralelos.Custom filters can be created to handle cross-cutting concerns. Entre os exemplos de interesses paralelos estão o tratamento de erros, cache, configuração, autorização e registro em log.Examples of cross-cutting concerns include error handling, caching, configuration, authorization, and logging. Filtros evitam a duplicação do código.Filters avoid duplicating code. Por exemplo, um filtro de exceção de tratamento de erro poderia consolidar o tratamento de erro.For example, an error handling exception filter could consolidate error handling.

Este documento se aplica ao Razor Pages, a controladores de API e controladores com exibição.This document applies to Razor Pages, API controllers, and controllers with views.

Exibir ou baixar exemplo (como baixar).View or download sample (how to download).

Como os filtros funcionamHow filters work

Os filtros são executados dentro do pipeline de invocação de ações do ASP.NET Core, às vezes chamado de pipeline de filtros.Filters run within the ASP.NET Core action invocation pipeline, sometimes referred to as the filter pipeline. O pipeline de filtros é executado após o ASP.NET Core selecionar a ação a ser executada.The filter pipeline runs after ASP.NET Core selects the action to execute.

A solicitação é processada por meio de Outro Middleware, do Middleware de Roteamento, da Seleção de Ação e do Pipeline de Invocação de Ações do ASP.NET Core.

Tipos de filtroFilter types

Cada tipo de filtro é executado em um estágio diferente no pipeline de filtros:Each filter type is executed at a different stage in the filter pipeline:

  • Filtros de autorização são executados primeiro e são usados para determinar se o usuário tem autorização para a solicitação.Authorization filters run first and are used to determine whether the user is authorized for the request. Os filtros de autorização podem causar um curto-circuito do pipeline se uma solicitação não for autorizada.Authorization filters short-circuit the pipeline if the request is unauthorized.

  • Filtros de recurso:Resource filters:

    • Execute após a autorização.Run after authorization.
    • OnResourceExecuting pode executar o código antes do restante do pipeline de filtros.OnResourceExecuting can run code before the rest of the filter pipeline. Por exemplo, OnResourceExecuting pode executar o código antes do model binding.For example, OnResourceExecuting can run code before model binding.
    • OnResourceExecuted pode executar o código após a conclusão do restante do pipeline.OnResourceExecuted can run code after the rest of the pipeline has completed.
  • Filtros de ação podem executar código imediatamente antes e depois de um método de ação individual ser chamado.Action filters can run code immediately before and after an individual action method is called. Eles podem ser usados para manipular os argumentos passados para uma ação, bem como o resultado da ação.They can be used to manipulate the arguments passed into an action and the result returned from the action. Os filtros de ação não são compatíveis com o Razor Pages.Action filters are not supported in Razor Pages.

  • Filtros de exceção são usados para aplicar políticas globais para exceções sem tratamento que ocorrem antes que qualquer coisa tenha sido gravada no corpo da resposta.Exception filters are used to apply global policies to unhandled exceptions that occur before anything has been written to the response body.

  • Filtros de resposta podem executar código imediatamente antes e depois da execução de resultados de ações individuais.Result filters can run code immediately before and after the execution of individual action results. Eles são executados somente quando o método de ação é executado com êxito.They run only when the action method has executed successfully. Eles são úteis para a lógica que precisa envolver a execução da exibição ou do formatador.They are useful for logic that must surround view or formatter execution.

O diagrama a seguir mostra como os tipos de filtro interagem no pipeline de filtros.The following diagram shows how filter types interact in the filter pipeline.

A solicitação é processada por meio de Filtros de autorização, Filtros de recurso, Model binding, Filtros de ação, Execução de ação e Conversão do resultado de ação, Filtros de exceção, Filtros de resultado e Execução de resultado.

ImplementaçãoImplementation

Os filtros dão suporte a implementações síncronas e assíncronas por meio de diferentes definições de interface.Filters support both synchronous and asynchronous implementations through different interface definitions.

Os filtros síncronos podem executar o código antes (On-Stage-Executing) e depois (On-Stage-Executed) do estágio de pipeline.Synchronous filters can run code before (On-Stage-Executing) and after (On-Stage-Executed) their pipeline stage. Por exemplo, OnActionExecuting é chamado antes que o método de ação seja chamado.For example, OnActionExecuting is called before the action method is called. OnActionExecuted é chamado após o método de ação retornar.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.
    }
}

Os filtros assíncronos definem um 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.
    }
}

No código anterior, o SampleAsyncActionFilter tem um ActionExecutionDelegate (next) que executa o método de ação.In the preceding code, the SampleAsyncActionFilter has an ActionExecutionDelegate (next) that executes the action method. Cada um dos métodos On-Stage-ExecutionAsync usa um FilterType-ExecutionDelegate que executa o estágio de pipeline do filtro.Each of the On-Stage-ExecutionAsync methods take a FilterType-ExecutionDelegate that executes the filter's pipeline stage.

Vários estágios do filtroMultiple filter stages

É possível implementar interfaces para vários estágios do filtro em uma única classe.Interfaces for multiple filter stages can be implemented in a single class. Por exemplo, a classe ActionFilterAttribute implementa IActionFilter, IResultFilter e os respectivos equivalentes assíncronos.For example, the ActionFilterAttribute class implements IActionFilter, IResultFilter, and their async equivalents.

Implemente ou a versão assíncrona ou a versão síncrona de uma interface de filtro, não ambas.Implement either the synchronous or the async version of a filter interface, not both. Primeiro, o tempo de execução verifica se o filtro implementa a interface assíncrona e, se for esse o caso, a chama.The runtime checks first to see if the filter implements the async interface, and if so, it calls that. Caso contrário, ela chama os métodos da interface síncrona.If not, it calls the synchronous interface's method(s). Se as interfaces síncrona e assíncrona forem implementadas em uma classe, somente o método assíncrono será chamado.If both asynchronous and synchronous interfaces are implemented in one class, only the async method is called. Ao usar classes abstratas como ActionFilterAttribute, substitua apenas os métodos síncronos ou o método assíncrono para 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 filtro internosBuilt-in filter attributes

O ASP.NET Core inclui filtros internos baseados em atributos que podem ser organizados em subclasses e personalizados.ASP.NET Core includes built-in attribute-based filters that can be subclassed and customized. Por exemplo, o filtro de resultado a seguir adiciona um cabeçalho à resposta: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);
    }
}

Os atributos permitem que os filtros aceitem argumentos, conforme mostrado no exemplo acima.Attributes allow filters to accept arguments, as shown in the preceding example. Aplique o AddHeaderAttribute a um controlador ou método de ação e especifique o nome e o valor do cabeçalho 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.");
    }

Várias interfaces de filtro têm atributos correspondentes que podem ser usados como classes base para implementações personalizadas.Several of the filter interfaces have corresponding attributes that can be used as base classes for custom implementations.

Atributos de filtro:Filter attributes:

Escopos e ordem de execução dos filtrosFilter scopes and order of execution

Um filtro pode ser adicionado ao pipeline com um de três escopos:A filter can be added to the pipeline at one of three scopes:

  • Usando um atributo em uma ação.Using an attribute on an action.
  • Usando um atributo em um controlador.Using an attribute on a controller.
  • Globalmente para todos os controladores e ações, como mostra o código a seguir: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);
}

O código anterior adiciona três filtros globalmente usando a coleção MvcOptions.Filters.The preceding code adds three filters globally using the MvcOptions.Filters collection.

Ordem padrão de execuçãoDefault order of execution

Quando há vários filtros para um determinado estágio do pipeline, o escopo determina a ordem padrão de execução dos filtros.When there are multiple filters for a particular stage of the pipeline, scope determines the default order of filter execution. Filtros globais circundam filtros de classe, que, por sua vez, circundam filtros de método.Global filters surround class filters, which in turn surround method filters.

Como resultado do aninhamento de filtro, o código posterior dos filtros é executado na ordem inversa do código anterior.As a result of filter nesting, the after code of filters runs in the reverse order of the before code. A sequência de filtro:The filter sequence:

  • O código anterior dos filtros globais.The before code of global filters.
    • O código anterior dos filtros de controlador.The before code of controller filters.
      • O código anterior dos filtros de método de ação.The before code of action method filters.
      • O código posterior dos filtros de método de ação.The after code of action method filters.
    • O código posterior dos filtros de controlador.The after code of controller filters.
  • O código posterior dos filtros globais.The after code of global filters.

O exemplo a seguir ilustra a ordem na qual os métodos de filtro são chamados para filtros de ação síncrona.The following example that illustrates the order in which filter methods are called for synchronous action filters.

SequênciaSequence Escopo do filtroFilter scope Método do filtroFilter method
11 GlobalGlobal OnActionExecuting
22 ControladorController OnActionExecuting
33 MétodoMethod OnActionExecuting
44 MétodoMethod OnActionExecuted
55 ControladorController OnActionExecuted
66 GlobalGlobal OnActionExecuted

Esta sequência mostra:This sequence shows:

  • O filtro de método está aninhado no filtro de controlador.The method filter is nested within the controller filter.
  • O filtro de controlador está aninhado no filtro global.The controller filter is nested within the global filter.

Filtros no nível do controlador e do Razor PageController and Razor Page level filters

Cada controlador que herda da classe base Controller inclui os métodos Controller.OnActionExecuting, Controller.OnActionExecutionAsync e Controller.OnActionExecuted OnActionExecuted.Every controller that inherits from the Controller base class includes Controller.OnActionExecuting, Controller.OnActionExecutionAsync, and Controller.OnActionExecuted OnActionExecuted methods. Estes métodos:These methods:

  • Encapsulam os filtros executados para uma determinada ação.Wrap the filters that run for a given action.
  • OnActionExecuting é chamado antes de qualquer um dos filtros da ação.OnActionExecuting is called before any of the action's filters.
  • OnActionExecuted é chamado após todos os filtros da ação.OnActionExecuted is called after all of the action filters.
  • OnActionExecutionAsync é chamado antes de qualquer um dos filtros da ação.OnActionExecutionAsync is called before any of the action's filters. O código no filtro após next é executado após o método de ação.Code in the filter after next runs after the action method.

Por exemplo, no download de exemplo, MySampleActionFilter é aplicado globalmente na inicialização.For example, in the download sample, MySampleActionFilter is applied globally in startup.

O TestController:The TestController:

  • Aplica SampleActionFilterAttribute ([SampleActionFilter]) à ação FilterTest2:Applies the SampleActionFilterAttribute ([SampleActionFilter]) to the FilterTest2 action:
  • Substitui OnActionExecuting e 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);
    }
}

Navegar até https://localhost:5001/Test/FilterTest2 executa o seguinte código: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, confira Implementar filtros do Razor Page substituindo os métodos de filtro.For Razor Pages, see Implement Razor Page filters by overriding filter methods.

Substituindo a ordem padrãoOverriding the default order

É possível substituir a sequência padrão de execução implementando IOrderedFilter.The default sequence of execution can be overridden by implementing IOrderedFilter. IOrderedFilter expõe a propriedade Order que tem precedência sobre o escopo para determinar a ordem da execução.IOrderedFilter exposes the Order property that takes precedence over scope to determine the order of execution. Um filtro com um valor de Order menor:A filter with a lower Order value:

  • Executa o código anterior antes de um filtro com um valor mais alto de Order.Runs the before code before that of a filter with a higher value of Order.
  • Executa o código posterior após um filtro com um valor mais alto de Order.Runs the after code after that of a filter with a higher Order value.

A propriedade Order pode ser definida com um parâmetro de construtor:The Order property can be set with a constructor parameter:

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

Considere os mesmos filtros de 3 ações mostrados no exemplo anterior.Consider the same 3 action filters shown in the preceding example. Se a propriedade Order do controlador e os filtros globais estiverem definidos como 1 e 2, respectivamente, a ordem de execução será invertida.If the Order property of the controller and global filters is set to 1 and 2 respectively, the order of execution is reversed.

SequênciaSequence Escopo do filtroFilter scope Propriedade OrderOrder property Método do 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

A propriedade Order substitui o escopo ao determinar a ordem na qual os filtros serão executados.The Order property overrides scope when determining the order in which filters run. Os filtros são classificados primeiro pela ordem e o escopo é usado para desempatar.Filters are sorted first by order, then scope is used to break ties. Todos os filtros internos implementam IOrderedFilter e definem o valor de Order padrão como 0.All of the built-in filters implement IOrderedFilter and set the default Order value to 0. Para os filtros internos, o escopo determina a ordem, a menos que você defina Order com um valor diferente de zero.For built-in filters, scope determines order unless Order is set to a non-zero value.

Cancelamento e curto-circuitoCancellation and short-circuiting

O pipeline de filtro pode sofrer um curto-circuito por meio da configuração da propriedade Result no parâmetro ResourceExecutingContext fornecido ao método do filtro.The filter pipeline can be short-circuited by setting the Result property on the ResourceExecutingContext parameter provided to the filter method. Por exemplo, o filtro de Recurso a seguir impede que o resto do pipeline seja executado: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)
    {
    }
}

No código a seguir, os filtros ShortCircuitingResourceFilter e AddHeader têm como destino o método de ação SomeResource.In the following code, both the ShortCircuitingResourceFilter and the AddHeader filter target the SomeResource action method. O ShortCircuitingResourceFilter:The ShortCircuitingResourceFilter:

  • É executado primeiro, porque ele é um filtro de recurso e AddHeader é um filtro de ação.Runs first, because it's a Resource Filter and AddHeader is an Action Filter.
  • Causa um curto-circuito no restante do pipeline.Short-circuits the rest of the pipeline.

Portanto, o filtro AddHeader nunca é executado para a ação SomeResource.Therefore the AddHeader filter never runs for the SomeResource action. Esse comportamento seria o mesmo se os dois filtros fossem aplicados no nível do método de ação, desde que ShortCircuitingResourceFilter fosse executado primeiro.This behavior would be the same if both filters were applied at the action method level, provided the ShortCircuitingResourceFilter ran first. O ShortCircuitingResourceFilter é executado primeiro, devido ao seu tipo de filtro ou pelo uso explícito da propriedade 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.");
    }

Injeção de dependênciaDependency injection

Filtros podem ser adicionados por tipo ou por instância.Filters can be added by type or by instance. Se você adicionar uma instância, ela será usada para cada solicitação.If an instance is added, that instance is used for every request. Se um tipo for adicionado, ele será ativado pelo tipo.If a type is added, it's type-activated. Um filtro ativado por tipo significa:A type-activated filter means:

  • Uma instância é criada para cada solicitação.An instance is created for each request.
  • Qualquer dependência de construtor é preenchida pela injeção de dependência (DI).Any constructor dependencies are populated by dependency injection (DI).

Filtros que são implementados como atributos e adicionados diretamente a classes de controlador ou métodos de ação não podem ter dependências de construtor fornecidas pela DI (injeção de dependência).Filters that are implemented as attributes and added directly to controller classes or action methods cannot have constructor dependencies provided by dependency injection (DI). Dependências de construtor não podem ser fornecidas pela DI porque:Constructor dependencies cannot be provided by DI because:

  • Os atributos precisam ter os parâmetros de construtor fornecidos quando são aplicados.Attributes must have their constructor parameters supplied where they're applied.
  • Essa é uma limitação do funcionamento dos atributos.This is a limitation of how attributes work.

Os filtros a seguir são compatíveis com dependências de construtor fornecidas pela injeção de dependência:The following filters support constructor dependencies provided from DI:

Os filtros anteriores podem ser aplicados a um método de ação ou controlador:The preceding filters can be applied to a controller or action method:

Os agentes estão disponíveis na DI.Loggers are available from DI. No entanto, evite criar e usar filtros apenas para fins de registro em log.However, avoid creating and using filters purely for logging purposes. O registro em log da estrutura interna normalmente fornece o que é necessário para o registro em log.The built-in framework logging typically provides what's needed for logging. Registro em log adicionado aos filtros:Logging added to filters:

  • Deve se concentrar em questões de domínio de negócios ou comportamento específico ao filtro.Should focus on business domain concerns or behavior specific to the filter.
  • Não deve registrar ações ou outros eventos da estrutura.Should not log actions or other framework events. Os filtros internos registram ações e eventos da estrutura.The built in filters log actions and framework events.

ServiceFilterAttributeServiceFilterAttribute

Os tipos de implementação do filtro de serviço são registrados em ConfigureServices.Service filter implementation types are registered in ConfigureServices. Um ServiceFilterAttribute recupera uma instância do filtro da DI.A ServiceFilterAttribute retrieves an instance of the filter from DI.

O código a seguir mostra 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.
    }
}

No código a seguir, AddHeaderResultServiceFilter é adicionado ao contêiner de DI: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);
}

No código a seguir, o atributo ServiceFilter recupera uma instância do filtro AddHeaderResultServiceFilter da DI:In the following code, the ServiceFilter attribute retrieves an instance of the AddHeaderResultServiceFilter filter from DI:

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

Ao usar ServiceFilterAttribute, configurar ServiceFilterAttribute.IsReusable:When using ServiceFilterAttribute, setting ServiceFilterAttribute.IsReusable:

  • Fornece uma dica de que a instância de filtro pode ser reutilizada fora do escopo de solicitação em que foi criada.Provides a hint that the filter instance may be reused outside of the request scope it was created within. O tempo de execução do ASP.NET Core não garante:The ASP.NET Core runtime doesn't guarantee:

    • Que uma única instância do filtro será criada.That a single instance of the filter will be created.
    • Que o filtro não será solicitado novamente no contêiner de DI em algum momento posterior.The filter will not be re-requested from the DI container at some later point.
  • Não deve ser usado com um filtro que dependa dos serviços com um tempo de vida diferente 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 expõe o método CreateInstance para criar uma instância de IFilterMetadata.IFilterFactory exposes the CreateInstance method for creating an IFilterMetadata instance. CreateInstance carrega o tipo especificado na DI.CreateInstance loads the specified type from DI.

TypeFilterAttributeTypeFilterAttribute

O TypeFilterAttribute é semelhante ao ServiceFilterAttribute, mas seu tipo não é resolvido diretamente por meio do contêiner de DI.TypeFilterAttribute is similar to ServiceFilterAttribute, but its type isn't resolved directly from the DI container. Ele cria uma instância do tipo usando Microsoft.Extensions.DependencyInjection.ObjectFactory.It instantiates the type by using Microsoft.Extensions.DependencyInjection.ObjectFactory.

Como os tipos TypeFilterAttribute não são resolvidos diretamente do contêiner de DI:Because TypeFilterAttribute types aren't resolved directly from the DI container:

  • Os tipos referenciados usando o TypeFilterAttribute não precisam ser registrados no contêiner de DI.Types that are referenced using the TypeFilterAttribute don't need to be registered with the DI container. Eles têm suas dependências atendidas pelo contêiner de DI.They do have their dependencies fulfilled by the DI container.
  • Opcionalmente, o TypeFilterAttribute pode aceitar argumentos de construtor para o tipo.TypeFilterAttribute can optionally accept constructor arguments for the type.

Ao usar TypeFilterAttribute, configurar TypeFilterAttribute.IsReusable:When using TypeFilterAttribute, setting TypeFilterAttribute.IsReusable:

  • Fornece uma dica de que a instância de filtro pode ser reutilizada fora do escopo de solicitação em que foi criada.Provides hint that the filter instance may be reused outside of the request scope it was created within. O tempo de execução do ASP.NET Core não fornece garantias de que uma única instância do filtro será criada.The ASP.NET Core runtime provides no guarantees that a single instance of the filter will be created.

  • Não deve ser usado com um filtro que dependa dos serviços com um tempo de vida diferente de singleton.Should not be used with a filter that depends on services with a lifetime other than singleton.

O exemplo a seguir mostra como passar argumentos para um tipo usando 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 autorizaçãoAuthorization filters

Filtros de autorização:Authorization filters:

  • São os primeiros filtros executados no pipeline de filtro.Are the first filters run in the filter pipeline.
  • Controlam o acesso aos métodos de ação.Control access to action methods.
  • Têm um método anterior, mas não têm um método posterior.Have a before method, but no after method.

Filtros de autorização personalizados exigem uma estrutura de autorização personalizada.Custom authorization filters require a custom authorization framework. Prefira configurar as políticas de autorização ou escrever uma política de autorização personalizada em vez de escrever um filtro personalizado.Prefer configuring the authorization policies or writing a custom authorization policy over writing a custom filter. O filtro de autorização interno:The built-in authorization filter:

  • Chama o sistema de autorização.Calls the authorization system.
  • Não autoriza solicitações.Does not authorize requests.

Não gera exceções dentro de filtros de autorização:Do not throw exceptions within authorization filters:

  • A exceção não será tratada.The exception will not be handled.
  • Os filtros de exceção não tratarão a exceção.Exception filters will not handle the exception.

Considere a possibilidade de emitir um desafio quando ocorrer uma exceção em um filtro de autorização.Consider issuing a challenge when an exception occurs in an authorization filter.

Saiba mais sobre Autorização.Learn more about Authorization.

Filtros de recursoResource filters

Filtros de recurso:Resource filters:

Os filtros de recursos são úteis para causar um curto-circuito na maior parte do pipeline.Resource filters are useful to short-circuit most of the pipeline. Por exemplo, um filtro de cache pode evitar o restante do pipeline em uma ocorrência no cache.For example, a caching filter can avoid the rest of the pipeline on a cache hit.

Exemplos de filtros de recurso:Resource filter examples:

Filtros de açãoAction filters

Importante

Os filtros de ação não se aplicam ao Razor Pages.Action filters do not apply to Razor Pages. O Razor Pages é compatível com IPageFilter e IAsyncPageFilter.Razor Pages supports IPageFilter and IAsyncPageFilter . Para obter mais informações, confira Métodos de filtro para Páginas Razor.For more information, see Filter methods for Razor Pages.

Filtros de ação:Action filters:

O código a seguir mostra um exemplo de filtro de ação: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.
    }
}

A classe ActionExecutingContext fornece as seguintes propriedades:The ActionExecutingContext provides the following properties:

  • ActionArguments - permite a leitura das entradas para um método de ação.ActionArguments - enables the inputs to an action method be read.
  • Controller – permite a manipulação da instância do controlador.Controller - enables manipulating the controller instance.
  • Result – configuração de Result execução de curtos-circuitos do método de ação e dos filtros de ação posteriores.Result - setting Result short-circuits execution of the action method and subsequent action filters.

Gerar uma exceção em um método de ação:Throwing an exception in an action method:

  • Impede a execução de filtros subsequentes.Prevents running of subsequent filters.
  • Ao contrário da configuração Result, é tratada como uma falha e não como um resultado bem-sucedido.Unlike setting Result, is treated as a failure instead of a successful result.

A classe ActionExecutedContext fornece Controller e Result, além das seguintes propriedades:The ActionExecutedContext provides Controller and Result plus the following properties:

  • Canceled – verdadeiro se a execução da ação tiver sofrido curto-circuito por outro filtro.Canceled - True if the action execution was short-circuited by another filter.

  • Exception – não será nulo se a ação ou um filtro de ação executado antes tiver apresentado uma exceção.Exception - Non-null if the action or a previously run action filter threw an exception. Definir essa propriedade como nulo:Setting this property to null:

    • Trata efetivamente a exceção.Effectively handles the exception.
    • Result é executado como se tivesse retornado do método de ação.Result is executed as if it was returned from the action method.

Para um IAsyncActionFilter, uma chamada para o ActionExecutionDelegate:For an IAsyncActionFilter, a call to the ActionExecutionDelegate:

  • Executa todos os próximos filtros de ação e o método de ação.Executes any subsequent action filters and the action method.
  • Retorna ActionExecutedContext.Returns ActionExecutedContext.

Para fazer um curto-circuito, atribua Microsoft.AspNetCore.Mvc.Filters.ActionExecutingContext.Result a uma instância de resultado e não chame o next (ActionExecutionDelegate).To short-circuit, assign Microsoft.AspNetCore.Mvc.Filters.ActionExecutingContext.Result to a result instance and don't call next (the ActionExecutionDelegate).

A estrutura fornece um ActionFilterAttribute abstrato que você pode colocar em uma subclasse.The framework provides an abstract ActionFilterAttribute that can be subclassed.

O filtro de ação OnActionExecuting pode ser usado para:The OnActionExecuting action filter can be used to:

  • Validar o estado do modelo.Validate model state.
  • Retornar um erro se o estado for invá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);
        }
    }

O método OnActionExecuted é executado após o método de ação:The OnActionExecuted method runs after the action method:

  • E pode ver e manipular os resultados da ação por meio da propriedade Result.And can see and manipulate the results of the action through the Result property.

  • Canceled é definido como verdadeiro se a execução da ação tiver sofrido curto-circuito por outro filtro.Canceled is set to true if the action execution was short-circuited by another filter.

  • Exception é definido como um valor não nulo se a ação ou um filtro de ação posterior tiver apresentado uma exceção.Exception is set to a non-null value if the action or a subsequent action filter threw an exception. Definindo Exception como nulo:Setting Exception to null:

    • Trata efetivamente uma exceção.Effectively handles an exception.
    • ActionExecutedContext.Result é executado como se fosse retornado normalmente do método de ação.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 exceçãoException filters

Filtros de exceção:Exception filters:

O exemplo de filtro de exceção a seguir usa uma exibição de erro personalizada para mostrar detalhes sobre exceções que ocorrem quando o aplicativo está em desenvolvimento: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;
    }
}

Filtros de exceção:Exception filters:

  • Não têm eventos anteriores nem posteriores.Don't have before and after events.
  • Implementam OnException ou OnExceptionAsync.Implement OnException or OnExceptionAsync.
  • Tratam as exceções sem tratamento que ocorrem no Razor Page ou na criação do controlador, no model binding, nos filtros de ação ou nos métodos de ação.Handle unhandled exceptions that occur in Razor Page or controller creation, model binding, action filters, or action methods.
  • Não capturam as exceções que ocorrem em filtros de recurso, em filtros de resultado ou na execução do resultado de MVC.Do not catch exceptions that occur in resource filters, result filters, or MVC result execution.

Para tratar uma exceção, defina a propriedade ExceptionHandled como true ou grave uma resposta.To handle an exception, set the ExceptionHandled property to true or write a response. Isso interrompe a propagação da exceção.This stops propagation of the exception. Um filtro de exceção não pode transformar uma exceção em "êxito".An exception filter can't turn an exception into a "success". Somente um filtro de ação pode fazer isso.Only an action filter can do that.

Filtros de exceção:Exception filters:

  • São bons para interceptar as exceções que ocorrem nas ações.Are good for trapping exceptions that occur within actions.
  • Não são tão flexíveis quanto o middleware de tratamento de erro.Are not as flexible as error handling middleware.

Prefira o middleware para tratamento de exceção.Prefer middleware for exception handling. Use filtros de exceção apenas quando o tratamento de erros for diferente com base no método de ação chamado.Use exception filters only where error handling differs based on which action method is called. Por exemplo, um aplicativo pode ter métodos de ação para os pontos de extremidade da API e para modos de exibição/HTML.For example, an app might have action methods for both API endpoints and for views/HTML. Os pontos de extremidade da API podem retornar informações de erro como JSON, enquanto as ações baseadas em modo de exibição podem retornar uma página de erro 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 resultadoResult filters

Filtros de resultado:Result filters:

IResultFilter e IAsyncResultFilterIResultFilter and IAsyncResultFilter

O código a seguir mostra um filtro de resultado que adiciona um cabeçalho 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.
    }
}

O tipo de resultado que está sendo executado depende da ação.The kind of result being executed depends on the action. Uma ação que retorna um modo de exibição incluiria todo o processamento de Razor como parte do ViewResult em execução.An action returning a view would include all razor processing as part of the ViewResult being executed. Um método de API pode executar alguma serialização como parte da execução do resultado.An API method might perform some serialization as part of the execution of the result. Saiba mais sobre resultados de açãoLearn more about action results

Filtros de resultado são executados somente para resultados bem-sucedidos – quando a ação ou filtros da ação produzem um resultado de ação.Result filters are only executed for successful results - when the action or action filters produce an action result. Filtros de resultado não são executados quando filtros de exceção tratam uma exceção.Result filters are not executed when exception filters handle an exception.

O método Microsoft.AspNetCore.Mvc.Filters.IResultFilter.OnResultExecuting pode fazer o curto-circuito da execução do resultado da ação e dos filtros de resultados posteriores definindo Microsoft.AspNetCore.Mvc.Filters.ResultExecutingContext.Cancel como 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. Grave no objeto de resposta ao fazer um curto-circuito para evitar gerar uma resposta vazia.Write to the response object when short-circuiting to avoid generating an empty response. A geração de uma exceção em IResultFilter.OnResultExecuting:Throwing an exception in IResultFilter.OnResultExecuting will:

  • Impedir a execução do resultado da ação e dos próximos filtros.Prevent execution of the action result and subsequent filters.
  • Ser tratada como uma falha e não como um resultado com êxito.Be treated as a failure instead of a successful result.

Após a execução do método Microsoft.AspNetCore.Mvc.Filters.IResultFilter.OnResultExecuted:When the Microsoft.AspNetCore.Mvc.Filters.IResultFilter.OnResultExecuted method runs:

  • Provavelmente, a resposta foi enviada ao cliente e não pode ser alterada.The response has likely been sent to the client and cannot be changed.
  • Se uma exceção foi lançada, o corpo da resposta não será enviado.If an exception was thrown, the response body is not sent.

ResultExecutedContext.Canceled será definido como true se a execução do resultado da ação tiver sofrido curto-circuito por outro filtro.ResultExecutedContext.Canceled is set to true if the action result execution was short-circuited by another filter.

ResultExecutedContext.Exception será definido como um valor não nulo se o resultado da ação ou um filtro de resultado posterior tiver gerado uma exceção.ResultExecutedContext.Exception is set to a non-null value if the action result or a subsequent result filter threw an exception. Definir Exception como nulo trata uma exceção com eficiência e impede que ela seja gerada novamente pelo ASP.NET Core posteriormente no pipeline.Setting Exception to null effectively handles an exception and prevents the exception from being rethrown by ASP.NET Core later in the pipeline. Não há nenhuma maneira confiável para gravar dados em uma resposta ao manipular uma exceção em um filtro de resultado.There is no reliable way to write data to a response when handling an exception in a result filter. Se os cabeçalhos tiverem sido liberados para o cliente quando o resultado de uma ação gerar uma exceção, não haverá mecanismo confiável para enviar um código de falha.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.

Para um IAsyncResultFilter, uma chamada para await next no ResultExecutionDelegate executa qualquer filtro de resultado posterior e o resultado da ação.For an IAsyncResultFilter, a call to await next on the ResultExecutionDelegate executes any subsequent result filters and the action result. Para causar um curto-circuito, defina ResultExecutingContext.Cancel como true e não chame o 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;
        }

    }
}

A estrutura fornece um ResultFilterAttribute abstrato que você pode colocar em uma subclasse.The framework provides an abstract ResultFilterAttribute that can be subclassed. A classe AddHeaderAttribute mostrada anteriormente é um exemplo de atributo de filtro de resultado.The AddHeaderAttribute class shown previously is an example of a result filter attribute.

IAlwaysRunResultFilter e IAsyncAlwaysRunResultFilterIAlwaysRunResultFilter and IAsyncAlwaysRunResultFilter

As interfaces IAlwaysRunResultFilter e IAsyncAlwaysRunResultFilter declaram uma implementação IResultFilter que é executada para todos os resultados da ação.The IAlwaysRunResultFilter and IAsyncAlwaysRunResultFilter interfaces declare an IResultFilter implementation that runs for all action results. O filtro é aplicado a todos os resultados da ação, a menos que:The filter is applied to all action results unless:

Filtra o que não é IExceptionFilter, e IAuthorizationFilter não causa curto-circuito em IAlwaysRunResultFilter e IAsyncAlwaysRunResultFilter.Filters other than IExceptionFilter and IAuthorizationFilter don't short-circuit IAlwaysRunResultFilter and IAsyncAlwaysRunResultFilter.

Por exemplo, o filtro a seguir sempre é executado e define o resultado de uma ação (ObjectResult) com um código de status 422 Entidade Não Processável quando ocorre falha na negociação de conteúdo: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. Portanto, uma instância IFilterFactory pode ser usada como uma instância IFilterMetadata em qualquer parte do pipeline de filtro.Therefore, an IFilterFactory instance can be used as an IFilterMetadata instance anywhere in the filter pipeline. Quando o tempo de execução se prepara para invocar o filtro, tenta convertê-lo em um IFilterFactory.When the runtime prepares to invoke the filter, it attempts to cast it to an IFilterFactory. Se essa conversão for bem-sucedida, o método CreateInstance será chamado para criar a instância IFilterMetadata invocada.If that cast succeeds, the CreateInstance method is called to create the IFilterMetadata instance that is invoked. Isso fornece um design flexível, porque o pipeline de filtro preciso não precisa ser definido explicitamente quando o aplicativo é iniciado.This provides a flexible design, since the precise filter pipeline doesn't need to be set explicitly when the app starts.

Implemente IFilterFactory usando implementações personalizadas de atributo como outra abordagem à criação de 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;
        }
    }
}

O código anterior pode ser testado executando o exemplo para download:The preceding code can be tested by running the download sample:

  • Invocar as ferramentas de desenvolvedor F12.Invoke the F12 developer tools.
  • Navegue até https://localhost:5001/Sample/HeaderWithFactoryNavigate to https://localhost:5001/Sample/HeaderWithFactory

As ferramentas de desenvolvedor F12 exibem os seguintes cabeçalhos de resposta adicionados pelo código de exemplo: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

O código anterior cria o cabeçalho de resposta interno: My header.The preceding code creates the internal: My header response header.

IFilterFactory implementado em um atributoIFilterFactory implemented on an attribute

Filtros que implementam IFilterFactory são úteis para filtros que:Filters that implement IFilterFactory are useful for filters that:

  • Não exigem a passagem de parâmetros.Don't require passing parameters.
  • Tenha dependências de construtor que precisem ser atendidas pela DI.Have constructor dependencies that need to be filled by DI.

TypeFilterAttribute implementa IFilterFactory.TypeFilterAttribute implements IFilterFactory. IFilterFactory expõe o método CreateInstance para criar uma instância de IFilterMetadata.IFilterFactory exposes the CreateInstance method for creating an IFilterMetadata instance. CreateInstance carrega o tipo especificado do contêiner de serviços (DI).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.");
        }
    }
}

O código a seguir mostra três abordagens para aplicar o [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");
}

No código anterior, decorar o método com [SampleActionFilter] é a abordagem preferida para aplicar o SampleActionFilter.In the preceding code, decorating the method with [SampleActionFilter] is the preferred approach to applying the SampleActionFilter.

Usando middleware no pipeline de filtrosUsing middleware in the filter pipeline

Filtros de recursos funcionam como middleware, no sentido em que envolvem a execução de tudo o que vem depois no pipeline.Resource filters work like middleware in that they surround the execution of everything that comes later in the pipeline. Mas os filtros diferem do middleware porque fazem parte do ASP.NET Core, o que significa que têm acesso ao contexto e a constructos do 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 o middleware como um filtro, crie um tipo com um método Configure que especifica o middleware para injeção no pipeline de filtros.To use middleware as a filter, create a type with a Configure method that specifies the middleware to inject into the filter pipeline. O exemplo a seguir usa o middleware de localização para estabelecer a cultura atual para uma solicitação: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 executar o 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}");
}

Filtros de middleware são executados no mesmo estágio do pipeline de filtros que filtros de recurso, antes do model binding e depois do restante do pipeline.Middleware filters run at the same stage of the filter pipeline as Resource filters, before model binding and after the rest of the pipeline.

Próximas açõesNext actions