Skip to content

Instantly share code, notes, and snippets.

@ebicoglu
Last active March 25, 2020 07:22
Show Gist options
  • Save ebicoglu/eebfbc7368b3ab1b739afdf56a293d8f to your computer and use it in GitHub Desktop.
Save ebicoglu/eebfbc7368b3ab1b739afdf56a293d8f to your computer and use it in GitHub Desktop.
Override account/default.cshtml

How to customize the UI of ABP Commercial MVC project

I'll make an example with the Acme.BookStore project and modify the login page of the ABP Commercial MVC template.

To replace a view/CSS with a new one, rename your new file as the original one and put it in the same directory with the original directory path.

For this example, I'll overwrite Account/Login page. Below is the content of my customized login view. Create a file named Default.cshtml and put it in the folder *Acme.BookStore\src\Acme.BookStore.Web\Themes\Lepton\Layouts\Account*

Set this file as Embeded Resource. This is needed only for the files that come from the ABP Framework and modules.

Default.cshtml

@using System.Globalization
@using Microsoft.Extensions.Localization
@using Microsoft.Extensions.Options
@using Volo.Abp.AspNetCore.MultiTenancy
@using Volo.Abp.AspNetCore.Mvc.AntiForgery
@using Volo.Abp.AspNetCore.Mvc.UI.Components.LayoutHook
@using Volo.Abp.AspNetCore.Mvc.UI.Layout
@using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy.Localization
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Lepton.Bundling
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Lepton.Themes.Lepton.Components.Content.Alerts
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Components
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Lepton.Themes.Lepton.Components.Header.Brand
@using Volo.Abp.AspNetCore.Mvc.UI.Theme.Lepton.Themes.Lepton.Components.Toolbar.LanguageSwitch
@using Volo.Abp.AspNetCore.Mvc.UI.Theming
@using Volo.Abp.AspNetCore.Mvc.UI.Widgets.Components.WidgetScripts
@using Volo.Abp.AspNetCore.Mvc.UI.Widgets.Components.WidgetStyles
@using Volo.Abp.Localization
@using Volo.Abp.MultiTenancy
@inject IAbpAntiForgeryManager AbpAntiForgeryManager
@inject IBrandingProvider BrandingProvider
@inject IPageLayout PageLayout
@inject IOptions<AbpMultiTenancyOptions> MultiTenancyOptions
@inject IOptions<AbpLocalizationOptions> LocalizationOptions
@inject ICurrentTenant CurrentTenant
@inject IStringLocalizer<AbpUiMultiTenancyResource> MultiTenancyStringLocalizer
@inject ITenantResolveResultAccessor TenantResolveResultAccessor
@{
    Layout = null;
    AbpAntiForgeryManager.SetCookie();
    var containerClass = ViewBag.FluidLayout == true ? "container-fluid" : "container"; 
}

<!DOCTYPE html>

<html lang="@System.Globalization.CultureInfo.CurrentCulture.Name">
<head>
    @await Component.InvokeLayoutHookAsync(LayoutHooks.Head.First, StandardLayouts.Account)
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">

    <title>@(ViewBag.Title == null ? BrandingProvider.AppName : ViewBag.Title)</title>

    <abp-style-bundle name="@LeptonThemeBundles.Styles.Global" />

    <abp-style src="/Themes/Lepton/Layouts/Account/Default.css" />

    @await Component.InvokeAsync(typeof(WidgetStylesViewComponent))

    @await RenderSectionAsync("styles", false)
    @await Component.InvokeLayoutHookAsync(LayoutHooks.Head.Last, StandardLayouts.Account)
</head>
<body class="abp-account-layout login-page-body">
    @await Component.InvokeLayoutHookAsync(LayoutHooks.Body.First, StandardLayouts.Account)

    <div class="loader">
        <div class="indicator">
            <svg width="16px" height="12px">
                <polyline id="back" points="1 6 4 6 6 11 10 1 12 6 15 6"></polyline>
                <polyline id="front" points="1 6 4 6 6 11 10 1 12 6 15 6"></polyline>
            </svg>
        </div>
    </div>
     
    <div class="container-fluid">
        <div class="@containerClass responsive-image">

            <h1 class="text-center title-font">Welcome to My Custom Login Page</h1>

            <abp-row>
                <abp-column size-md="_7" size-lg="_5" class="mx-auto">

                    <div class="card transparent-background mb-5">
                        <div class="card-header">
                            <h2 class="card-title d-inline-block">Please Sign In</h2>
                            @if (LocalizationOptions.Value.Languages.Count > 1)
                            {
                                <nav class="navbar navbar-expand p-0 pt-1 float-right">
                                    <ul class="navbar-nav ml-auto toolbar-nav">
                                        <li class="nav-item">
                                            @(await Component.InvokeAsync<LanguageSwitchViewComponent>())
                                        </li>
                                    </ul>
                                </nav>
                            }
                        </div>

                        @if (MultiTenancyOptions.Value.IsEnabled &&
                     (TenantResolveResultAccessor.Result?.AppliedResolvers?.Contains(CookieTenantResolveContributor.ContributorName) == true))
                        {
                            <div class="card-header bg-light">
                                <div class="tenant-switch-box">

                                    <div class="row">
                                        <div class="col pr-1">
                                            <h6 class="m-0">
                                                @MultiTenancyStringLocalizer["Tenant"]
                                            </h6>
                                            @if (CurrentTenant.Id == null)
                                            {
                                                <i class="text-muted">@MultiTenancyStringLocalizer["NotSelected"]</i>
                                            }
                                            else
                                            {
                                                <span> Your tenant name <strong>@(CurrentTenant.Name ?? CurrentTenant.Id.Value.ToString())</strong></span>
                                            }
                                        </div>
                                        <div class="col-auto pl-1">
                                            <a id="AbpTenantSwitchLink" style="cursor: pointer" href="javascript:;" class="btn btn-sm btn-outline-primary float-right">@MultiTenancyStringLocalizer["Switch"]</a>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        }
                        <div class="card-body">
                            @(await Component.InvokeAsync<ContentAlertsViewComponent>())
                            @RenderBody()
                        </div>
                    </div>

                </abp-column>
            </abp-row>
        </div>
        <div class="p-4 text-center text-muted">
            @await Html.PartialAsync("~/Themes/Lepton/Layouts/Account/_Footer.cshtml")
        </div>
    </div>

    <abp-script-bundle name="@LeptonThemeBundles.Scripts.Global" />

    <script type="text/javascript" src="~/Abp/ApplicationConfigurationScript"></script>
    <script type="text/javascript" src="~/Abp/ServiceProxyScript"></script>

    @await Component.InvokeAsync(typeof(WidgetScriptsViewComponent))

    @await RenderSectionAsync("scripts", false)

    @await Component.InvokeLayoutHookAsync(LayoutHooks.Body.Last, StandardLayouts.Account)
</body>
</html>

Create your own Default.css and put it in the same folder Acme.BookStore\src\Acme.BookStore.Web\Themes\Lepton\Layouts\Account Set this file as Embeded Resource.

Default.css

.login-header {
    height: 110px;
    background-color: grey;
    padding-top: 20px;
    margin-right: auto;
    margin-left: auto;
    padding-left: 0px;
    padding-right: 0px;
}

.login-page-body {
    background: white;
}

.logo-container {
    float: right !important;
}

.responsive-image {
    background-color: bisque;
    width: 100% !important;
}

.title-font {
    font-size: 32px;
    color: #FFFFFF;
    font-weight: 300;
    padding: 18px 0 44px;
    text-align: center;
}

.transparent-background {
    background: rgba(255, 255, 255, 0.5);
    border-color: #FFFFFF;
}

.btn.btn-primary {
    width: auto !important;
}

.navbar {
    background-color: transparent !important;
}

.btn.btn-outline-primary {
    color: #011c4c !important;
    border-color: #011c4c !important;
}

a {
    color: #011c4c !important;
}


Edit the existing BookStoreWebModule.cs and add the below to have 1 global CSS file. This will override the defaults:

BookStoreWebModule.cs

public override void ConfigureServices(ServiceConfigurationContext context)
        {
        //...
            Configure<AbpBundlingOptions>(options =>
            {
                //add your global css files
                options
                    .StyleBundles
                    .Get(StandardBundles.Styles.Global)
                    .AddFiles("/Pages/app.css");
             });

Add the global app.css file in this directory => Acme.BookStore\src\Acme.BookStore.Web\Pages\app.css. And add some sample styles to overwrite the defaults:

 .navbar {
    background-color: #011C4C!important;
}

(This step is needed for v2.1.1 and older versions) Create a new file, named _ViewImports.cshtml for ABP TagHelpers and put it in the Acme.BookStore\src\Acme.BookStore.Web\Themes\Lepton\Layouts

_ViewImports.cshtml

@using System.Globalization
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bootstrap
@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bundling
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment