How to render the AspNetUserRole in razor page?

sblb 1,231 Reputation points
2023-11-02T10:49:17.82+00:00

Hi, the post follows on from the exchange in the post here :

https://learn.microsoft.com/en-us/answers/questions/1407352/dynamic-roles-based-authorisation-in-blazor-webass

I tried to mange the User role in AdminPage.razor ; below the code in razor page.


  <table class="table">
        <thead>
            <tr>
                <th>Name</th>
                <th>Authenfication</th>
                <th>Role</th>               
            </tr>
        </thead>
        <tbody>
            @foreach (var userT in aDmin)
            {
                <tr>
                    <td>@userT.UserName</td>
                    <td>@userT.IsAuthenticated</td>
                    <td>
                    <InputSelect @bind-Value="@userT.Role" >
                     @foreach (var roleUser in Enum.GetValues(typeof(RoleUser)))
                                {
									<option value="@roleUser">@roleUser</option>
                                }
                        </InputSelect>
                    </td>
                    <td>@userT.Role</td>
                    <td></td>
                </tr>
            }
        </tbody>
    </table>
@code {
   
    IEnumerable<CurrentUser>? aDmin;

    public string[]? roleUser { get; set; } = Enum.GetNames(typeof(RoleUser));

    protected override async Task OnInitializedAsync() 
    {        
       aDmin = await client.GetFromJsonAsync<CurrentUser[]>("api/auth/CurrentUserInfo"); 
    }

When I run my application I obtain :

User's image

User's image

But I received An unhandled error has occurred

Failed to load resource: the server responded with a status of 404

blazor.webassembly.js:1 crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100] Unhandled exception rendering component: Object reference not set to an instance of an object.System.NullReferenceException: Object reference not set to an instance of an object. at FollowUpDash.Client.Pages.AdministrateurPage.AdminPage.BuildRenderTree(RenderTreeBuilder __builder) in C:\App\sbd\FollowUpDash - LAST - OK - v7\FollowUpDash\Client\Pages\AdministrateurPage\AdminPage.razor:line 37 at Microsoft.AspNetCore.Components.ComponentBase.<.ctor>b__6_0(RenderTreeBuilder builder) at Microsoft.AspNetCore.Components.Rendering.ComponentState.RenderIntoBatch(RenderBatchBuilder batchBuilder, RenderFragment renderFragment, Exception& renderFragmentException)

blazor.webassembly.js:1 crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]

Unhandled exception rendering component: The JSON value could not be converted to FollowUpDash.Shared.Models.CurrentUser[]. Path: $ | LineNumber: 0 | BytePositionInLine: 1.

System.Text.Json.JsonException: The JSON value could not be converted to FollowUpDash.Shared.Models.CurrentUser[]. Path: $ | LineNumber: 0 | BytePositionInLine: 1.

at System.Text.Json.ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(Type propertyType)

at System.Text.Json.Serialization.JsonCollectionConverter`2[[FollowUpDash.Shared.Models.CurrentUser[], FollowUpDash.Shared, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[FollowUpDash.Shared.Models.CurrentUser, FollowUpDash.Shared, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, CurrentUser[]& value)

at System.Text.Json.Serialization.JsonConverter`1[[FollowUpDash.Shared.Models.CurrentUser[], FollowUpDash.Shared, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, CurrentUser[]& value)

at System.Text.Json.Serialization.JsonConverter`1[[FollowUpDash.Shared.Models.CurrentUser[], FollowUpDash.Shared, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)

at System.Text.Json.JsonSerializer.ReadCore[CurrentUser[]](JsonConverter jsonConverter, Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)

at System.Text.Json.JsonSerializer.ReadCore[CurrentUser[]](JsonReaderState& readerState, Boolean isFinalBlock, ReadOnlySpan`1 buffer, JsonSerializerOptions options, ReadStack& state, JsonConverter converterBase)

at System.Text.Json.JsonSerializer.ContinueDeserialize[CurrentUser[]](ReadBufferState& bufferState, JsonReaderState& jsonReaderState, ReadStack& readStack, JsonConverter converter, JsonSerializerOptions options)

at System.Text.Json.JsonSerializer.<ReadAllAsync>d__65`1[[FollowUpDash.Shared.Models.CurrentUser[], FollowUpDash.Shared, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].MoveNext()

at System.Net.Http.Json.HttpContentJsonExtensions.<ReadFromJsonAsyncCore>d__4`1[[FollowUpDash.Shared.Models.CurrentUser[], FollowUpDash.Shared, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].MoveNext()

at System.Net.Http.Json.HttpClientJsonExtensions.<GetFromJsonAsyncCore>d__13`1[[FollowUpDash.Shared.Models.CurrentUser[], FollowUpDash.Shared, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].MoveNext()

at FollowUpDash.Client.Pages.AdministrateurPage.AdminPage.OnInitializedAsync() in C:\App\sbd\FollowUpDash - LAST - OK - v7\FollowUpDash\Client\Pages\AdministrateurPage\AdminPage.razor:line 71

at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()

at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)

How can I fix this problem?

Thanks in advance

Developer technologies .NET Blazor
{count} votes

Accepted answer
  1. AgaveJoe 1,510 Reputation points
    2023-11-03T17:27:25.96+00:00

    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);
                }
            }
        }
    
    }
    
    
    

0 additional answers

Sort by: Most helpful

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.