Condividi tramite


Accesso HttpContext in ASP.NET Core

Nota

Questa non è la versione più recente di questo articolo. Per la versione corrente, vedere la versione .NET 9 di questo articolo.

Avviso

Questa versione di ASP.NET Core non è più supportata. Per altre informazioni, vedere i criteri di supporto di .NET e .NET Core. Per la versione corrente, vedere la versione .NET 9 di questo articolo.

Importante

Queste informazioni si riferiscono a un prodotto non definitive che può essere modificato in modo sostanziale prima che venga rilasciato commercialmente. Microsoft non riconosce alcuna garanzia, espressa o implicita, in merito alle informazioni qui fornite.

Per la versione corrente, vedere la versione .NET 9 di questo articolo.

HttpContext incapsula tutte le informazioni su una singola richiesta e risposta HTTP. Un'istanza HttpContext viene inizializzata quando viene ricevuta una richiesta HTTP. L'istanza HttpContext è accessibile dal middleware e dai framework dell'app, ad esempio controller API Web, Razor Pagine, SignalR, gRPC e altro ancora.

Per informazioni sull'uso HttpContext con una richiesta e una risposta HTTP, vedere Usare HttpContext in ASP.NET Core.

Accesso HttpContext da Razor pagine

Pages RazorPageModel espone la PageModel.HttpContext proprietà :

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

        // ...
    }
}

La stessa proprietà può essere usata nella visualizzazione pagina corrispondente Razor :

@page
@model IndexModel

@{
    var message = HttpContext.Request.PathBase;

    // ...
}

Accesso HttpContext da una Razor visualizzazione in MVC

Razor le visualizzazioni nel modello MVC espongono tramite HttpContext la RazorPage.Context proprietà nella vista. L'esempio seguente recupera il nome utente corrente in un'app Intranet usando l'autenticazione di Windows:

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

    // ...
}

Accesso HttpContext da un controller

I controller espongono la ControllerBase.HttpContext proprietà :

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

        // ...

        return View();
    }
}

Accesso HttpContext da API minime

Per usare HttpContext da API minime, aggiungere un HttpContext parametro:

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

Accesso HttpContext dal middleware

Per usare HttpContext da componenti middleware personalizzati, usare il HttpContext parametro passato nel Invoke metodo o InvokeAsync :

public class MyCustomMiddleware
{
    // ...

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

Accesso HttpContext da SignalR

Per usare HttpContext da SignalR, chiamare il GetHttpContext metodo su Hub.Context:

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

        // ...
    }
}

Accesso HttpContext dai metodi gRPC

Per usare HttpContext i metodi gRPC, vedere Risolvere HttpContext nei metodi gRPC.

Accesso HttpContext da componenti personalizzati

Per altri framework e componenti personalizzati che richiedono l'accesso a HttpContext, l'approccio consigliato consiste nel registrare una dipendenza usando il contenitore di inserimento delle dipendenze predefinito. Il contenitore di inserimento delle dipendenze fornisce a IHttpContextAccessor tutte le classi che la dichiarano come dipendenza nei relativi costruttori:

var builder = WebApplication.CreateBuilder(args);

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

Nell'esempio seguente :

  • UserRepository dichiara la dipendenza da IHttpContextAccessor.
  • La dipendenza viene fornita quando l'inserimento delle dipendenze risolve la catena di dipendenze e crea un'istanza di 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 accesso da un thread in background

HttpContext non è thread-safe. La lettura o scrittura delle proprietà HttpContext di fuori dell'elaborazione di una richiesta può provocare un'eccezione NullReferenceException.

Nota

Se l'app genera errori sporadici NullReferenceException , esaminare parti del codice che avviano l'elaborazione in background o che continuano l'elaborazione dopo il completamento di una richiesta. Cercare errori, ad esempio la definizione di un metodo controller come async void.

Per eseguire in modo sicuro operazioni in background con i HttpContext dati:

  • Copiare i dati necessari durante l'elaborazione della richiesta.
  • Passare i dati copiati a un'attività in background.
  • Non fare riferimento ai HttpContext dati nelle attività parallele. Estrarre i dati necessari dal contesto prima di avviare le attività parallele.

Per evitare codice non sicuro, non passare HttpContext mai a un metodo che esegue il lavoro in background. Passare invece i dati necessari. Nell'esempio seguente viene SendEmail chiamato SendEmailCoreAsync per iniziare a inviare un messaggio di posta elettronica. Il valore dell'intestazione X-Correlation-Id viene passato a anziché a SendEmailCoreAsyncHttpContext. L'esecuzione del codice non attende SendEmailCoreAsync il completamento:

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 nei Razor componenti (Blazor)

Di solito, è consigliabile evitare il rendering interattivo con IHttpContextAccessor perché non sempre è disponibile un HttpContext valido.

IHttpContextAccessor può essere usato per i componenti di cui viene eseguito il rendering statico nel server. Tuttavia, è consigliabile evitarlo, se possibile.

HttpContext può essere usato come parametro a catena solo nei componenti radice sottoposti a rendering statico per attività generali, ad esempio l'ispezione e la modifica di intestazioni o altre proprietà nel App componente (Components/App.razor). Il valore è sempre null per il rendering interattivo.

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

Per gli scenari in cui HttpContext è necessario nei componenti interattivi, è consigliabile fluire i dati tramite lo stato del componente persistente dal server. Per altre informazioni, vedere ASP.NET core server-side e Blazor Web App altri scenari di sicurezza.

Non usare IHttpContextAccessor/HttpContext direttamente o indirettamente nei Razor componenti delle app lato Blazor server. Blazor le app vengono eseguite all'esterno del contesto della pipeline core ASP.NET. Non HttpContext è garantito che sia disponibile all'interno di IHttpContextAccessore HttpContext non sia garantito che contenga il contesto che ha avviato l'app Blazor .

L'approccio consigliato per passare lo stato della richiesta all'app consiste nell'usare Blazor i parametri del componente radice durante il rendering iniziale dell'app. In alternativa, l'app può copiare i dati in un servizio con ambito nell'evento del ciclo di vita di inizializzazione del componente radice da usare nell'app. Per altre informazioni, vedere ASP.NET core server-side e Blazor Web App altri scenari di sicurezza.

Un aspetto critico della sicurezza lato Blazor server è che l'utente collegato a un determinato circuito potrebbe essere aggiornato a un certo punto dopo che il Blazor circuito è stato stabilito, ma IHttpContextAccessornon viene aggiornato. Per altre informazioni sulla gestione di questa situazione con i servizi personalizzati, vedere Blazor Web App e lato server core.

HttpContext incapsula tutte le informazioni su una singola richiesta e risposta HTTP. Un'istanza HttpContext viene inizializzata quando viene ricevuta una richiesta HTTP. L'istanza HttpContext è accessibile dal middleware e dai framework dell'app, ad esempio controller API Web, Razor Pagine, SignalR, gRPC e altro ancora.

Per informazioni sull'uso HttpContext con una richiesta e una risposta HTTP, vedere Usare HttpContext in ASP.NET Core.

Accesso HttpContext da Razor pagine

Pages RazorPageModel espone la PageModel.HttpContext proprietà :

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

        // ...
    }
}

La stessa proprietà può essere usata nella visualizzazione pagina corrispondente Razor :

@page
@model IndexModel

@{
    var message = HttpContext.Request.PathBase;

    // ...
}

Accesso HttpContext da una Razor visualizzazione in MVC

Razor le visualizzazioni nel modello MVC espongono tramite HttpContext la RazorPage.Context proprietà nella vista. L'esempio seguente recupera il nome utente corrente in un'app Intranet usando l'autenticazione di Windows:

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

    // ...
}

Accesso HttpContext da un controller

I controller espongono la ControllerBase.HttpContext proprietà :

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

        // ...

        return View();
    }
}

Accesso HttpContext dal middleware

Quando si utilizzano componenti middleware personalizzati, HttpContext viene passato al Invoke metodo o InvokeAsync :

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

Accesso HttpContext da componenti personalizzati

Per altri framework e componenti personalizzati che richiedono l'accesso a HttpContext, l'approccio consigliato consiste nel registrare una dipendenza usando il contenitore di inserimento delle dipendenze predefinito. Il contenitore di inserimento delle dipendenze fornisce a IHttpContextAccessor tutte le classi che la dichiarano come dipendenza nei relativi costruttori:

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

Nell'esempio seguente :

  • UserRepository dichiara la dipendenza da IHttpContextAccessor.
  • La dipendenza viene fornita quando l'inserimento delle dipendenze risolve la catena di dipendenze e crea un'istanza di 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 accesso da un thread in background

HttpContext non è thread-safe. La lettura o scrittura delle proprietà HttpContext di fuori dell'elaborazione di una richiesta può provocare un'eccezione NullReferenceException.

Nota

Se l'app genera errori sporadici NullReferenceException , esaminare parti del codice che avviano l'elaborazione in background o che continuano l'elaborazione dopo il completamento di una richiesta. Cercare errori, ad esempio la definizione di un metodo controller come async void.

Per eseguire in modo sicuro operazioni in background con i HttpContext dati:

  • Copiare i dati necessari durante l'elaborazione della richiesta.
  • Passare i dati copiati a un'attività in background.
  • Non fare riferimento ai HttpContext dati nelle attività parallele. Estrarre i dati necessari dal contesto prima di avviare le attività parallele.

Per evitare codice non sicuro, non passare mai l'oggetto HttpContext in un metodo che esegue il lavoro in background. Passare invece i dati necessari. Nell'esempio SendEmailCore seguente viene chiamato per iniziare a inviare un messaggio di posta elettronica. L'oggetto correlationId viene passato a , non all'oggetto SendEmailCoreHttpContext. L'esecuzione del codice non attende SendEmailCore il completamento:

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 nei Razor componenti (Blazor)

IHttpContextAccessor in genere è consigliabile evitare il rendering interattivo perché un HttpContext valido non è sempre disponibile.

IHttpContextAccessor può essere usato per i componenti di cui viene eseguito il rendering statico nel server. Tuttavia, è consigliabile evitarlo, se possibile.

HttpContext può essere usato come parametro a catena solo nei componenti radice sottoposti a rendering statico per attività generali, ad esempio l'ispezione e la modifica di intestazioni o altre proprietà nel App componente (Components/App.razor). Il valore è sempre null per il rendering interattivo.

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

Per gli scenari in cui HttpContext è necessario nei componenti interattivi, è consigliabile fluire i dati tramite lo stato del componente persistente dal server. Per altre informazioni, vedere ASP.NET core server-side e Blazor Web App altri scenari di sicurezza.

Non usare IHttpContextAccessor/HttpContext direttamente o indirettamente nei Razor componenti delle app lato Blazor server. Blazor le app vengono eseguite all'esterno del contesto della pipeline core ASP.NET. Non HttpContext è garantito che sia disponibile all'interno di IHttpContextAccessore HttpContext non sia garantito che contenga il contesto che ha avviato l'app Blazor .

L'approccio consigliato per passare lo stato della richiesta all'app consiste nell'usare Blazor i parametri del componente radice durante il rendering iniziale dell'app. In alternativa, l'app può copiare i dati in un servizio con ambito nell'evento del ciclo di vita di inizializzazione del componente radice da usare nell'app. Per altre informazioni, vedere ASP.NET core server-side e Blazor Web App altri scenari di sicurezza.

Un aspetto critico della sicurezza lato Blazor server è che l'utente collegato a un determinato circuito potrebbe essere aggiornato a un certo punto dopo che il Blazor circuito è stato stabilito, ma IHttpContextAccessornon viene aggiornato. Per altre informazioni sulla gestione di questa situazione con i servizi personalizzati, vedere Blazor Web App e lato server core.