Error When Posting Back From Drop Down .NET MVC 5

时间:2015-10-30 23:43:29

标签: c# asp.net asp.net-mvc-5 visual-studio-2015

I am new to .NET MVC but have a spent a great deal of time crawling through the other posts on SO for answers to my problem but I haven't been able to find anything. I am working on extending the Identity 2.0 sample project. I have been able to implement a drop-down using the HTML helper on the Create form for a new ApplicationUser, but I cannot move past an error "There is no ViewData item of type 'IEnumerable' that has the key 'TeamList'". I can see what the issue is - that the ViewModel and Model for ApplicationUser have a different type for the Team property (ICollection), but I have no idea what to do about it. My code is below: Snippet from ApplicationUser Model: [Display(Name = "First Name")] public string firstName { get; set; } [Display(Name = "Last Name")] public string lastName { get; set; } [Display(Name = "Hawks Number")] public int number { get; set; } [Display(Name = "Successful Logins")] public int successfulLogins { get; set; } [Display(Name = "Password Status")] public bool tempPassword { get; set; } public virtual ICollection<Team> Teams { get; set; } Snippet from RegisterViewModel ViewModel: [Display(Name = "Assigned Teams")] public ICollection<Team> Teams { get; set; } Snippet from UserAdminController Controller: // GET: /Users/Create public async Task<ActionResult> Create() { //Get the list of Roles ViewBag.RoleId = new SelectList(await RoleManager.Roles.ToListAsync(), "Name", "Name"); //Get list of Teams IdentityDB _db = new IdentityDB(); ViewBag.Teams = new SelectList(_db.Teams, "Name", "Name"); return View(); } // // POST: /Users/Create [HttpPost] public async Task<ActionResult> Create(RegisterViewModel userViewModel, params string[] selectedRoles) { IdentityDB _db = new IdentityDB(); // TODO: RESOLVE ISSUE WITH TEAM SELECTION if (ModelState.IsValid) { var user = new ApplicationUser { UserName = userViewModel.Email, Email = userViewModel.Email, firstName = userViewModel.firstName, lastName = userViewModel.lastName, number = userViewModel.number, successfulLogins = 0, tempPassword = true, }; var adminresult = await UserManager.CreateAsync(user, userViewModel.Password); //Add User to the selected Roles if (adminresult.Succeeded) { if (selectedRoles != null) { var result = await UserManager.AddToRolesAsync(user.Id, selectedRoles); if (!result.Succeeded) { ModelState.AddModelError("", result.Errors.First()); ViewBag.RoleId = new SelectList(await RoleManager.Roles.ToListAsync(), "Name", "Name"); return View(); } } } else { ModelState.AddModelError("", adminresult.Errors.First()); ViewBag.RoleId = new SelectList(RoleManager.Roles, "Name", "Name"); return View(); } Snippet from View: <div class="form-group"> @Html.LabelFor(m => m.Teams, new { @class = "col-md-2 control-label" }) <div class="col-md-10"> @Html.DropDownListFor(m => m.Teams, (IEnumerable<SelectListItem>)ViewBag.Teams, "- Please Select a Team -", new { @class = "form-control" }) </div> </div> It took a while for to move past a "Cannot Implicitly Convert" error to get to this point. I have tried using LINQ to attempt to find the Team record but of course the ViewModel never even picks up the HTTP POST. Any help would be much appreciated. If there is more information I can provide please just let me know.

1 个答案:

答案 0 :(得分:1)

发生错误是因为在POST方法中,您返回视图,但没有将值重新分配给ViewBag.Teams(正如您在GET方法中所做的那样),因此它为null。但是,您的下拉列表正在尝试绑定到无法完成的集合(<select>元素仅回发其所选选项的值)并且绑定将始终失败。

您的代码中不清楚您使用Teams,因为它在您的POST方法中未提及,但您需要将视图模型更改为:

public class RegisterViewModel
{
  [Display(Name = "Assigned Teams")]
  [Required(ErrorMessage = "Please select a team")]
  public string SelectedTeam { get; set; }
  public SelectList TeamsList { get; set; }
  ....
}

然后在GET方法中,初始化模型并将其返回

RegisterViewModel model = new RegisterViewModel();
model.TeamsList = new SelectList(_db.Teams, "Name", "Name");
return View(model);

并在视图中

@Html.LabelFor(m => m.Teams, new { @class = "col-md-2 control-label" })
@Html.DropDownListFor(m => m.SelectedTeam, Model.TeamsList, "- Please Select a Team -", new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.Teams)

并且在POST方法中,如果由于ModelState无效而需要返回视图,则在返回视图之前重新分配SelectList

[HttpPost]
public async Task<ActionResult> Create(RegisterViewModel model, params string[] selectedRoles)
{
    ....
    // if you need to return the view, then
    model.TeamsList = new SelectList(_db.Teams, "Name", "Name");
    return View(model);
}

附注:由于您使用的是视图模型,因此它还应包含用于选择角色的属性,并从POST方法中删除params string[] selectedRoles参数。