How to improve the role management in Blazor Server?

Cenk 1,036 Reputation points
2024-01-13T11:33:36.54+00:00

Hi,

I am working on a Blazor Server application. I am using identity management. I have 2 issues to get help.

In my application, I have these roles:

string[] roles = new string[] { "Administrators", "User", "Accountant", "Warehouse", "Test" };

There is a user management section in my application, that lists all the users and their roles. If the admin edits a user, this modal popup below opens with the selected user's details. In this screenshot, this user's role is User. (dropdown)

Ekran görüntüsü 2024-01-13 140643

Here is how popup displays

async Task EditUser(IdentityUser _IdentityUser)
{
    // Set the selected user
    // as the current user
    objUser = _IdentityUser;

    // Get the user
    var user = await _UserManager.FindByIdAsync(objUser.Id);
    if (user != null)
    {
    // Is user in administrator role?
    var UserResult =
        await _UserManager
        .IsInRoleAsync(user, ADMINISTRATION_ROLE);

        CurrentUserRole = UserResult ? ADMINISTRATION_ROLE : "User";
    }

	// Open the Popup
	ShowPopup = true;

}


<div class="modal" tabindex="-1" style="display: block" role="dialog">

        <div class="modal-dialog">

            <div class="modal-content">

                <div class="modal-header">

                    <h3 class="modal-title">User Details</h3>

                    <!-- Button to close the popup -->

                    <button type="button" class="close"
                    @onclick="ClosePopup">

                        <span aria-hidden="true">X</span>

                    </button>

                </div>

                <!-- Edit form for the current user -->

                <div class="modal-body">

                    <!-- Only show Id if not a new user -->
                    @if (objUser.Id != "")

                    {
                        <p>@objUser.Id</p>
                    }

                    <!-- Only allow edit if a new user -->
                    @if (objUser.Id != "")

                    {
                        <p>@objUser.UserName</p>
                    }

                    else

                    {
                        <input class="form-control" type="text"
                   placeholder="UserName"
                   @bind="objUser.UserName" style="margin-bottom: 10px"/>
                    }

                    <input class="form-control" type="text"
                   placeholder="Email"
                   @bind="objUser.Email" style="margin-bottom: 10px"/>

                    <input class="form-control" type="password"
                   placeholder="Password"
                   @bind="objUser.PasswordHash" style="margin-bottom: 10px"/>

                    <select class="form-control"
                    @bind="@CurrentUserRole" style="margin-bottom: 10px">

                        @foreach (var option in Options)

                        {
                            <option value="@option">

                                @option

                            </option>
                        }

                    </select>

                    <br /><br />

                    <!-- Button to save the user -->

                    <button class="btn btn-primary"
                    @onclick="SaveUser" style="margin-right: 10px">

                        Save

                    </button>

                    <!-- Only show delete button if not a new record -->
                    @if (objUser.Id != "")

                    {
                        <!-- Button to delete the forecast -->

                        <button class="btn btn-danger"
                    @onclick="DeleteUser">

                            Delete

                        </button>
                    }

                    <br />

                    <span style="color: red">@strError</span>

                </div>

            </div>

        </div>

    </div>
}
  1. How can I set the CurrentUserRole (dropdown) so that it does not set only the User role? I want the user's role to be selected on the dropdown.
  2. After updating a user's role through the modal popup in my application, that user's role is updated in the modal, but not in the [AspNetUserRoles] table in the database. How can I ensure that the table is updated correctly when a user's role is changed through the modal?

Here is the database records. All users seem to have a User role, but in the modal, it looks OK.

asp.net_roles

aspnet_user_roles

Developer technologies | ASP.NET | ASP.NET Core
Developer technologies | .NET | Blazor
Developer technologies | C#
{count} votes

1 answer

Sort by: Most helpful
  1. AgaveJoe 30,126 Reputation points
    2024-01-13T21:36:57.9466667+00:00

    It is not clear how your modal works and there are other unknowns in the code.
    A modal is HTML that is shown or hidden. With that in mind I created the following working example. The component shows a list of users with a button that selects the user. Selecting a user shows the use below the line (<hr />) and selects the user's role from the InputSelect. If the user is not in a role then "--Select--" is displayed. Select a role and click the Update User Role button to assign the role. Click the "Select User" button to see what role the user is in. Keep in mind, this is demo code to convey a concept it is not production ready code.
    The code also assumes you have the RoleManager configured in Program.cs.

    builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
        .AddRoles<IdentityRole>()
        .AddEntityFrameworkStores<ApplicationDbContext>();
    

    Sample

    @page "/useradmin/userrolemanager"
    @using Microsoft.AspNetCore.Identity;
    <h3>User Role Manager</h3>
    
    <div>
        <table class="table">
            <thead>
                <tr>
                    <th>Id</th>
                    <th>Username</th>
                    <th>Email</th>
                    <th></th>
                </tr>
            </thead>
            <tbody>
                @foreach (var user in users)
                {
                    <tr>
                        <td>@user.Id</td>
                        <td>@user.UserName</td>
                        <td>@user.Email</td>
                        <td><button @onclick="() => SelectUser(user.Id)">Select User</button></td>
                    </tr>
                }
            </tbody>
        </table>
    </div>
    <hr />
    <div>
        <div>
            @selectedUser
        </div>
        <div>
            <InputSelect @bind-Value="userRole">
                <option value>--select--</option>
                @foreach(var role in roles)
                {
                    <option value="@role.Name">
                        @role.Name
                    </option>
                }
            </InputSelect>
        </div>
        <div>
            <button @onclick="() => UpdateUserRole()">Update User Role</button>
        </div>
    </div>
    
    @code {
        [Inject]
        public RoleManager<IdentityRole> roleManager { get; set; }
        [Inject]
        public UserManager<IdentityUser> userManager { get; set; }
    
        private List<IdentityRole> roles = new List<IdentityRole>();
        private List<IdentityUser> users = new List<IdentityUser>();
        private string selectedUser { get; set; } = "Select a user";
        private string userRole { get; set; }
    
        protected override async Task OnInitializedAsync()
        {
            roles = roleManager.Roles.ToList();
            users = userManager.Users.ToList();
        }
    
        private async Task SelectUser(string id)
        {
            var user = await userManager.FindByIdAsync(id);
            selectedUser = user.UserName;
            userRole = (await userManager.GetRolesAsync(user)).FirstOrDefault() ?? "";
        }
    
        private async Task UpdateUserRole()
        {
            var user = await userManager.FindByNameAsync(selectedUser);
            var uRole = (await userManager.GetRolesAsync(user)).FirstOrDefault();
            if (uRole != null)
            {
                await userManager.RemoveFromRoleAsync(user, uRole);
            }
            await userManager.AddToRoleAsync(user, userRole);
        }
    }
    
    

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.