September 19, 2026

Build a Complete App with ASP.Net, C#, SQL Lite – Part 10

Updated August 2026 — Part 10 restored (user profile in the header + dropdown Name fix).

In this part we finish the Identity work from Part 9: show the logged-in user in the header, and provide links to profile and logout. Before that, we fix a small UX bug — Country (and similar) dropdowns that show IDs instead of names.

Previously:

We will cover:

  1. Show Name instead of Id in SelectLists
  2. Pass the current user into the layout
  3. Header UI – greeting, profile, logout
  4. Optional Profile page (FirstName / LastName)
  5. Quick test checklist

1. Show Name instead of Id in SelectLists

On New Patient, the Country dropdown may list country IDs instead of country names. That happens when SelectList uses the wrong display property.

Step 1: Open PatientController.cs and find where you build the Country list (Create/Edit GET actions). It often looks like:

ViewData["CountryId"] = new SelectList(_context.Countries, "Id", "Id");

Step 2: Change the third argument from "Id" to "Name" (the property on your Country model that holds the display text):

ViewData["CountryId"] = new SelectList(_context.Countries, "Id", "Name");

Do the same in Edit if you pass a selected value:

ViewData["CountryId"] = new SelectList(_context.Countries, "Id", "Name", patient.CountryId);

Step 3: In Views/Patient/Create.cshtml (and Edit), the dropdown should bind to CountryId as the value, while the list text comes from Name:

<select asp-for="CountryId" class="form-control"
        asp-items="ViewBag.CountryId"></select>

Repeat for any other FK dropdowns (State, City, …) that currently show IDs.

2. Pass the current user into the layout

Part 9 added FirstName / LastName on ApplicationUser. The layout needs that data for every page.

Option A – inject UserManager in _Layout.cshtml (simple for this series):

@using Microsoft.AspNetCore.Identity
@using YourApp.Data
@inject SignInManager<ApplicationUser> SignInManager
@inject UserManager<ApplicationUser> UserManager

Then, inside the header markup:

@if (SignInManager.IsSignedIn(User))
{
    var appUser = await UserManager.GetUserAsync(User);
    var display = appUser?.FirstName ?? appUser?.Email ?? User.Identity?.Name;
    <!-- use display below -->
}

If your layout is not already async, change the top of _Layout.cshtml to use an async pattern supported by your ASP.NET Core version, or load the display name in a ViewComponent (cleaner for larger apps).

Option B – ViewComponent UserNavViewComponent:

public class UserNavViewComponent : ViewComponent
{
    private readonly UserManager<ApplicationUser> _users;
    public UserNavViewComponent(UserManager<ApplicationUser> users) => _users = users;

    public async Task<IViewComponentResult> InvokeAsync()
    {
        var user = await _users.GetUserAsync(HttpContext.User);
        return View(user);
    }
}

Invoke with @await Component.InvokeAsync("UserNav").

3. Header UI – greeting, profile, logout

In the navbar (right side), replace a static “Login” with a signed-in menu:

<ul class="navbar-nav">
@if (SignInManager.IsSignedIn(User))
{
    var appUser = await UserManager.GetUserAsync(User);
    var display = !string.IsNullOrWhiteSpace(appUser?.FirstName)
        ? $"{appUser.FirstName} {appUser.LastName}".Trim()
        : appUser?.Email;

    <li class="nav-item">
        <span class="nav-link">Hello, @display</span>
    </li>
    <li class="nav-item">
        <a class="nav-link" asp-area="Identity" asp-page="/Account/Manage/Index">Profile</a>
    </li>
    <li class="nav-item">
        <form class="form-inline" asp-area="Identity" asp-page="/Account/Logout"
              asp-route-returnUrl="@Url.Action("Index", "Home")" method="post">
            <button type="submit" class="nav-link btn btn-link">Logout</button>
        </form>
    </li>
}
else
{
    <li class="nav-item">
        <a class="nav-link" asp-area="Identity" asp-page="/Account/Register">Register</a>
    </li>
    <li class="nav-item">
        <a class="nav-link" asp-area="Identity" asp-page="/Account/Login">Login</a>
    </li>
}
</ul>

Logout must be a POST (Identity antiforgery). Do not use a plain GET link for logout.

4. Optional Profile page (FirstName / LastName)

Scaffolded Identity already has Manage under /Identity/Account/Manage. To edit FirstName/LastName:

Step 1: Scaffold Identity pages for Account/Manage/Index if you have not (Visual Studio → Add → New Scaffolded Item → Identity).

Step 2: Extend the Manage InputModel:

[Required]
[Display(Name = "First name")]
public string FirstName { get; set; }

[Required]
[Display(Name = "Last name")]
public string LastName { get; set; }

Step 3: On GET, load from ApplicationUser; on POST, assign and await _userManager.UpdateAsync(user).

Step 4: Add matching inputs in the Manage Index Razor page (same pattern as Register in Part 9).

5. Quick test checklist

  1. Register a user with FirstName/LastName (Part 9).
  2. Log in — header shows Hello, {FirstName}….
  3. Open Profile — change names; header updates after refresh.
  4. Logout — returns to login/home; protected pages redirect to login ([Authorize] on Home from Part 9).
  5. New Patient — Country dropdown shows names, saves correct CountryId.

Next steps

You now have a usable Identity shell on the hospital app. Natural follow-ons: roles (Admin vs Staff), seed data for countries, and locking down Patient/CRUD actions with [Authorize(Roles = "...")]. Keep building on the same SQLite + Identity setup from Parts 4 and 9.

Kindson Munonye

Kindson Munonye is a software engineer and technical author covering machine learning, statistics, REST APIs, Python, and software engineering. He publishes free tutorials on The Genius Blog and live classes on Alkademy. GitHub · LinkedIn · About · Alkademy

View all posts by Kindson Munonye →
0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted