Search code examples
c#asp.net-mvcentity-frameworkasp.net-identityusermanager

How to correct exception when registering user entity framework


I am trying to add roles to my default mvc6 project. I am getting a exception in my register.cshtml

@model TransparentEnergy.Models.RegisterViewModel

<div class="col-md-6">
    <div class="card">
      <div class="card-header">
          <h2>Register New User</h2>
      </div>
       <div class="card-body card-padding">
            @using (Html.BeginForm("Register", "Account", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
           {
              @Html.AntiForgeryToken()
                @Html.ValidationSummary("", new { @class = "text-danger" })
            <div class="card-body card-padding">
                <div class="form-group">
                    <label for="Email" class="col-sm-2 control-label">Email</label>
                    <div class="col-sm-10">
                        <div class="fg-line">
                            @Html.TextBoxFor(m => m.Email, new { @class = "form-control fg-input" })
                        </div>
                    </div>
                </div>
                <div class="form-group">
                    <label for="Password" class="col-sm-2 control-label">Password</label>
                    <div class="col-sm-10">

                        <div class="fg-line">
                            @Html.PasswordFor(m => m.Password, new { @class = "form-control fg-input" })
                        </div>
                    </div>
                </div>
                <div class="form-group">
                    <label for="ConfirmPassword" class="col-sm-2 control-label">Confirm Password</label>
                    <div class="col-sm-10">

                        <div class="fg-line">
                            @Html.PasswordFor(m => m.ConfirmPassword, new { @class = "form-control fg-input" })
                        </div>
                    </div>
                </div>
                <div class="form-group">
                    <label for="Name" class="col-sm-2 control-label">Role Type</label>
                    <div class="col-sm-10">
                        <div class="fg-line select">
                                @Html.DropDownList("Name", null, new { @class = "form-control selectpicker"})
                        </div>
                    </div>
                </div>
                <div class="form-group">
                    <div class="col-sm-offset-2 col-sm-10">
                        <button type="submit" class="btn btn-primary btn-lg">Register</button>
                    </div>
                </div>
            </div>

        }

        @section Scripts {
            @Scripts.Render("~/bundles/jqueryval")
        }

    </div>
</div>

Error Message is

The ViewData item that has the key 'Name' is of type 'System.String' but must be of type 'IEnumerable'.

AccountController

   // GET: /Account/Register
    [AllowAnonymous]
    public ActionResult Register()
    {
        ViewBag.Name = new SelectList(context.Roles.ToList(), "Name", "Name");
        return View();
    }

    //
    // POST: /Account/Register
    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> Register(RegisterViewModel model)
    {
        if (ModelState.IsValid)
        {
            var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
            var result = await UserManager.CreateAsync(user, model.Password);
            if (result.Succeeded)
            {

                //Assign Role to user Here 
                await this.UserManager.AddToRoleAsync(user.Id, model.Name);
                //Ends Here


                await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);

                return RedirectToAction("Index", "Home");
            }
            AddErrors(result);
        }

        // If we got this far, something failed, redisplay form
        return View(model);
    }

RegisterViewModel

public class RegisterViewModel
{
    [Required]
    [EmailAddress]
    [Display(Name = "Email")]
    public string Email { get; set; }

    [Required]
    [Display(Name = "Full Name")]
    public string FullName { get; set; }

    [Required]
    [Display(Name = "Role")]
    public string Name { get; set; }
}

Solution

  • Your ViewModel:

    public class RegisterViewModel
    {
    [Required]
    [EmailAddress]
    [Display(Name = "Email")]
    public string Email { get; set; }
    
    [Required]
    [Display(Name = "Full Name")]
    public string FullName { get; set; }
    
    [Required]
    [Display(Name = "Role")]
    public string Name { get; set; }
    
    //store roles
    public IEnumerable<Role> Roles {get;set;}
    }
    

    Your GET controller:

    [AllowAnonymous]
    public ActionResult Register()
    {
        RegisterViewModel model = new RegisterViewModel();
        //Controller should not intervene with presentation logic
        //so SelectList is not used here
        model.Roles = context.Roles.ToList();
    
        return View(model);
    }
    

    Finally your View, change:

    @Html.DropDownList("Name", null, new { @class = "form-control selectpicker"})
    

    To:

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

    Update: Your POST controller:

      model.Roles = context.Roles.ToList();
      // If we got this far, something failed, redisplay form
       return View(model);