Saya harus mengatakan saya cukup terkejut bahwa HttpContext adalah null di dalam konstruktor. Saya yakin itu untuk alasan kinerja. Telah mengkonfirmasikan bahwa menggunakan IPrincipalseperti yang dijelaskan di bawah ini berhasil memasukkannya ke dalam konstruktor. Ini pada dasarnya melakukan hal yang sama seperti jawaban yang diterima, tetapi dengan cara yang lebih antarmuka.
Bagi siapa pun yang menemukan pertanyaan ini mencari jawaban untuk pertanyaan umum "Bagaimana cara mendapatkan pengguna saat ini?" Anda dapat Userlangsung mengaksesnya dari Controller.User. Tetapi Anda hanya dapat melakukan ini di dalam metode tindakan (saya berasumsi karena pengontrol tidak hanya berjalan dengan HttpContexts dan untuk alasan kinerja).
Namun - jika Anda membutuhkannya di konstruktor (seperti yang dilakukan OP) atau perlu membuat objek injeksi lain yang membutuhkan pengguna saat ini, maka di bawah ini adalah pendekatan yang lebih baik:
Masukkan IPrincipal untuk mendapatkan pengguna
Pertama bertemu IPrincipaldanIIdentity
public interface IPrincipal
{
IIdentity Identity { get; }
bool IsInRole(string role);
}
public interface IIdentity
{
string AuthenticationType { get; }
bool IsAuthenticated { get; }
string Name { get; }
}
IPrincipaldan IIdentitymewakili pengguna dan nama pengguna. Wikipedia akan menghibur Anda jika 'Kepala Sekolah' terdengar aneh .
Penting untuk disadari bahwa baik Anda mendapatkannya dari IHttpContextAccessor.HttpContext.User, ControllerBase.Useratau ControllerBase.HttpContext.UserAnda mendapatkan suatu objek yang dijamin menjadi ClaimsPrincipalobjek yang diimplementasikanIPrincipal .
Tidak ada jenis Pengguna lain yang digunakan ASP.NET untuk Usersaat ini, (tetapi itu tidak berarti hal lain tidak dapat diterapkan IPrincipal).
Jadi jika Anda memiliki sesuatu yang memiliki ketergantungan 'nama pengguna saat ini' yang ingin Anda suntikkan, Anda harus menyuntikkan IPrincipaldan tentu saja tidak IHttpContextAccessor.
Penting: Jangan buang waktu untuk menyuntikkan IPrincipallangsung ke pengontrol Anda, atau metode tindakan - tidak ada gunanya karena Usersudah tersedia untuk Anda di sana.
Masuk startup.cs:
// Inject IPrincipal
services.AddTransient<IPrincipal>(provider => provider.GetService<IHttpContextAccessor>().HttpContext.User);
Kemudian di objek DI Anda yang membutuhkan pengguna, Anda baru saja menyuntikkan IPrincipaluntuk mendapatkan pengguna saat ini.
Hal yang paling penting di sini adalah jika Anda melakukan pengujian unit, Anda tidak perlu mengirimkannya HttpContext, tetapi hanya perlu mengejek sesuatu yang mewakili IPrincipal yang sebenarnya bisa jadi ClaimsPrincipal .
Satu hal ekstra penting yang saya tidak 100% yakin. Jika Anda perlu untuk mengakses klaim yang sebenarnya dari ClaimsPrincipalyang Anda butuhkan untuk cor IPrincipaluntuk ClaimsPrincipal. Ini baik-baik saja karena kita tahu 100% bahwa pada waktu proses itu dari jenis itu (karena itulah HttpContext.User). Saya sebenarnya suka melakukan ini di konstruktor karena saya sudah tahu pasti ada yang IPrincipal akan menjadi ClaimsPrincipal.
Jika Anda sedang mengejek, buatClaimsPrincipal saja langsung dan berikan ke apa pun IPrincipal.
Persisnya mengapa tidak ada antarmuka untuk IClaimsPrincipalSaya tidak yakin. Saya berasumsi MS memutuskan ClaimsPrincipalitu hanya 'koleksi' khusus yang tidak memerlukan antarmuka.