c# - C# - 如何从ASP.NET核心视图访问我的ApplicationUser属性?

我正在开发一个ASP.Net vNext /MVC6项目,

如何从User属性返回到ApplicationUser,以检索自定义属性?

我知道如何从User.GetUserId()值查找ApplicationUser ,具体而言,我不希望:

  • 从我的视图中执行类型的数据库查找(关注点分离)
  • 必须为每个控制器添加逻辑以检索当前用户的详细信息(DRY原则)
  • 必须为每个ViewModel添加一个用户属性,

从视图中获取自定义用户属性的最佳方法是什么?

时间:

我认为你应该使用用户的声明属性,我找到了很好的帖子: http://benfoster.io/blog/customising-claims-transformation-in-aspnet-core-identity

用户类


public class ApplicationUser : IdentityUser


{


 public string MyProperty { get; set; }


}



把MyProperty放到认证用户的声明中。 出于这个目的,重写UserClaimsPrincipalFactory,


public class MyUserClaimsPrincipalFactory : UserClaimsPrincipalFactory<ApplicationUser, IdentityRole>


{


 public MyUserClaimsPrincipalFactory (


 UserManager<ApplicationUser> userManager,


 RoleManager<IdentityRole> roleManager,


 IOptions<IdentityOptions> optionsAccessor) : base(userManager, roleManager, optionsAccessor)


 {


 }



 public async override Task<ClaimsPrincipal> CreateAsync(ApplicationUser user)


 {


 var principal = await base.CreateAsync(user);



 //Putting our Property to Claims


 //I'm using ClaimType.Email, but you may use any other or your own


 ((ClaimsIdentity)principal.Identity).AddClaims(new[] {


 new Claim(ClaimTypes.Email, user.MyProperty)


 });



 return principal;


 }


}



在Startup.cs中注册UserClaimsPrincipalFactory


public void ConfigureServices(IServiceCollection services)


{


 //...


 services.AddScoped<IUserClaimsPrincipalFactory<ApplicationUser>, MyUserClaimsPrincipalFactory>();


 //...


}



现在可以像这样访问


User.Claims.FirstOrDefault(v => v.Type == ClaimTypes.Email).Value;



可以创建一个扩展


namespace MyProject.MyExtensions


{


 public static class MyUserPrincipalExtension


 {


 public static string MyProperty(this ClaimsPrincipal user)


 {


 if (user.Identity.IsAuthenticated)


 {


 return user.Claims.FirstOrDefault(v => v.Type == ClaimTypes.Email).Value;


 }



 return"";


 }


 }


}



应该添加@Using来查看(将它添加到全局_ViewImport.cshtml中)


@using MyProject.MyExtensions



最后我们可以在视图中使用这个属性作为方法调用

 
@User.MyProperty()



 

我有相同的问题,但是我选择了不同的解决方案,不是创建ClaimsPrincipal的扩展方法,让扩展方法检索自定义用户属性。

以下是我的扩展方法:


public static class PrincipalExtensions


{


 public static string ProfilePictureUrl(this ClaimsPrincipal user, UserManager<ApplicationUser> userManager)


 {


 if (user.Identity.IsAuthenticated)


 {


 var appUser = userManager.FindByIdAsync(user.GetUserId()).Result;



 return appUser.ProfilePictureUrl;


 }



 return"";


 }


}



接下来,在我的视图(LoginPartial视图)中注入UserManager,然后将该UserManager传输到扩展方法:


@inject Microsoft.AspNet.Identity.UserManager<ApplicationUser> userManager;


<img src="@User.ProfilePictureUrl(userManager)">



首先,我定义了一个接口:


public interface ICurrentUser


 {


 /// <summary>


 /// Gets the display name of the user.


 /// </summary>


 /// <value>The display name.</value>


 string DisplayName { get; }



 /// <summary>


 /// Gets the login name of the user. This is typically what the user would enter in the login screen, but may be


 /// something different.


 /// </summary>


 /// <value>The name of the login.</value>


 string LoginName { get; }



 /// <summary>


 /// Gets the unique identifier of the user. Typically this is used as the Row ID in whatever store is used to persist


 /// the user's details.


 /// </summary>


 /// <value>The unique identifier.</value>


 string UniqueId { get; }



 /// <summary>


 /// Gets a value indicating whether the user has been authenticated.


 /// </summary>


 /// <value><c>true</c> if this instance is authenticated; otherwise, <c>false</c>.</value>


 bool IsAuthenticated { get; }



然后,我在一个具体的类中实现它:


/// <summary>


/// Encapsulates the concept of a 'current user' based on ASP.Net Identity.


/// </summary>


/// <seealso cref="MS.Gamification.DataAccess.ICurrentUser" />


public class AspNetIdentityCurrentUser : ICurrentUser


 {


 private readonly IIdentity identity;


 private readonly UserManager<ApplicationUser, string> manager;


 private ApplicationUser user;



 /// <summary>


 /// Initializes a new instance of the <see cref="AspNetIdentityCurrentUser" /> class.


 /// </summary>


 /// <param name="manager">The ASP.Net Identity User Manager.</param>


 /// <param name="identity">The identity as reported by the HTTP Context.</param>


 public AspNetIdentityCurrentUser(ApplicationUserManager manager, IIdentity identity)


 {


 this.manager = manager;


 this.identity = identity;


 }



 /// <summary>


 /// Gets the display name of the user. This implementation returns the login name.


 /// </summary>


 /// <value>The display name.</value>


 public string DisplayName => identity.Name;



 /// <summary>


 /// Gets the login name of the user.


 /// something different.


 /// </summary>


 /// <value>The name of the login.</value>


 public string LoginName => identity.Name;



 /// <summary>


 /// Gets the unique identifier of the user, which can be used to look the user up in a database.


 /// the user's details.


 /// </summary>


 /// <value>The unique identifier.</value>


 public string UniqueId


 {


 get


 {


 if (user == null)


 user = GetApplicationUser();


 return user.Id;


 }


 }



 /// <summary>


 /// Gets a value indicating whether the user has been authenticated.


 /// </summary>


 /// <value><c>true</c> if the user is authenticated; otherwise, <c>false</c>.</value>


 public bool IsAuthenticated => identity.IsAuthenticated;



 private ApplicationUser GetApplicationUser()


 {


 return manager.FindByName(LoginName);


 }


 }



最后,我在我的DI内核(我在使用Ninject )中进行了以下配置:


 kernel.Bind<ApplicationUserManager>().ToSelf()


 .InRequestScope();


 kernel.Bind<ApplicationSignInManager>().ToSelf().InRequestScope();


 kernel.Bind<IAuthenticationManager>()


 .ToMethod(m => HttpContext.Current.GetOwinContext().Authentication)


 .InRequestScope();


 kernel.Bind<IIdentity>().ToMethod(p => HttpContext.Current.User.Identity).InRequestScope();


 kernel.Bind<ICurrentUser>().To<AspNetIdentityCurrentUser>();



然后只要想访问当前用户,只要添加ICurrentUser类型的构造函数参数,就可以将它插入控制器。

我喜欢这个解决方案,因为它很好地封装了关注,并避免了我的控制器。

你需要使用当前用户的名称来搜索(例如,Entity Framework ):


HttpContext.Current.User.Identity.Name



...