Blazor Identity - user available in razor HTML, not in @code

David Thielen 3,211 Reputation points
2023-05-05T13:57:00.9933333+00:00

This is really weird. In the html part of a razor page (Blazor server using ASP.NET Identity) I can use the following:

<div class="text-center">@context.User.Identity?.Name</div>

But in the @code I cannot call:

var name = context.User.Identity?.Name;

Why?

And yes I do have CascadingAuthenticationState in App.razor

<CascadingAuthenticationState>
    <Router AppAssembly="@typeof(App).Assembly">
        <Found Context="routeData">
            <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
                <NotAuthorized>
                    <h1>Sorry, you're not authorized to view this page.</h1>
                    <p>You may want to try logging in (as someone with the necessary authorization).</p>
                </NotAuthorized>
            </AuthorizeRouteView>
            <FocusOnNavigate RouteData="@routeData" Selector="h1" />
        </Found>
        <NotFound>
            <PageTitle>Not found</PageTitle>
            <LayoutView Layout="@typeof(MainLayout)">
                <p role="alert">Sorry, there's nothing at this address.</p>
            </LayoutView>
        </NotFound>
    </Router>
</CascadingAuthenticationState>

Here's an example. It's longer than I prefer but what matters is the @context.User.Identity?.Name - which works

@using System.Drawing

@inject Services.TokenProvider TokenProvider

<AuthorizeView>
    <Authorized>
        <nav>
            <DxMenu Orientation="Orientation.Horizontal"
                    DropDownActionMode="MenuDropDownActionMode.Click"
                    DisplayMode="MenuDisplayMode.Desktop"
                    CollapseItemsToHamburgerMenu="true"
                    CollapseItemToIconMode="MenuCollapseItemToIconMode.All">
                <Items>
                    <DxMenuItem CssClass="notoggle" Position="ItemPosition.Start">
                        <Template Context="menuContext">
                            <div id="drop-down-target" style="margin: 10px" class="menu-icon" @onclick="() => IsOpen = !IsOpen">
                                <img src="@_base64Image" class="resizable-image circled s-16 menu-icon" alt="User Avatar placeholder" />
                            </div>
                            <DxDropDown @bind-IsOpen="@IsOpen" Width="200" PositionTarget="#drop-down-target"
                                        PositionMode="DropDownPositionMode.Bottom" FooterVisible="true" Context="popupContext">
                                <BodyTextTemplate Context="bodyContext">
                                    <div class="w-100 user-profile ">
                                        <div class="flex-column align-items-center justify-content-center">
                                            <div class="logo-container d-flex align-items-center justify-content-center">
                                                <img src="@_base64Image" class="resizable-image circled s-64" alt="User Avatar placeholder" />
                                            </div>
                                            <div class="user-name-container bm-3 mb-2">
                                                <div class="text-center">@context.User.Identity?.Name</div>
                                            </div>
                                            <div class="d-flex justify-content-center log-off-btn">
                                                <a href="/profile">View profile</a>
                                            </div>
                                        </div>
                                    </div>
                                </BodyTextTemplate>
                                <FooterTextTemplate>
                                    <form action="/identity/account/logout" method="post">
                                        <button class="nav-link btn btn-link" type="submit">
                                            <span class="oi oi-account-logout" aria-hidden="true"></span> Log out (@context.User.Identity?.Name)
                                        </button>
                                        <input name="__RequestVerificationToken" type="hidden"
                                               value="@TokenProvider.XsrfToken">
                                    </form>
                                </FooterTextTemplate>
                            </DxDropDown>
                        </Template>
                    </DxMenuItem>
                    <DxMenuItem Text="Dashboard" IconCssClass="oi oi-spreadsheet" NavigateUrl="/user/dashboard" />
                    <DxMenuItem Text="Search Events" IconCssClass="oi oi-magnifying-glass" NavigateUrl="/search" />
                    <DxMenuItem Text="History" IconCssClass="oi oi-list" NavigateUrl="/history" />
                    <DxMenuItem Text="Pending" IconCssClass="oi oi-inbox" NavigateUrl="/pending" />
                    <DxMenuItem CssClass="no-background" Text="3 days to the election" Position="ItemPosition.End" />
                </Items>
            </DxMenu>
        </nav>
    </Authorized>
    <NotAuthorized>
        <nav>
            <DxMenu Orientation="Orientation.Horizontal"
                    DropDownActionMode="MenuDropDownActionMode.Click"
                    DisplayMode="MenuDisplayMode.Desktop"
                    CollapseItemsToHamburgerMenu="true"
                    CollapseItemToIconMode="MenuCollapseItemToIconMode.All">
                <Items>
                    <DxMenuItem Text="Home" IconCssClass="oi oi-home" NavigateUrl="/" />
                    <DxMenuItem Text="Login" IconCssClass="oi oi-account-login" NavigateUrl="/identity/account/Login?ReturnUrl=/dashboard" />
                    <DxMenuItem Text="Register" IconCssClass="oi oi-document" NavigateUrl="/Account/Register" />
                    <DxMenuItem CssClass="no-background" Text="the election is in 3 days" Position="ItemPosition.End" />
                </Items>
            </DxMenu>
        </nav>
    </NotAuthorized>
</AuthorizeView>
<!--
<p>image: <img src="@_base64Image" width="32" height="32" alt="User Avatar placeholder"/></p>
-->
@code {
    private bool IsOpen { get; set; } = false;
    private string _base64Image;

    private Bitmap Avatar
    {
        get
        {
            // will get this from DB
            return new Bitmap("wwwroot/images/DavidThielen.jpg");
        }
    }

    protected override Task OnInitializedAsync()
    {
        _base64Image = Avatar.ConvertToBase64();

        // This will NOT compile
        var name = context.User.Identity?.Name;

        return Task.CompletedTask;
    }
}

But in the @code part context is not recognized.

??? - thanks - dave

Developer technologies | .NET | Blazor
{count} votes

2 answers

Sort by: Most helpful
  1. Michael Washington 921 Reputation points MVP
    2023-05-06T13:39:13.1466667+00:00

    This should work:

    @inject AuthenticationStateProvider AuthenticationStateProvider
    
    @code {
    ClaimsPrincipal ClaimsPrincipalUser;
    
    protected override async Task OnInitializedAsync()
    {
      var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
      ClaimsPrincipalUser = authState.User;      
    
      if (ClaimsPrincipalUser.Identity != null)
      {
         var UsersName = ClaimsPrincipalUser.Identity.Name;       
      }
    }
    
    1 person found this answer helpful.
    0 comments No comments

  2. AgaveJoe 30,126 Reputation points
    2023-05-06T12:12:21.6633333+00:00

    That link does show using @context.User.Identity?.Name in the html component. But it does not explain why @context works in the html, but context does not work in the @code.

    Copied form the official documentation.

    The AuthorizeView component selectively displays UI content depending on whether the user is authorized. This approach is useful when you only need to display data for the user and don't need to use the user's identity in procedural logic.

    The component exposes a context variable of type AuthenticationState (@context in Razor syntax), which you can use to access information about the signed-in user:

    The context is available only in the markup. If you need to access Identity in code than use the AuthenticationStateProvider.

    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.