ASP.NET Core の HttpContext
にアクセスする
Note
これは、この記事の最新バージョンではありません。 現在のリリースについては、この記事の .NET 8 バージョンを参照してください。
警告
このバージョンの ASP.NET Core はサポート対象から除外されました。 詳細については、「.NET および .NET Core サポート ポリシー」を参照してください。 現在のリリースについては、この記事の .NET 8 バージョンを参照してください。
重要
この情報はリリース前の製品に関する事項であり、正式版がリリースされるまでに大幅に変更される可能性があります。 Microsoft はここに示されている情報について、明示か黙示かを問わず、一切保証しません。
現在のリリースについては、この記事の .NET 8 バージョンを参照してください。
HttpContext を指定すると、個々の HTTP 要求と応答に関するすべての情報がカプセル化されます。 HttpContext
インスタンスは、HTTP 要求の受信時に初期化されます。 HttpContext
インスタンスには、ミドルウェアや Web API コントローラー、Razor Pages、SignalR、gRPC などのアプリ フレームワークからアクセスできます。
HTTP の要求と応答での HttpContext
の使用について詳しくは、「ASP.NET Core で HttpContext を使用する」をご覧ください。
Razor Pages から HttpContext
にアクセスする
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 の 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();
}
}
Minimal 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 になることがあります。
Note
アプリで NullReferenceException
エラーが散発的に生成される場合、コードの中で、バックグラウンド処理を開始する部分や要求完了後に処理を続行する部分を見直してください。 コントローラー メソッドを async void
として定義するなどの間違いを探します。
HttpContext
データでバックグラウンド作業を安全に行うには:
- 要求処理中に必要なデータをコピーします。
- コピーしたデータをバックグラウンド タスクに渡します。
- 並列タスクで
HttpContext
データを参照 "しないで" ください。 必要なデータは、並列タスクを開始する前にコンテキストから抽出してください。
アンセーフ コードを避けるために、バックグラウンド処理を行わないメソッドには HttpContext
を決して渡さないでください。 代わりに必要なデータを渡してください。 次の例では、電子メールの送信を開始するために SendEmail
が SendEmailCoreAsync
を呼びします。 X-Correlation-Id
ヘッダーの値は、HttpContext
ではなく SendEmailCoreAsync
に渡されます。 コードの実行では、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)
有効な HttpContext
が使用できないため、対話型レンダリングでは IHttpContextAccessor を避ける必要があります。
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 要求と応答に関するすべての情報がカプセル化されます。 HttpContext
インスタンスは、HTTP 要求の受信時に初期化されます。 HttpContext
インスタンスには、ミドルウェアや Web API コントローラー、Razor Pages、SignalR、gRPC などのアプリ フレームワークからアクセスできます。
HTTP の要求と応答での HttpContext
の使用について詳しくは、「ASP.NET Core で HttpContext を使用する」をご覧ください。
Razor Pages から HttpContext
にアクセスする
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 の 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 になることがあります。
Note
アプリで NullReferenceException
エラーが散発的に生成される場合、コードの中で、バックグラウンド処理を開始する部分や要求完了後に処理を続行する部分を見直してください。 コントローラー メソッドを async void
として定義するなどの間違いを探します。
HttpContext
データでバックグラウンド作業を安全に行うには:
- 要求処理中に必要なデータをコピーします。
- コピーしたデータをバックグラウンド タスクに渡します。
- 並列タスクで
HttpContext
データを参照 "しないで" ください。 必要なデータは、並列タスクを開始する前にコンテキストから抽出してください。
アンセーフ コードを避けるために、バックグラウンド処理を行わないメソッドには HttpContext
を決して渡さないでください。 代わりに必要なデータを渡してください。 次の例では、電子メールの送信を開始するために SendEmailCore
が呼び出されます。 correlationId
は、HttpContext
ではなく SendEmailCore
に渡されます。 コードの実行では、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)
有効な HttpContext
が使用できないため、対話型レンダリングでは IHttpContextAccessor を避ける必要があります。
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 のセキュリティに関するその他のシナリオ」を参照してください。
ASP.NET Core