Search code examples
asp.netasp.net-mvcasp.net-identityasp.net-identity-2user-roles

Role ID does not exist when i using dynamic dropdown list


I create a dynamic dropdown list with this code :

[AllowAnonymous]
public ActionResult Register()
{
    var roles = db.Roles.Select(r => new { RoleID = r.Id, RoleName = r.Name }).ToList();
    ViewBag.Roles = new SelectList(roles, "RoleID", "RoleName");

    return View();
}

View:

<div class="form-group">
    <label>نقش</label>
    <div class="col-md-10">
        @Html.DropDownListFor(item => item.UserRoles, ViewBag.Roles as SelectList, "-- Select --")
    </div>
</div>

When I select the Role for Register show me this error :

enter image description here

User is created in table AspNetUsers but not in AspNetUserRoles.

What is the problem? /********************************************************************************************/

Edit

Model:

enter image description here

Contoller :

[HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> Register(RegisterViewModel model, HttpPostedFileBase UserPhoto)
    {
        if (ModelState.IsValid)
        {
            model.DateRegister = DateTime.Now;
            var user = new ApplicationUser
            {
                UserName = model.UserName,
                Name = model.Name,
                Family = model.Family,
                PhoneNumber = model.PhoneNumber,
                Gender = model.Gender,
                BirthDay = model.BirthDay,
                DateRegister = model.DateRegister,
                IsActive = false,
                Email = model.Email
            };

            if (UserPhoto != null)
            {
                UserPhoto = Request.Files[0];
                var ext = System.IO.Path.GetExtension(UserPhoto.FileName);
                if (ext == ".jpeg" || ext == ".jpg" || ext == ".png")
                {

                    string filename = model.PhoneNumber + ext;
                    UserPhoto.SaveAs(Server.MapPath(@"~/Image/" + filename));
                    user.UserPhoto = filename;
                }
            }

            var result = await UserManager.CreateAsync(user, model.Password);
            if (result.Succeeded)
            {

                await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
                await UserManager.AddToRoleAsync(user.Id,model.UserRoles);
                return RedirectToAction("Index", "Home");
            }
            AddErrors(result);
        }
        return View(model);
    }

Solution

  • AFAIK, AddToRoleAsync method requires 2 input parameters: user ID and role name as string, not role GUID.

    The main problem is SelectList on first Register action method passed RoleID content for second input parameter instead of RoleName, which throwing exception since role GUID certainly doesn't exist for role name when processing POST request. Hence, controller code should be changed to pass role name as value on DropDownListFor:

    [AllowAnonymous]
    public ActionResult Register()
    {
        var roles = db.Roles.Select(r => new { RoleID = r.Id, RoleName = r.Name }).ToList();
        ViewBag.Roles = new SelectList(roles, "RoleName", "RoleName");
    
        return View();
    }
    

    At this point, DropDownListFor ensures that model.UserRoles passed with RoleName as role name value for role assignment.

    References:

    Why does a role shows as "not exist" even when present in the database (asp.net mvc)

    UserManagement.AddToRoleAsync = https://msdn.microsoft.com/en-us/library/dn497537(v=vs.108).aspx

    SelectList = https://msdn.microsoft.com/en-us/library/system.web.mvc.selectlist(v=vs.118).aspx