by WebSurfer
19. September 2023 14:59
ASP.NET Core Web アプリ内のカスタムクラスから HttpContext にアクセスする方法を備忘録として書いておきます。下の画像は、カスタムクラスから HttpContext にアクセスし、ログイン中のユーザー名を取得して表示したものです。赤枠の部分がそれです。

その方法は Microsoft のドキュメント「ASP.NET Core で HttpContext にアクセスする」の中の「カスタム コンポーネントから HttpContext を使用する」を見ればすぐ分かるのですが、どこに書いてあったか忘れて探し回ることがないように自分のブログに書いておくことにしました。
基本的にどうするかというと、Visual Studio のテンプレートを使って作成する ASP.NET Core アプリには Dependency Injection (DI) 機能が組み込まれていますのでそれを利用します。
まず、DI コンテナに IHttpContextAccessor サービスと、それを利用するカスタムクラスを登録します。具体的には、Program.cs に以下のようにコードを追加します。
using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;
using Microsoft.EntityFrameworkCore;
using MvcNet7App.Data;
using MvcNet7App.Libraries;
var builder = WebApplication.CreateBuilder(args);
// ・・・中略・・・
// DI コンテナに IHttpContextAccessor サービスを登録
builder.Services.AddHttpContextAccessor();
// それを利用するカスタムクラスを登録
builder.Services.AddTransient<IUserRepository, UserRepository>();
// ・・・後略・・・
カスタムクラス UserRepository の例は以下の通りです。DI 機能によって、コンストラクタ経由で IHttpContextAccessor サービスを inject できるようにしています。LogCurrentUser メソッドは、inject された IHttpContextAccessor サービスから HttpContext にアクセスし、ログイン中のユーザー名を取得して戻り値として返します。
namespace MvcNet7App.Libraries
{
public class UserRepository : IUserRepository
{
// DI でコンストラクタの引数経由 IHttpContextAccessor
// サービスを inject できるよう設定
private readonly IHttpContextAccessor _httpContextAccessor;
public UserRepository(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public string? LogCurrentUser()
{
// ログイン中のユーザー名を取得
var username = _httpContextAccessor.HttpContext?
.User.Identity?.Name;
return username;
}
}
public interface IUserRepository
{
public string? LogCurrentUser();
}
}
上のカスタムクラスを利用する場合は、組み込みの DI 機能を使ってカスタムクラスのインスタンスが渡されるようにします。例えば、MVC の Controller の場合、以下のようにコンストラクタの引数を経由してカスタムクラスのインスタンスを渡しています。
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using MvcNet7App.Libraries;
using MvcNet7App.Models;
using System.Diagnostics;
namespace MvcNet7App.Controllers
{
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
// 組み込みの DI 機能によりコンストラクタの引数経由で
// カスタムクラスのインスタンスが渡される
private readonly Libraries.IUserRepository _user;
public HomeController(ILogger<HomeController> logger,
IUserRepository user)
{
_logger = logger;
_user = user;
}
public IActionResult Index()
{
ViewBag.Username = _user.LogCurrentUser();
return View();
}
// ・・・中略・・・
}
}
ユーザーが上の Home/Index を要求すると、ASP.NET は HomeController のインスタンスを生成して要求を処理しますが、その際 DI コンテナに登録された UserRepository クラスと IHttpContextAccessor サービスのインスタンスは自動的・連鎖的に生成され、コンストラクタの引数経由で inject されます。
なので、Index アクションメソッドで、inject された UserRepository クラスの LogCurrentUser メソッドを使ってログイン中のユーザー名を取得できます。
取得したユーザー名を ViewBag を使って View に渡し、ブラウザ上に表示したのがこの記事の一番上の画像です。赤枠の中の surfer@mail.example.com がそれです。
なお、Controller や View から HttpContext にアクセスする場合は、DI 機能などは使う必要はなく、もっと簡単にできます。詳しくは「ASP.NET Core の HttpContext にアクセスする」を見てください。