It's not possible!! What's happen
I've explained this error. There no way for me to figure out what mistakes you are making since you did not provide any code. You should debug your code.
I build a working demo using the design I described several times. This is not production code! Feel free to update the demo code as needed.
Shared models
public class UserModel
{
public string Id { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
}
public class RoleModel
{
public string Id { get; set; } = string.Empty;
public string Name { get; set; } = string.Empty;
}
public class UserRolesModel
{
public string UserName { get; set; } = string.Empty;
public List<string> RoleNames { get; set; } = new List<string>();
}
UserRoles controller (server)
[Route("api/[controller]/[action]")]
[ApiController]
public class UserRolesController : ControllerBase
{
private readonly UserManager<ApplicationUser> _userManager;
private readonly ApiSqliteContext _context;
public UserRolesController(UserManager<ApplicationUser> userManager, ApiSqliteContext context)
{
_userManager = userManager;
_context = context;
}
[HttpGet]
public IActionResult GetUserWithoutRoles()
{
var usersWithoutRoles = _context.Users.FromSqlRaw($@"SELECT u.*
FROM AspNetUsers u
LEFT JOIN AspNetUserRoles ur ON u.Id = ur.UserId
WHERE ur.UserId IS NULL")?.Select(u => new UserModel()
{
Id = u.Id,
UserName = u.UserName,
Email = u.Email
});
return Ok(usersWithoutRoles);
}
[HttpGet("{Username}")]
public async Task<IActionResult> GetUserRolesByUsername(string Username)
{
UserRolesModel model = new UserRolesModel() { UserName = Username };
ApplicationUser? user = _context.Users.FirstOrDefault(u => u.UserName == Username);
IList<string> roles = await _userManager.GetRolesAsync(user);
model.RoleNames = roles.ToList();
return Ok(model);
}
[HttpPost]
public async Task<IActionResult> UpdateUserRoles(UserRolesModel input)
{
//Remove all the user's roles.
ApplicationUser? user = _context.Users.FirstOrDefault(u => u.UserName == input.UserName);
IList<string> roles = await _userManager.GetRolesAsync(user);
foreach(var role in roles)
{
await _userManager.RemoveFromRoleAsync(user, role);
}
foreach(var role in input.RoleNames)
{
await _userManager.AddToRoleAsync(user, role);
}
UserRolesModel model = new UserRolesModel() { UserName = user.UserName };
model.RoleNames = (await _userManager.GetRolesAsync(user)).ToList();
return Ok(model);
}
}
Users controller (server)
[Route("api/[controller]")]
[ApiController]
public class UsersController : ControllerBase
{
private readonly ApiSqliteContext _context;
public UsersController(ApiSqliteContext context)
{
_context = context;
}
[HttpGet]
public async Task<IActionResult> Get() {
List<UserModel> users = await _context.Users.Select(u => new UserModel()
{
Id = u.Id,
UserName = u.UserName,
Email = u.Email
}).ToListAsync();
return Ok(users);
}
}
Roles Controller (server)
[Route("api/[controller]")]
[ApiController]
public class RolesController : ControllerBase
{
private readonly ApiSqliteContext _context;
public RolesController(ApiSqliteContext context)
{
_context= context;
}
public async Task<IActionResult> Get()
{
List<RoleModel> roles = await _context.Roles.Select(r => new RoleModel() { Id = r.Id, Name = r.Name }).ToListAsync();
return Ok(roles);
}
}
App users component that list the users (client)
@page "/appusers"
@using BlazorWasmHosted.Shared
@inject HttpClient Http
@inject NavigationManager Navigation
@attribute [Authorize(Roles = "Admin")]
<PageTitle>Users Accounts</PageTitle>
<h1>User Accounts</h1>
@if (userAccounts == null)
{
<p><em>Loading...</em></p>
}
else
{
<table class="table">
<thead>
<tr>
<th>UserName</th>
<th>Email</th>
</tr>
</thead>
<tbody>
@foreach (var userAccount in userAccounts)
{
<tr>
<td>@userAccount.UserName</td>
<td>@userAccount.Email</td>
<td>
<button class="btn btn-primary" @onclick="@(e => NavigateToUserRolesComponent(userAccount.UserName))">
Edit Roles
</button>
</td>
</tr>
}
</tbody>
</table>
}
@code {
private UserModel[]? userAccounts;
protected override async Task OnInitializedAsync()
{
userAccounts = await Http.GetFromJsonAsync<UserModel[]>("api/Users");
}
private void NavigateToUserRolesComponent(string Id)
{
Navigation.NavigateTo($"userroles/{Id}");
}
}
User roles component to manage roles (client)
@page "/userroles/{Username}"
@inject HttpClient Http
@inject NavigationManager Navigation
@inject ILogger<UserRoles> Logger
<PageTitle>User Roles</PageTitle>
<h1>User Role Management</h1>
<hr />
@if (roles == null)
{
<p><em>Loading...</em></p>
}
else
{
<EditForm Model="userRolesModel" OnValidSubmit="@Submit">
<div>Managing roles for @Username </div>
<input type="hidden" @bind-value="Username" name="Username" />
<div>
@foreach (var role in roles)
{
<div>
<input type="checkbox"
value="role.Name"
name="RoleNames"
checked="@IsInRole(role.Name)"
@onchange="eventArgs => { CheckboxClicked(role.Name, eventArgs.Value); }"> @role.Name
</div>
}
</div>
<div>
<button type="submit">Submit</button>
</div>
</EditForm>
}
@code {
private RoleModel[] roles;
private UserRolesModel userRolesModel { get; set; } = new();
protected override async Task OnInitializedAsync()
{
//Get the user's roles by username
userRolesModel = await Http.GetFromJsonAsync<UserRolesModel>($"api/UserRoles/GetUserRolesByUsername/{Username}");
//Get the roles from the database
roles = await Http.GetFromJsonAsync<RoleModel[]>("api/Roles");
}
private bool IsInRole(string RoleName)
{
return userRolesModel.RoleNames.Any(r => r == RoleName);
}
[Parameter]
public string? Username { get; set; }
async Task Submit()
{
userRolesModel.UserName = Username;
Logger.LogInformation("Username = {username}", userRolesModel.UserName);
foreach (string role in userRolesModel.RoleNames)
{
Logger.LogInformation("RoleName = {role}", role);
}
await Http.PostAsJsonAsync<UserRolesModel>("api/UserRoles/UpdateUserRoles", userRolesModel);
Navigation.NavigateTo($"appusers");
}
private void CheckboxClicked(string role, object isChecked)
{
if ((bool)isChecked)
{
if (!userRolesModel.RoleNames.Contains(role))
{
userRolesModel.RoleNames.Add(role);
}
}
else
{
if (userRolesModel.RoleNames.Contains(role))
{
userRolesModel.RoleNames.Remove(role);
}
}
}
}