Search code examples
asp.net-mvcentity-frameworkasp.net-identityviewmodel

Showing Type instead of data in DropDownListFor()


Trying to Populate Users and Roles with a ViewModel , but it shows type instead of data like System.Data.Entity.DynamicProxies.AppUser.xxx ( for Users) and System.Data.Entity.DynamicProxies.IdentityRole.xxx ( for Roles) .

Code as follows.

public class AppUser : IdentityUser
    {
        //add custom properties which have not included in IdentityUser before
        public string Designation { get; set; }

        public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<AppUser> manager)
        {
            // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType 
            var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
            // Add custom user claims here 
            return userIdentity;
        }

        public static ERPContext Create()
        {
            return new ERPContext();
        }
    } 



public class AppRole : IdentityRole
    {
        public AppRole() : base() { }
        public AppRole(string name) : base(name) { }
        // extra properties here 
        public string Description { get; set; }
    }

ViewModel

public class UserAssignRoleViewModel
    {

        public string Username { get; set; }

        public string Role { get; set; }
        [Required]
        public List<AppUser> Users { get; set; }
        [Required]
        public List<IdentityRole> Roles { get; set; }

        public int SelectedId { set; get; }

        public int SelectedRoleId { set; get; }
    }

RoleController

  public ActionResult ManageUserRoles()
        {
            //this code is also an alternate way to fetch the roles from Owin // Startup config
            // var roles = HttpContext.GetOwinContext().GetUserManager<RoleManager<IdentityRole>>().Roles;
            //var rolelist = context.Roles.OrderBy(r => r.Name).ToList().Select(rr => new SelectListItem { Value = rr.Name.ToString(), Text = rr.Name }).ToList();
            var model = new UserAssignRoleViewModel();
            var users = context.Users.ToList();
            users.Select(s => new SelectListItem
            {
                Value = s.Id.ToString(),
                Text = s.UserName.ToString()
            });
            var roles = context.Roles.ToList();
            roles.Select(s => new SelectListItem
            {
                Value = s.Id.ToString(),
                Text = s.Name.ToString()
            });
            ViewBag.Users = users;
            //var list = context.Roles.OrderBy(r => r.Name).ToList().Select(rr => new SelectListItem { Value = rr.Name.ToString(), Text = rr.Name }).ToList();
            //ViewBag.Roles = list;
            model.Users = users;
            model.Roles = roles;
            return View(model);
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult RoleAddToUser(string UserName, string RoleName)
        {
            AppUser user = context.Users.Where(u => u.UserName.Equals(UserName, StringComparison.CurrentCultureIgnoreCase)).FirstOrDefault();
            var userManager = new UserManager<AppUser>(new UserStore<AppUser>(context));

            userManager.AddToRole(user.Id, RoleName);

            ViewBag.ResultMessage = "Role Assigned successfully !";

            // prepopulat users for the view dropdown
            var _users = context.Users.OrderBy(r => r.UserName).ToList().Select(rr => new SelectListItem { Value = rr.UserName.ToString(), Text = rr.UserName }).ToList();
            ViewBag.Users = _users;
            // prepopulat roles for the view dropdown
            var _roles = context.Roles.OrderBy(r => r.Name).ToList().Select(rr => new SelectListItem { Value = rr.Name.ToString(), Text = rr.Name }).ToList();
            ViewBag.Roles = _roles;

            return View("ManageUserRoles");
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult GetRoles(string UserName)
        {
            if (!string.IsNullOrWhiteSpace(UserName))
            {
                AppUser user = context.Users.Where(u => u.UserName.Equals(UserName, StringComparison.CurrentCultureIgnoreCase)).FirstOrDefault();
                var userManager = new UserManager<AppUser>(new UserStore<AppUser>(context));

                ViewBag.RolesForThisUser = userManager.GetRoles(user.Id);


                // prepopulat roles for the view dropdown
                var list = context.Roles.OrderBy(r => r.Name).ToList().Select(rr => new SelectListItem { Value = rr.Name.ToString(), Text = rr.Name }).ToList();
                ViewBag.Roles = list;
                // prepopulat roles for the view dropdown
                var users = context.Users.OrderBy(r => r.UserName).ToList().Select(rr => new SelectListItem { Value = rr.UserName.ToString(), Text = rr.UserName }).ToList();
                ViewBag.Users = users;
            }

            return View("ManageUserRoles");
        }

Above code has few commented codes which I tried earlier .

Finally, the view is as follows

@model ERPLite.Models.UserAssignRoleViewModel
@{
    ViewBag.Title = "ManageUserRoles";

}

@Html.ActionLink("Create New Role", "Create") | @Html.ActionLink("Manage User Role", "ManageUserRoles")
<hr />


@using (Html.BeginForm("RoleAddToUser", "Role"))
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)


    <p>

        User Name: @Html.DropDownListFor(x => x.SelectedId, new SelectList(Model.Users), "Select")
        @*Role Name: @Html.DropDownList("RoleName", (IEnumerable<SelectListItem>)ViewBag.Roles, "Select ...")*@
        Role Name: @Html.DropDownListFor(u => u.SelectedRoleId, new SelectList(Model.Roles), "Select ...")
    </p>

    <input type="submit" value="Save" />
}
<hr />
<h3>Get Roles for a User</h3>
@using (Html.BeginForm("GetRoles", "Role"))
{
    @Html.AntiForgeryToken()
    <p>
        Username : @Html.TextBox("UserName")
        <input type="submit" value="Get Roles for this User" />
    </p>
}

@if (ViewBag.RolesForThisUser != null)
{
    <div style="background-color:yellow;">
        <h3>Roles for this user </h3>
        <ol>
            @foreach (string s in ViewBag.RolesForThisUser)
            {
                <li>@s</li>
            }
        </ol>
    </div>
}

While I was using ViewBag it works perfectly except the Validation for theDropdowns ( Required Validation) was not able to implement, so adopted ViewModel with Required Annotation and ViewModel is the recommended way in such scenarios. Appreciate any help . Thanks in advance . Using MVC 5 , CodeFirst EF with Identity.


Solution

  • You are using your identity models in your view model instead of SelectListItem.

    In your view model change

        [Required]
        public List<AppUser> Users { get; set; }
        [Required]
        public List<IdentityRole> Roles { get; set; }
    

    to

        public List<SelectListItem> Users { get; set; }
        public List<SelectListItem> Roles { get; set; }
    

    and add a Required attribute to SelectedIdand SelectedRoleId.

    In your ManageUserRoles action change the population of your view model to

            model.Users = users.Select(s => new SelectListItem
            {
                Value = s.Id.ToString(),
                Text = s.UserName.ToString()
            });
            var roles = context.Roles.ToList();
            model.Roles = roles.Select(s => new SelectListItem
            {
                Value = s.Id.ToString(),
                Text = s.Name.ToString()
            });
    

    Btw, using Select() like this

    var roles = context.Roles.ToList();
            roles.Select(s => new SelectListItem
            {
                Value = s.Id.ToString(),
                Text = s.Name.ToString()
            });
    

    does nothing. You have to assign the results of Select to a variable.