Доступ к HttpContext в ASP.NET Core

Примечание.

Это не последняя версия этой статьи. В текущей версии см. версию .NET 10 этой статьи.

Предупреждение

Эта версия ASP.NET Core больше не поддерживается. Дополнительные сведения см. в политике поддержки .NET и .NET Core. В текущей версии см. версию .NET 10 этой статьи.

HttpContext инкапсулирует все сведения об одном HTTP-запросе и ответе. Экземпляр HttpContext инициализируется при получении HTTP-запроса. Экземпляр HttpContext доступен через промежуточное ПО и платформы приложений, такие как контроллеры Web API, Razor Pages, SignalR, gRPC и многое другое.

Сведения об использовании HttpContext с HTTP-запросом и ответом см. в разделе Use HttpContext в ASP.NET Core.

Доступ к HttpContext из Razor Pages

Класс Razor Pages PageModel предоставляет свойство HttpContext.

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

        // ...
    }
}

Это свойство можно использовать в соответствующем Razor представлении страницы:

@page
@model IndexModel

@{
    var message = HttpContext.Request.PathBase;
    
    // ...
}

Доступ к HttpContext из Razor представления в MVC

Представления Razor в шаблоне MVC предоставляют HttpContext через свойство Context в представлении. В следующем примере извлекается текущее имя пользователя в приложении интрасети с помощью проверки подлинности Windows:

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

Доступ к HttpContext из контроллера

Контроллеры предоставляют свойство HttpContext.

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

        // ...

        return View();
    }
}

Доступ к HttpContext из минимальных API

Чтобы использовать HttpContext из Minimal APIs:

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

Доступ к HttpContext из промежуточного ПО

Чтобы использовать HttpContext из пользовательских промежуточных компонентов, передайте параметр в метод Invoke или InvokeAsync:

public class MyCustomMiddleware
{
    // ...

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

Доступ к HttpContext из SignalR

Чтобы использовать HttpContext с SignalR, вызовите GetHttpContext на Context.

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

        // ...
    }
}

Доступ к HttpContext из методов gRPC

Чтобы использовать HttpContext из методов gRPC, см. раздел Разрешение HttpContext в методах gRPC.

Доступ к HttpContext из пользовательских компонентов

Для других платформ и пользовательских компонентов, которым требуется доступHttpContext, рекомендуется зарегистрировать зависимость с помощью встроенного контейнера внедрения зависимостей (DI). Контейнер DI предоставляет IHttpContextAccessor всем классам, объявляющим его в качестве зависимости в своих конструкторах.

var builder = WebApplication.CreateBuilder(args);

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

В следующем примере :

  • Экземпляр UserRepository объявляет свою зависимость от IHttpContextAccessor.
  • Зависимость предоставляется, когда 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;

        // ...
    }
}
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 из фонового потока

HttpContext не является потокобезопасным. Чтение или запись свойств HttpContext вне обработки запроса может привести к ошибке NullReferenceException .

Примечание.

Если приложение создает нерегулярные NullReferenceException ошибки, просмотрите части кода, начинающего фоновую обработку или код, продолжающий обработку после завершения запроса. Ищите ошибки, такие как определение метода контроллера как async void.

Для безопасной работы с данными HttpContext в фоновом режиме:

  • Скопируйте необходимые данные во время обработки запроса.
  • Передайте скопированные данные в фоновую задачу.
  • Не ссылайтесь на HttpContext данные в параллельных задачах. Перед запуском параллельных задач извлеките необходимые данные из контекста.

Чтобы избежать небезопасного кода, никогда не передавайте HttpContext в метод, который выполняет фоновую работу. Вместо этого передайте нужные данные.

В следующем примере метод SendEmail вызывает метод SendEmailCoreAsync, чтобы начать отправку электронного письма. Значение заголовка X-Correlation-Id передается в SendEmailCoreAsync, а не в HttpContext. Код не ждет завершения выполнения метода 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)
    {
        // ...
    }
}

В следующем примере SendEmailCore метод вызывается для начала отправки сообщения электронной почты. Параметр correlationId передается в SendEmailCore, а не в HttpContext. Код не ждет завершения выполнения метода 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 в Razor компонентах (Blazor)

Если вы хотите получить доступ к IHttpContextAccessor или HttpContext в компонентах Razor (приложения Blazor), см. раздел IHttpContextAccessor/HttpContext в приложениях ASP.NET Core Blazor /.