How Pages Work in .NET

We believe Editors should have full control over the pages on their website and should not rely on a developer to create new pages for them.

The agilitycms-dotnet-starter makes it easy to source content and generates your website pages for you based on your sitemap in Agility CMS.

This means that Editors in the CMS control what pages are available, what their URLs are, and exactly what UI components (we call these Component Models) make up each page.

Page Generation

The following example is based on the Blog Template instance.

The above figure represents a sitemap of Layouts as well as the Components that are on each page - all are managed in the CMS.

This means that when a build occurs in your .NET site, the following pages will be auto-generated for you:

  1. /
  2. /blog
  3. /blog-posts/* - your dynamic page route for all of your blog posts (i.e. /blog/my-first-post)
  4. /about

Page Rendering

The .NET 5 starter can generate and serve pages in response to requests from browsers. It uses the AgilityPage.cshtml.cs file to source the Static and Dynamic page items from our Sitemap in Agility, and the AgilityPage.cshtml file is what renders out your Page Modules to display the front-end.

AgilityPage.cshtml.cs:


using System.Collections.Generic;
using System.Threading.Tasks;
using Agility.NET.FetchAPI.Helpers;
using Agility.NET.FetchAPI.Models.API;
using Agility.NET.FetchAPI.Models.Data;
using Agility.NET.FetchAPI.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace Agility.NET.Starter.Pages
{
    public class AgilityPageModel : PageModel
    {
        private readonly FetchApiService _fetchApiService;
        
        public PageResponse PageResponse { get; set; }
        public List ContentZones { get; set; }
        public string Locale { get; set; }
        public SitemapPage SitemapPage { get; set; }

        public AgilityPageModel(ILogger logger, IOptions appSettings, FetchApiService fetchApiService)
        {
            _fetchApiService = fetchApiService;
        }

        public async Task OnGetAsync()
        {
            var sitemapPage = (SitemapPage) RouteData.Values["agilityPage"];

            if (sitemapPage == null) return Page();

            var getPageExpandedParameters = new GetPageParameters()
            {
                PageId = sitemapPage.PageID,
                Locale = sitemapPage.Locale,
                ExpandAllContentLinks = true,
                ContentLinkDepth = 2
            };

            var content = await _fetchApiService.GetPage(getPageExpandedParameters);
            var deserializedContent = DynamicHelpers.DeserializeTo(content);

            if (deserializedContent == null) return Page();
            
            deserializedContent.IsDynamicPage = (deserializedContent.Dynamic != null);

            if (deserializedContent.IsDynamicPage)
            {
                deserializedContent.Name = deserializedContent.IsDynamicPage ? sitemapPage.Name : deserializedContent.Name;
                RouteData.Values["dynamicFields"] = deserializedContent.Dynamic;

                var getItemParameters = new GetItemParameters()
                {
                    ContentId = sitemapPage.ContentID,
                    Locale = sitemapPage.Locale,
                    ContentLinkDepth = 3,
                    ExpandAllContentLinks = true
                };

                var contentItem = await _fetchApiService.GetContentItem(getItemParameters);
                RouteData.Values["contentItem"] = contentItem;
            }

            List contentZonesExpanded = DynamicHelpers.DeserializeContentZones(deserializedContent.Zones.ToString());

            PageResponse = deserializedContent;
            Locale = sitemapPage.Locale;
            ContentZones = contentZonesExpanded;
            SitemapPage = sitemapPage;

            return Page();

        }
    }
}

AgilityPage.cshtml:

@page
@using NET.Core.Helpers
@using NET.FetchAPI.Models

@model NET.Starter.Pages.AgilityPageModel

@{
    Layout = PageHelpers.GetPageTemplatePath(Model.PageResponse.TemplateName);
    var scripts = Model.PageResponse.Scripts;
}

@{

    DefineSection("SEO", async () =>
    {
        Write(await Component.InvokeAsync("SEO", Model.PageResponse));
    });
}

@if (!string.IsNullOrEmpty(scripts.Top))
{
    @Html.Raw($"<script>{scripts.Top}</script>")
}

@{
    DefineSection("TopZone", async () =>
    {
        Write(await Component.InvokeAsync("SiteHeader", Model.Locale));
    });
}

@foreach (var contentZone in Model.ContentZones)
{
    DefineSection(contentZone.ReferenceName, async () =>
    {

        foreach (var model in contentZone.Modules)
        {
            var moduleModel = new ModuleModel()
            {
                Locale = Model.Locale,
                Module = model.Item.Fields.ToString()
            };

            Write(await Component.InvokeAsync(model.Item.Properties.DefinitionName, moduleModel));
        }
    });
}

@if (!string.IsNullOrEmpty(scripts.Bottom))
{
    @Html.Raw($"<script>{scripts.Bottom}</script>")
}