Skip to content

Report 21: Page Templates Side-by-Side Comparison

Date: 2026-02-27 Scope: All root .cshtml files in Views/ (page templates and master layouts), excluding Partials/ subdirectories. V8 source: psCreditUnion/Progress.Web/Views/ V17 target: dbl.Progress/src/www/Views/


1. Overview

Metric Count
V8 root .cshtml files 48
V17 root .cshtml files 46
Migrated (1:1 or consolidated) 44
V8-only (not migrated) 3 (LoanBoxContactControl, NewsCategoryItems, TrustpilotWidget)
V17-only (new) 1 (_ViewImports.cshtml)
Consolidated 1 (masterNoHeaderNoFooter.cshtml merged into masterNoHeaderNof.cshtml in v17)

Migration Pattern Summary

Every migrated template applies the same set of repeating transformation patterns:

ID Pattern V8 V17
P1 Base class @inherits Umbraco.Web.Mvc.UmbracoViewPage @inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage
P2 Strongly-typed model @inherits ...UmbracoViewPage<ContentModels.Xyz> Removed; use Model.Value<T>() directly
P3 Settings lookup Umbraco.ContentSingleAtXPath("//...") @inject ISiteSettingsService SiteSettings
P4 CSS/JS bundling Html.RequiresCss() / Html.RequiresJs() / Html.RenderCssHere() / Html.RenderJsHere() <link> / <script> tags + Html.AddScript() / Html.RenderScripts() / Html.RenderCss()
P5 Cached partials Html.CachedPartial("...", Model, 3600, true) await Html.CachedPartialAsync("...", Model, TimeSpan.FromHours(1), cacheByPage: true)
P6 Sync partials Html.Partial("...") / Html.RenderPartial("...") await Html.PartialAsync("...")
P7 Grid rendering Html.GetGridHtml(Model, "grid", "template", ...) Model.Value<BlockGridModel>("grid") + Html.PartialAsync("blockgrid/...")
P8 BlockList rendering Html.GetBlockListHtml(Model, "Blocks") Model.Value<BlockListModel>("blocks") + Html.PartialAsync("blocklist/default", ...)
P9 Dictionary values Umbraco.GetDictionaryValue("key") @inject IDictionaryService Dictionary + Dictionary.GetValue("key")
P10 Color picker #@color (double-hash bug) .TrimStart('#') applied to all color values
P11 Bool properties Model.Value<String>("x") == "True" Model.Value<bool>("x")
P12 Bootstrap data attrs data-spy, data-target, data-offset data-bs-spy, data-bs-target, data-bs-offset
P13 Macro rendering Umbraco.RenderMacro("...") Replaced with BlockGrid/BlockList content or ViewComponents
P14 Surface controllers Html.RenderAction("...", "...Surface") await Component.InvokeAsync("...")
P15 Umbraco Forms Html.RenderUmbracoFormDependencies() Removed (v17 Forms handles its own dependencies)

2. Side-by-Side Comparisons

A. master.cshtml -- The Main Layout

The most important file. Controls HTML shell, CSS/JS loading, header/footer, GTM, fonts, and search for every page.

Inherits and Imports

v8 (Umbraco 8)
@inherits Umbraco.Web.Mvc.UmbracoViewPage
@using ClientDependency.Core.Mvc
@using Progress.Core.Helpers
@using System.Web.Configuration
@using System.Text.RegularExpressions
@using Umbraco.Forms.Mvc
v17 (Umbraco 17)
@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage
@using Umbraco.Cms.Core.Models.PublishedContent
@using System.Text.RegularExpressions
@using Progress.Umbraco.Helpers
@inject ISiteSettingsService SiteSettings
@inject IDictionaryService Dictionary
@inject Microsoft.AspNetCore.Hosting.IWebHostEnvironment WebHostEnvironment

What changed:

  • P1: Base class namespace changed from Umbraco.Web.Mvc to Umbraco.Cms.Web.Common.Views
  • P3: ClientDependency.Core.Mvc removed entirely; replaced by DI-injected services
  • P3: System.Web.Configuration (ASP.NET 4.x) removed; no WebConfigurationManager in .NET Core
  • P3: Umbraco.Forms.Mvc removed; Forms handles its own dependencies in v17
  • P3: Three @inject directives replace all XPath content queries

Settings Resolution

v8 (Umbraco 8)
var settings = Umbraco.ContentSingleAtXPath("//websiteConfiguration");
string domainName = HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority);
var Mobile = Request.Browser["IsMobile"];

var gtsettings = Umbraco.ContentSingleAtXPath("//googleTagManagerConfiguration");
var googleTagManagerHeader = gtsettings.Value<string>("googleTagManagerHeader");

var stylesSettings = Umbraco.ContentSingleAtXPath("//siteStyleConfiguration");
var menuSettings = Umbraco.ContentSingleAtXPath("//menuConfiguration");
var menuStyle = menuSettings.Value<string>("menuStyle");

var cookieNotice = Umbraco.GetDictionaryValue("cookieNotice");

string searchUrl = Umbraco.ContentAtXPath("//search")
    .Single(c => c.Parent.Id == Model.Root().Id)
    .Url();
v17 (Umbraco 17)
var website = SiteSettings.Website;
var styles = SiteSettings.Styles;
var menu = SiteSettings.Menu;
var gtm = SiteSettings.GoogleTagManager;

var gtmHeader = gtm?.GoogleTagManagerHeader;
var menuStyle = menu?.MenuStyle?.ToLowerInvariant();

var searchUrl = SiteSettings.SearchPage?.Url();

var cookieNotice = Dictionary.GetValue("cookieNotice");
var gotoTop = Dictionary.GetValue("GotoTop");

What changed:

  • P3: Five separate ContentSingleAtXPath() calls replaced by a single ISiteSettingsService injection (cached per request)
  • P9: Umbraco.GetDictionaryValue() replaced by Dictionary.GetValue()
  • HttpContext.Current removed (not available in .NET Core)
  • Request.Browser["IsMobile"] removed (responsive CSS replaces server-side mobile detection)
  • Null-safe operators (?.) used throughout for robustness

CSS and JS Loading

v8 (Umbraco 8)
Html.RequiresCss("~/vendor/bootstrap/css/bootstrap.min.css", 0);
Html.RequiresCss("~/vendor/slick/slick.css", 3);
Html.RequiresCss($"~/content/common{commonCssVersion}.css", 10);

Html.RequiresJs("/vendor/bootstrap/js/bootstrap.bundle.min.js", 1, new { defer = "defer" });
Html.RequiresJs("/vendor/lazysizes/lazySizes.min.js", 12, new { async = "async" });

// In <head>:
@Html.RenderCssHere()

// Before </body>:
@Html.RenderJsHere()
v17 (Umbraco 17)
// Static <link> tags in <head>:
<link rel="stylesheet" href="~/vendor/bootstrap/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/vendor/slick/slick.css" />
<link rel="stylesheet" href="~/content/CommonV2.css" />
<link rel="stylesheet" href="~/css/umbraco-blockgrid.css" />

// Script helper calls before </body>:
Html.AddScript("~/vendor/bootstrap/js/bootstrap.bundle.min.js", 1, defer: true);
Html.AddScript("~/vendor/lazySizes/lazySizes.min.js", 12, true);

// Partials can contribute CSS/JS:
@Html.RenderCss()
@Html.RenderScripts()

What changed:

  • P4: ClientDependency framework (RequiresCss/RequiresJs/RenderCssHere/RenderJsHere) replaced entirely
  • CSS now uses explicit <link> tags in <head> (order matches v8 priorities)
  • JS uses custom Html.AddScript() helper with named parameters (async:, defer:)
  • Versioned CSS file common{version}.css replaced by CommonV2.css
  • New: umbraco-blockgrid.css added for BlockGrid layout support
  • New: gridSlider.css and homeSlider.css loaded globally
  • New: jQuery UI CSS/JS added globally (was loaded per-component in v8)
  • jQuery CDN fallback added: window.jQuery || document.write(...)

Cached Partials (Header/Footer)

v8 (Umbraco 8)
@Html.CachedPartial("SiteLayout/headerMenu4", Model, 3600, true)
@Html.Partial("SiteLayout/footer")

@Html.RenderUmbracoFormDependencies()
v17 (Umbraco 17)
@await Html.CachedPartialAsync("SiteLayout/headerMenu4", Model,
    TimeSpan.FromHours(1), cacheByPage: true)
@await Html.PartialAsync("SiteLayout/footer")

What changed:

  • P5: CachedPartial becomes CachedPartialAsync with await; cache duration uses TimeSpan instead of seconds
  • P6: Html.Partial becomes await Html.PartialAsync
  • P15: RenderUmbracoFormDependencies() removed entirely
  • P12: data-spy="scroll" becomes data-bs-spy="scroll" (Bootstrap 5)

Body Tag and Bottom Section

v8 (Umbraco 8)
<body id="page-@strBodyTagID" data-spy="scroll" data-target="#fixedNavbar" data-offset="1">

@Html.RenderJsHere()
@RenderSection("ScriptsBottom", false)
@Html.PageScripts()
<input id="cultureAll" name="culture" type="hidden"
       value="@System.Threading.Thread.CurrentThread.CurrentCulture.ToString()">
v17 (Umbraco 17)
<body id="page-@bodyId" data-bs-spy="scroll" data-bs-target="#fixedNavbar" data-bs-offset="1">

@Html.RenderScripts()
@RenderSection("scripts", false)
<input type="hidden" id="cultureAll" name="culture" value="@fullCulture" />

What changed:

  • P12: All Bootstrap data attributes gain bs- prefix
  • P4: RenderJsHere() + PageScripts() consolidated into single RenderScripts()
  • Section name changed from "ScriptsBottom" to "scripts" for consistency
  • Culture uses Model.GetCultureFromDomains() instead of Thread.CurrentThread.CurrentCulture

B. home.cshtml -- Grid to BlockGrid Conversion

Shows the core content rendering transformation from v8 Grid to v17 BlockGrid.

v8 (Umbraco 8)

@inherits Umbraco.Web.Mvc.UmbracoViewPage
@using Progress.Core.Extensions
@using Umbraco.Web
@using Umbraco.Core.PropertyEditors.ValueConverters
@using ClientDependency.Core.Mvc
@using Umbraco.Web.Models;

@{
    Html.RequiresJs("~/Scripts/aosInit.js", 25, new { async = "async" });
}
@{
    Layout = "master.cshtml";
}
@Html.Partial("home/slider")

<div class="container bodyStart homepage">
    @Html.GetGridHtml(Model, "grid", "homePageGrid", true, false)
</div>

v17 (Umbraco 17)

@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage
@using Umbraco.Cms.Core.Models.Blocks
@using Microsoft.AspNetCore.Mvc.ViewFeatures
@using www.Extensions
@using Progress.Umbraco.Helpers
@{
    Layout = "master.cshtml";
}

@{
    Html.AddScript("~/Scripts/aosInit.js", 25, async: true);
}

@await Html.PartialAsync("Home/slider")

<div class="container bodyStart homepage">
    @{
        var grid = Model.Value<BlockGridModel>("grid");
        if (grid != null && grid.Any())
        {
            @await Html.PartialAsync("blockgrid/BootstrapGrid", grid,
                new ViewDataDictionary(ViewData) {
                    { "ColumnBreakpoint", "xl" },
                    { "RowClasses", "row clearfix" },
                    { "ColumnClasses", "column mx-0 mx-md-0" },
                    { "UseContainer", false },
                    { "MergeAreaClasses", true }
                }, true)
        }
    }
</div>

What changed:

  • P1: Base class namespace updated
  • P4: Html.RequiresJs() becomes Html.AddScript() with named async: parameter
  • P6: Html.Partial("home/slider") becomes await Html.PartialAsync("Home/slider")
  • P7: Single-line Html.GetGridHtml(Model, "grid", "homePageGrid", true, false) replaced with:
    • Model.Value<BlockGridModel>("grid") to get the typed model
    • Html.PartialAsync("blockgrid/BootstrapGrid", grid, viewData) for rendering
    • ViewDataDictionary with layout parameters (ColumnBreakpoint, RowClasses, UseContainer, etc.)
  • Null-check added (grid != null && grid.Any()) -- v8 grid helper handled null internally
  • Container <div> preserved exactly (class "container bodyStart homepage")

C. standardPage.cshtml -- Generic Page with Grid + Header Image

Demonstrates header image/color handling, the color picker double-hash fix, and multi-section grid rendering.

v8 (Umbraco 8)

@inherits Umbraco.Web.Mvc.UmbracoViewPage
@using Progress.Core.Extensions
@using Umbraco.Web
@using Umbraco.Core.PropertyEditors.ValueConverters

@{
    Layout = "master.cshtml";

    if (Model.Value<IPublishedContent>("headerImage") != null)
    {
        var myHeaderImage = Model.Value<IPublishedContent>("headerImage");
        myHeaderImageUrl = myHeaderImage.Url;
        var fileExtensionOne = myHeaderImage.GetProperty("UmbracoExtension").GetSourceValue();
        fileExtension = fileExtensionOne.ToString();

        if (fileExtension.ToString() != "mp4")
        {
            var headerImage = Model.Value<IPublishedContent>("headerImage").Url;
            myImage = headerImage + mycrop;
            style = "background-image: url('" + myImage + "')";
        }
    }
    else
    {
        var backgroundColorNew = Model.Value<String>("headerColour");
        if (backgroundColorNew != "")
        {
            backgroundColor = backgroundColorNew;
        }
        var solidColor = Model.Value<String>("solidColour");
        if (solidColor == "True")
        {
            style = "background-color:#" + backgroundColor;
        }
    }
}

<div class="container content-page with-header">
    @Html.GetGridHtml(Model, "grid", "standardPageGridBootStrap", true, false)
</div>

v17 (Umbraco 17)

@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage
@using Umbraco.Cms.Core.Models.Blocks
@using Microsoft.AspNetCore.Mvc.ViewFeatures
@using www.Extensions

@{
    Layout = "master.cshtml";

    var headerImage = Model.Value<IPublishedContent>("headerImage");

    if (headerImage != null)
    {
        myHeaderImageUrl = headerImage.Url();
        fileExtension = headerImage.Value<string>("umbracoExtension") ?? "";

        if (fileExtension.ToLowerInvariant() != "mp4")
        {
            myImage = myHeaderImageUrl + mycrop;
            style = $"background-image: url('{myImage}')";
        }
    }
    else
    {
        var backgroundColorNew = Model.Value<string>("headerColour") ?? "";
        if (!string.IsNullOrEmpty(backgroundColorNew))
        {
            backgroundColor = backgroundColorNew.TrimStart('#');
        }
        var solidColor = Model.Value<bool>("solidColour");
        if (solidColor)
        {
            style = $"background-color:#{backgroundColor}";
        }
    }
}

<div class="container content-page with-header">
    @{
        var grid = Model.Value<BlockGridModel>("grid");
        if (grid != null)
        {
            @await Html.PartialAsync("blockgrid/_MultiSectionGrid", grid,
                new ViewDataDictionary(ViewData) {
                    { "PageName", Model.Name },
                    { "InjectH1", true },
                    { "ColumnBreakpoint", "md" },
                    { "RowClasses", "row clearfix mainbody" },
                    { "ColumnClasses", "column" },
                    { "UseContainer", true },
                    { "ContainerClass", "container" },
                    { "SectionBreakpoint", "lg" }
                }, true)
        }
    }
</div>

What changed:

  • P1: Base class namespace updated
  • P10: Color values get .TrimStart('#') to prevent double-hash bug (##e47d51)
  • P11: Model.Value<String>("solidColour") == "True" becomes Model.Value<bool>("solidColour")
  • Media property access: myHeaderImage.GetProperty("UmbracoExtension").GetSourceValue() becomes headerImage.Value<string>("umbracoExtension")
  • .Url property becomes .Url() method call
  • Null-safe patterns: ?? "" and !string.IsNullOrEmpty() replace bare != ""
  • String interpolation: $"background-color:#{backgroundColor}" replaces concatenation
  • P7: Html.GetGridHtml() replaced with _MultiSectionGrid partial (supports v8 multi-section layout structure)
  • Grid partial receives layout config via ViewDataDictionary (InjectH1, UseContainer, ContainerClass, etc.)

3. Complete File Mapping Table

Master Layouts

# v8 File v17 File Status Patterns Notes
1 master.cshtml master.cshtml MIGRATED P1,P3,P4,P5,P6,P9,P12,P15 Main layout; XPath to DI; ClientDependency to static tags
2 masterNoHeaderNoFooter.cshtml masterNoHeaderNoFooter.cshtml CONSOLIDATED P1,P3,P4 Was 4 lines in v8 (Layout=null); v17 is full standalone layout identical to masterNoHeaderNof
3 masterNoHeaderNof.cshtml masterNoHeaderNof.cshtml MIGRATED P1,P3,P4 Full standalone layout with CSS/JS but no header/footer; v17 identical to masterNoHeaderNoFooter
4 MasterThirdParty.cshtml MasterThirdParty.cshtml MIGRATED P1,P3,P4,P5,P6,P9,P12 Near-identical to master.cshtml; same transformation patterns
5 MasterLogin.cshtml MasterLogin.cshtml MIGRATED P1,P3,P4,P5,P6,P9,P12 Simplified layout for login pages; uses <cache> tag helper instead of CachedPartialAsync
6 -- _ViewImports.cshtml NEW -- v17-only; provides global @using and @addTagHelper directives

Home Page Templates

# v8 File v17 File Status Patterns Notes
7 home.cshtml home.cshtml MIGRATED P1,P4,P6,P7 Grid to BlockGrid via BootstrapGrid partial
8 homeGrid.cshtml homeGrid.cshtml MIGRATED P1,P4,P7,P14 Html.RenderAction to Component.InvokeAsync; homepageH1 script externalized
9 homeFullWidthSection.cshtml homeFullWidthSection.cshtml MIGRATED P1,P4,P6,P7,P14 Two grids (grid + bottomGrid) both converted to BlockGrid

Standard Page Templates

# v8 File v17 File Status Patterns Notes
10 standardPage.cshtml standardPage.cshtml MIGRATED P1,P7,P10,P11 Header image + color picker + _MultiSectionGrid
11 StandardPageNew.cshtml standardPageNew.cshtml MIGRATED P1,P4,P7,P8 BlockList header + Grid body; case normalized in v17
12 standardPageWow.cshtml standardPageWow.cshtml MIGRATED P1,P4,P7,P10,P11 AOS animations; height dropdown wrapped in try-catch for Flexible.Dropdown bug
13 standardPageWithImageText.cshtml standardPageWithImageText.cshtml MIGRATED P1,P4,P7,P10,P11 Similar to standardPageWow with image+text header
14 StandardPageNewNoHeaderNoFooter.cshtml StandardPageNewNoHeaderNoFooter.cshtml MIGRATED P1,P4,P7,P8 Uses masterNoHeaderNoFooter layout
15 StandardPageThirdParty.cshtml StandardPageThirdParty.cshtml MIGRATED P1,P7,P8 Uses MasterThirdParty layout

Article Templates

# v8 File v17 File Status Patterns Notes
16 article.cshtml article.cshtml MIGRATED P1,P6,P10,P11 Color picker fix; renders ArticleContent partial
17 articleList.cshtml articleList.cshtml MIGRATED P1,P7,P10,P11 Article listing page
18 articleListPaging.cshtml articleListPaging.cshtml MIGRATED P1,P7 Paginated article list
19 articleType2.cshtml articleType2.cshtml MIGRATED P1,P6,P7 Alternate article layout
20 ArticleContentType2.cshtml ArticleContentType2.cshtml MIGRATED P1,P6,P7 Alternate article content type
21 LatestArticlesPaging.cshtml LatestArticlesPaging.cshtml MIGRATED P1,P7 Latest articles with pagination

FAQ Templates

# v8 File v17 File Status Patterns Notes
22 Faq.cshtml Faq.cshtml MIGRATED P1,P4,P7,P8 BlockList + Grid; uses _MultiSectionGrid
23 Faq1.cshtml Faq1.cshtml MIGRATED P1,P4,P7,P8 Alternate FAQ layout
24 FaqWithSchema.cshtml FaqWithSchema.cshtml MIGRATED P1,P4,P7,P8 FAQ with JSON-LD schema markup

Functional Templates

# v8 File v17 File Status Patterns Notes
25 search.cshtml search.cshtml MIGRATED P1,P3,P9,P10,P11 Umbraco.ContentQuery.Search replaced with Examine fluent API; form-group to mb-3; no-gutters to g-0
26 contactus.cshtml contactus.cshtml MIGRATED P1,P7,P10,P11 ContactUsGrid to _MultiSectionGrid
27 error.cshtml error.cshtml MIGRATED P1,P7,P10,P11 Error page with grid content
28 sitemap.cshtml sitemap.cshtml MIGRATED P1 XML sitemap; @helper syntax replaced with @functions returning IHtmlContent; HttpContext.Current replaced with Context.Request
29 robots.cshtml robots.cshtml MIGRATED P1 text/plain output; Request.Url replaced with Context.Request.Scheme/Host; v8-only paths removed
30 cookies.cshtml cookies.cshtml MIGRATED P1,P7 Cookie policy page
31 privacyPolicy.cshtml privacyPolicy.cshtml MIGRATED P1,P7 Privacy policy page
32 termsAndConditions.cshtml termsAndConditions.cshtml MIGRATED P1,P7 Terms page

Login and Authentication Templates

# v8 File v17 File Status Patterns Notes
33 Login1.cshtml Login1.cshtml MIGRATED P1,P7,P13 Umbraco.RenderMacro("Login") replaced with BlockGrid content rendering
34 CustomerOnlyPage1.cshtml CustomerOnlyPage1.cshtml MIGRATED P1,P3,P7,P10,P11 Uses MasterLogin layout; grid content
35 TokenAuthentication.cshtml TokenAuthentication.cshtml MIGRATED P1,P4,P7,P8 BlockList + Grid; same pattern as StandardPageNew

Special Templates

# v8 File v17 File Status Patterns Notes
36 SPALoader.cshtml SPALoader.cshtml MIGRATED P1,P3,P9 HtmlAgilityPack parsing; Server.MapPath to WebHostEnvironment.WebRootPath; Dictionary injection
37 popUpForms.cshtml popUpForms.cshtml MIGRATED P1,P2,P13 Macro form rendering; v17 has TODO placeholder for Umbraco.Forms integration
38 NoPreviewAvailable.cshtml NoPreviewAvailable.cshtml MIGRATED P1 Standalone info page; v17 simplified with flexbox layout
39 TestimonialsBlock.cshtml TestimonialsBlock.cshtml MIGRATED P1,P7 Testimonials display page
40 testimonials.cshtml testimonials.cshtml MIGRATED P1,P7 Alternate testimonials template
41 gallery.cshtml gallery.cshtml MIGRATED P1,P7,P10 Photo gallery page
42 galleryList.cshtml galleryList.cshtml MIGRATED P1,P7 Gallery listing page
43 help.cshtml help.cshtml MIGRATED P1,P7 Help/support page
44 loanInputCTA.cshtml loanInputCTA.cshtml MIGRATED P1,P7 Loan calculator CTA page
45 releaseNotesWidget.cshtml releaseNotesWidget.cshtml MIGRATED P1,P2 Release notes dropdown; strongly-typed model removed
46 TermsAndConditionsMobile.cshtml TermsAndConditionsMobile.cshtml MIGRATED P1 Mobile T&C view

V8-Only (Not Migrated to V17)

# v8 File v17 File Status Patterns Notes
47 LoanBoxContactControl.cshtml -- OBSOLETE -- Empty template (Layout = null only); content type unused in active databases
48 NewsCategoryItems.cshtml -- OBSOLETE -- Empty template (Layout = null only); content type unused in active databases
49 TrustpilotWidget.cshtml -- OBSOLETE -- Empty template (Layout = null only); content type unused in active databases

4. Gaps and Notable Differences

Templates Not Migrated (3)

v8 File Reason
LoanBoxContactControl.cshtml Empty stub template (4 lines: @inherits + Layout = null). No content rendering. Content type appears unused.
NewsCategoryItems.cshtml Empty stub template (3 lines). No content rendering. Content type appears unused.
TrustpilotWidget.cshtml Empty stub template (3 lines). No content rendering. Content type appears unused.

All three are empty templates that only set Layout = null with no body content. They were likely created by ModelsBuilder but never implemented. Per the shared codebase policy, these should be cross-validated against all client databases before removal from the codebase.

V17-Only Template (1)

v17 File Purpose
_ViewImports.cshtml Global @using directives and @addTagHelper registrations. ASP.NET Core convention (no v8 equivalent). Imports: Umbraco.Extensions, Umbraco.Cms.Web.Common.PublishedModels, Progress.Baseline.Core.Services, Progress.Umbraco.Extensions, www.Services, Umbraco.Community.UmbNav.Core.

Consolidated Template (1)

v8 Files v17 Result
masterNoHeaderNoFooter.cshtml (4 lines) + masterNoHeaderNof.cshtml (159 lines) Both exist in v17 with identical full layout code. The v8 masterNoHeaderNoFooter.cshtml was a minimal 4-line file; v17 expanded it to a full standalone layout matching masterNoHeaderNof.cshtml.

Key Architectural Differences

  1. Grid to BlockGrid: Every @Html.GetGridHtml(Model, ...) call is replaced with Model.Value<BlockGridModel>(...) + Html.PartialAsync("blockgrid/..."). Two partial renderers are used:

    • blockgrid/BootstrapGrid -- for simple single-section pages (home, homeGrid)
    • blockgrid/_MultiSectionGrid -- for multi-section pages with H1 injection (standardPage, contactus, error, etc.)
  2. Macro Elimination: All Umbraco.RenderMacro() calls removed. Login macro replaced with BlockGrid content. Form macro has a TODO placeholder.

  3. Surface Controller Elimination: Html.RenderAction("...", "...Surface") replaced with Component.InvokeAsync("...") ViewComponents.

  4. popUpForms.cshtml: The Umbraco Forms rendering is currently a TODO placeholder in v17. The v8 version used Umbraco.RenderMacro("renderUmbracoForm", ...) which is not available in v17. This needs the Umbraco.Forms v17 package integration.

  5. Search Implementation: v8 used Umbraco.ContentQuery.Search() which is removed in v17. Replaced with direct Examine index querying via IExamineManager with fluent API.

Migration documentation by Double for Progress Credit Union