Skip to content
Menu
Search
Browse documentation & this page

Developer Guide

Adding Settings pages

Put a page of your own on the CMS Settings menu: where the file goes, how it is placed, and what the CMS does for you.

The Settings menu in the CMS is extensible. A page you write appears in the same sidebar as Cendia's own (Configuration, Users, Content Types and the rest), opens with the same header, and is protected the same way. You can add it to an existing group or start a new one, and choose where it sits in that group.

There is no registration call and no menu file to edit. The page's location and one attribute are all the CMS needs.

What the CMS does for you

For every Razor Page in your site's Extensions/Settings/ folder, the CMS:

  • serves it at /cms/settings/<name>, where <name> is the file name in lowercase;
  • draws it inside the CMS shell: top bar, Settings sidebar, and the standard page header;
  • makes it Administrator-only, like every other Settings screen. You cannot forget this and you cannot turn it off.

A page that also carries [SettingsPage] is listed in the sidebar.

Step 1: create the page

Add a Razor Page, the .cshtml and its PageModel, to Extensions/Settings/ in your site. This example is Extensions/Settings/Corporate.cshtml, so it is served at /cms/settings/corporate.

YourSite/
  Extensions/
    Settings/
      _ViewImports.cshtml      ← ships with the Starter
      Corporate.cshtml
      Corporate.cshtml.cs

The Starter already includes Extensions/Settings/_ViewImports.cshtml. If your site predates it, create it:

@using Cendia.Settings
@namespace YourSite.Extensions.Settings
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

Do not add a _ViewStart.cshtml or set Layout. The CMS supplies the layout for this folder.

Step 2: put it on the menu

Give the PageModel [SettingsPage]. It takes three things: the group to list it under, the menu name, and a subtitle.

using Cendia.Settings;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace YourSite.Extensions.Settings;

[SettingsPage("People", "Corporate", "Accounts that are billed together on one corporate invoice.",
    Title = "Corporate Accounts", Order = 5)]
public class CorporateModel : PageModel
{
    public void OnGet() { }
}
Argument Required What it does
group yes The sidebar heading it is listed under. Cendia's groups are Site, People, Content model and Designer. Matching is case-insensitive.
menuName yes What the sidebar says.
subtitle yes One line under the page title saying what the page is for. Every Settings page has one.
Title no The page heading, when it should say more than the menu name. Defaults to the menu name.
Order no Where it sits in its group. See step 3.

You can put the attribute in the .cshtml instead, with @attribute [SettingsPage(...)]. Use one place, not both.

Step 3: choose where it sits

Cendia numbers its own entries 10, 20, 30… within each group, in the order they appear. Your Order places your page among them:

Order Result, in the People group (Users 10, Groups 20, Permissions 30)
5 Above Users
15 Between Users and Groups
25 Between Groups and Permissions
(left out) At the bottom, after Permissions

If your page has the same number as a Cendia entry, Cendia's entry comes first. Two pages of your own with the same number are sorted by menu name.

A new group. Use a group name Cendia does not have, such as "Integrations", and it becomes a new heading after Cendia's own groups. Several new groups appear in the order the CMS first finds them. Use Order to arrange the pages inside a group.

Step 4: write the page body

Do not write a title or subtitle in the page. The CMS draws both from [SettingsPage], so every Settings screen opens the same way. Write only what goes beneath them.

@page
@model CorporateModel
@{
    ViewData["CmsWidth"] = "narrow";
}

@section PageActions {
    <button type="button" class="btn btn-primary btn-sm">+ New Account</button>
}

<form method="post">
    <label asp-for="AccountName" class="form-label">Account name</label>
    <input asp-for="AccountName" class="form-control" />
    <button type="submit" class="btn btn-primary mt-2">Add</button>
</form>
  • @section PageActions: buttons and links shown at the right-hand end of the header, beside the title. Optional.
  • ViewData["CmsWidth"]: how much of the column the page uses.
    • Leave it out for the full width (up to 1400px). This suits wide tables and editors.
    • "medium" uses about two thirds. This suits a settings form with sections.
    • "narrow" uses about half. This suits a short form or a short list.
  • Forms, handlers (OnPost, OnPostSave…), tag helpers and RedirectToPage() all work as they do in any Razor Page. Anti-forgery tokens are added to <form method="post"> automatically.

Step 5: run it

Restart the site, sign in as an Administrator, and open Settings. The page is listed in its group, highlighted when you are on it, and served at /cms/settings/corporate.

Detail pages and sub-pages

A page in Extensions/Settings/ without [SettingsPage] is still served and still Administrator-only, but it is not listed in the sidebar. Use this for a screen you reach from your listed page, such as an edit screen for one record:

Extensions/Settings/Corporate/Index.cshtml    → /cms/settings/corporate          (listed)
Extensions/Settings/Corporate/Edit.cshtml     → /cms/settings/corporate/edit     (not listed)

A folder's Index page is served at the folder's address. A sub-page under a listed page keeps that page highlighted in the sidebar.

Because an unlisted page has no attribute to take its header from, it sets its own:

@{
    ViewData["Title"] = Model.Account.Name;
    ViewData["Subtitle"] = "A corporate account and the users billed to it.";
}

Rules to know

  • Names must not collide. Cendia's own Settings pages use /cms/settings/configuration, /cms/settings/users and so on. Do not name your file after one of them.
  • Addresses are lowercase. Corporate.cshtml is /cms/settings/corporate. Link to it by that address rather than with asp-page, since the page is not in the cms area.
  • It lives in Extensions, not Models. A Settings page is configuration for your installation, not part of your content model, so it belongs beside your other extensions (Extensions/Jobs, Extensions/Fields).
  • The Starter has a worked example. Extensions/Settings/SettingsPage.Example.cs and .cshtml ship commented out. Rename them and uncomment them to try it, then delete them once you have a page of your own.