13

I'm new to ASP.NET Core, most of my existing experience is with Java/PHP, and a little ASP.NET MVC about 10 years ago.

I'm using a Mac so I'm trying to build a project using Visual Studio Code and ASP.NET Core.

I've created a web application using 'yo'. I've changed the default database connection string to use an MSSQL database I have on a server. I've ran the dotnet ef database update command to create the necessary tables in the database.

I wanted to add firstname and lastname to the user, so I've created the columns in the AspNetUser table, and edited the ApplicationUser class to reflect this;

namespace pabulicms.Models
{
    // Add profile data for application users by adding properties to the ApplicationUser class
    public class ApplicationUser : IdentityUser
    {    
        public string Firstname { get; set; }
        public string Lastname { get; set; }
    }
}

I've gone ahead and amended the view model for the registration form to include the firstname and lastname, and I've updated the Signup method so that the firstname and lastname is saved to the database.

By default the _LoginPartial.cshtml view displays the users username(email address), I'd like to change this to display the users full name, but I'm unsure as to how I do this.

This is what the _LoginPartial looks like at the moment;

@using Microsoft.AspNetCore.Identity
@using pabulicms.Models

@inject SignInManager<ApplicationUser> SignInManager
@inject UserManager<ApplicationUser> UserManager

@if (SignInManager.IsSignedIn(User))
{
    <form asp-area="" asp-controller="Account" asp-action="Logout" method="post" id="logoutForm" class="navbar-right">
        <ul class="nav navbar-nav navbar-right">
            <li>
                <a asp-area="" asp-controller="Manage" asp-action="Index" title="Manage">Hello @UserManager.GetUserName(User)!</a>
            </li>
            <li>
                <button type="submit" class="btn btn-link navbar-btn navbar-link">Log out</button>
            </li>
        </ul>
    </form>
}
else
{
    <ul class="nav navbar-nav navbar-right">
        <li><a asp-area="" asp-controller="Account" asp-action="Register">Register</a></li>
        <li><a asp-area="" asp-controller="Account" asp-action="Login">Log in</a></li>
    </ul>
}

It's obviously this line I need to change;

Hello @UserManager.GetUserName(User)!

However changing it to @UserManager.GetFirstname(User)! doesn't work, as it tells me that the method GetFirstname doesn't exist;

haldo
  • 8,119
  • 5
  • 24
  • 35
SheppardDigital
  • 2,671
  • 6
  • 33
  • 57

4 Answers4

30

I searched a lot and finally found this solution:

Change this: @UserManager.GetUserName(User)

To this: @UserManager.GetUserAsync(User).Result.LastName

refer to: Link

7

ASP.NET Core Identity library uses claims-based approach to Authorization. It means that a logged in user (the one you can access via User object in your views) has some list of claims (name-value pairs) associated with it. By default, that list contains two claims: for ID and username. However, it's easy to add to that list any other claim you need (first/last name, the name of the company, current user's balance, etc.).
You will just need to create your own implementation of IUserClaimsPrincipalFactory interface and register it in DI to override the default one.

Here is the article with a step-by-step description how to do it.

You can skip the first part ("zero" part to be more exact) "Preparations" if you already have the additional properties (like FirstName/LastName) in your ApplicationUser class.

Sergiy
  • 1,807
  • 2
  • 16
  • 23
JohnAssist
  • 71
  • 1
  • 2
2

In the end I used a view component.

First I created a view component myprojectname/ViewComponents/AccountStatusViewComponent.cs

namespace myprojectname.ViewComponents
{
    public class AccountStatusViewComponent : ViewComponent
    {

        private readonly SignInManager<ApplicationUser> _signInManager;
        private readonly UserManager<ApplicationUser> _userManager;

        public AccountStatusViewComponent(SignInManager<ApplicationUser> signInManager, UserManager<ApplicationUser> userManager)
        {
            _signInManager = signInManager;
            _userManager = userManager;
        }

        public async Task<IViewComponentResult> InvokeAsync()
        {
            AccountStatusModel model = new AccountStatusModel();
            model.User = _userManager.GetUserAsync(Request.HttpContext.User).Result;

            return View(model);
        }
    }
}

Next I created the view for the view component myprojectname/Views/Shared/Components/AccountStatus/Default.cshtml

@model AccountStatusModel

@using Microsoft.AspNetCore.Identity
@using myprojectname.Models.ViewComponentModels;
@using myprojectname.Models

@inject SignInManager<ApplicationUser> SignInManager
@inject UserManager<ApplicationUser> UserManager

@if (SignInManager.IsSignedIn(User))
{
    <form asp-area="" asp-controller="Account" asp-action="Logout" method="post" id="logoutForm" class="navbar-right">
        <ul class="nav navbar-nav navbar-right">
            <li>
                <a asp-area="" asp-controller="Manage" asp-action="Index" title="Manage">Hello @Model.User.Firstname @Model.User.Lastname</a>
            </li>
            <li>
                <button type="submit" class="btn btn-link navbar-btn navbar-link">Log out</button>
            </li>
        </ul>
    </form>
}
else
{
    <ul class="nav navbar-nav navbar-right">
        <li><a asp-area="" asp-controller="Account" asp-action="Register">Register</a></li>
        <li><a asp-area="" asp-controller="Account" asp-action="Login">Log in</a></li>
    </ul>
}

I created a model to hold the data I wanted passing the view in myprojectname/Models/ViewComponentModels/AccountStatusModel.cs

using System;
namespace pabulicms.Models.ViewComponentModels
{
    public class AccountStatusModel
    {
        public ApplicationUser User { get; set; }
    }
}

Finally, in the example .NET website I edited the file Views/Shared/_Layout.cshtml and replaced this line;

@await Html.PartialAsync("_LoginPartial")

With;

@await Component.InvokeAsync("AccountStatus")
SheppardDigital
  • 2,671
  • 6
  • 33
  • 57
-1

my simple way :

top of view

@{
    @inject UserManager<ApplicationUser> UserManager;
    var DisplayName= UserManager.Users.FirstOrDefault(m=>m.UserName==User.Identity.Name).FullName;
}

Hello @DisplayName

ofcourse may it's not be a best way with best performance but worked for me.