1

I want to create roles with respective claims in asp.net core 2+, so I create a view like:

@page
@model Security.Dto.Models.ApplicationRoleModel

<form asp-controller="security" asp-action="CreateRole" method="post">

    <h4>Create new Role</h4>
    <hr />
    <div asp-validation-summary="All" class="text-danger"></div>
    <div class="form-group" id="item-list">
        <label>Role Name</label>
        <input asp-for="RoleClaimList[0].Role.Name" class="form-control roles" />
    </div>
    <a href="#" id="add">Add another</a>


    <div class="form-group" id="claim-list">
        <label>Claim Type</label>
        <input asp-for="RoleClaimList[0].ClaimList[0].Type" class="form-control " />
        <label>Claim Value</label>
        <input asp-for="RoleClaimList[0].ClaimList[0].Value" class="form-control claims" />
    </div>
    <br />
    <button type="submit" class="btn btn-default">Create</button>

</form>

@section Scripts {
    <script>
        $(function () {
            $("#add").click(function (e) {
                e.preventDefault();
                var i = ($(".roles").length);
                var n = '<label>Role Name</label><input class="form-control roles" name="RoleClaimList[' + i + '].Role.Name" />'
                $("#item-list").append(n);
            });

        });
    </script>
}

Controller:

public async Task<IActionResult> CreateRole(ApplicationRoleModel model)
        {
            try
            {
                foreach (var item in model.RoleClaimList)
                {
                    var roleExists = await _roleManager.RoleExistsAsync(item.Role.Name);
                    if (roleExists) continue;
                    var createRole = _roleManager.CreateAsync(item.Role);
                    foreach (var claim in item.ClaimList)
                    {
                        await _roleManager.AddClaimAsync(item.Role, claim);
                    }
                }
                return Ok();
            }
            catch (Exception e)
            {
                return BadRequest();
            }
        }

ApplicationRoleModel:

public class ApplicationRoleModel 
    {
        public List<RoleClaimModel> RoleClaimList { get; set; }
      
    }

RoleClaimModel:

 public class ClaimsToRoleModel
    {
        public List<RoleClaimModel> RoleClaimList { get; set; }
    }

    public class RoleClaimModel
    {
        public ApplicationRole Role { get; set; }
        public List<Claim> ClaimList { get; set; }
    }

So when I run and debbug it, Role come correctly but ClaimList always count 0 or come null

enter image description here

Someone looks what am I doing wrong? How can I map ClaimList property model correctly from view?

Regards

1 Answer 1

1

Your problem is caused because the Claim class doesn't have a constructor that takes 0 parameters so when the framework attempts to create a new one it cannot, so you end up with an empty or null object.

To solve the issue you need to use your own custom class in your hierarchy:

public class CustomClaim
{
    public string Type { get; set; }
    public string Value { get; set; }
}

public class RoleClaimModel
{
    public ApplicationRole Role { get; set; }
    public List<CustomClaim> ClaimList { get; set; }
}

Now the framework can create the CustomClaim and serialize it to your API. In your controller you can translate your CustomClaim into the .NET Claim and pass that to your _roleManager:

public async Task<IActionResult> CreateRole(ApplicationRoleModel model)
{
    try
    {
        foreach (var item in model.RoleClaimList)
        {
            var roleExists = await _roleManager.RoleExistsAsync(item.Role.Name);
            if (roleExists) continue;
            var createRole = _roleManager.CreateAsync(item.Role);
            foreach (var claim in item.ClaimList)
            {
                var c = new System.Security.Claims.Claim(claim.Type, claim.Value);

                await _roleManager.AddClaimAsync(item.Role, c);
            }
        }
        return Ok();
    }
    catch (Exception e)
    {
        return BadRequest();
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.