I use Simple Membership in ASP.NET MVC 5 to use my existing SQL Server. In Register page I use dropdownbox to polpulate the user roles. In my Account controller I use [HttpGet] and [HttpPost] for Register Action. When I run my web app and goto Register page I can see my DropDownBox poplulated with data from my SqlServer.
But when I try to create new user and select a role I get error as;
"There is no ViewData item of type 'IEnumerable' that has the key 'roleName'"
Here is my Account Controller code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using SimpleMemberShip.Models;
using WebMatrix.WebData;
using System.Web.Security;
namespace SimpleMemberShip.Controllers
{
public class AccountController : Controller
{
// ****** REGISTER PAGE ACTION ******
[HttpGet]
public ActionResult Register()
{
//Roles for DropDown Box
IEnumerable<SelectListItem> RolesList = new System.Web.Mvc.SelectList(System.Web.Security.Roles.GetAllRoles(), "roleName");
ViewData["roleName"] = RolesList;
return View();
}
// ****** REGISTER PAGE ACTION with PARAMETERS ******
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Register(Register registerdata, string RoleName)
{
if (ModelState.IsValid)
{
try
{
WebSecurity.CreateUserAndAccount(registerdata.Username, registerdata.Password);
System.Web.Security.Roles.AddUserToRole(registerdata.Username, RoleName);
return RedirectToAction("Index", "Home");
}
catch (MembershipCreateUserException exception)
{
ModelState.AddModelError("", "Warning: Username exist...");
return View(registerdata);
}
}
ModelState.AddModelError("", "Warning: Username exist....");
return View(registerdata);
}
}
}
And here is the my Register.cshtml code look like:
@using SimpleMemberShip.Models
@model Register
@{
ViewBag.Title = "Register";
}
<h2>New User Registration</h2>
<br />
<div>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
@Html.ValidationSummary()
<label>User Name:</label>
@Html.TextBoxFor(m => m.Username, new { @class = "form-control" })
<br />
<label>User Password:</label>
@Html.PasswordFor(m => m.Password, new { @class = "form-control" })
<br />
<label>Roles</label>
@Html.DropDownList("roleName", (System.Web.Mvc.SelectList)ViewBag.roleName, "Select a Role")
<br />
<br />
<button class="btn btn-primary">Register</button>
}
</div>
Does anyone know where I am making mistakes?
Kind Regards,
What most likely happens in that you have some kind of error in the way you register a user, and the validation fails. In that case you are returning the same view, which is fine:
return View(registerdata);
However you are not repopulating the ViewData["roleName"]
element which the view depends on. Since ASP.NET MVC does not maintain any kind of state, this element needs to be repopulated on each request. So consider doing that, exactly the same way you were doing it before in the GET action, and the error should go away.
As a side note, you are mixing two ways of passing data from controller into view, model and ViewData. This is not very maintainable and obvious, so I suggest you stick to model approach only. Which should not be very hard - add a list of role names as a property of the model, and make sure to initialize it on every request.