question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Styling Identity Razor Pages to use default Blazor theme is very difficult with available documentation

See original GitHub issue

Issue description

I just added Identity to my existing Blazor Server project using Identity Scaffolding. I followed this Microsoft learn guide here.

However, since Identity uses Razor pages instead of Razor components, the styling of the UI changes when a visitor navigates between Identity pages and components.

For eg: The page initially loads like this:

And when the user hits the Login link at the top right corner, the login page opens which looks so ugly 😩:

To fix that, I tried to follow this guide at Microsoft learn. But I was hit with this error (code link here):

The name 'Engine' does not exist in the current context

After few days of pulling hair, I found the answer to my question here: https://stackoverflow.com/a/74408719/8644294

Now, I’m hit with a different issue, i.e. _Layout.cshtml can’t find the partial view. image

As you can see, the _LoginPartial.cshtml is inside ~/Features/Shared/Layout/_LoginPartial.cshtml. image

I tried it again by supplying .cshtml file name extension which should force it to look for partial views in the same folder as mentioned here.

It says it didn’t even look at any locations 😳: image

After spending hours upon hours on this, I removed the check altogether and just went like this: image

Now the page loads, but the UI looks all messed up: image

I thought the whole point of this was to make the layout look like the first picture.

Conclusion

I think the Identity documentation isn’t organized properly and seriously lacking. To do something this simple, I’ve wasted days and still haven’t been able to complete it. If I can suggest something, how about Microsoft creates simple working code sample for all the Auth scenarios in the documentation? That way if the directions in the documentations don’t work, we can take a look at the provided sample code.

Even though this has been mentioned a lot before, I still would like to reiterate it: Please support Identity in Blazor without having to resort to these Razor Pages and all the added complexity.

Link to public reproduction project repository

https://github.com/affableashish/blazor-server-auth

Target framework

  • .NET Core
  • .NET Framework
  • .NET Standard
dotnet --info output or About VS info
C:\Users\Ashish>dotnet --info
.NET SDK (reflecting any global.json):
 Version:   6.0.301
 Commit:    43f9b18481

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.19044
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\6.0.301\

Host (useful for support):
  Version: 6.0.6
  Commit:  7cca709db2

.NET SDKs installed:
  5.0.300 [C:\Program Files\dotnet\sdk]
  6.0.301 [C:\Program Files\dotnet\sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.All 2.1.28 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.30 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.1.28 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.30 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.1.15 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.1.26 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 5.0.6 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 6.0.6 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 2.1.28 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.30 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.15 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.26 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 5.0.6 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.6 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.WindowsDesktop.App 3.1.15 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 3.1.26 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 5.0.6 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 6.0.6 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

To install additional .NET runtimes or SDKs:
  https://aka.ms/dotnet-download

Issue Analytics

  • State:closed
  • Created 10 months ago
  • Reactions:6
  • Comments:9 (3 by maintainers)

github_iconTop GitHub Comments

4reactions
affableashishcommented, Nov 28, 2022

Hello everyone 👋, I worked on this and figured out a solution that works. 😌 Please do a review of it 🕵️‍♂️ and let me know if how I’m doing it is a good practice or not. If not, please give me pointers on how to improve it.

If you guys think it’s good, I can even contribute to the MSFT documentation. (Just tell me how to do it)


In summary, I took MainLayout.razor and put it inside _Layout.cshtml.

Step 1:

Since we’re using NavMenu and LoginDisplay razor components inside _Layout.cshtml, add these to the top of _Layout.cshtml:

@using HMT.Web.Server.Features.Shared.Layout.NavMenu
@using HMT.Web.Server.Features.Identity

Step 2:

Replace <body> with this:

<body>
    <div class="page">
        <div class="sidebar">
            <component type="typeof(NavMenu)" render-mode="ServerPrerendered" />
        </div>

        <main>
            <div class="top-row px-4 logindisplay">
                <component type="typeof(LoginDisplay)" render-mode="ServerPrerendered" />
            </div>

            <article class="content px-4">
                @RenderBody()
            </article>

            <div class="bottom-row px-4">
                <a href="">
                    <img src="/images/logo-black.png" width="40"/>
                    <span class="fs-4">HMT</span>
                </a>
            </div>

            <div id="blazor-error-ui">
                <environment include="Staging,Production">
                    An error has occurred. This application may no longer respond until reloaded.
                </environment>
                <environment include="Development">
                    An unhandled exception has occurred. See browser dev tools for details.
                </environment>
                <a href="" class="reload">Reload</a>
                <a class="dismiss">🗙</a>
            </div>
        </main>
    </div>

    <script src="~/Identity/lib/jquery/dist/jquery.js"></script>
    <script src="~/Identity/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
    <script src="~/Identity/js/site.js" asp-append-version="true"></script>
    @RenderSection("Scripts", required: false)
    <script src="_framework/blazor.server.js"></script>
</body>

If you’re thinking that I just cut and pasted <div class="page"> section from MainLayout.razor, you’re absolutely right.😁

Step 3:

Create: Features/Shared/Layout/_Layout.cshtml.css file. Now cut and paste all the css styles from your MainLayout.razor.css to _Layout.cshtml.css. For reference, this is how mine looks like.

Step 4:

All that remains inside MainLayout.razor is this:

@inherits LayoutComponentBase
<PageTitle>Handy Man's Tool</PageTitle>
@Body

Step 5:

Wrap AuthorizeView in LoginDisplay.razor with <CascadingAuthenticationState>. The reason is that if you try to use a Razor Component that has Authorize components from component that IS NOT wrapped with <CascadingAuthenticationState>, it won’t work, That is the reason why <component type="typeof(LoginDisplay)" render-mode="ServerPrerendered" /> doesn’t work in _Layout.cshtml without it.

Step 6:

If you want to protect the NavLinks in NavMenu, wrap them inside AuthorizeView, and since NavMenu is rendered from _Layout.cshtml, don’t forget to wrap them inside <CascadingAuthenticationState>. For eg: Mine looks like this:

<CascadingAuthenticationState>
    <div class="@NavMenuCssClass" @onclick="ToggleNavMenu">
        <nav class="flex-column">
            <div class="nav-item px-3">
                <NavLink class="nav-link" href="" Match="NavLinkMatch.All">
                    <span class="oi oi-home" aria-hidden="true"></span> Home
                </NavLink>
            </div>
            <AuthorizeView>
                <div class="nav-item px-3">
                    <NavLink class="nav-link" href="counter">
                        <span class="oi oi-plus" aria-hidden="true"></span> Counter
                    </NavLink>
                </div>
                <div class="nav-item px-3">
                    <NavLink class="nav-link" href="fetchdata">
                        <span class="oi oi-list-rich" aria-hidden="true"></span> Fetch data
                    </NavLink>
                </div>
            </AuthorizeView>
        </nav>
    </div>
</CascadingAuthenticationState>

Step 7:

Remove the following files as they’re unnecessary:

  1. Areas/Identity/Pages/_ValidationScriptsPartial.cshtml (as I’m not overriding it.)
  2. Features/Shared/Layout/_ViewImports.cshtml
  3. Features/Shared/Layout/_LoginPartial.cshtml (Using LoginDisplay instead)

Full source code

https://github.com/affableashish/blazor-server-auth/tree/feature/LayoutWithIdentityPages

Demo

Unauthorized View image

Login Page image

Authorized View image

1reaction
guardrexcommented, Feb 13, 2023

Sure thing, @affableashish. I’m sorry that I didn’t reach the whole subject as planned … I was going to do all of this work in February/March of 2022. That was the plan, and you see how well that went! 😩 I was clobbered with lots of other issues that had higher priority. Once we reached the work for .NET 7, there was no way to get into the weeds with it in 2022. That’s why at this point when you look at the UE pass tracking section of https://github.com/dotnet/AspNetCore.Docs/issues/28001 you see all of those BLUE links in the Security node part of the list. Those are all kinds of issues that have been opened pertaining to asks for authn/z doc updates that weren’t actually bugs. They were piling up in the prior year (2021), and that became worse throughout 2022. I’m glad to have reached it this year … right now … and even working on it at this very instant.

I will take a look at everything you’ve posted here and the cross-links that you just provided ☝️. It’s up to PU if they’d like to leave this issue open. I focus on the docs side of things and take care of the issues in the docs repo.

Thanks again for all of your input and ideas. If everything goes well, I think that the work on the Security node will be complete within a month or two. It just depends on the workload. You’ll see a number of improvements. Again, please open a docs issue whenever you spot something for potential improvement … and, of course, for outright 🐞 fixes 😈 … from the bottom of any topic. Issues on the docs repo for Blazor come directly to me, and I’ll get back to you ASAP 🏃.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Styling Identity Scaffolded Razor Pages to use default ...
The documentation totally misses these 2 lines that need to be ... If the steps mentioned below are hard to follow, take a...
Read more >
Style Authentication Endpoints to use default Blazor theme
The scaffolded identity uses razor pages and not Blazor. If you want to change styles of the login page I suggest editing the...
Read more >
ASP.NET Core Blazor forms and input components
Learn how to use forms with field validation and built-in input components in Blazor.
Read more >
Blazor Server App with .NET 6 and Syncfusion UI Components
We'll also integrate the Microsoft Identity technology into our Blazor ... /SalesManagementApp/ Pages /Index. razor ⭐️ Styling the Syncfusion ...
Read more >
Razor Pages for ASP.NET Core - Full Course (.NET 6)
Learn the basics of Razor Pages for ASP. ... (1:11:35) Setup Program.cs to use DbContext ⌨️ (1:17:15) Create Database ⌨️ (1:22:57) ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found