Open Closed

How do I override the login page on a blazor server project #9333


User avatar
0
itlpierre created

I am building a Blazor server project, and i want to customise the login page. I have attempted to follow several online guides but none have actually yielded any results. These are some of the guides I've tried using.

https://stackoverflow.com/questions/78907251/how-to-customize-auth-pages-and-settings-abp-framework-blazor https://abp.io/community/articles/how-to-customize-the-login-page-of-an-abp-blazor-application-by4o9yms https://abp.io/support/questions/3217/How-can-I-customize-login-page-in-blazor-server-app

Perhaps these are just too old and out of date, so can anyone from the support team give me the method that works in 2025? As of now, it seems that cshtml pages created in a blazor project are ignored (cant even route to the page). Thank you

For context, im on ABP version 9.0.1, UI Blazor Server, EF Core with sql server, and untiered


7 Answer(s)
  • User Avatar
    0
    berkansasmaz created
    Support Team .NET Developer

    Blazor Server don't have login UI, so you're redirected to authentication server UI to log in. So the authentication server is built with MVC UI. You can customize the login page like in a regular MVC application template: https://abp.io/docs/latest/framework/ui/mvc-razor-pages/customization-user-interface

    So if you create Pages/Account/Login.cshtml as below you can customize it.

    Pages/Account/Login.cshtml:

    @page
    @using Microsoft.AspNetCore.Mvc.Localization
    @using Microsoft.Extensions.Options
    @using Owl.reCAPTCHA
    @using Volo.Abp.Account.Localization
    @using Volo.Abp.Account.Public.Web.Pages.Account;
    @using Volo.Abp.Account.Public.Web.Security.Recaptcha
    @using Volo.Abp.Account.Settings
    @using Volo.Abp.Identity;
    @using Volo.Abp.Settings
    @model LoginModel
    @inject IHtmlLocalizer<AccountResource> L
    @inject Volo.Abp.AspNetCore.Mvc.UI.Layout.IPageLayout PageLayout
    @inject ISettingProvider SettingProvider
    @{
        PageLayout.Content.Title = L["Login"].Value;
        var reCaptchaVersion = await SettingProvider.GetAsync<int>(AccountSettingNames.Captcha.Version);
        if (Model.UseCaptcha)
        {
            await Model.ReCaptchaOptions.SetAsync(reCaptchaVersion == 3 ? reCAPTCHAConsts.V3 : reCAPTCHAConsts.V2);
        }
    
    }
    
    @section scripts
        {
        <abp-script-bundle name="@typeof(LoginModel).FullName">
            <abp-script src="/Pages/Account/Login.js" />
        </abp-script-bundle>
    
        @if (Model.UseCaptcha)
        {
            if (reCaptchaVersion == 3)
            {
                <recaptcha-script-v3 />
                <recaptcha-script-v3-js action="login" execute="false" />
            }
            else
            {
                <recaptcha-script-v2 />
            }
        }
    }
    
    @if (Model.IsLinkLogin)
    {
        <abp-alert alert-type="Warning">
            @L["LinkAccountWarning", Url.PageLink()]
        </abp-alert>
    }
    
    @if (Model.BackToExternalLogins)
    {
        <div class="d-grid gap-2">
            <a class="mb-3 btn btn-primary btn-block" href="@Url.Page("./ExternalLogins")">@L["Back"]</a>
        </div>
    }
    <div class="account-module-form">
    
        @if (Model.IsSelfRegistrationEnabled)
        {
            <h5 class="mb-2">@L["NotAMemberYet"] <a class="text-decoration-none" href="@Url.Page("./Register", new {returnUrl = Model.ReturnUrl, returnUrlHash = Model.ReturnUrlHash})">@L["Register"]</a></h5>
        }
    
        @if (Model.EnableLocalLogin)
        {
            <form method="post" id="loginForm">
                @if (Model.UseCaptcha)
                {
                    <input class="mb-3" data-captcha="true" type="hidden" name="@RecaptchaValidatorBase.RecaptchaResponseKey" id="@RecaptchaValidatorBase.RecaptchaResponseKey"/>
                }
                <div>
                    <div class="form-floating mb-2">
                        <input asp-for="LoginInput.UserNameOrEmailAddress" type="text" class="form-control" placeholder="name@example.com">
                        @Html.LabelFor(m => m.LoginInput.UserNameOrEmailAddress)
                        <span asp-validation-for="LoginInput.UserNameOrEmailAddress"/>
                    </div>
    
                    <div class="form-floating mb-2">
                        <input asp-for="LoginInput.Password" id="password-input" type="password" class="form-control" placeholder="Password">
                        @Html.LabelFor(m => m.LoginInput.Password)
                        <i id="PasswordVisibilityButton" class="bi bi-eye-slash show-pass-icon" data-bs-toggle="tooltip" data-bs-placement="top" data-bs-html="true" aria-label="@L["ShowPassword"]" data-bs-original-title="@L["ShowPassword"]"></i>
                        <i id="capslockicon" class="bi bi-capslock caps-lock-icon" style="display: none;" data-bs-toggle="tooltip" data-bs-placement="top" data-bs-html="true" aria-label="<i class='bi bi-exclamation-circle'></i> @L["CapsLockOn"]!" data-bs-original-title="<i class='bi bi-exclamation-circle'></i> @L["CapsLockOn"]!"></i>
                        <span asp-validation-for="LoginInput.Password"/>
                    </div>
                </div>
                <abp-row>
                    <abp-column>
                        <div class="form-switch ps-2">
                            <abp-input asp-for="LoginInput.RememberMe" class="mb-4"/>
                        </div>
                    </abp-column>
                    <abp-column class="text-end">
                        <a href="@Url.Page("./ForgotPassword", new {returnUrl = Model.ReturnUrl, returnUrlHash = Model.ReturnUrlHash})">@L["ForgotPassword"]</a>
                    </abp-column>
                </abp-row>
    
                @if (reCaptchaVersion == 2)
                {
                    <script>
                        recaptchaCallback = function (token) {
                            $('form button[type=submit]').removeAttr("disabled");
                            $('#@RecaptchaValidatorBase.RecaptchaResponseKey').val(token)
                        };
                    </script>
                    <div class="mb-3">
                        <recaptcha-div-v2 callback="recaptchaCallback"/>
                    </div>
                }
    
                <div class="d-grid gap-2">
                    <abp-button button-type="Primary" type="submit" class="mb-3" name="Action" value="Login" disabled="true">
                        <i class="bi bi-box-arrow-in-right me-1"></i>
                        @L["Login"]
                    </abp-button>
                </div>
    
                @if (Model.ShowCancelButton)
                {
                    <div class="d-grid gap-2">
                        <abp-button button-type="Secondary" type="submit" formnovalidate="formnovalidate" class="mb-3" name="Action" value="Cancel">@L["Cancel"]</abp-button>
                    </div>
                }
            </form>
        }
    
        @if (Model.VisibleExternalProviders.Any())
        {
            if(Model.EnableLocalLogin)
            {
                <hr/>
                @L["OrSignInWith"]
                <br/>
            }
            else
            {
                @L["SignInWithOneOfTheFollowingProviders"]
            }
    
            <form asp-page="./Login" asp-page-handler="ExternalLogin"
                  asp-route-returnUrl="@Model.ReturnUrl"
                  asp-route-returnUrlHash="@Model.ReturnUrlHash"
                  asp-route-linkTenantId="@Model.LinkTenantId"
                  asp-route-linkUserId="@Model.LinkUserId"
                  asp-route-linkToken="@Model.LinkToken"
                  method="post">
                @foreach (var provider in Model.VisibleExternalProviders)
                {
                    <button type="submit"
                            class="mt-2 me-2 btn btn-outline-primary btn-sm"
                            name="provider"
                            value="@provider.AuthenticationScheme"
                            data-busy-text="@L["ProcessingWithThreeDot"]">
                        @if (provider.Icon != null)
                        {
                            <i class="@provider.Icon"></i>
                        }
                        <span>@provider.DisplayName</span>
                    </button>
                }
            </form>
        }
    </div>
    
  • User Avatar
    0
    itlpierre created

    Yes I've tried that. As i said in my original post, I tried overriding using the docs and following the method given, but even when i create a Login.cshtml page in my Pages directory under the Blazor project, it doesnt seem to redirect the mvc route to the new page i created. Do you have any solution for this.

  • User Avatar
    0
    EngincanV created
    Support Team .NET Developer

    Yes I've tried that. As i said in my original post, I tried overriding using the docs and following the method given, but even when i create a Login.cshtml page in my Pages directory under the Blazor project, it doesnt seem to redirect the mvc route to the new page i created. Do you have any solution for this.

    Hi, I've tried just before with a new blazor server solution (non-tiered), and successfully overridden the page:

    Can you please confirm that you created the Login.cshtml file under the Account folder?

  • User Avatar
    0
    itlpierre created

    [EngincanV] said:

    Yes I've tried that. As i said in my original post, I tried overriding using the docs and following the method given, but even when i create a Login.cshtml page in my Pages directory under the Blazor project, it doesnt seem to redirect the mvc route to the new page i created. Do you have any solution for this.

    Hi, I've tried just before with a new blazor server solution (non-tiered), and successfully overridden the page:

    Can you please confirm that you created the Login.cshtml file under the Account folder?

    Hi Engincan,

    Yes, i did exactly that but its still not working. does it have anything to do with the fact that im using the basic ui template?

  • User Avatar
    0
    enisn created
    Support Team .NET Developer

    Hi,

    does it have anything to do with the fact that im using the basic ui template?

    I posted an article about that topic, you may want to follow this one for the basic theme: https://abp.io/community/articles/you-do-it-wrong-customizing-abp-login-page-correctly-bna7wzt5#gsc.tab=0

  • User Avatar
    0
    itlpierre created

    [enisn] said: Hi,

    does it have anything to do with the fact that im using the basic ui template?

    I posted an article about that topic, you may want to follow this one for the basic theme: https://abp.io/community/articles/you-do-it-wrong-customizing-abp-login-page-correctly-bna7wzt5#gsc.tab=0

    I'll look into this, will update when I've tried it out

  • User Avatar
    0
    EngincanV created
    Support Team .NET Developer

    [itlpierre] said:

    [enisn] said: Hi,

    does it have anything to do with the fact that im using the basic ui template?

    I posted an article about that topic, you may want to follow this one for the basic theme:
    https://abp.io/community/articles/you-do-it-wrong-customizing-abp-login-page-correctly-bna7wzt5#gsc.tab=0

    I'll look into this, will update when I've tried it out

    Thanks for the update. We will be waiting for your response.

Boost Your Development
ABP Live Training
Packages
See Trainings
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❤️ on ABP v9.3.0-preview. Updated on June 13, 2025, 11:37