Orchard Core Custom Settings - Prompt Templates
Create Custom Site Settings
You are an Orchard Core expert. Generate code and configuration for creating custom site-wide settings sections using the CustomSettings stereotype.
Guidelines
- Enable the
OrchardCore.CustomSettingsfeature to use custom site settings. - Custom settings are organized in sections, each represented by a content type with the
CustomSettingsstereotype. - When creating a custom settings content type, disable
Creatable,Listable,Draftable, andSecurablemetadata — they do not apply. - Do not mark existing content types with the
CustomSettingsstereotype; this will break existing content items of that type. - Custom settings sections appear in the Settings menu alongside module-provided settings.
- Each section gets a dedicated permission under the
OrchardCore.CustomSettingsfeature group in the Roles editor. - Access custom settings in code via
ISiteService.GetCustomSettingsAsync("TypeName"), which returns aContentItem. - Access custom settings in Liquid via
{{ Site.Properties.TypeName.PartName }}. - Custom settings are stored as named JSON properties inside the site document.
- All C# classes must use the
sealedmodifier, except View Models. - All recipe JSON must be wrapped in the root
{ "steps": [...] }format.
Enabling Custom Settings
{
"steps": [
{
"name": "Feature",
"enable": [
"OrchardCore.CustomSettings"
],
"disable": []
}
]
}
Creating a Custom Settings Type via Code
Step 1: Define the Content Part
public sealed class {{SettingsPartName}} : ContentPart
{
public string {{PropertyName}} { get; set; }
public bool {{BoolPropertyName}} { get; set; }
}
Step 2: Register the Content Type with CustomSettings Stereotype
public sealed class Migrations : DataMigration
{
private readonly IContentDefinitionManager _contentDefinitionManager;
public Migrations(IContentDefinitionManager contentDefinitionManager)
{
_contentDefinitionManager = contentDefinitionManager;
}
public async Task<int> CreateAsync()
{
await _contentDefinitionManager.AlterTypeDefinitionAsync("{{SettingsTypeName}}", type => type
.DisplayedAs("{{Settings Display Name}}")
.Stereotype("CustomSettings")
.WithPart("{{SettingsPartName}}", part => part
.WithPosition("0")
)
);
return 1;
}
}
The CustomSettings stereotype tells Orchard Core this content type represents a site settings section rather than a regular content item.
Step 3: Register Services in Startup
public sealed class Startup : StartupBase
{
public override void ConfigureServices(IServiceCollection services)
{
services.AddContentPart<{{SettingsPartName}}>();
}
}
Accessing Custom Settings in Code
Use ISiteService.GetCustomSettingsAsync() to retrieve a custom settings section as a ContentItem:
public sealed class MyService
{
private readonly ISiteService _siteService;
public MyService(ISiteService siteService)
{
_siteService = siteService;
}
public async Task<{{SettingsPartName}}> GetSettingsAsync()
{
ContentItem settingsItem = await _siteService.GetCustomSettingsAsync("{{SettingsTypeName}}");
return settingsItem.GetOrCreate<{{SettingsPartName}}>();
}
}
Alternatively, read the named custom settings content item from the site document:
var siteSettings = await _siteService.GetSiteSettingsAsync();
if (siteSettings.TryGet<ContentItem>("{{SettingsTypeName}}", out var settingsItem))
{
// Use settingsItem here.
}
Use GetSiteSettingsAsync() for read-only access. If you plan to modify the site document and then call UpdateSiteSettingsAsync(), load a mutable copy first with LoadSiteSettingsAsync().
Accessing Custom Settings in Controllers
public sealed class MyController : Controller
{
private readonly ISiteService _siteService;
public MyController(ISiteService siteService)
{
_siteService = siteService;
}
public async Task<IActionResult> Index()
{
ContentItem settingsItem = await _siteService.GetCustomSettingsAsync("{{SettingsTypeName}}");
var settings = settingsItem.GetOrCreate<{{SettingsPartName}}>();
return View(settings);
}
}
Accessing Custom Settings in Liquid
Custom settings are available via the Site.Properties object. Each section is accessible by its content type name:
{{ Site.Properties.{{SettingsTypeName}}.{{SettingsPartName}}.{{PropertyName}} }}
For example, accessing an HtmlBodyPart on a BlogSettings section:
{{ Site.Properties.BlogSettings.HtmlBodyPart.Html | raw }}
Permissions
Each custom settings section automatically receives a dedicated permission. To manage access:
- Navigate to Security → Roles in the admin dashboard.
- Edit the desired role.
- Under the
OrchardCore.CustomSettingsfeature group, check the permission for the settings section.
Custom Settings with Content Fields
Custom settings parts can include content fields for richer configuration:
public sealed class Migrations : DataMigration
{
private readonly IContentDefinitionManager _contentDefinitionManager;
public Migrations(IContentDefinitionManager contentDefinitionManager)
{
_contentDefinitionManager = contentDefinitionManager;
}
public async Task<int> CreateAsync()
{
await _contentDefinitionManager.AlterTypeDefinitionAsync("BrandingSettings", type => type
.DisplayedAs("Branding Settings")
.Stereotype("CustomSettings")
.WithPart("BrandingSettings", part => part
.WithPosition("0")
)
);
await _contentDefinitionManager.AlterPartDefinitionAsync("BrandingSettings", part => part
.WithField("Logo", field => field
.OfType("MediaField")
.WithDisplayName("Site Logo")
.WithPosition("0")
)
.WithField("FooterText", field => field
.OfType("HtmlField")
.WithDisplayName("Footer Text")
.WithPosition("1")
.WithEditor("Wysiwyg")
)
.WithField("SocialLink", field => field
.OfType("LinkField")
.WithDisplayName("Social Media Link")
.WithPosition("2")
)
);
return 1;
}
}
When using content fields, the fields are rendered automatically by content field display drivers — no manual handling in the display driver is needed.
Configuring Custom Settings via Recipe
Use the custom-settings recipe step to set values for a custom settings section:
{
"steps": [
{
"name": "custom-settings",
"{{SettingsTypeName}}": {
"ContentItemId": "[js:uuid()]",
"ContentType": "{{SettingsTypeName}}",
"{{SettingsPartName}}": {
"{{PropertyName}}": "{{value}}",
"{{BoolPropertyName}}": true
}
}
}
]
}
Creating Custom Settings Content Type via Recipe
{
"steps": [
{
"name": "ContentDefinition",
"ContentTypes": [
{
"Name": "{{SettingsTypeName}}",
"DisplayName": "{{Settings Display Name}}",
"Settings": {
"ContentTypeSettings": {
"Stereotype": "CustomSettings"
}
},
"ContentTypePartDefinitionRecords": [
{
"PartName": "{{SettingsPartName}}",
"Name": "{{SettingsPartName}}",
"Settings": {
"ContentTypePartSettings": {
"Position": "0"
}
}
}
]
}
]
}
]
}
Important Notes
- Use
GetCustomSettingsAsync()for read-only access (returns cached instance). - Custom settings content types must not be confused with the
DisplayDriver<ISite>pattern used for module-specific site settings;CustomSettingsis a content-based approach managed entirely through the content type system. - Content types with
CustomSettingsstereotype should not haveCreatable,Listable,Draftable, orSecurableenabled.