在 ASP.NET Core 中访问 HttpContext
注意
此版本不是本文的最新版本。 有关当前版本,请参阅本文的 .NET 9 版本。
警告
此版本的 ASP.NET Core 不再受支持。 有关详细信息,请参阅 .NET 和 .NET Core 支持策略。 有关当前版本,请参阅本文的 .NET 9 版本。
HttpContext 封装了有关个别 HTTP 请求和响应的所有信息。 收到 HTTP 请求时,HttpContext
实例会进行初始化。
HttpContext
实例可通过中间件和应用框架(如 Web API 控制器、Razor Pages、SignalR、gRPC 等)访问。
有关将 HttpContext
与 HTTP 请求和响应一起使用的信息,请参阅在 ASP.NET Core 中使用 HttpContext。
从 HttpContext
Pages 访问 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;
// ...
}
从 MVC 的 HttpContext
视图中访问 Razor
MVC 模式中的 Razor 视图通过视图上的 HttpContext
属性公开 RazorPage.Context。 下面的示例使用 Windows 身份验证检索 Intranet 应用中的当前用户名:
@{
var username = Context.User.Identity.Name;
// ...
}
通过控制器访问 HttpContext
控制器公开 ControllerBase.HttpContext 属性:
public class HomeController : Controller
{
public IActionResult About()
{
var pathBase = HttpContext.Request.PathBase;
// ...
return View();
}
}
通过最小 API 访问 HttpContext
若要通过最小 API 使用 HttpContext
,请添加 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();
// ...
}
}
通过 gRPC 方法访问 HttpContext
若要通过 gRPC 方法使用 HttpContext
,请参阅在 gRPC 方法中解析 HttpContext
。
通过自定义组件访问 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
传递给执行后台工作的方法。 而是传递所需要的数据。 在以下示例中,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)
有关详细信息,请参阅 ASP.NET Core Blazor 应用中IHttpContextAccessor/HttpContext。
HttpContext 封装了有关个别 HTTP 请求和响应的所有信息。 收到 HTTP 请求时,HttpContext
实例会进行初始化。
HttpContext
实例可通过中间件和应用框架(如 Web API 控制器、Razor Pages、SignalR、gRPC 等)访问。
有关将 HttpContext
与 HTTP 请求和响应一起使用的信息,请参阅在 ASP.NET Core 中使用 HttpContext。
从 HttpContext
Pages 访问 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;
// ...
}
从 MVC 的 HttpContext
视图中访问 Razor
MVC 模式中的 Razor 视图通过视图上的 HttpContext
属性公开 RazorPage.Context。 下面的示例使用 Windows 身份验证检索 Intranet 应用中的当前用户名:
@{
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
传递给执行后台工作的方法。 而是传递所需要的数据。 在以下示例中,调用 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)
有关详细信息,请参阅 ASP.NET Core Blazor 应用中IHttpContextAccessor/HttpContext。