值不能为空。 参数名称:items(在下拉列表中)ASP.NET MVC5

我的代码有问题,我正在使用MVC5附带的注册表单,我添加了一个字段“Role”作为下拉列表,在创建新用户时为用户分配角色。 如下图所示 在此处输入图像描述

现在为了做到这一点,我修改了“RegisterViewModel”并添加了以下属性

public IdentityRole Role { get; set; } [Required] [Display(Name = "Roles List")] public IEnumerable RolesList { get; set; } 

在“AccountController”中,我更改了注册表单的Register操作,如下所示:

 // GET: /Account/Register [AllowAnonymous] public ActionResult Register() { var _context = new ApplicationDbContext(); var roles = _context.Roles.ToList(); var viewModel = new RegisterViewModel { RolesList = roles }; return View(viewModel); } 

在视图“Register.cshtml”中,我添加了此下拉列表以在视图中加载角色并将角色发布到控制器

 
@Html.LabelFor(m => m.Role.Id, new { @class = "col-md-2 control-label" })
@Html.DropDownListFor(m => m.Role, new SelectList(Model.RolesList, "Name", "Name"), "Select Role", new { @class = "form-control" })

在注册控制器中,发布注册表,我添加了这个

 // POST: /Account/Register [HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] public async Task Register(RegisterViewModel model) { if (ModelState.IsValid) { var user = new ApplicationUser() { UserName = model.UserName , centerName = model.centerName }; var result = await UserManager.CreateAsync(user, model.Password); if (result.Succeeded) { var role = new IdentityRole(model.Role.Name); //I added this line to store the user and its roles in AspNetUserRoles table await UserManager.AddToRoleAsync(user.Id, role.Name); await SignInAsync(user, isPersistent: false); return RedirectToAction("Index", "Home"); } else { AddErrors(result); } } 

现在,当尝试注册用户并发布表单时,我收到以下错误:

 Server Error in '/' Application. Value cannot be null. Parameter name: items Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. Exception Details: System.ArgumentNullException: Value cannot be null. Parameter name: items Source Error: Line 41: @Html.LabelFor(m => m.Role.Name, new { @class = "col-md-2 control-label" }) Line 42: 
Line 43: @Html.DropDownListFor(m => m.Role, new SelectList(Model.RolesList, "Name", "Name"), "Select Role", new { @class = "form-control" }) Line 44:
Line 45:
Source File: c:..\TransactionsSystem\Views\Account\Register.cshtml Line: 43

我尝试了不同的解决方案来解决它,但没有任何效果,任何人都可以提供帮助或建议吗?

您不能将元素绑定到复杂对象(这是Role是什么),并且当您提交表单时, ModelState无效(您尝试将RolesList的选定Name属性绑定到typeof IdentityRole )。 然后返回视图,但没有重新填充RolesList属性,因此它为null (因此错误)。

视图模型不应包含数据模型,您应该查看模型

 public class RegisterViewModel { .... [Required(ErrorMessage = "Please select a role")] public string Role { get; set; } public IEnumerable RoleList { get; set; } } 

并在GET方法中

 var roles = _context.Roles.Select(r => r.Name); var viewModel = new RegisterViewModel { RolesList = new SelectList(roles) }; return View(viewModel); 

并在视图中

 @Html.LabelFor(m => m.Role, new { @class = "col-md-2 control-label" }) 
@Html.DropDownListFor(m => m.Role, Model.RolesList, "Select Role", new { @class = "form-control" })

这将解决与Role相关的无效ModelState问题,但如果由于其他ModelState问题确实需要返回视图,则必须首先在返回视图之前重新填充该集合

 if (!ModelState.IsValid) { var roles = _context.Roles.Select(r => r.Name); model.RolesList = new SelectList(roles); return View(model); } .... // save and redirect 

我个人会在你的控制器中创建选择列表并将其传递给模型,写出类似的东西

  var RolesList = new List { new SelectListItem { Value = string.Empty, Text = "Please select a Role..." } }; RolesList.AddRange(roles.Select(t => new SelectListItem { Text = t.role, Value = t.Id.ToString() }));` 

然后将其添加到您的模型中,然后在您的模型中使用

 @Html.DropDownListFor(m => m.Role, Model.RoleList, new { @class = "form-control" }) 

这个方法/语法对我有用,但我不确定它是否是“最佳实践”

我在MVC5中为编辑现有用户而工作的解决方案

型号(部分)

 public IEnumerable Roles { get; set; } 

视图

 @Html.DropDownListFor(model => model.UserRole, new SelectList(Model.Roles, Model.UserRole), new { @class = "form-control" }) 

控制器(获取)

  var model = new EditUserViewModel() { UserName = user.UserName, Email = user.Email, IsEnabled = user.IsEnabled, Id = user.Id, PhoneNumber = user.PhoneNumber, UserRole = userRoleName, // a list of all roles Roles = from r in RoleManager.Roles orderby r.Name select r.Name }; 

这个答案再次被编辑,现在它完美地运作了

我想出了一个新的解决方案,我不需要列出所需的列表,我只能创建属性RoleName并使其成为必需。

在RegisterViewModel中,我只将这些行添加到RegisterViewModel:

  [Display(Name = "Roles List")] public List RolesList { get; set; } [Required (ErrorMessage = "Please Select the Role")] public string RoleName { get; set; } 

在视图中,我像这样制作了下拉列表

 
@Html.LabelFor(m => m.RoleName, new { @class = "col-md-2 control-label" })
@Html.DropDownListFor(m => m.RoleName, new SelectList(Model.RolesList, "Name", "Name"), "Select Role", new { @class = "form-control" })