在 ASP.NET Core 中存取 HttpContext
注意
這不是這篇文章的最新版本。 如需目前版本,請參閱本文的 .NET 8 版本。
警告
不再支援此版本的 ASP.NET Core。 如需詳細資訊,請參閱 .NET 和 .NET Core 支援原則。 如需目前版本,請參閱本文的 .NET 8 版本。
HttpContext 會封裝關於個別 HTTP 要求和回應的所有資訊。 收到 HTTP 要求時,會初始化 HttpContext
執行個體。 該 HttpContext
執行個體可透過中介軟體和應用程式架構來存取,例如 Web API 控制器、Razor 頁面、SignalR、gRPC 等等。
如需使用 HttpContext
搭配 HTTP 要求和回應的相關資訊,請參閱在 ASP.NET Core 中使用 HttpContext。
從 Razor 頁面存取 HttpContext
Razor 頁面 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 中的 Razor 檢視存取 HttpContext
MVC 模式中的 Razor 檢視會透過檢視上的 RazorPage.Context 屬性公開 HttpContext
。 以下範例會在內部網路應用程式中使用 Windows 驗證,擷取目前的使用者名稱:
@{
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
,請使用傳遞至 Invoke
或 InvokeAsync
方法的 HttpContext
參數:
public class MyCustomMiddleware
{
// ...
public async Task InvokeAsync(HttpContext context)
{
// ...
}
}
從 SignalR 存取 HttpContext
若要從 SignalR 使用 HttpContext
,請在 Hub.Context 上呼叫 GetHttpContext 方法:
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
資料。 啟動平行工作之前,先從內容擷取所需的資料。
若要避免不安全的程式碼,請勿將 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)
{
// ...
}
}
Razor 元件中的 IHttpContextAccessor
/HttpContext
(Blazor)
IHttpContextAccessor 必須避免使用互動式轉譯,因為沒有有效的 HttpContext
可用。
IHttpContextAccessor 可用於伺服器上靜態轉譯的元件。 不過,建議您盡可能避免。
只能在一般工作的靜態轉譯根元件中將 HttpContext 用作 級聯參數,例如檢查和修改 App
元件 (Components/App.razor
) 中的標頭或其他屬性。 用於互動式轉譯的值一律是 null
。
[CascadingParameter]
public HttpContext? HttpContext { get; set; }
針對互動式元件中所需 HttpContext 的案例,建議您透過伺服器的持續元件狀態來流動資料。 如需詳細資訊,請參閱 伺服器端 ASP.NET Core Blazor的其他安全性案例。
請勿在伺服器端 Blazor 應用程式的 Razor 元件中直接或間接使用 IHttpContextAccessor/HttpContext。 Blazor 應用程式會在 ASP.NET Core 管線內容之外執行。 既不保證 HttpContext 在 IHttpContextAccessor 中可用,也不保證 HttpContext 會保留啟動了 Blazor 應用程式的內容。
建議在 Blazor 應用程式的初始轉譯期間,透過根元件參數將要求狀態傳遞給此應用程式。 或者,應用程式可以將資料複製到根元件初始化生命週期事件中的範圍服務,以便在整個應用程式中使用。 如需詳細資訊,請參閱伺服器端 ASP.NET Core Blazor 其他安全性案例。
伺服器端 Blazor 安全性的一個重要層面是,附加至指定線路的使用者可能會在建立 Blazor 線路後的某個時間點進行更新,但 IHttpContextAccessor不會更新。 如需使用自訂服務解決這種情況的詳細資訊,請參閱伺服器端 ASP.NET Core Blazor 其他安全性案例。
HttpContext 會封裝關於個別 HTTP 要求和回應的所有資訊。 收到 HTTP 要求時,會初始化 HttpContext
執行個體。 該 HttpContext
執行個體可透過中介軟體和應用程式架構來存取,例如 Web API 控制器、Razor 頁面、SignalR、gRPC 等等。
如需使用 HttpContext
搭配 HTTP 要求和回應的相關資訊,請參閱在 ASP.NET Core 中使用 HttpContext。
從 Razor 頁面存取 HttpContext
Razor 頁面 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 中的 Razor 檢視存取 HttpContext
MVC 模式中的 Razor 檢視會透過檢視上的 RazorPage.Context 屬性公開 HttpContext
。 以下範例會在內部網路應用程式中使用 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)
{
// ...
}
}
Razor 元件中的 IHttpContextAccessor
/HttpContext
(Blazor)
IHttpContextAccessor 必須避免使用互動式轉譯,因為沒有有效的 HttpContext
可用。
IHttpContextAccessor 可用於伺服器上靜態轉譯的元件。 不過,建議您盡可能避免。
只能在一般工作的靜態轉譯根元件中將 HttpContext 用作 級聯參數,例如檢查和修改 App
元件 (Components/App.razor
) 中的標頭或其他屬性。 用於互動式轉譯的值一律是 null
。
[CascadingParameter]
public HttpContext? HttpContext { get; set; }
針對互動式元件中所需 HttpContext 的案例,建議您透過伺服器的持續元件狀態來流動資料。 如需詳細資訊,請參閱 伺服器端 ASP.NET Core Blazor的其他安全性案例。
請勿在伺服器端 Blazor 應用程式的 Razor 元件中直接或間接使用 IHttpContextAccessor/HttpContext。 Blazor 應用程式會在 ASP.NET Core 管線內容之外執行。 既不保證 HttpContext 在 IHttpContextAccessor 中可用,也不保證 HttpContext 會保留啟動了 Blazor 應用程式的內容。
建議在 Blazor 應用程式的初始轉譯期間,透過根元件參數將要求狀態傳遞給此應用程式。 或者,應用程式可以將資料複製到根元件初始化生命週期事件中的範圍服務,以便在整個應用程式中使用。 如需詳細資訊,請參閱伺服器端 ASP.NET Core Blazor 其他安全性案例。
伺服器端 Blazor 安全性的一個重要層面是,附加至指定線路的使用者可能會在建立 Blazor 線路後的某個時間點進行更新,但 IHttpContextAccessor不會更新。 如需使用自訂服務解決這種情況的詳細資訊,請參閱伺服器端 ASP.NET Core Blazor 其他安全性案例。