Acceso a HttpContext en ASP.NET Core

HttpContext encapsula toda la información sobre una solicitud y una respuesta HTTP individual. Una instancia de HttpContext se inicializa cuando se recibe una solicitud HTTP. Se puede acceder a la instancia de HttpContext mediante middleware y marcos de aplicaciones, como controladores de API web, Razor Pages, SignalR, gRPC, etc.

Para obtener información sobre el uso de HttpContext con una solicitud y respuesta HTTP, consulte Uso de HttpContext en ASP.NET Core.

Acceso a HttpContext desde Razor Pages

PageModel de Razor Pages expone la propiedad PageModel.HttpContext:

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

        // ...
    }
}

Se puede usar la misma propiedad en la vista de Razor Pages correspondiente.

@page
@model IndexModel

@{
    var message = HttpContext.Request.PathBase;

    // ...
}

Acceso a HttpContext desde una vista de Razor en MVC

Las vistas Razor del patrón de MVC exponen el objeto HttpContext mediante la propiedad RazorPage.Context en la vista. En el ejemplo siguiente se recupera el nombre de usuario actual de una aplicación de intranet mediante Autenticación de Windows:

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

    // ...
}

Acceso a HttpContext desde un controlador

Los controladores exponen la propiedad ControllerBase.HttpContext:

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

        // ...

        return View();
    }
}

Acceso a HttpContext desde API mínimas

Para usar HttpContext desde API mínimas, agregue un parámetro HttpContext:

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

Acceso a HttpContext desde middleware

Para usar HttpContext desde componentes de middleware personalizados, use el parámetro HttpContext pasado al método Invoke o InvokeAsync:

public class MyCustomMiddleware
{
    // ...

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

Acceso a HttpContext desde SignalR

Para usar HttpContext desde SignalR, llame al método GetHttpContext en Hub.Context:

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

        // ...
    }
}

Acceso a HttpContext desde los métodos de gRPC

Para usar HttpContext desde los métodos de gRPC, consulteResolución HttpContext en métodos de gRPC.

Acceso a HttpContext desde componentes personalizados

Para los componentes de otro marco y componentes personalizados que requieren acceso a HttpContext, el enfoque recomendado es registrar una dependencia mediante el contenedor integrado de inserción de dependencias (DI). El contenedor de DI proporciona IHttpContextAccessor a cualquier clase que la declare como una dependencia en sus constructores:

var builder = WebApplication.CreateBuilder(args);

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

En el ejemplo siguiente:

  • UserRepository declara su dependencia de IHttpContextAccessor.
  • La dependencia se proporciona cuando DI resuelve la cadena de dependencias y crea una instancia de 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;

        // ...
    }
}

Acceso a HttpContext desde un subproceso en segundo plano

HttpContext no es seguro para subprocesos. La lectura o escritura de propiedades de HttpContext fuera del procesamiento de una solicitud puede iniciar una excepción NullReferenceException.

Nota

Si la aplicación inicia errores NullReferenceException esporádicos, revise los elementos del código que inician el procesamiento en segundo plano, o bien que lo continúan después de que se complete una solicitud. Busque errores, como la definición de un método de controlador como async void.

Para realizar el trabajo en segundo plano de forma segura con datos HttpContext:

  • Copie los datos necesarios durante el procesamiento de la solicitud.
  • Pase los datos copiados a una tarea en segundo plano.
  • No haga referencia a datos de HttpContext en tareas paralelas. Extraiga los datos necesarios del contexto antes de iniciar las tareas paralelas.

Para evitar código no seguro, no pase nunca HttpContext a un método que realice trabajos en segundo plano. En su lugar, pase los datos que necesite. En el ejemplo siguiente, SendEmail llama a SendEmailCoreAsync para empezar a enviar un correo electrónico. El valor del encabezado X-Correlation-Id se pasa a SendEmailCoreAsync en lugar de a HttpContext. La ejecución de código no espera a que se complete 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 en componentes de Razor (Blazor)

IHttpContextAccessor debe evitarse con la representación interactiva porque no hay un HttpContext válido disponible.

IHttpContextAccessor se puede usar para los componentes que se representan estáticamente en el servidor. Sin embargo, se recomienda evitarlo si es posible.

HttpContextse puede usar como parámetro en cascada solo en componentes raíz representados estáticamente para tareas generales, como inspeccionar y modificar encabezados u otras propiedades del componente App (Components/App.razor). El valor siempre es null para la representación interactiva.

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

En escenarios en los que se requiere el HttpContext en componentes interactivos, se recomienda hacer fluir los datos a través del estado del componente persistente desde el servidor. Para más información, veaOtros escenarios de seguridad de Blazor en ASP.NET Core del lado servidor.

No use IHttpContextAccessor/HttpContext directa o indirectamente en los componentes Razor de las aplicaciones Blazor del lado servidor. Las aplicaciones de Blazor se ejecutan fuera del contexto de la canalización de ASP.NET Core. No se garantiza que HttpContext esté disponible en IHttpContextAccessor, ni tampoco que HttpContext contenga el contexto que ha iniciado la aplicación de Blazor.

El enfoque recomendado para pasar el estado de solicitud a la aplicación de Blazor es a través de parámetros de componente raíz durante la representación inicial de la aplicación. Como alternativa, la aplicación puede copiar los datos en un servicio con ámbito en el evento de ciclo de vida de inicialización del componente raíz para usarlos en toda la aplicación. Para más información, veaOtros escenarios de seguridad de Blazor en ASP.NET Core del lado servidor.

Un aspecto crítico de la seguridad de Blazor del lado servidor es que el usuario asociado a un circuito determinado podría actualizarse en algún momento después de establecer el circuito de Blazor, pero IHttpContextAccessorno se actualiza. Para obtener más información sobre cómo abordar esta situación con servicios personalizados, consulte: ASP.NET Core Blazor en el lado del servidor: escenarios de seguridad adicionales.

HttpContext encapsula toda la información sobre una solicitud y una respuesta HTTP individual. Una instancia de HttpContext se inicializa cuando se recibe una solicitud HTTP. Se puede acceder a la instancia de HttpContext mediante middleware y marcos de aplicaciones, como controladores de API web, Razor Pages, SignalR, gRPC, etc.

Para obtener información sobre el uso de HttpContext con una solicitud y respuesta HTTP, consulte Uso de HttpContext en ASP.NET Core.

Acceso a HttpContext desde Razor Pages

PageModel de Razor Pages expone la propiedad PageModel.HttpContext:

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

        // ...
    }
}

Se puede usar la misma propiedad en la vista de Razor Pages correspondiente.

@page
@model IndexModel

@{
    var message = HttpContext.Request.PathBase;

    // ...
}

Acceso a HttpContext desde una vista de Razor en MVC

Las vistas Razor del patrón de MVC exponen el objeto HttpContext mediante la propiedad RazorPage.Context en la vista. En el ejemplo siguiente se recupera el nombre de usuario actual de una aplicación de intranet mediante Autenticación de Windows:

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

    // ...
}

Acceso a HttpContext desde un controlador

Los controladores exponen la propiedad ControllerBase.HttpContext:

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

        // ...

        return View();
    }
}

Acceso a HttpContext desde middleware

Cuando se trabaja con componentes de middleware personalizados, HttpContext se pasa al método Invoke o InvokeAsync:

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

Acceso a HttpContext desde componentes personalizados

Para los componentes de otro marco y componentes personalizados que requieren acceso a HttpContext, el enfoque recomendado es registrar una dependencia mediante el contenedor integrado de inserción de dependencias (DI). El contenedor de DI proporciona IHttpContextAccessor a cualquier clase que la declare como una dependencia en sus constructores:

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

En el ejemplo siguiente:

  • UserRepository declara su dependencia de IHttpContextAccessor.
  • La dependencia se proporciona cuando DI resuelve la cadena de dependencias y crea una instancia de 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);
    }
}

Acceso a HttpContext desde un subproceso en segundo plano

HttpContext no es seguro para subprocesos. La lectura o escritura de propiedades de HttpContext fuera del procesamiento de una solicitud puede iniciar una excepción NullReferenceException.

Nota

Si la aplicación inicia errores NullReferenceException esporádicos, revise los elementos del código que inician el procesamiento en segundo plano, o bien que lo continúan después de que se complete una solicitud. Busque errores, como la definición de un método de controlador como async void.

Para realizar el trabajo en segundo plano de forma segura con datos HttpContext:

  • Copie los datos necesarios durante el procesamiento de la solicitud.
  • Pase los datos copiados a una tarea en segundo plano.
  • No haga referencia a datos de HttpContext en tareas paralelas. Extraiga los datos necesarios del contexto antes de iniciar las tareas paralelas.

Para evitar código no seguro, no pase nunca HttpContext a un método que realice trabajos en segundo plano. En su lugar, pase los datos que necesite. En el ejemplo siguiente, se llama a SendEmailCore para empezar a enviar un correo electrónico. correlationId se pasa a SendEmailCore, no a HttpContext. La ejecución de código no espera a que se complete 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 en componentes de Razor (Blazor)

IHttpContextAccessor debe evitarse con la representación interactiva porque no hay un HttpContext válido disponible.

IHttpContextAccessor se puede usar para los componentes que se representan estáticamente en el servidor. Sin embargo, se recomienda evitarlo si es posible.

HttpContextse puede usar como parámetro en cascada solo en componentes raíz representados estáticamente para tareas generales, como inspeccionar y modificar encabezados u otras propiedades del componente App (Components/App.razor). El valor siempre es null para la representación interactiva.

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

En escenarios en los que se requiere el HttpContext en componentes interactivos, se recomienda hacer fluir los datos a través del estado del componente persistente desde el servidor. Para más información, veaOtros escenarios de seguridad de Blazor en ASP.NET Core del lado servidor.

No use IHttpContextAccessor/HttpContext directa o indirectamente en los componentes Razor de las aplicaciones Blazor del lado servidor. Las aplicaciones de Blazor se ejecutan fuera del contexto de la canalización de ASP.NET Core. No se garantiza que HttpContext esté disponible en IHttpContextAccessor, ni tampoco que HttpContext contenga el contexto que ha iniciado la aplicación de Blazor.

El enfoque recomendado para pasar el estado de solicitud a la aplicación de Blazor es a través de parámetros de componente raíz durante la representación inicial de la aplicación. Como alternativa, la aplicación puede copiar los datos en un servicio con ámbito en el evento de ciclo de vida de inicialización del componente raíz para usarlos en toda la aplicación. Para más información, veaOtros escenarios de seguridad de Blazor en ASP.NET Core del lado servidor.

Un aspecto crítico de la seguridad de Blazor del lado servidor es que el usuario asociado a un circuito determinado podría actualizarse en algún momento después de establecer el circuito de Blazor, pero IHttpContextAccessorno se actualiza. Para obtener más información sobre cómo abordar esta situación con servicios personalizados, consulte: ASP.NET Core Blazor en el lado del servidor: escenarios de seguridad adicionales.