How to update User Roles along with other data through .NetCore 8 WebAPI –

P. G. Choudhury 41 Reputation points
2024-11-14T10:52:18.1233333+00:00

Hi forum members,

As the question suggests, I am facing some difficulty in updating user roles with other data through my code. I am unable to visualize how to do it. Let me explain the scenario in detail.

I have used .netcore Identity and EntityFramework to set up the database for my application. I modified my IdentityUser entity so that it contains some additional fields like FullName, MobileNumber and SubscriptionType. SubscriptionType can be Monthly, Quarterly or Yearly. The AspNetRoles table has 4 roles in it like Actor, Musician, Painter, Photographer. While registration/creating new user I am providing the requisite info which includes Role also and all the data is being saved to the AspNetUsers and AspNetUserRoles tables as expected. I am able to fetch the data for a logged in user. What I want next is to provide Update functionality so that the logged in user can update his/her MobileNumber, SubscriptionType and Role. This is where my knowledge is falling short as I am unable to construct the code. Needless to mention, only an authorized user should be able to update self profile.

Surely the update operation should be based on user id of the logged in entity. I understand that the RoleId in AspNetUserRoles table should get updated with the new value. Also, the code block should check if the edited new MobileNumber exists in the database and should give error. This is my requirement. I am using minimal API approach in my project .  Let me share some code from my project so you can see the parts that I have put in place till now.

Program.cs  -

using ForSideSystems.API.Data;
using ForSideSystems.API.Models;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.SqlServer;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using System.Text;
using ForSideSystems.API.Extensions;
using ForSideSystems.API.Controllers;
 
 
var builder = WebApplication.CreateBuilder(args);
 
// Add services to the container.
builder.Services.AddControllers();
 
… blablabla
- blablabla
- blablabla
 
app.UseDefaultFiles();
app.UseStaticFiles();
 
app.MapControllers();
 
app.MapGroup("/api/Accounts")
    .MapAccountEndpoints();
 
app.Run();

AccountEndpoints.cs –

public static class AccountEndpoints
{
    public static IEndpointRouteBuilder MapAccountEndpoints(this IEndpointRouteBuilder app)
    {
        app.MapGet("/userprofile", GetUserProfile);
       //app.MapPut("/updateuserprofile", UpdateUserProfile);
       //or I am not sure could be
       // app.MapPost("/updateuserprofile", UpdateUserProfile);      
 return app;
    }
 
    [Authorize]
    private static async Task<IResult> GetUserProfile(ClaimsPrincipal user, UserManager<AppUser> userManager)
    {
        string userName = user.Claims.First(x => x.Type == "name").Value;
        string role = user.FindFirst(ClaimTypes.Role).Value;
 
        string currentUserID = user.FindFirst(ClaimTypes.NameIdentifier).Value;
 
        var loggedInUser = await userManager.FindByIdAsync(currentUserID);
 
        return Results.Ok(new
        {
            FullName = userName,
            Email = loggedInUser.Email,
            Mobile = loggedInUser.MobileNumber,
            SubscriptionType = loggedInUser.SubscriptionType,
            Role=role
        });
    }
 
}

AppUser.cs -

public class AppUser : IdentityUser
{
    public string FullName { get; set; } = string.Empty;

    public string MobileNumber { get; set; } = string.Empty;
    public string SubscriptionType { get; set; } = string.Empty;
}

As you can see, inside the AccountEndpoints.cs class there is GetUserProfile method to fetch and show logged in user details. I am parsing the jWT token sent from swagger authorize facility to get my necessary information. If you need more code block from my existing and working code base, please do ask, I will be more than glad to share.

Please help me construct the logic and the code for the UpdateUserProfile method. Some help needed from you on this scenario. Been stuck with this for few days now.

Thanks in advance,

Microsoft Identity Manager
Microsoft Identity Manager
A family of Microsoft products that manage a user's digital identity using identity synchronization, certificate management, and user provisioning.
709 questions
Entity Framework Core
Entity Framework Core
A lightweight, extensible, open-source, and cross-platform version of the Entity Framework data access technology.
754 questions
ASP.NET Core
ASP.NET Core
A set of technologies in the .NET Framework for building web applications and XML web services.
4,639 questions
ASP.NET API
ASP.NET API
ASP.NET: A set of technologies in the .NET Framework for building web applications and XML web services.API: A software intermediary that allows two applications to interact with each other.
346 questions
{count} votes

2 answers

Sort by: Most helpful
  1. Bruce (SqlWork.com) 67,251 Reputation points
    2024-11-14T22:01:56.1133333+00:00

    did you follow the docs:

    https://learn.microsoft.com/en-us/aspnet/core/security/authentication/customize-identity-model?view=aspnetcore-8.0

    the is a roles domain table, and user / role join tables that maps a user to their roles. in the user principal, roles are added as claims. this load is usually done by the role provider when the authentication ticket is mapped to a user principal.

    in your sample, you are getting the role from eh principal, but you don't show the code where you add the role support like:

    builder.Services.AddDefaultIdentity<IdentityUser>( ... )  
        .AddRoles<IdentityRole>()
    

  2. P. G. Choudhury 41 Reputation points
    2024-11-15T14:40:57.9466667+00:00

    Hi @AgaveJoe @Bruce (SqlWork.com) and @Tiny Wang-MSFT

    I finally managed to implement the method for updating user role alongwith other user data like MobileNumber & SubscriptionType.

    The logic was to first remove the entry from AspNetUserRoles for the logged in user and add the new role freshly.
    Like so:
    await userManager.RemoveFromRoleAsync(loggedInUser, role); var roleResult = await userManager.AddToRoleAsync(loggedInUser, updateModel.Role);

    The full code in AccountEndpoints.cs class :

    [Authorize]
    private static async Task<IResult> UpdateUserProfile([FromBody] UpdateUserViewModel updateModel, ClaimsPrincipal user, UserManager<AppUser> userManager)
    {
        string loggedInUserID = user.FindFirst(ClaimTypes.NameIdentifier).Value;
        var loggedInUser = await userManager.FindByIdAsync(loggedInUserID);
        string role = user.FindFirst(ClaimTypes.Role).Value;
        if (loggedInUser != null)
        {
            loggedInUser.SubscriptionType = updateModel.SubscriptionType;
            loggedInUser.MobileNumber = updateModel.MobileNumber;
            
            var result = await userManager.UpdateAsync(loggedInUser);
            if (result.Succeeded)
            {
                await userManager.RemoveFromRoleAsync(loggedInUser, role);
                var roleResult = await userManager.AddToRoleAsync(loggedInUser, updateModel.Role);
                if(roleResult.Succeeded)
                {
                    return Results.Ok(new
                    {
                        Message = "User primary details updated!"
                    });
                }
                else
                {
                    return Results.BadRequest(new
                    {
                        Message = "Unable to update user role!"
                    });
                }
            }
            else
            {
                return Results.BadRequest(new
                {
                    Message = "Problem updating user primary details!"
                });
            }
        }
        else
        {
            return Results.NotFound(new
            {
                Message = "No user found with given credentials!"
            });
        }
    }
    

    I have updated my git repo with the latest working changes. So you can find it there too.

    Thanks anyways,

    0 comments No comments

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.