Je dois dire que j'ai été assez surpris que HttpContext soit nul à l'intérieur du constructeur. Je suis sûr que c'est pour des raisons de performance. Avoir confirmé que l'utilisation IPrincipalcomme décrit ci-dessous l'injecte dans le constructeur. Il fait essentiellement la même chose que la réponse acceptée, mais d'une manière plus interface.
Pour tous ceux qui trouvent cette question à la recherche d'une réponse au générique "Comment obtenir l'utilisateur actuel?" vous pouvez simplement accéder Userdirectement à partir de Controller.User. Mais vous ne pouvez le faire qu'à l'intérieur des méthodes d'action (je suppose que les contrôleurs ne fonctionnent pas uniquement avec HttpContexts et pour des raisons de performances).
Cependant - si vous en avez besoin dans le constructeur (comme OP l'a fait) ou si vous devez créer d'autres objets injectables qui ont besoin de l'utilisateur actuel, alors la solution ci-dessous est une meilleure approche:
Injectez IPrincipal pour obtenir l'utilisateur
Première rencontre IPrincipaletIIdentity
public interface IPrincipal
{
IIdentity Identity { get; }
bool IsInRole(string role);
}
public interface IIdentity
{
string AuthenticationType { get; }
bool IsAuthenticated { get; }
string Name { get; }
}
IPrincipalet IIdentityreprésente l'utilisateur et le nom d'utilisateur. Wikipedia vous réconfortera si «Principal» semble étrange .
Il est important de se rendre compte que si vous l' obtenez à partir IHttpContextAccessor.HttpContext.User, ControllerBase.Userou ControllerBase.HttpContext.Uservous faire un objet qui est garanti d'être un ClaimsPrincipalobjet qui met en œuvreIPrincipal .
Il n'y a aucun autre type d'utilisateur utilisé par ASP.NET pour Userle moment (mais cela ne veut pas dire que quelque chose d'autre ne pourrait pas être implémenté IPrincipal).
Donc, si vous avez quelque chose qui a une dépendance du «nom d'utilisateur actuel» que vous voulez injecter, vous devriez l'injecter IPrincipalet certainement pas IHttpContextAccessor.
Important: ne perdez pas de temps à injecter IPrincipaldirectement dans votre manette ou votre méthode d'action - c'est inutile car Uservous y êtes déjà disponible.
Dans startup.cs:
// Inject IPrincipal
services.AddTransient<IPrincipal>(provider => provider.GetService<IHttpContextAccessor>().HttpContext.User);
Ensuite, dans votre objet DI qui a besoin de l'utilisateur que vous venez d'injecter IPrincipalpour obtenir l'utilisateur actuel.
La chose la plus importante ici est que si vous faites des tests unitaires, vous n'avez pas besoin d'envoyer un HttpContext, mais seulement de vous moquer de quelque chose qui représente IPrincipal ce qui peut simplement être ClaimsPrincipal .
Une chose supplémentaire importante dont je ne suis pas sûr à 100%. Si vous avez besoin d'accéder aux demandes d' indemnités de ClaimsPrincipalvous devez convertir IPrincipalà ClaimsPrincipal. C'est très bien car nous savons à 100% qu'au moment de l'exécution, c'est de ce type (puisque c'est ce qui HttpContext.Userest). En fait, j'aime faire cela dans le constructeur car je sais déjà avec certitude que tout IPrincipal sera un fichier ClaimsPrincipal.
Si vous vous moquez, créezClaimsPrincipal simplement un directement et transmettez-le à tout ce qui prend IPrincipal.
Exactement pourquoi il n'y a pas d'interface pour IClaimsPrincipalje ne suis pas sûr. Je suppose que MS a décidé que ce ClaimsPrincipaln'était qu'une «collection» spécialisée qui ne justifiait pas une interface.