Acessar HttpContext no ASP.NET Core

HttpContext encapsula todas as informações específicas sobre uma solicitação e uma resposta HTTP específicas. Uma instância HttpContext é inicializada quando uma solicitação HTTP é recebida. A instância HttpContext pode ser acessada por middleware e estruturas como controladores de API Web, Razor Pages, SignalR, gRPC e muito mais.

Para obter informações sobre como usar HttpContext com uma solicitação e resposta HTTP, consulte Usar HttpContext no ASP.NET Core.

Acessar HttpContext do Razor Pages

O Razor Pages PageModel expõe a propriedade PageModel.HttpContext:

public class IndexModel : PageModel
{
    public void OnGet()
    {
        var message = HttpContext.Request.PathBase;

        // ...
    }
}

A mesma propriedade pode ser usada no Modo de Exibição de Página correspondente de Razor:

@page
@model IndexModel

@{
    var message = HttpContext.Request.PathBase;

    // ...
}

Acessar HttpContext de um modo de exibição Razor no MVC

Razor exibições no padrão MVC expõem o HttpContext por meio da propriedade RazorPage.Context na exibição. O exemplo a seguir recupera o nome de usuário atual em um aplicativo de Intranet usando a Autenticação do Windows:

@{
    var username = Context.User.Identity.Name;

    // ...
}

Acessar HttpContext a partir de um controlador

Os controladores expõem a propriedade ControllerBase.HttpContext:

public class HomeController : Controller
{
    public IActionResult About()
    {
        var pathBase = HttpContext.Request.PathBase;

        // ...

        return View();
    }
}

Acessar HttpContext de APIs mínimas

Para usar HttpContext a partir de APIs mínimas, adicione um parâmetro HttpContext:

app.MapGet("/", (HttpContext context) => context.Response.WriteAsync("Hello World"));

Acessar HttpContext do middleware

Para usar HttpContext a partir de componentes de middleware personalizados, use o parâmetro HttpContext passado para o método Invoke ou InvokeAsync :

public class MyCustomMiddleware
{
    // ...

    public async Task InvokeAsync(HttpContext context)
    {
        // ...
    }
}

Acessar HttpContext a partir de SignalR

Para usar HttpContext a partir de SignalR, chame o método GetHttpContext em Hub.Context:

public class MyHub : Hub
{
    public async Task SendMessage()
    {
        var httpContext = Context.GetHttpContext();

        // ...
    }
}

Acessar HttpContext a partir de métodos gRPC

Para usar HttpContext a partir de métodos gRPC, consulte Resolver HttpContext em métodos gRPC.

Acessar HttpContext a partir de componentes personalizados

Para outras estruturas e componentes personalizados que exigem acesso ao HttpContext, a abordagem recomendada é registrar uma dependência usando o contêiner integrado de DI (injeção de dependência). O contêiner de DI fornece o IHttpContextAccessor para todas as classes que o declaram como uma dependência em seus construtores.

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllersWithViews();
builder.Services.AddHttpContextAccessor();
builder.Services.AddTransient<IUserRepository, UserRepository>();

No exemplo a seguir:

  • o UserRepository declara sua dependência no IHttpContextAccessor.
  • A dependência é fornecida quando a injeção de dependência resolve a cadeia de dependências e cria uma instância do UserRepository.
public class UserRepository : IUserRepository
{
    private readonly IHttpContextAccessor _httpContextAccessor;

    public UserRepository(IHttpContextAccessor httpContextAccessor) =>
        _httpContextAccessor = httpContextAccessor;

    public void LogCurrentUser()
    {
        var username = _httpContextAccessor.HttpContext.User.Identity.Name;

        // ...
    }
}

HttpContext acesso de um thread em segundo plano

HttpContext não é thread-safe. Ler ou gravar propriedades de HttpContext fora do processamento de uma solicitação pode resultar em um NullReferenceException.

Observação

Se seu aplicativo gera erros NullReferenceException esporádicos, revise as partes do código que iniciam o processamento em segundo plano ou que continuam o processamento depois que uma solicitação é concluída. Procure por erros como a definição de um método controlador como async void.

Para executar com segurança o trabalho em segundo plano com os dados de HttpContext:

  • Copie os dados necessários durante o processamento da solicitação.
  • Passe os dados copiados para uma tarefa em segundo plano.
  • Não referencie dados HttpContext em tarefas paralelas. Extraia os dados necessários do contexto antes de iniciar as tarefas paralelas.

Para evitar o código não seguro, nunca passe o HttpContext para um método que realiza o trabalho em segundo plano. Em vez disso, passe os dados necessários. Em vez disso, passe os dados necessários. No exemplo a seguir, SendEmail chama SendEmailCoreAsync para começar a enviar um email. O valor do cabeçalho de X-Correlation-Id é passado para SendEmailCoreAsync em vez de HttpContext. A execução do código não aguarda a conclusão de SendEmailCoreAsync:

public class EmailController : Controller
{
    public IActionResult SendEmail(string email)
    {
        var correlationId = HttpContext.Request.Headers["X-Correlation-Id"].ToString();

        _ = SendEmailCoreAsync(correlationId);

        return View();
    }

    private async Task SendEmailCoreAsync(string correlationId)
    {
        // ...
    }
}

IHttpContextAccessor/HttpContext em componentes Razor (Blazor)

IHttpContextAccessor deve ser evitado com a renderização interativa porque não há um HttpContext disponível válido.

IHttpContextAccessor pode ser usado para componentes que são renderizados estaticamente no servidor. No entanto, recomendamos evitá-lo, se possível.

HttpContext pode ser usado como um parâmetro em cascata apenas em componentes raiz renderizados estaticamente para tarefas gerais, como inspecionar e modificar cabeçalhos ou outras propriedades no componente App (Components/App.razor). O valor é sempre null para renderização interativa.

[CascadingParameter]
public HttpContext? HttpContext { get; set; }

Para cenários em que o componente HttpContext é necessário em componentes interativos, recomendamos fluir os dados por meio do estado de componente persistente do servidor. Para obter mais informações, confira Cenários de segurança adicionais Blazor do ASP.NET Core do lado do servidor.

Não use IHttpContextAccessor/HttpContext direta ou indiretamente nos componentes Razor dos aplicativos Blazor do lado do servidor. Os aplicativos Blazor são executados fora do contexto do pipeline ASP.NET Core. Não há garantia de que o HttpContext esteja disponível no IHttpContextAccessor e não há garantia de que o HttpContext mantenha o contexto que iniciou o aplicativo Blazor.

A abordagem recomendada para passar o estado da solicitação para o aplicativo Blazor é por meio de parâmetros de componente raiz durante a renderização inicial do aplicativo. Como alternativa, o aplicativo pode copiar os dados para um serviço com escopo no evento de ciclo de vida de inicialização do componente raiz para uso em todo o aplicativo. Para obter mais informações, confira Cenários de segurança adicionais Blazor do ASP.NET Core do lado do servidor.

Um aspecto crítico da segurança de Blazor do lado do servidor é que o usuário anexado a determinado circuito pode ser atualizado em algum momento após o circuito Blazor ser estabelecido, mas o IHttpContextAccessornão ser atualizado. Para obter mais informações sobre como lidar com essa situação usando serviços personalizados, confira Outros cenários de segurança do ASP.NET Core Blazor do servidor.

HttpContext encapsula todas as informações específicas sobre uma solicitação e uma resposta HTTP específicas. Uma instância HttpContext é inicializada quando uma solicitação HTTP é recebida. A instância HttpContext pode ser acessada por middleware e estruturas como controladores de API Web, Razor Pages, SignalR, gRPC e muito mais.

Para obter informações sobre como usar HttpContext com uma solicitação e resposta HTTP, consulte Usar HttpContext no ASP.NET Core.

Acessar HttpContext do Razor Pages

O Razor Pages PageModel expõe a propriedade PageModel.HttpContext:

public class IndexModel : PageModel
{
    public void OnGet()
    {
        var message = HttpContext.Request.PathBase;

        // ...
    }
}

A mesma propriedade pode ser usada no Modo de Exibição de Página correspondente de Razor:

@page
@model IndexModel

@{
    var message = HttpContext.Request.PathBase;

    // ...
}

Acessar HttpContext de um modo de exibição Razor no MVC

Razor exibições no padrão MVC expõem o HttpContext por meio da propriedade RazorPage.Context na exibição. O exemplo a seguir recupera o nome de usuário atual em um aplicativo de Intranet usando a Autenticação do Windows:

@{
    var username = Context.User.Identity.Name;

    // ...
}

Acessar HttpContext a partir de um controlador

Os controladores expõem a propriedade ControllerBase.HttpContext:

public class HomeController : Controller
{
    public IActionResult About()
    {
        var pathBase = HttpContext.Request.PathBase;

        // ...

        return View();
    }
}

Acessar HttpContext do middleware

Ao trabalhar com componentes de middleware personalizados, HttpContext é passado para o método Invoke ou InvokeAsync:

public class MyCustomMiddleware
{
    public Task InvokeAsync(HttpContext context)
    {
        // ...
    }
}

Acessar HttpContext a partir de componentes personalizados

Para outras estruturas e componentes personalizados que exigem acesso ao HttpContext, a abordagem recomendada é registrar uma dependência usando o contêiner integrado de DI (injeção de dependência). O contêiner de DI fornece o IHttpContextAccessor para todas as classes que o declaram como uma dependência em seus construtores.

public void ConfigureServices(IServiceCollection services)
{
     services.AddControllersWithViews();
     services.AddHttpContextAccessor();
     services.AddTransient<IUserRepository, UserRepository>();
}

No exemplo a seguir:

  • o UserRepository declara sua dependência no IHttpContextAccessor.
  • A dependência é fornecida quando a injeção de dependência resolve a cadeia de dependências e cria uma instância do UserRepository.
public class UserRepository : IUserRepository
{
    private readonly IHttpContextAccessor _httpContextAccessor;

    public UserRepository(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    public void LogCurrentUser()
    {
        var username = _httpContextAccessor.HttpContext.User.Identity.Name;
        service.LogAccessRequest(username);
    }
}

HttpContext acesso de um thread em segundo plano

HttpContext não é thread-safe. Ler ou gravar propriedades de HttpContext fora do processamento de uma solicitação pode resultar em um NullReferenceException.

Observação

Se seu aplicativo gera erros NullReferenceException esporádicos, revise as partes do código que iniciam o processamento em segundo plano ou que continuam o processamento depois que uma solicitação é concluída. Procure por erros como a definição de um método controlador como async void.

Para executar com segurança o trabalho em segundo plano com os dados de HttpContext:

  • Copie os dados necessários durante o processamento da solicitação.
  • Passe os dados copiados para uma tarefa em segundo plano.
  • Não referencie dados HttpContext em tarefas paralelas. Extraia os dados necessários do contexto antes de iniciar as tarefas paralelas.

Para evitar o código não seguro, nunca passe o HttpContext para um método que realiza o trabalho em segundo plano. Em vez disso, passe os dados necessários. No exemplo a seguir, SendEmailCore é chamado para começar a enviar um email. O correlationId é passado para SendEmailCore, não para HttpContext. A execução do código não aguarda a conclusão de SendEmailCore:

public class EmailController : Controller
{
    public IActionResult SendEmail(string email)
    {
        var correlationId = HttpContext.Request.Headers["x-correlation-id"].ToString();

        _ = SendEmailCore(correlationId);

        return View();
    }

    private async Task SendEmailCore(string correlationId)
    {
        // ...
    }
}

IHttpContextAccessor/HttpContext em componentes Razor (Blazor)

IHttpContextAccessor deve ser evitado com a renderização interativa porque não há um HttpContext disponível válido.

IHttpContextAccessor pode ser usado para componentes que são renderizados estaticamente no servidor. No entanto, recomendamos evitá-lo, se possível.

HttpContext pode ser usado como um parâmetro em cascata apenas em componentes raiz renderizados estaticamente para tarefas gerais, como inspecionar e modificar cabeçalhos ou outras propriedades no componente App (Components/App.razor). O valor é sempre null para renderização interativa.

[CascadingParameter]
public HttpContext? HttpContext { get; set; }

Para cenários em que o componente HttpContext é necessário em componentes interativos, recomendamos fluir os dados por meio do estado de componente persistente do servidor. Para obter mais informações, confira Cenários de segurança adicionais Blazor do ASP.NET Core do lado do servidor.

Não use IHttpContextAccessor/HttpContext direta ou indiretamente nos componentes Razor dos aplicativos Blazor do lado do servidor. Os aplicativos Blazor são executados fora do contexto do pipeline ASP.NET Core. Não há garantia de que o HttpContext esteja disponível no IHttpContextAccessor e não há garantia de que o HttpContext mantenha o contexto que iniciou o aplicativo Blazor.

A abordagem recomendada para passar o estado da solicitação para o aplicativo Blazor é por meio de parâmetros de componente raiz durante a renderização inicial do aplicativo. Como alternativa, o aplicativo pode copiar os dados para um serviço com escopo no evento de ciclo de vida de inicialização do componente raiz para uso em todo o aplicativo. Para obter mais informações, confira Cenários de segurança adicionais Blazor do ASP.NET Core do lado do servidor.

Um aspecto crítico da segurança de Blazor do lado do servidor é que o usuário anexado a determinado circuito pode ser atualizado em algum momento após o circuito Blazor ser estabelecido, mas o IHttpContextAccessornão ser atualizado. Para obter mais informações sobre como lidar com essa situação usando serviços personalizados, confira Outros cenários de segurança do ASP.NET Core Blazor do servidor.