Поделиться через


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

Примечание.

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

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

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

Внимание

Эта информация относится к предварительному выпуску продукта, который может быть существенно изменен до его коммерческого выпуска. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.

В текущем выпуске см . версию .NET 8 этой статьи.

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

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

Доступ HttpContext из Razor страниц

Класс Razor Pages PageModel предоставляет свойство 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 через свойство RazorPage.Context в представлении. В следующем примере имя текущего пользователя в приложении интрасети извлекается с использованием проверки подлинности Windows:

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

    // ...
}

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

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

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

        // ...

        return View();
    }
}

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

Для использования HttpContext через минимальные API, добавьте параметр HttpContext:

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

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

Для использования HttpContext из пользовательского ПО промежуточного слоя используйте параметр HttpContext, передаваемый в метод Invoke или InvokeAsync:

public class MyCustomMiddleware
{
    // ...

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

Доступ HttpContext из SignalR

Чтобы использовать HttpContext из SignalR, вызовите метод GetHttpContext для Hub.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>();

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

  • 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;

        // ...
    }
}

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

IHttpContextAccessor/HttpContext в Razor компонентах (Blazor)

IHttpContextAccessor необходимо избежать интерактивной отрисовки, так как не существует допустимой HttpContext возможности.

IHttpContextAccessor можно использовать для компонентов, которые статически отрисовываются на сервере. Тем не менее, мы рекомендуем избегать его, если это возможно.

HttpContext можно использовать в качестве каскадного параметра только в статически отрисованных корневых компонентах для общих задач, таких как проверка и изменение заголовков или других свойств компонента App (Components/App.razor). Значение всегда null предназначено для интерактивной отрисовки.

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

В сценариях, где HttpContext требуется в интерактивных компонентах, рекомендуется передавать данные через постоянное состояние компонента с сервера. Дополнительные сведения см . на стороне сервера ASP.NET Основных Blazor дополнительных сценариев безопасности.

Не используйте IHttpContextAccessor/HttpContext непосредственно или косвенно в Razor компонентах серверных Blazor приложений. Blazor приложения выполняются вне контекста конвейера ASP.NET Core. Он HttpContext не гарантируется, что он доступен в пределах приложения IHttpContextAccessorи HttpContext не гарантируется, что он будет содержать контекст, который запустил Blazor приложение.

Рекомендуемый подход для передачи состояния Blazor запроса приложению осуществляется через параметры корневого компонента во время первоначальной отрисовки приложения. Кроме того, приложение может скопировать данные в службу с областью действия в событии жизненного цикла инициализации корневого компонента для использования в приложении. Дополнительные сведения см . на стороне сервера ASP.NET Основных Blazor дополнительных сценариев безопасности.

Критически важный аспект безопасности на стороне Blazor сервера заключается в том, что пользователь, подключенный к заданному каналу, может быть обновлен в какой-то момент после Blazor установки канала, но IHttpContextAccessorне обновляется. Дополнительные сведения об устранении этой ситуации с пользовательскими службами см. в дополнительных сценариях безопасности на стороне сервера ASP.NET CoreBlazor.

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

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

Доступ HttpContext из Razor страниц

Класс Razor Pages PageModel предоставляет свойство 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 через свойство RazorPage.Context в представлении. В следующем примере имя текущего пользователя в приложении интрасети извлекается с использованием проверки подлинности Windows:

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

    // ...
}

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

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

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

        // ...

        return View();
    }
}

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

При работе с компонентами пользовательского ПО промежуточного слоя HttpContext передается в метод Invoke или InvokeAsync.

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

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

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

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;
        service.LogAccessRequest(username);
    }
}

HttpContext доступ из фонового потока

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

Примечание.

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

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

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

Чтобы избежать небезопасного кода, никогда не передавайте HttpContext в метод, который выполняет фоновую работу. Вместо этого передайте нужные данные. В приведенном ниже примере метод 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 возможности.

IHttpContextAccessor можно использовать для компонентов, которые статически отрисовываются на сервере. Тем не менее, мы рекомендуем избегать его, если это возможно.

HttpContext можно использовать в качестве каскадного параметра только в статически отрисованных корневых компонентах для общих задач, таких как проверка и изменение заголовков или других свойств компонента App (Components/App.razor). Значение всегда null предназначено для интерактивной отрисовки.

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

В сценариях, где HttpContext требуется в интерактивных компонентах, рекомендуется передавать данные через постоянное состояние компонента с сервера. Дополнительные сведения см . на стороне сервера ASP.NET Основных Blazor дополнительных сценариев безопасности.

Не используйте IHttpContextAccessor/HttpContext непосредственно или косвенно в Razor компонентах серверных Blazor приложений. Blazor приложения выполняются вне контекста конвейера ASP.NET Core. Он HttpContext не гарантируется, что он доступен в пределах приложения IHttpContextAccessorи HttpContext не гарантируется, что он будет содержать контекст, который запустил Blazor приложение.

Рекомендуемый подход для передачи состояния Blazor запроса приложению осуществляется через параметры корневого компонента во время первоначальной отрисовки приложения. Кроме того, приложение может скопировать данные в службу с областью действия в событии жизненного цикла инициализации корневого компонента для использования в приложении. Дополнительные сведения см . на стороне сервера ASP.NET Основных Blazor дополнительных сценариев безопасности.

Критически важный аспект безопасности на стороне Blazor сервера заключается в том, что пользователь, подключенный к заданному каналу, может быть обновлен в какой-то момент после Blazor установки канала, но IHttpContextAccessorне обновляется. Дополнительные сведения об устранении этой ситуации с пользовательскими службами см. в дополнительных сценариях безопасности на стороне сервера ASP.NET CoreBlazor.