我正在与Identity 2学习MVC的过程中,我正在采取一个示例项目并调整它以适合我试图从WebForms与ASP转换的网站。网络会员提供商。
我现在遇到的问题是让我的头围绕着我如何从另一个表中获得一个值来填充类中的属性。
我有一个叫做AppUser.cs的类,它继承自IdentityUser。它使用EntityFramework映射到一个名为"AspNetUsers"的表。我使用EF迁移向该表添加了更多属性(First/Last Name)。现在我想显示用户被分配到的角色,最终需要获得可用角色的列表并将它们添加到下拉列表中。我添加了RoleName属性到我的AppUser类,但我假设,由于该数据没有存储在AspNetUsers表中,这就是为什么我得到一个错误"无效列名'RoleName'"。
我如何填充角色和/或在我的AppUser类中获得可用角色的列表,以便我可以在视图中显示它?
public class AppUser : IdentityUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string RoleName { get; set; }
}
视图"Index"上的模型。cshtml "是AppUser.
@model IEnumerable<AppUser>
这是控制器的ActionResult。
public ActionResult Index() {
return View(UserManager.Users);
}
private AppUserManager UserManager {
get {
return HttpContext.GetOwinContext().GetUserManager<AppUserManager>();
}
}
这是AppUserManager.cs
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin;
using SampleMvcSite.Models;
namespace SampleMvcSite.Infrastructure {
public class AppUserManager : UserManager<AppUser> {
public AppUserManager(IUserStore<AppUser> store)
: base(store) {
}
public static AppUserManager Create(
IdentityFactoryOptions<AppUserManager> options,
IOwinContext context) {
AppIdentityDbContext db = context.Get<AppIdentityDbContext>();
AppUserManager manager = new AppUserManager(new UserStore<AppUser>(db));
manager.PasswordValidator = new CustomPasswordValidator {
RequiredLength = 6,
RequireNonLetterOrDigit = false,
RequireDigit = false,
RequireLowercase = true,
RequireUppercase = true
};
manager.UserValidator = new CustomUserValidator(manager) {
AllowOnlyAlphanumericUserNames = true,
RequireUniqueEmail = true
};
return manager;
}
}
}
更新代码:我最终创建了一个名为UserEditViewModel的类,我还包括在我正在调整的示例项目中的apple类。
public class UserEditViewModel : IdentityUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string UserRole { get; set; }
public IEnumerable<AppRole> AllRoles { get; set; }
}
public class AppRole : IdentityRole {
public AppRole() : base() { }
public AppRole(string name) : base(name) { }
}
然后在我的控制器中,我做了以下操作。请记住,我只允许一个用户一次被分配到一个角色,所以理论上应该只有一个角色,这就是为什么我只调用userRoles[0]。由于我在一些示例用户之后添加了RoleManager,因此我有几个未分配给角色的用户。我添加了一个检查,以确保角色有一个计数,如果没有,我显示"User"作为他们的角色。我将返回并添加代码,以便在没有找到角色的情况下实际将用户添加到"user"角色。
List<UserEditViewModel> UserList = new List<UserEditViewModel>();
var users = UserManager.Users;
foreach (AppUser user in users)
{
var userRoles = await UserManager.GetRolesAsync(user.Id);
string roleName = userRoles.Count() == 0 ? "User" : userRoles[0];
UserEditViewModel editUser = new UserEditViewModel();
editUser.UserName = user.UserName;
editUser.FirstName = user.FirstName;
editUser.LastName = user.LastName;
editUser.Email = user.Email;
editUser.UserRole = roleName;
editUser.AllRoles = RoleManager.Roles;
UserList.Add(editUser);
}
return View(UserList);
这里是视图
<div class="form-group">
<label>Role:</label> @Html.DisplayNameFor(model => model.UserRole)
</div>
我会看一下ViewModels。在视图中更新实体模型通常是不好的做法——尤其是与安全相关的实体。见https://www.stevefenton.co.uk/2013/03/Why-You-Never-Expose-Your-Domain-Model-As-Your-MVC-Model/
使用视图模型,您可以在控制器中填充List<Role>
的属性并在视图中使用,而另一个属性如RoleId用于用户的角色。
在POST中,您可以这样做:
if (ModelState.IsValid)
{
var roleMgr = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(context));
var userMgr = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
var role = roleMgr.FindById(viewmodel.RoleId);
if (role != null) userMgr.AddToRole(viewmodel.UserId, role.Name);
}
视图:
<div class="form-group">
@Html.LabelFor(model => model.RoleId)
<div class="col-md-2">
@Html.DropDownListFor(model => model.RoleId, Model.RoleList, htmlAttributes: new { @class = "form-control" })
</div>
<div class="col-md-10 col-md-offset-2">
@Html.ValidationMessageFor(model => model.RoleId, "", new { @class = "text-danger" })
</div>
</div>