Table of Contents

Razor components and pages

In the below table, you can see all shared Razor pages and partials (.cshtml) and the BasePageModel base class that ship under Pages/ in the CodeBlock.DevKit.Web.Blazor.Server package.

Name What it is for
BasePageModel Base class for Razor Pages: maps Result to ViewData, model validation helpers.
Error (Error.cshtml + Error.cshtml.cs) Server-side error page and model for Razor hosts.
SetCulture Applies culture cookie and redirects.
_SimpleLayout Minimal Razor layout partial for .cshtml pages.
_Pagination Server-rendered pagination partial.
_SelectLanguage Culture selector on Razor pages.
_ServerValidationSummary Server-side validation messages.

Reference

In the below sections, you can see all information about each Razor page, partial, or page model so you know where it lives and what it is used for. You can also copy the embedded source to create your own implementation when you customize those files.

BasePageModel.cs

Base PageModel for Razor Pages that follow DevKit conventions: applies [ModelStateValidating] and helpers that map Result<T> and ModelState into ViewData for consistent UI feedback.

  • Namespace / notes: CodeBlock.DevKit.Web.Blazor.Server.Pages
// Copyright (c) CodeBlock.Dev. All rights reserved.
// For more information visit https://codeblock.dev

using CodeBlock.DevKit.Core.Helpers;
using CodeBlock.DevKit.Web.Filters;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace CodeBlock.DevKit.Web.Blazor.Server.Pages;

/// <summary>
/// Base class for Razor Pages that provides common functionality for result handling and error management.
/// Automatically validates model state and provides helper methods for parsing results to view data.
/// Inherit from this class to get consistent error handling and result processing across your pages.
/// </summary>
[ModelStateValidating]
public class BasePageModel : PageModel
{
    /// <summary>
    /// Parses a Result object and populates ViewData with success status, message, and errors.
    /// Automatically sets ViewData keys for consistent error display in Razor views.
    /// </summary>
    /// <typeparam name="T">The type of data in the result</typeparam>
    /// <param name="result">The result object to parse</param>

    protected void ParseResultToViewData<T>(Result<T> result)
    {
        ViewData["IsSuccess"] = result.IsSuccess;
        ViewData["Message"] = result.Message;
        ViewData["Errors"] = result.Errors;
    }

    /// <summary>
    /// Parses ModelState errors and populates ViewData with error information.
    /// Extracts all validation errors from the model state and formats them for display.
    /// </summary>
    /// <param name="modelState">The ModelStateDictionary containing validation errors</param>

    protected void ParseModelStateErrorsToViewData(ModelStateDictionary modelState)
    {
        var errors = new List<string>();
        foreach (var modelStateKey in modelState.Keys)
        {
            foreach (var modelError in modelState[modelStateKey].Errors)
                errors.Add(modelError.ErrorMessage);
        }

        ViewData["IsSuccess"] = false;
        ViewData["Errors"] = errors;
    }
}

Error.cshtml

Server-side error HTML shown when an unhandled exception bubbles to the error pipeline (hosts that mix Razor Pages with the shared library).

  • Path: CodeBlock.DevKit/src/1-Libraries/Source/Web.Blazor.Server/Pages/Error.cshtml
  • Namespace / notes: Razor page markup
@page "/error"
@model CodeBlock.DevKit.Web.Blazor.Server.Pages.ErrorModel
@using CodeBlock.DevKit.Application.Services
@using CodeBlock.DevKit.Core.Resources
@using CodeBlock.DevKit.Core.Resources
@using Microsoft.AspNetCore.Identity
@using Microsoft.Extensions.Localization
@inject IStringLocalizer<CoreResource> Localizer
@inject ICurrentUser CurrentUser
@inject IStringLocalizer<CoreResource> CoreLocalizer

@{
    ViewData["Title"] = @Localizer[CoreResource.Error_Page_Title];
    Layout = "_SimpleLayout";
}


<div class="simple-card-header">
    <h3 class="simple-card-title text-warning">@Localizer[CoreResource.Error_Page_Title]</h3>
</div>

<div class="simple-body">
    <div class="simple-status-icon-container">
        <i class="bi bi-exclamation-triangle simple-status-icon warning"></i>
    </div>

    <div>
        <div class="simple-alert-content text-warning">
            <p> @Localizer[CoreResource.Error_Page_Content]</p>
        </div>
    </div>
</div>


Error.cshtml.cs

Code-behind for Error: ErrorModel with no-cache headers and [IgnoreAntiforgeryToken] so /error stays safe to hit from failure paths.

  • Namespace / notes: CodeBlock.DevKit.Web.Blazor.Server.Pages
// Copyright (c) CodeBlock.Dev. All rights reserved.
// For more information visit https://codeblock.dev

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace CodeBlock.DevKit.Web.Blazor.Server.Pages;

/// <summary>
/// Page model for the error page that displays application errors to users.
/// Configured to prevent caching and ignore antiforgery tokens for error scenarios.
/// Used as the default error handler for unhandled exceptions in the application.
/// </summary>
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
[IgnoreAntiforgeryToken]
public class ErrorModel : PageModel
{
    /// <summary>
    /// Initializes a new instance of the ErrorModel.
    /// </summary>
    public ErrorModel() { }

    /// <summary>
    /// Handles GET requests to the error page.
    /// Called when users navigate to the error page or when errors are redirected.
    /// </summary>
    public void OnGet() { }
}

SetCulture.cshtml

Culture switch endpoint: writes the culture cookie (or equivalent) and redirects back to the return URL so Razor-based flows pick up the new locale.

  • Path: CodeBlock.DevKit/src/1-Libraries/Source/Web.Blazor.Server/Pages/SetCulture.cshtml
  • Namespace / notes: Razor page markup
@page "/setculture"
@using CodeBlock.DevKit.Web.Localization
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Localization
@attribute [AllowAnonymous]
@inject LocalizationSettings LocalizationSettings

@functions
{

    public async Task<IActionResult> OnGet([FromQuery] string lang, [FromQuery] string returnUrl)
    {
        if (LocalizationSettings.HasLanguage(lang))
        {
            HttpContext.Response.Cookies.Append(
            LocalizationSettings.CookieName,
            CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(lang)));
        }

        return LocalRedirect(returnUrl ?? Url.Content("~/"));
    }
}

_SimpleLayout.cshtml

Minimal layout partial for .cshtml pages—shared chrome (title area, main wrapper) without pulling in the full Blazor app layout.

  • Path: CodeBlock.DevKit/src/1-Libraries/Source/Web.Blazor.Server/Pages/Shared/_SimpleLayout.cshtml
  • Namespace / notes: Razor partial
@using CodeBlock.DevKit.Contracts.Models
@using CodeBlock.DevKit.Contracts.Services
@using CodeBlock.DevKit.Web.Blazor.Server.Components
@using Microsoft.AspNetCore.Hosting
@using Microsoft.AspNetCore.Mvc.ViewEngines
@using CodeBlock.DevKit.Web.Localization
@inject LocalizationSettings LocalizationSettings
@inject ApplicationSettings ApplicationSettings
@inject ISettingAccessorService SettingAccessorService
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

<!DOCTYPE html>
<html dir="@LocalizationSettings.GetCurrentLanguageDirection()" lang="@LocalizationSettings.GetCurrentLanguageCode()" style="font-family: @LocalizationSettings.GetCurrentLanguageFont() !important">
<head>

    <component type="typeof(HeadTags)" render-mode="ServerPrerendered" />
    <meta name="description" content="@ApplicationSettings.Localized.Description">
    <title>@ViewData["Title"]</title>
    <base href="~/" />
    <link href="css/cb.general.nspa.@(LocalizationSettings.GetCurrentLanguageDirection().ToLower()).min.css?v=1.6.0-beta5" rel="stylesheet" />
</head>
<body style="background-color:#362e6f; font-family: @LocalizationSettings.GetCurrentLanguageFont() !important">
   
    <div class="simple-layout-wrapper">
        <!-- Fullscreen Background -->
        <div class="simple-fullscreen-bg"></div>
        
        <!-- Animated Background -->
        <div class="bg-animation">
            <div class="floating-orb floating-orb-1"></div>
            <div class="floating-orb floating-orb-2"></div>
            <div class="floating-orb floating-orb-3"></div>
            <div class="floating-orb floating-orb-4"></div>
            <div class="floating-orb floating-orb-5"></div>
            <div class="floating-orb floating-orb-6"></div>
            <div class="floating-orb floating-orb-7"></div>
            <div class="floating-orb floating-orb-8"></div>
        </div>

        <div class="simple-language-wrapper">
            <partial name="_SelectLanguage" model="@("language-btn")" />
        </div>

        <div class="simple-container">
            <div class="simple-wrapper">
                <div class="simple-branding">
                    <a href="/" class="simple-brand-link">
                        @if (SettingAccessorService.Settings.Identity.ShowLogo)
                        {
                            <img class="simple-logo" src="/images/logos/logo.png" alt="@ApplicationSettings.Localized.Name" />
                        }

                        @if (SettingAccessorService.Settings.Identity.ShowAppName)
                        {
                            <h1 class="simple-app-name">@ApplicationSettings.Localized.Name</h1>
                        }
                        else if (!SettingAccessorService.Settings.Identity.ShowLogo)
                        {
                            <h1 class="simple-app-name">Welcome</h1>
                        }
                    </a>
                </div>
                @RenderBody()
            </div>
        </div>
    </div>

    <script src="~/js/cb.general.nspa.min.js?v=1.6.0-beta5"></script>

    @RenderSection("Scripts", required: false)
</body>
</html>

_Pagination.cshtml

Server-rendered pager partial for MVC-style or Razor Pages lists (links built from view data or the page model).

  • Path: CodeBlock.DevKit/src/1-Libraries/Source/Web.Blazor.Server/Pages/Shared/_Pagination.cshtml
  • Namespace / notes: Razor partial
@using CodeBlock.DevKit.Web.Blazor.Server.Helpers
@using CodeBlock.DevKit.Core.Resources
@using Microsoft.Extensions.Localization
@model PaginationModel
@inject IStringLocalizer<CoreResource> CoreLocalizer

<nav class="blog-pagination">
    <div class="container">
        <div class="row">
            <div class="w-100 overflow-auto">
                <ul class="pagination justify-content-center flex-nowrap" style="min-width: max-content;">
                    <li class="page-item @(Model.CurrentPage > 1 ? "cursor-pointer" : "disabled")">
                        @if (Model.CurrentPage > 1)
                        {
                            <a class="page-link" href="@Model.GetPageUrl(Model.CurrentPage - 1)">&laquo;</a>
                        }
                        else
                        {
                            <span class="page-link">&laquo;</span>
                        }
                    </li>

                    @if (Model.ShowFirstPage)
                    {
                        <li class="page-item @(Model.CurrentPage == 1 ? "active" : "")">
                            <a class="page-link" href="@Model.GetPageUrl(1)">1</a>
                        </li>
                        @if (Model.FirstEllipsisNeeded)
                        {
                            <li class="page-item disabled">
                                <span class="page-link">...</span>
                            </li>
                        }
                    }

                    @foreach (var visiblePage in Model.VisiblePages)
                    {
                        <li class="page-item @(visiblePage == Model.CurrentPage ? "active" : "")">
                            <a class="page-link" href="@Model.GetPageUrl(visiblePage)">@visiblePage</a>
                        </li>
                    }

                    @if (Model.ShowLastPage)
                    {
                        @if (Model.LastEllipsisNeeded)
                        {
                            <li class="page-item disabled">
                                <span class="page-link">...</span>
                            </li>
                        }
                        <li class="page-item @(Model.CurrentPage == Model.TotalPages ? "active" : "")">
                            <a class="page-link" href="@Model.GetPageUrl(Model.TotalPages)">@Model.TotalPages</a>
                        </li>
                    }

                    <li class="page-item @(Model.CurrentPage < Model.TotalPages ? "cursor-pointer" : "disabled")">
                        @if (Model.CurrentPage < Model.TotalPages)
                        {
                            <a class="page-link" href="@Model.GetPageUrl(Model.CurrentPage + 1)">&raquo;</a>
                        }
                        else
                        {
                            <span class="page-link">&raquo;</span>
                        }
                    </li>
                </ul>
            </div>
        </div>
    </div>

    @if (Model.ShowInfoArea)
    {
        <div class="blog-pagination-info d-flex justify-content-between">
            <span>@CoreLocalizer[CoreResource.Total_Records]: <strong>@Model.TotalRecords</strong></span>
            <span>@CoreLocalizer[CoreResource.Page] <strong>@(Model.TotalPages == 0 ? 0 : Model.CurrentPage)</strong> @CoreLocalizer[CoreResource.Of] <strong>@Model.TotalPages</strong></span>
        </div>
    }
</nav>

_SelectLanguage.cshtml

Culture selector fragment for Razor views—same intent as the Blazor SelectLanguage component, for server-rendered pages.

  • Path: CodeBlock.DevKit/src/1-Libraries/Source/Web.Blazor.Server/Pages/Shared/_SelectLanguage.cshtml
  • Namespace / notes: Razor partial
@model string
@using CodeBlock.DevKit.Web.Localization
@using Microsoft.AspNetCore.Http.Extensions;
@inject LocalizationSettings LocalizationSettings
@{
    string BtnClass = Model ?? "btn btn-outline-primary";
}

@if (LocalizationSettings.HasMoreThanOneLanguage())
{
    <div id="select-language" class="btn f-sm-group">
        <button type="button" class="@BtnClass dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
            @LocalizationSettings.GetCurrentLanguageName()
        </button>
        <ul class="dropdown-menu">
            @foreach (var item in LocalizationSettings.Languages)
            {
                var setCultureUrl = $"/setculture?lang={item.Code}&returnUrl={Context.Request.GetEncodedPathAndQuery()}";

                <li><a class="dropdown-item" href="@setCultureUrl">@item.Name</a></li>
            }
        </ul>
    </div>
}


_ServerValidationSummary.cshtml

Renders ModelState validation errors in one block—use after postbacks when you want a single summary above the form.

  • Path: CodeBlock.DevKit/src/1-Libraries/Source/Web.Blazor.Server/Pages/Shared/_ServerValidationSummary.cshtml
  • Namespace / notes: Razor partial
@{
    var errors = new List<string>();

    if (ViewData["Errors"] != null)

        errors = (List<string>)ViewData["Errors"];

    bool hasError = errors.Count > 0;
}

@if (ViewData["Message"] != null || hasError)

{
    <div class="border @((bool)ViewData["IsSuccess"]==false?"border-danger text-danger":"border-success text-success")">
        <h6>@ViewData["Message"]</h6>
        @if (hasError)
        {
            <ul>
                @foreach (var error in errors)

                {
                    <li>@error</li>
                }
            </ul>
        }
    </div>
}

See also

  • Customizing Razor UIpath override (same relative path under your client’s Pages tree) and Razor UI layouts.