Building a User administration page, how to do it

Posted 3 years ago by mgp
Edited 3 years ago
0

Hi, I'm struggling to add an admin page that list the Application Users. I was hoping I could just use something like List(IdentityUser) users = context.Users.ToList() and in my html just loop through the list. Is there a simple way to do this? I noticed that the App.razor page uses the context to get the Current User.

  • 1

    I'm going to assume you're trying to do this in the client. I'm not completely sure if this is a secure enough way or the best approach, but hopefully someone will chime in if it isn't.

    Keep in mind, this example isn't setup to Authorize by Roles, but it would need to be. I've kept it simpler in order to answer the specific question.

    First, you'll need to add the Microsoft.AspNetCore.Identity.EntityFrameworkCore NuGet package to the Client project and the Shared project (or maybe a Models project if your architecture is setup that way).

    Add a using directive to your Client _Imports file

    @using YourProject.Shared

    Copy the ApplicationUser.cs file from YourProject.Server > Models to YourProject.Shared. This model just inherits IdentityUser.

    public class ApplicationUser : IdentityUser
    {
    }

    If you wanted, you could add some validation attributes

    public class ApplicationUser : IdentityUser
    {
        [Required]
        [MaxLength(256)]
        public override string UserName { get; set; }
    }

    Create a Controller in your Server project called MembersController

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using YourProject.Server.Models;
    using Microsoft.AspNetCore.Authorization;
    using Microsoft.AspNetCore.Identity;
    using Microsoft.AspNetCore.Mvc;
    
    namespace YourProject.Server.Controllers
    {
        [Authorize]
        [ApiController]
        [Route("api/members")]
        public class MembersController : ControllerBase
        {
            private UserManager<ApplicationUser> _userManager;
    
            public MembersController(UserManager<ApplicationUser> userManager)
            {
                _userManager = userManager;
            }
    
            [HttpGet]
            public List<ApplicationUser> Get()
            {
                try
                {
                    var users = _userManager.Users.OrderBy(p => p.UserName).ToList();
                    return users;
                }
                catch(Exception ex)
                {
                    throw ex;
                }
            }
        }
    }

    And add a component (i.e. Members.razor)

    @page "/admin/membership"
    @using Microsoft.AspNetCore.Authorization
    @using Microsoft.AspNetCore.Components.WebAssembly.Authentication
    
    @inject HttpClient HttpClient
    @attribute [Authorize]
    
    <h3>Users</h3>
    
    @if (_users == null)
    {
        <span>Loading Users...</span>
    }
    else
    {
        <ul>
            @foreach (var user in _users)
            {
                <li>@user.UserName</li>
            }
        </ul>
    }
    
    <div class="@_exceptionClass">
        @_error
    </div>
    
    @code {
        private List<ApplicationUser> _users;
        private string _exceptionClass = "d-none";
        private string _error;
    
        protected override async Task OnInitializedAsync()
        {
            try
            {
                _users = await HttpClient.GetFromJsonAsync<List<ApplicationUser>>("api/members");
            }
            catch (AccessTokenNotAvailableException exception)
            {
                exception.Redirect();
            }
            catch(Exception ex)
            {
                _exceptionClass = "d-block alert alert-danger";
                _error = ex.Message;
            }
        }
    
    }
    Posted 3 years ago by selliott Edited 3 years ago
  • 0

    First of all, I do not see a user name for who replied with this, but whoever it was, Thank you very much! (Ah, never mind, when I posted this reply your name appears, Thank you very much selliot!)

    While I waited for an answer, I just created a model with the fields I want the application administrators to see. I then created a controller based on that model. In the Crud methods I simply queried the Users Table and moved the data over to the class variables in a lambda statement. This worked, but the above was what I was wanting. I did not want to write another model class then remove code from my migrations to keep an unnecessary table from being created. 

    Of course, I'm going to use an authorize attribute on the page, in the controller, and an authorizeview in the navmenu using roles authorization. Is there anything else I need to do to secure the page and source? 

    Also I have another question that may or may not be related to this page. I took authorization off in order to test the page while I develop it.  I seem to be getting an AccessTokenNotAvailableException even when I am not protecting the page. That bugs me because public pages should not be getting those errors should they? I handled it in a try catch with a redirect, which takes me to a login page. But again why is the page getting Access token error when no authorization is on the page or the controller?

    Posted 3 years ago by mgp Edited 3 years ago
  • 1

    When you want to allow anonymous access, you can add another HttpClient to your Program.cs file in the Client project.

    builder.Services.AddHttpClient("YourProject.AnonymousAPI", client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress));

    Then you need to inject IHttpClientFactory into your component

    @inject IHttpClientFactory httpClientFactory

    Then when you call your Controller, it would be something like this

    var http = httpClientFactory.CreateClient("YourProject.AnonymousAPI");
    var response = await http.PostAsJsonAsync<string>("api/somepagenamehere");
    Posted 3 years ago by selliott Edited 3 years ago
  • 0

    Wow Selliott. Thank you again that worked. =)

    Posted 3 years ago by mgp
Someone is typing...

Post a Reply

You must be logged in to add a new post.
Number of online users: 0
An error has occurred. This application may no longer respond until reloaded. Reload 🗙