Accéder à HttpContext dans ASP.NET Core

HttpContext encapsule toutes les informations sur une requête et une réponse HTTP individuelles. Une instance HttpContext est initialisée lorsqu’une requête HTTP est reçue. L’instance HttpContext est accessible par les intergiciels et frameworks d’application comme les contrôleurs d’API web, Razor Pages, SignalR, gRPC, etc.

Pour plus d’informations sur l’utilisation de HttpContext avec une requête et une réponse HTTP, consultez Utiliser HttpContext dans ASP.NET Core.

Accéder à HttpContext à partir de Razor Pages

PageModel de Razor Pages expose la propriété PageModel.HttpContext :

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

        // ...
    }
}

La même propriété peut être utilisée dans la vue de page Razor correspondante :

@page
@model IndexModel

@{
    var message = HttpContext.Request.PathBase;

    // ...
}

Accéder à HttpContext à partir d’une vue Razor dans le modèle-vue-contrôleur

Les vues Razor dans le modèle MVC exposent HttpContext via la propriété RazorPage.Context sur la vue. L’exemple suivant récupère le nom d’utilisateur actif dans une application intranet en utilisant l’authentification Windows :

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

    // ...
}

Accéder à HttpContext à partir d’un contrôleur

Les contrôleurs exposent la propriété ControllerBase.HttpContext :

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

        // ...

        return View();
    }
}

Accès à HttpContext à partir d’API minimales

Pour utiliser HttpContext à partir d’API minimales, ajoutez un paramètre HttpContext :

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

Accéder à HttpContext à partir d’un intergiciel

Pour utiliser HttpContext à partir de composants d’intergiciel personnalisés, utilisez le paramètre HttpContext passé à la méthode Invoke ou InvokeAsync :

public class MyCustomMiddleware
{
    // ...

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

Accès à HttpContext à partir de SignalR

Pour utiliser HttpContext à partir de SignalR, appelez la méthode GetHttpContext sur Hub.Context :

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

        // ...
    }
}

Accès à HttpContext à partir de méthodes gRPC

Pour utiliser HttpContext à partir de méthodes gRPC, consultez Résoudre HttpContext dans les méthodes gRPC.

Accéder à HttpContext à partir de composants personnalisés

Pour les autres infrastructures et les composants personnalisés qui requièrent l’accès à HttpContext, l’approche recommandée consiste à inscrire une dépendance à l’aide du conteneur d’injection de dépendances (DI) intégré. Le conteneur d’injection de dépendances fournit le IHttpContextAccessor à toutes les classes qui le déclarent en tant que dépendance dans leurs constructeurs :

var builder = WebApplication.CreateBuilder(args);

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

Dans l’exemple suivant :

  • UserRepository déclare sa dépendance par rapport à IHttpContextAccessor.
  • Il y a dépendance lorsque l’injection de dépendances résout la chaîne de dépendance et crée une instance 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;

        // ...
    }
}

Accès de HttpContext à partir d’un thread en arrière-plan

HttpContext n’est pas thread-safe. La lecture ou l’écriture de propriétés de HttpContext en dehors du traitement d’une requête peut entraîner une exception NullReferenceException.

Notes

Si votre application génère des erreurs NullReferenceException sporadiques, examinez les parties du code qui démarrent le traitement en arrière-plan ou qui continue le traitement après qu’une requête a abouti. Recherchez des erreurs comme une méthode de contrôleur qui serait définie en tant que async void.

Pour effectuer un travail en arrière-plan en toute sécurité avec des données HttpContext :

  • Copiez les données nécessaires pendant le traitement de la requête.
  • Transmettez les données copiées à une tâche en arrière-plan.
  • Ne référencez pas les données HttpContext dans les tâches parallèles. Extrayez les données nécessaires à partir du contexte avant de commencer les tâches parallèles.

Pour éviter un code non sécurisé, ne transmettez jamais HttpContext dans une méthode qui effectue un travail en arrière-plan. Transmettez les données requises à la place. Dans l’exemple suivant, SendEmail appelle SendEmailCoreAsync pour commencer à envoyer un e-mail. La valeur de l’en-tête X-Correlation-Id est passée à SendEmailCoreAsync au lieu de HttpContext. L’exécution du code n’attend pas que SendEmailCoreAsync se termine :

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)
    {
        // ...
    }
}

Éviter IHttpContextAccessor/HttpContext dans les composants Razor

IHttpContextAccessor doit être évité avec le rendu interactif, car il n’existe pas de HttpContext valide disponible.

IHttpContextAccessor peut être utilisé pour les composants rendus statiquement sur le serveur. Toutefois, nous vous recommandons de l’éviter si possible.

HttpContext peut être utilisé comme paramètre en cascade uniquement dans les composants racines rendus statiquement pour les tâches générales, telles que l’inspection et la modification d’en-têtes ou d’autres propriétés dans le composant App (Components/App.razor). La valeur est toujours null pour le rendu interactif.

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

Pour les scénarios où HttpContext est requis dans les composants interactifs, nous vous recommandons de transmettre les données via l’état du composant persistant à partir du serveur. Pour plus d’informations, consultez Autres scénarios de sécurité ASP.NET Core Blazor côté serveur.

N’utilisez pas IHttpContextAccessor/HttpContext directement ou indirectement dans les composants Razor des applications Blazor côté serveur. Les applications Blazor s’exécutent en dehors du contexte de pipeline ASP.NET Core. Le HttpContext n’est pas garanti d’être disponible dans le IHttpContextAccessor, et HttpContext n’est pas garanti de conserver le contexte qui a démarré l’application Blazor.

L’approche recommandée pour passer l’état de la requête à l’application Blazor consiste à utiliser les paramètres de composant racine pendant le rendu initial de l’application. L’application peut également copier les données dans un service délimité dans l’événement de cycle de vie d’initialisation du composant racine pour une utilisation dans l’application. Pour plus d’informations, consultez Autres scénarios de sécurité ASP.NET Core Blazor côté serveur.

Un aspect essentiel de la sécurité de Blazor côté serveur réside dans le fait que l’utilisateur attaché à un circuit donné peut être mis à jour à un moment donné après l’établissement du circuit Blazor, mais que le IHttpContextAccessorn’est pas mis à jour. Pour plus d’informations sur la résolution de cette situation avec des services personnalisés, consultez Autres scénarios de sécurité ASP.NET Core Blazor côté serveur.

HttpContext encapsule toutes les informations sur une requête et une réponse HTTP individuelles. Une instance HttpContext est initialisée lorsqu’une requête HTTP est reçue. L’instance HttpContext est accessible par les intergiciels et frameworks d’application comme les contrôleurs d’API web, Razor Pages, SignalR, gRPC, etc.

Pour plus d’informations sur l’utilisation de HttpContext avec une requête et une réponse HTTP, consultez Utiliser HttpContext dans ASP.NET Core.

Accéder à HttpContext à partir de Razor Pages

PageModel de Razor Pages expose la propriété PageModel.HttpContext :

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

        // ...
    }
}

La même propriété peut être utilisée dans la vue de page Razor correspondante :

@page
@model IndexModel

@{
    var message = HttpContext.Request.PathBase;

    // ...
}

Accéder à HttpContext à partir d’une vue Razor dans le modèle-vue-contrôleur

Les vues Razor dans le modèle MVC exposent HttpContext via la propriété RazorPage.Context sur la vue. L’exemple suivant récupère le nom d’utilisateur actif dans une application intranet en utilisant l’authentification Windows :

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

    // ...
}

Accéder à HttpContext à partir d’un contrôleur

Les contrôleurs exposent la propriété ControllerBase.HttpContext :

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

        // ...

        return View();
    }
}

Accéder à HttpContext à partir d’un intergiciel

Lorsque vous travaillez avec des composants d’intergiciel personnalisés, HttpContext est transmis à la méthode Invoke ou InvokeAsync :

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

Accéder à HttpContext à partir de composants personnalisés

Pour les autres infrastructures et les composants personnalisés qui requièrent l’accès à HttpContext, l’approche recommandée consiste à inscrire une dépendance à l’aide du conteneur d’injection de dépendances (DI) intégré. Le conteneur d’injection de dépendances fournit le IHttpContextAccessor à toutes les classes qui le déclarent en tant que dépendance dans leurs constructeurs :

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

Dans l’exemple suivant :

  • UserRepository déclare sa dépendance par rapport à IHttpContextAccessor.
  • Il y a dépendance lorsque l’injection de dépendances résout la chaîne de dépendance et crée une instance 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);
    }
}

Accès de HttpContext à partir d’un thread en arrière-plan

HttpContext n’est pas thread-safe. La lecture ou l’écriture de propriétés de HttpContext en dehors du traitement d’une requête peut entraîner une exception NullReferenceException.

Notes

Si votre application génère des erreurs NullReferenceException sporadiques, examinez les parties du code qui démarrent le traitement en arrière-plan ou qui continue le traitement après qu’une requête a abouti. Recherchez des erreurs comme une méthode de contrôleur qui serait définie en tant que async void.

Pour effectuer un travail en arrière-plan en toute sécurité avec des données HttpContext :

  • Copiez les données nécessaires pendant le traitement de la requête.
  • Transmettez les données copiées à une tâche en arrière-plan.
  • Ne référencez pas les données HttpContext dans les tâches parallèles. Extrayez les données nécessaires à partir du contexte avant de commencer les tâches parallèles.

Pour éviter un code non sécurisé, ne transmettez jamais HttpContext dans une méthode qui effectue un travail en arrière-plan. Transmettez les données requises à la place. Dans l’exemple suivant, SendEmailCore est appelé pour commencer à envoyer un e-mail. correlationId est passé à SendEmailCore, et non à HttpContext. L’exécution du code n’attend pas que SendEmailCore se termine :

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)
    {
        // ...
    }
}

Éviter IHttpContextAccessor/HttpContext dans les composants Razor

IHttpContextAccessor doit être évité avec le rendu interactif, car il n’existe pas de HttpContext valide disponible.

IHttpContextAccessor peut être utilisé pour les composants rendus statiquement sur le serveur. Toutefois, nous vous recommandons de l’éviter si possible.

HttpContext peut être utilisé comme paramètre en cascade uniquement dans les composants racines rendus statiquement pour les tâches générales, telles que l’inspection et la modification d’en-têtes ou d’autres propriétés dans le composant App (Components/App.razor). La valeur est toujours null pour le rendu interactif.

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

Pour les scénarios où HttpContext est requis dans les composants interactifs, nous vous recommandons de transmettre les données via l’état du composant persistant à partir du serveur. Pour plus d’informations, consultez Autres scénarios de sécurité ASP.NET Core Blazor côté serveur.

N’utilisez pas IHttpContextAccessor/HttpContext directement ou indirectement dans les composants Razor des applications Blazor côté serveur. Les applications Blazor s’exécutent en dehors du contexte de pipeline ASP.NET Core. Le HttpContext n’est pas garanti d’être disponible dans le IHttpContextAccessor, et HttpContext n’est pas garanti de conserver le contexte qui a démarré l’application Blazor.

L’approche recommandée pour passer l’état de la requête à l’application Blazor consiste à utiliser les paramètres de composant racine pendant le rendu initial de l’application. L’application peut également copier les données dans un service délimité dans l’événement de cycle de vie d’initialisation du composant racine pour une utilisation dans l’application. Pour plus d’informations, consultez Autres scénarios de sécurité ASP.NET Core Blazor côté serveur.

Un aspect essentiel de la sécurité de Blazor côté serveur réside dans le fait que l’utilisateur attaché à un circuit donné peut être mis à jour à un moment donné après l’établissement du circuit Blazor, mais que le IHttpContextAccessorn’est pas mis à jour. Pour plus d’informations sur la résolution de cette situation avec des services personnalisés, consultez Autres scénarios de sécurité ASP.NET Core Blazor côté serveur.