Search code examples
c#asp.net-mvcasp.net-identity

Don't save the value in extra field in IdentityRole


In IdentityFramework I add new field for my database the standart table Role(Description),enter image description here

When I add the new role, I want to have the description for this role.

I make the cshtml file

@using (Html.BeginForm("CreateRole", "Role", FormMethod.Post))
{
@Html.AntiForgeryToken()
<div id="create-role-box">
    @Html.ValidationSummary(false)

    <div class="form-group">
        <label class="create-role-color">Название роли:</label>
        @Html.TextBoxFor(x => x.Name, new { @class = "input-form-create-role create-role-color" })
        @Html.ValidationMessageFor(x => x.Name)
    </div>

    <div class="form-group">
        <label class="create-role-color">Описание роли:</label>
        @Html.TextBoxFor(x => x.Description, new { @class = "input-form-create-role create-role-color" })
        @Html.ValidationMessageFor(x => x.Description)
    </div>

    <div class="form-group" style="margin: 22px 0px 0px 0px;">
        <button type="submit" class="button-create-role">Добавить</button>

        @Html.ActionLink("Отмена", "Index", null, new { @class = "button-cancel" })
    </div>
</div>

}

post query in controller

 public async Task<ActionResult> CreateRole([Required]string name, string description)
    {
        if (ModelState.IsValid)
        {
            IdentityResult result = await roleManager.CreateRoleAsync(name, description);

            if (result.Succeeded)
            {
                return RedirectToAction("Index");
            }
            else
            {
                AddErrorsFromResult(result);
            }
        }
        return View(name);
    }

the CreateRoleAsync(name, description); method i discribe in repository

 public async Task<IdentityResult> CreateRoleAsync(string name, string description)
    {
        IdentityResult result = await userRole.CreateAsync(new UserRole(name, description));
        return result;
    }

and my UserRole model is

public class UserRole : IdentityRole
{
    public UserRole(string name, string description) : base(name)
    {
        description = Description;
    }

    public string Description { get; set; }
}

and if it's need my context

public class IdentityUserContext : IdentityDbContext<UserModel>
{
    public IdentityUserContext() : base("UserIdentityDbContext")
    {

    }
    // creating method realize by ninject in Ninject.Web.Common.cs WebUI->App_Start
}

the problem is that the description doesn't save in database,problem,

it's null but the method take the value of the description, why id isn't save in database.


Solution

  • First rename your UserRole class to ApplicationRole as follows because UserRole is confusing. UserRole should be named for User and Role many-to-many join table.

    public class ApplicationRole : IdentityRole
    {
        public ApplicationRole(string name) : base(name){}
    
        public string Description { get; set; }
    }
    

    Now create a RoleViewModel as follows:

    public class RoleViewModel
    {
        public string Id { get; set; }
        [Required(AllowEmptyStrings = false)]
        [Display(Name = "RoleName")]
        public string Name { get; set; }
        public string Description { get; set; }
    }
    

    Then your Create view:

    @model Domain.ViewModels.RoleViewModel
    
    @using (Html.BeginForm())
    {
        // Your input fields and submit button here
    }
    

    Now write your CreateRole Post method as follows:

    [HttpPost]
    public async Task<ActionResult> CreateRole(RoleViewModel roleViewModel)
    {
        if (ModelState.IsValid)
        {
            var role = new ApplicationRole(roleViewModel.Name);
            role.Description = roleViewModel.Description; // <--- Here you have to assign the `Description` value
    
            var roleresult = await RoleManager.CreateAsync(role);
            if (!roleresult.Succeeded)
            {
                ModelState.AddModelError("", roleresult.Errors.First());
                return View();
            }
            return RedirectToAction("Index");
        }
        return View();
    }
    

    Now everything will work fine!


    If you want to create role from your repository method then write your CreateRoleAsync repository method as follows:

    public async Task<IdentityResult> CreateRoleAsync(ApplicationRole applicationRole)
    {
        IdentityResult result = await userRole.CreateAsync(applicationRole);
        return result;
    }
    

    Then call it in controller method as follows:

    [HttpPost]
    public async Task<ActionResult> CreateRole(RoleViewModel roleViewModel)
    {
        if (ModelState.IsValid)
        {
            var role = new ApplicationRole(roleViewModel.Name);
            role.Description = roleViewModel.Description; // <--- Here you have assign the Description value
    
            IdentityResult result = await roleManager.CreateRoleAsync(role); // <-- call your repository method here.
    
            if (!roleresult.Succeeded)
            {
                ModelState.AddModelError("", roleresult.Errors.First());
                return View();
            }
            return RedirectToAction("Index");
        }
        return View();
    }