Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Instructions on installing Umbraco on various platforms using various tools.
Before you install Umbraco, you must ensure that you can run it on your machine.
Identify and install the latest .NET SDK.
The fastest way to get the latest version of Umbraco up and running is by using the command line (CLI).
Open your command line.
Install the Umbraco templates:
dotnet new install Umbraco.Templates
Create a new project:
dotnet new umbraco --name MyProject
Navigate to the newly created project folder. It will be the folder containing the .csproj
file:
cd MyProject
Build and run the newly created Umbraco site:
dotnet run
The console will output a message similar to: [10:57:39 INF] Now listening on: https://localhost:44388
Open your browser and navigate to that URL.
Follow the instructions to finish up the installation of Umbraco.
There are numerous ways to install Umbraco. Below, you can find links to different installation methods that will help you install and set up Umbraco projects.
.NET CLI, included with the .NET Software Development Kit (SDK), can be used to install or uninstall .NET templates from NuGet. This can be done by using the dotnet new
command on any OS. The underlying Template Engine enables the creation of custom templates which make new project bootstrapping much faster. With a few steps you can have an Umbraco project running without the need for a code editor.
Visual Studio is used to write native code and managed code supported by .NET and many others. Its built-in tools provide the ability to develop and execute applications for any platform. Developers will be able to install Umbraco without ever having to leave Visual Studio.
Learn how to run an already installed local installation of Umbraco.
Visual Studio Code is an editor with an embedded webserver (through the IIS Express extension). A fast way to get you up and running with Umbraco.
From Umbraco v9 and above you can use the Nightly Builds to get the latest version to use and test before it is released. Learn how to install the Nightly builds to get started.
Since Umbraco 9 it has been possible to run Umbraco CMS natively on Linux or macOS High Sierra. To get Umbraco running you will need to follow some steps.
Use the Unattended installs when spinning up Umbraco instances on something like Azure Web Apps to avoid having to run through the installation wizard.
All the fundamentals of using Umbraco - from making a local installation to extending the backend.
In this part of the Umbraco CMS documentation, you can get to know the product and the default functionality. It is here you start your Umbraco journey with the installation, setup, and basics of working with the CMS.
The Umbraco UI works in all modern browsers:
Chrome (Latest)
Edge (Chromium)
Firefox (Latest)
Safari (Latest)
Below you can find the minimum requirements to run Umbraco 15 on your machine:
One of the
One of the following .NET Tools or Editors:
with the
2022 version 17.12 or higher.
Optional: version 2022.3 and higher
and higher
As Umbraco releases are aligned to the .NET release cadence, it's also aligned with Microsoft's Long-term support policy for the underlying framework. For the best experience, we would recommend that you ensure to be on the latest and supported Microsoft versions to run and host Umbraco CMS:
and other
For more information, see the article in the Microsoft documentation.
You can use to manage the hosting infrastructure. All Umbraco Cloud plans are hosted on Microsoft Azure, which gives your site a proven and solid foundation.
Ability to set file permissions to include create/read/write (or better) for the user that "owns" the Application Pool for your site. This would typically be NETWORK SERVICE.
The database account used in the connection string will need permission to read and write from tables. It will also require permission to create schema during installs and upgrades:
The db_owner
role has full permissions on the database.
To use an account with more restricted permissions, the db_datareader
and db_datawriter
roles will be needed for normal use to read from and write to the database. The db_ddladmin
role, which can modify the database schema, is required for installs and upgrades of the CMS and/or any packages that create database tables.
For more information on the Database-level roles, see the .
Information on the requirements to setup, install & upgrade Umbraco
How to install and configure your Umbraco installation.
Defines the system requirements to run Umbraco.
Umbraco installation steps and guidelines.
Covers the steps to upgrade your copy of Umbraco to a newer version.
Information about server setup for Umbraco including information about permissions and load balancing.
How to configure your Umbraco installation. Includes information about all of Umbraco's configuration files and options.
How to install the latest nightly builds.
Resources and links for older versions of Umbrco CMS.
This documentation platform covers only supported versions of the Umbraco CMS, excluding version 8. If you use an unsupported version, you need to go elsewhere.
Learn more about how long each major version of Umbraco is supported.
When a major version of Umbraco CMS goes End of Life (EOL), the documentation for this version will be unpublished 3 months later.
The documentation for all EOL versions will continue to be available on the UmbracoDocs GitHub repository.
The documentation for Umbraco 7 and 8 lives on our.umbraco.com.
Your main resource when building and managing an Umbraco CMS website.
Umbraco CMS is a flexible and editor-friendly Content Management System (CMS) that allows you to create beautiful and modern websites. Use the latest version of .NET, integrate with your favorite services, and help your customers launch a website tailored to their specific needs.
Learn more about Umbraco CMS and get an overview of the top features on Umbraco.com.
The documentation for Umbraco CMS provides information for experienced Umbraco and .NET developers. It also offers guides and high-level articles for people starting out with the CMS.
Umbraco 7 Documentation
Umbraco 8 Documentation
Umbraco v8+ uses Serilog for logging. When load balancing Umbraco consideration should be given as to how the log files from each server will be accessed.
There are many Serilog Sinks available and one of these may be appropriate to store logs for all servers in a central repository such as Azure Application Insights or Elmah.io.
For more information, see SeriLog Provided Sinks.
Fundamentals
Learn the basics of working with Umbraco CMS. How to install and setup your first site is also included in this section.
Install Umbraco CMS
Ready to get started with Umbraco? Head over to the Setup section to learn how to install Umbraco CMS.
Tutorials
Find detailed step-by-step guides on everything from building a site from scratch to implementing a custom maintenance page.
This section explains how the concept of infinite editing using the Sidebar in the Umbraco backoffice works.
This feature enables you to work with your content without losing the context of what you are doing.
Document Types are in different sections than content but the sidebar enables you to make changes to them directly from the content you are editing.
In the example showcased above, new options are being added to a Data Type, without losing the context of the content. The example also shows how you can edit images, without being sent to the 'Media' section.
The sidebar is a feature that comes out of the box with Umbraco. The feature can be customized, which enables you as a developer to improve the workflow for your editors.
Information on file and folder permissions required for Umbraco sites
Schema Alias: Umbraco.DateTime
UI Alias: Umb.PropertyEditorUi.DatePicker
Returns: Date
Displays a calendar UI for selecting dates which are saved as a DateTime value.
The only setting that is available for manipulating the Date property is to set a format. By default the format of the date in the Umbraco backoffice will be YYYY-MM-DD
, but you can change this to something else. See for the supported formats.
See for more information about why the dynamic approach is obsolete.
The Block Editors are property editors that enabled you to build advanced editor tools using a set of predefined Document Types.
This article is a work in progress and may undergo further revisions, updates, or amendments. The information contained herein is subject to change without notice.
Umbraco CMS currently ships with two Block Editors: the Block List and the Block Grid.
Learn how to create custom views for the blocks used in your Block Grid or Block List property editors.
This section focuses on how to create data using the Umbraco backoffice
This section focuses on how to create data using the Umbraco backoffice.
There are three kinds of content in Umbraco:
Your normal website content exists in the content section.
Media content such as images, videos, and PDFs are stored in the Media section.
Finally, Members, are used for user profiles and frontend authentication which you can find in the Members section.
A fundamental principle in Umbraco is that all content types have a definition (Document Types, Media Types, Member Types). These definitions are highly customizable, meaning you can add properties and have complete control over how the data is organized.
Defining Document Types, adding properties, and creating content.
Defining Media Types and uploading files to the media section, using upload fields and image cropper.
Defining Member Types and creating members for authentication and user profiles.
Creating and editing Data Types.
Schedule when content should be published / unpublished automatically.
Overview of how to add and reorder tabs, convert a group to a tab, and manage the “Generic” tab
Control who has access to the Umbraco backoffice and what permissions they have.
An introduction to Relations and Relation Types, creating, and managing relationships between different entities in Umbraco.
Using Dictionary Items, you can store a value for each language. Dictionary Items have a unique key that is used to fetch the value of the Dictionary Item.
How to keep the noise down whilst ensuring your important content versions stick around indefinitely.
On this page, you will find the default Document Types in Umbraco. If you want to use these document types, you can create them in the Settings section.
On this page, you will find the default Document Types in Umbraco. If you want to use these Document Types, you can create them in the Settings section.
A Document Type defines the content structure and fields that can be used across different content items. When creating a Document Type without a template, you focus solely on structured content without tying it to a specific design or layout. This is ideal for content that doesn’t require direct front-end rendering, such as reusable blocks or items managed within a headless CMS setup.
Use a Document Type without a template for structured, reusable content like metadata schemas, settings, or components such as product details and author profiles.
A Document Type with a Template combines the content structure with a predefined visual presentation. This approach links your structured content with a specific page design, ensuring a consistent and cohesive look and feel across your site. It allows you to manage content and its appearance separately, which makes updates more efficient.
Use a Document Type with a template for pages like blog posts, landing pages, or services that appear directly on the website.
An Element Type is a Document Type without a template designed for reusabale and repeatable set of properties. These are primarily used in editors like the Block List Editor or Block Grid Editor to create structured, nested content.
Element Types are not part of the Content tree and cannot render directly on the front end. When created, the Is an Element Type flag in the Permissions tab is automatically set to True.
Use an Element Type when defining building blocks for complex page layouts, such as grid blocks or call-to-action sections. They are an essential part of modular content design.
The Folder in the Document Types section is used to organize and structure your Document Types within the Settings section. It serves purely as an organizational container, with no impact on the Content section or site functionality.
Use a Folder to create logical groupings, like a folder named Compositions to hold all your Composition Document Types. This makes it easier to navigate and manage your Document Types, especially in larger projects.
Folders are a powerful tool to keep your Document Types organized and your backoffice tidy.
/appSettings*.json
Modify / Full control
Only needed for setting database and a global identifier during installation. So can be set to read-only afterwards for enhanced security.
/App_Plugins
Modify / Full control
Should always have modify rights as the folder and its files are used by packages. Not part of your project by default.
/umbraco
Modify / Full control
Should always have modify rights as the folder and its files are used for cache and storage.
/Views
Modify / Full control
Should always have modify rights as the folder and its files are used for Templates and Partial views
/wwwroot/css
Modify / Full control
Should always have modify rights as the folder and its files are used for css files.
/wwwroot/media
Modify / Full control
Should always have modify rights as the folder and its files are used for Media files uploaded via the Umbraco CMS backoffice.
/wwwroot/umbraco
Modify / Full control
Should always have modify rights as the folder and its files are used by packages. Not part of your project by default.
/wwwroot/scripts
Modify / Full control
Should always have modify rights as the folder and its files are used for script files.
@(Model.Content.GetPropertyValue<DateTime>("datePicker").ToString("dd MM yyyy"))
@{
@CurrentPage.datePicker.ToString("dd-MM-yyyy")
}
This section describes different ways of setting up servers for use with Umbraco
We strongly encourage the use of HTTPS with Umbraco installations especially in production environments. Using HTTPS will greatly enhance the security of your website, see the Security reference for more information.
To ensure a stable and smoothly running Umbraco installation, these permissions need to be set correctly.
Information about hosting a v9 application using IIS.
Information on how to deploy Umbraco in a Load Balanced scenario and other details to consider when setting up Umbraco for load balancing.
Best practices for running Umbraco on Azure Web Apps.
The runtime mode setting optimizes Umbraco for the best development experience or optimal production environment.
Creating, managing, and reusing templates in Umbraco.
Querying and rendering published content.
Querying and rendering media items.
Working with partial views in Umbraco's templates.
Working with CSS and JavaScript in Umbraco's templates.
All the code snippets you need to get a jump start on building templates with Razor in Umbraco CMS.
The Razor Cheatsheet is a collection of common methods used for building templates and views in Umbraco CMS.
Get the Umbraco 11 Cheatsheet: https://umbra.co/razorCheatsheet
You can also find the cheatsheet on GitHub where you can give feedback, contribute, or download the template used to generate the sheet.
Use the cheatsheet if you:
Use Models Builder on your project and
Use Umbraco 11.
Learn more about the default property editors that ships with an Umbraco installation.
A Property Editor is the editor that a Data Type references. A Data Type is defined by a user in the Umbraco backoffice and references a Property Editor. In Umbraco a Property Editor is defined in a JSON manifest file and associated JavaScript files.
When creating a Data Type, specify the property editor for the Data Type to use by selecting from the "Property editor" list (as shown below).
Umbraco comes pre-installed with many useful property editors.
Schema Alias: Umbraco.DateTime
UI Alias: Umb.PropertyEditorUi.DatePicker
Returns: DateTime
Displays a calendar UI for selecting dates which are saved as a DateTime value.
There is one setting available for manipulating the DateTime property.
The setting involves defining the format. The default date format in the Umbraco backoffice is YYYY-MM-DD HH:mm:ss
, but you can change it to a different format. See MomentJS.com for the supported formats.
@Model.DatePicker
@Model.Value("datePicker")
See the example below to see how a value can be added or changed programmatically. To update a value of a property editor you need the Content Service.
@using Umbraco.Cms.Core.Services
@inject IContentService ContentService
@{
// Create a variable for the GUID of the page you want to update
var guid = new Guid("32e60db4-1283-4caa-9645-f2153f9888ef");
// Get the page using the GUID you've defined
var content = ContentService.GetById(guid); // ID of your page
// Set the value of the property with alias 'datePicker'
content.SetValue("datePicker", DateTime.Now);
// Save the change
ContentService.Save(content);
}
Although the use of a GUID is preferable, you can also use the numeric ID to get the page:
@{
// Get the page using it's id
var content = ContentService.GetById(1234);
}
If Models Builder is enabled you can get the alias of the desired property without using a magic string:
@using Umbraco.Cms.Core.PublishedCache
@inject IPublishedContentTypeCache PublishedContentTypeCache
@{
// Set the value of the property with alias 'datePicker'
content.SetValue(Home.GetModelPropertyType(PublishedContentTypeCache, x => x.DatePicker).Alias, DateTime.Now);
}
Schema Alias: Umbraco.Decimal
UI Alias: Umb.PropertyEditorUi.Decimal
Returns: decimal
In the example above the possible values for the input field would be [8, 8.5, 9, 9.5, 10]
All other values will be removed in the content editor when saving or publishing.
If the value of Step Size is not set then all decimal values between 8 and 10 is possible to input in the content editor.
@Model.MyDecimal
@Model.Value("MyDecimal")
See the example below to see how a value can be added or changed programmatically. To update a value of a property editor you need the Content Service.
@using Umbraco.Cms.Core.Services
@inject IContentService ContentService
@{
// Create a variable for the GUID of the page you want to update
var guid = Guid.Parse("32e60db4-1283-4caa-9645-f2153f9888ef");
// Get the page using the GUID you've defined
var content = ContentService.GetById(guid); // ID of your page
// Set the value of the property with alias 'myDecimal'.
content.SetValue("myDecimal", 3);
// Save the change
ContentService.Save(content);
}
Although the use of a GUID is preferable, you can also use the numeric ID to get the page:
@{
// Get the page using it's id
var content = ContentService.GetById(1234);
}
If Models Builder is enabled you can get the alias of the desired property without using a magic string:
@using Umbraco.Cms.Core.PublishedCache
@inject IPublishedContentTypeCache PublishedContentTypeCache
@{
// Set the value of the property with alias 'myDecimal'
content.SetValue(Home.GetModelPropertyType(PublishedContentTypeCache, x => x.MyDecimal).Alias, 3);
}
In this article you can learn how to use the build in email property editor
Schema Alias: Umbraco.EmailAddress
UI Alias: Umb.PropertyEditorUi.EmailAddress
Returns: String
Displays an email address.
The Email Address Property Editor does not come with any further configuration. The property can be configured once it has been added to a Document Type.
@if (Model.HasValue("email"))
{
var emailAddress = Model.Value<string>("email");
<p>@emailAddress</p>
}
@if (!string.IsNullOrWhiteSpace(Model.Email))
{
<p>@Model.Email</p>
}
See the example below to learn how a value can be added or changed programmatically to an Email-address property. To update a value of a property editor you need the Content Service.
@using Umbraco.Cms.Core.Services;
@inject IContentService Services;
@{
// Get access to ContentService
var contentService = Services;
// Create a variable for the GUID of your page
var guid = new Guid("796a8d5c-b7bb-46d9-bc57-ab834d0d1248");
// Get the page using the GUID you've just defined
var content = contentService.GetById(guid);
// Set the value of the property with alias 'email'
content.SetValue("email", "[email protected]");
// Save the change
contentService.Save(content);
}
Schema Alias: Umbraco.ColorPicker.EyeDropper
UI Alias: Umb.PropertyEditorUi.EyeDropper
Returns: string
The Eye Dropper Color picker allows you to choose a color from the full color spectrum using HEX and RGBA.
@{
var color = Model.Color?.ToString();
if (color != null)
{
<body style="background-color: @color"></body>
}
}
@{
var color = Model.Value<string>("Color");
if (color != null)
{
<body style="background-color: @color"></body>
}
}
See the example below to see how a value can be added or changed programmatically. To update a value of a property editor you need the Content Service.
@using Umbraco.Cms.Core.Services
@inject IContentService ContentService
@{
// Create a variable for the GUID of the page you want to update
var guid = Guid.Parse("32e60db4-1283-4caa-9645-f2153f9888ef");
// Get the page using the GUID you've defined
var content = ContentService.GetById(guid); // ID of your page
// Set the value of the property with alias 'color'.
content.SetValue("color", "#6fa8dc");
// Save the change
ContentService.Save(content);
}
Although the use of a GUID is preferable, you can also use the numeric ID to get the page:
@{
// Get the page using it's id
var content = ContentService.GetById(1234);
}
If Models Builder is enabled you can get the alias of the desired property without using a magic string:
@using Umbraco.Cms.Core.PublishedCache
@inject IPublishedContentTypeCache PublishedContentTypeCache
@{
// Set the value of the property with alias 'color'
content.SetValue(Home.GetModelPropertyType(PublishedContentTypeCache, x => x.Color).Alias, "#6fa8dc");
// Set the value of the property with alias 'theme'
content.SetValue(Home.GetModelPropertyType(PublishedContentTypeCache, x => x.Theme).Alias, "rgba(111, 168, 220, 0.7)");
}
Schema Alias: Umbraco.Label
UI Alias: Umb.PropertyEditorUi.Label
Returns: String
Label is a non-editable control and can only be used to display a pre-set value.
If you want to set a value other than a String, you can define the data using one of the other available Data Types. These include Decimal, Date/time, Time, Integer, and Big integer.
There is also a Value Type: Long string if you need to set a long string value for your Label.
@{
if (Model.HasValue("pageLabel")){
<p>@(Model.Value("pageLabel"))</p>
}
}
@{
if (!string.IsNullOrEmpty(Model.PageLabel))
{
<p>@Model.PageLabel</p>
}
}
See the example below to see how a value can be added or changed programmatically. To update a value of a property editor you need the Content Service.
@using Umbraco.Cms.Core.Services
@inject IContentService ContentService
@{
// Create a variable for the GUID of the page you want to update
var guid = Guid.Parse("32e60db4-1283-4caa-9645-f2153f9888ef");
// Get the page using the GUID you've defined
var content = ContentService.GetById(guid); // ID of your page
// Set the value of the property with alias 'pageLabel'.
content.SetValue("pageLabel", "A pre-set string value");
// Save the change
ContentService.Save(content);
}
Although the use of a GUID is preferable, you can also use the numeric ID to get the page:
@{
// Get the page using it's id
var content = ContentService.GetById(1234);
}
If Models Builder is enabled you can get the alias of the desired property without using a magic string:
@using Umbraco.Cms.Core.PublishedCache
@inject IPublishedContentTypeCache PublishedContentTypeCache
@{
// Set the value of the property with alias 'pageLabel'
content.SetValue(Home.GetModelPropertyType(PublishedContentTypeCache, x => x.MyLabel).Alias, "A pre-set string value");
}
Schema Alias: Umbraco.MemberGroupPicker
UI Alias: Umb.PropertyEditorUi.MemberGroupPicker
Returns: string
The Member Group Picker opens a panel to pick one or more member groups from the Member section. The value saved is of type string (comma separated IDs).
@if (Model.HasValue("memberGroup"))
{
var memberGroup = Model.Value<string>("memberGroup");
<p>@memberGroup</p>
}
@if (!string.IsNullOrEmpty(Model.MemberGroup))
{
<p>@Model.MemberGroup</p>
}
See the example below to see how a value can be added or changed programmatically. To update a value of a property editor you need the Content Service.
@using Umbraco.Cms.Core.Services
@inject IContentService ContentService
@{
// Create a variable for the GUID of the page you want to update
var guid = new Guid("796a8d5c-b7bb-46d9-bc57-ab834d0d1248");
// Get the page using the GUID you've defined
var content = ContentService.GetById(guid); // ID of your page
// Set the value of the property with alias 'memberGroup'. The value is the specific ID of the member group
content.SetValue("memberGroup", 1067);
// Save the change
ContentService.Save(content);
}
You can also add multiple groups by creating a comma separated string with the desired member group IDs.
@{
// Set the value of the property with alias 'memberGroup'.
content.SetValue("memberGroup", "1067","1068");
}
Although the use of a GUID is preferable, you can also use the numeric ID to get the page:
@{
// Get the page using it's id
var content = ContentService.GetById(1234);
}
If Models Builder is enabled you can get the alias of the desired property without using a magic string:
@using Umbraco.Cms.Core.PublishedCache
@inject IPublishedContentTypeCache PublishedContentTypeCache
@{
// Set the value of the property with alias 'memberGroup'
content.SetValue(Home.GetModelPropertyType(PublishedContentTypeCache, x => x.MemberGroup).Alias, 1067);
}
Schema Alias: Umbraco.TextArea
UI Alias: Umb.PropertyEditorUi.TextArea
Returns: String
Textarea is an HTML textarea control for multiple lines of text. It can be configured to have a fixed character limit, as well as define how big the space for writing can be. By default, there is no character limit unless it's specifically set to a specific value like 200 for instance. If you don't specify the number of rows, 10 will be the amount of rows the textarea will be occupying, unless changed to a custom value.
@{
if (Model.HasValue("description")){
<p>@(Model.Value<string>("description"))</p>
}
}
@if (!Model.HasValue(Model.Description))
{
<p>@Model.Description</p>
}
See the example below to learn how a value can be added or changed programmatically to a Textarea property. To update a value of a property editor you need the Content Service.
@using Umbraco.Cms.Core.Services
@inject IContentService ContentService
@{
// Create a variable for the GUID of your page
var guid = new Guid("796a8d5c-b7bb-46d9-bc57-ab834d0d1248");
// Get the page using the GUID you've just defined
var content = ContentService.GetById(guid);
// Set the value of the property with alias 'description'
content.SetValue("description", "This is some text for the text area!");
// Save the change
ContentService.Save(content);
}
Although the use of a GUID is preferable, you can also use the numeric ID to get the page:
@{
// Get the page using it's id
var content = ContentService.GetById(1234);
}
If Models Builder is enabled you can get the alias of the desired property without using a magic string:
@using Umbraco.Cms.Core.PublishedCache
@inject IPublishedContentTypeCache PublishedContentTypeCache
@{
// Set the value of the property with alias 'description'
content.SetValue(Home.GetModelPropertyType(PublishedContentTypeCache, x => x.Description).Alias, "This is some text for the text area!");
}
An intro to achieving content variance at block level.
In a variant context, a Block Editor behaves like any other Umbraco property editor by default. The Blocks contained within the editor "belong" to the Document variant, and there is no connection between Blocks across variants.
In other words, both Block content and structure can vary between each Document variant.
This is the desired behavior for many cases. However, in some cases it is preferable to have a shared Block structure across all variants, where only the Block content varies.
This is known as Block Level Variance:
Block Level Variance is achieved when:
The Document Type is configured for variance, and
The Block Editor property is not configured for variance, and
The Block Editor property editor is configured to use Element Types that do vary.
When adding a new variant Block to one Document variant, it is automatically added to all variants of the Document.
The Block will start out in an "unexposed" state for all other Document variants than the one where it was added. It will remain like that for each variant until it is edited in that variant.
The "unexposed" state is visualized by a dimmed-down icon and title (or likely a missing title, if Umbraco Flavored Markdown is used):
It is entirely possible to mix and match variance and invariance within the scope of Block Level Variance. Invariance is fully supported, both at Block level and at Block property level.
Invariance within Block Level Variance follows the same rules as invariance at Document level:
Invariant content is added to and updated across all Document variants.
Invariant content is explicitly published for all published Document variants when one or more variants are published.
Consider a Document with English and Danish language variants, which is published in both languages.
An editor opens the English variant.
They add an invariant Block, and
They re-publish the English variant.
Result: The new block will appear in both the English and Danish published content.
An editor opens the Danish variant.
They update an invariant property value in a variant Block, and
They re-publish the Danish variant.
Result: The updated property value appears in both the English and Danish published content.
The Block Editor structure is invariant for Block Level Variance. This means that the structure follows the same rules for invariance as outlined in the section above.
In other words: If an editor changes the order of the Blocks in one Document variant, it changes for all Document variants. The change is applied to all published Document variants, as soon as one or more variants are published.
In this article you can learn about the different options you have for configuring the Rich Text Editor (RTE).
You have full control over which options should be available on the RTE.
In the example above, all 38 options have been enabled. These options include font styles like bold and italics, bullet lists, and options to embed videos and insert images.
You can customize the look of the toolbar:
Enhance the capabilities of the toolbar by enabling or disabling extensions.
Use the Toolbar designer to group together items and add additional rows if needed.
As well as the toolbar, you can configure extensions for the statusbar.
To apply custom styles to the Rich Text Editor, you can select from any existing stylesheets.
Stylesheets can be created in the Settings section. To learn more about this feature, see the Stylesheets in the Backoffice article.
Define height
and width
of the editor displayed in the content section.
Define the maximum size for images added through the Rich Text Editor.
If inserted images are larger than the dimensions defined here, the images will be resized automatically.
Select the width of the link picker overlay. The overlay size comes in three sizes: Small, Medium, Large, and Full.
Blocks can be added as elements in the Rich Text Editor. Configuration and rendering of Blocks are described in the Blocks in Rich Text Editor article.
Images added through the RTE are by default added to the root of the Media library.
Sometimes you might want to add the images to a specific folder. This folder can be configured using the "Image Upload Folder" setting.
Some of the backoffice users might be restricted to a specific part of the content tree. When the "Ignore User Start Nodes" is checked, the users can pick any piece of content from the content tree, when adding internal links through the RTE.
This guide will explain the API Users concept and how they differ from regular Users how to define
API Users allow for authorizing external access to the Management API.
An API User is identical to a regular User except for one thing: It has no password. In fact, API Users are not allowed to log into the backoffice like regular Users.
Instead, API Users hold the Client Credentials used to authorize against the Management API. When an external source authorizes using Client Credentials, it effectively assumes the identity of the API User.
Since API Users are identical to regular Users their backoffice access can be controlled in the same way. This allows for imposing detailed access control on the external sources connected to the Management API.
To create an API User:
Go to the Users section in the backoffice.
Select Create -> API User.
Enter the Name and Email of the new API user.
Select which User group the new user should be added to.
Click Create user.
This article describes how to run an Umbraco 9 site on a local IIS server.
This is a quick guide on getting your Umbraco website running locally on IIS.
The guide will assume you already have IIS configured and know your way around it, as well as having a local website you wish to host.
First, you need to ensure you have "Development time IIS support installed". To check this, go to the Visual Studio installer, click modify and check on the right side under "ASP.NET and web development":
Once that is installed you should set up a new IIS site - and make sure to add the hostname to your hosts file as well. Here is my setup for an example:
You might need to change permissions for the NuGet cache folder - C:\users\<username>\.nuget\packages
. The user or group (IIS_IUSRS) that the IIS site is running on requires Read permissions on this folder because this is where some of the files for Umbraco and Umbraco packages are being served from during development. If the IIS user or group does not have permission to read from the NuGet cache folder, you could run into a DirectoryNotFoundException
while running the site.
When the site is published these files are copied from the NuGet cache folder to wwwroot/umbraco
and wwwroot/App_Plugins
and these folders will typically have the correct permissions. For more information on setting permissions, see the article.
At this point you can go to your Visual Studio solution of the site and in the Properties
folder there is a launchSettings.json
file, that looks like this:
You can add a new profile called IIS, and point it at your local domain. Here it is with my example domain:
At this point IIS will be added to the launch profiles, and you can run the site from Visual Studio by choosing IIS in the dropdown:
And finally the site is running from your local IIS:
Follow these steps to set up an Umbraco project with VS Code. The benefit of using VS Code is that it is super quick to get up and running.
Go to and download VS Code for free.
Once installed, launch VS Code.
Click the extensions menu at the bottom on the left side. Then search for C# and install it.
Follow the to create your project folder.
Open your project folder in VS Code, your project will look something like this:
Now we need to tell VS Code how to run your project.
Open the command palette, you can use the shortcut Ctrl+Shift+P
, and type in Tasks: Configure
and select the Tasks: Configure Task
option:
Select "Create task.json from template"
Now select ".NET Core" as your template.
After this VS Code will have created a folder called .vscode
that contains a file called tasks.json
, it's this file that tells VS Code how to build your project.
Now that we've told VS Code how to build your project, we need to tell it how to launch it. VS Code can do this for you. First, select the little play button in the left side menu, and then select the "create a launch.json file" link.
This will prompt a menu to appear, select .NET 5+ and .NET Core:
Now you'll see a green play button appear with a dropdown where ".NET Core Launch (web)" is selected.
If you navigate to the Files section, a new launch.json
file is created in the .vscode
folder. When you press F5, the launch.json
file tells VS Code to build your project, run it, and then open a browser .
With that, you're ready to run the project! Press F5, or click the little green play button in the Run and Debug section to run your brand new Umbraco site locally.
This section continues from where we left off but covers the installation and configuration of Umbraco inside your web browser when you run Umbraco for the first time.
You will see the install screen where you will need to fill in some data before Umbraco can be installed.
When the installer is done, you will be logged into the backoffice.
Congratulations, you have installed an Umbraco site!
This article will help you migrate content to Umbraco 15, and outline options to skip this content migration
Umbraco 15 changes the internal data format of all .
If you maintain a large Umbraco site with extensive Block Editor usage, the upgrade to Umbraco 15+ might require a long-running content migration. For the duration of the migration, your site will be unresponsive and unable to serve requests.
You can track the progress of the migration in the logs.
It is advised to before upgrading. This will make the migration run faster.
It is possible to parallelize the content migration. This will speed up the migration for large sites.
For certain content structures, parallel content migration will fail. Therefore, parallel content migration is strictly opt-in.
If parallel content migration fails, the database state will be rolled back to the last known good state. You can then disable parallel content migration, and try the migration again.
To enable parallel content migration, add an IComposer
implementation to configure the ConvertBlockEditorPropertiesOptions
before initiating the upgrade process:
It is strongly recommended to let the migration run as part of the upgrade. However, if you are upgrading to Umbraco versions 15, 16, or 17, you can opt out of the migration. Your site will continue to work, albeit with a certain degree of performance degradation.
Blocks in Rich Text Editors might not work as expected if you opt out of the content migration.
You can opt out of migrating each Block Editor type individually. To opt-out, add an IComposer
implementation to configure the ConvertBlockEditorPropertiesOptions
before initiating the upgrade process:
Subsequently, you are responsible for performing the content migration yourself. This must be done before upgrading past Umbraco 17.
Custom code is required to perform the content migration. You can find inspiration in the core migrations:
for Block List properties.
for Block Grid properties.
for Rich Text Editor properties.
This custom code should not run while editors are working in the Umbraco backoffice.
The site may require a restart once the content migration is complete.
Exactly how you choose to compose your Dockerfile will depend on your project specific needs. This section is not intended as a comprehensive guide, rather as an overview of topics to be aware of when hosting in Docker.
Docker is a platform for developing, shipping, and running applications in containers. Multiple services exist for hosting these containers. For more information, refer to the
By default, files created inside a container are written to an ephemeral, writable container layer. This means that the files don't persist when the container is removed, and it's challenging to get files out of the container. Additionally, this writable layer is not suitable for performance-critical data processing.
This has implications when running Umbraco in Docker.
For more information, refer to the .
In general, when working with files and Docker you work in a "push" fashion with read-only layers. When you build, you take all your files and "push" them into this read-only layer.
This means that you should avoid making files on the fly, and instead rely on building your image.
In an Umbraco context, this means you should not create or edit template, script or stylesheet files via the backoffice. These should be deployed as part of your web application and not managed via Umbraco.
Similarly, you shouldn't use InMemory modelsbuilder, since that also relies on creating files on the disk. While this is not a hard requirement, it doesn't provide any value unless you are live editing your site.
Instead, configure models builder to use "source code" mode in development, and "none" in production, as .
Umbraco writes logs to the /umbraco/Logs/
directory. Due to the performance implications of writing to a writable layer, and the limited size, it is recommended to mount a volume to this directory.
The /umbraco/Data/
directory is used to store temporary files, such as file uploads. Considering the limitations of the writable layer, you should also mount a volume to this directory.
It's recommended to not store media in the writable layer. This is for similar performance reasons as logs, but also for practical hosting reasons. You likely want to persist media files between containers.
One solution is to use bind mounts. The ideal setup, though, is to store the media and ImageSharp cache externally. For more information, refer to the .
Your solution may require some specific files to run, such as license files. You will need to pass these files into the container at build time, or mount them externally.
When running websites in Docker, it's common to do so behind a reverse proxy or load balancer. In these scenarios you will likely handle SSL termination at the reverse proxy. This means that Umbraco will not be aware of the SSL termination, and will complain about not using HTTPS.
Umbraco checks for HTTPS in two locations:
The HstsCheck
health check - This will result in a failed healthcheck.
The UseHttpsValidator
- This will result in a build error, if Production runtime mode is used.
To avoid these checks failing, you can remove them in your project.
The health check must be removed via configuration, through the appsettings.json
file, environment variables, or similar. For more information see the .
The HstsCheck
key is E2048C48-21C5-4BE1-A80B-8062162DF124
so the appsettings will look something like:
The UseHttpsValidator
must be removed through code For more information see the .
The code to remove the validator can look something like:
Schema Alias: Umbraco.CheckBoxList
UI Alias: Umb.PropertyEditorUi.CheckBoxList
Returns: IEnumerable<string>
Displays a list of preset values as a list of checkbox controls. The text saved is an IEnumerable collection of the text values.
See the example below to see how a value can be added or changed programmatically. To update a value of a property editor you need the .
Although the use of a GUID is preferable, you can also use the numeric ID to get the page:
If Models Builder is enabled you can get the alias of the desired property without using a magic string:
Schema Alias: Umbraco.ListView
UI Alias: Umb.PropertyEditorUi.Collection
Returns: IEnumerable<IPublishedContent>
Collection displays a collection of categories when it is enabled on a Document Type with children.
Once Collections are configured, the parent content item displays its child items in a list view format within the content item itself. If Collections are not configured, the child items are displayed directly in the Content Tree, rather than being grouped within the parent content item.
It is possible to add more columns to the collection, via adding the properties through the picker modal. These properties are based on the Data Types which are used by the Document Type. The properties will listed for selection.
Once you have selected a column you want to display, define what its heading label should be and what kind of value it should display. You can also move the headers around, re-ordering how they should look. This is done by the move icon on the left side of the alias.
The template section is where you define what kind of value you want to display. The value of the column is in the value
variable.
Collection comes with two layouts by default. A list and a grid view. These views can be disabled if you are not interested in any of them.
You can also make your own layout and add it to the settings. For example, if you wanted to change the width or length of the grid, you will be able to do so.
Will sort your collection by the selection you choose in the dropdown. By default it selects "Last edited" and you get the following three columns:
Last edited - When the content node was last edited and saved.
Name - Name of the content node(s).
Created by - This is the user who the content node was created by.
You can add more sorting to this collection by adding more datatypes to the columns in the "Columns Displayed" section.
You can select order of the content nodes displayed, "Ascending [a-z]" or "Descending [z-a]". The order is affected by the "Order By" selection.
Defines how many child content nodes you want to see per page. This will limit how many content items you will see in your collection. If you set it to 5, then only 5 content items will be shown in the collection.
Changes the icon in the backoffice of the collection. By default it will look like the image below.
You can change the name of the collection itself. Default if empty: 'Child Items'.
Enable this to show the Content Workspace View by default instead of the collection's.
This example shows how to use a generic field from a child item and display its value in a collection.
You can use the syntax to display the label value. Here, the {=value}
placeholder retrieves the value of the Email property and displays it in the collection, as shown in the image below:
First, a Content Picker property needs to be present on the content item. In this example, the child item
has gotten a Content Picker Data Type with the alias of contentPicker
.
The child item has a document and the value that should be displayed is the name of the picked value. The next step is to reconfigure the template value in the collection setting.
This will take the value picked up by the content picker.
And display it in the collection. Shown in the example below:
Schema Alias: Umbraco.ContentPicker
UI Alias: Umb.PropertyEditorUi.DocumentPicker
Returns: IPublishedContent
The Document Picker opens a panel to pick a specific page from the content structure. The value saved is the selected nodes .
See the example below to see how a value can be added or changed programmatically. To update a value of a property editor you need the .
Although the use of a GUID is preferable, you can also use the numeric ID to get the page:
If Models Builder is enabled you can get the alias of the desired property without using a magic string:
Schema Alias: Umbraco.MemberPicker
UI Alias: Umb.PropertyEditorUi.MemberPicker
Returns: IPublishedContent
The member picker opens a panel to pick a specific member from the member section. The value saved is of type IPublishedContent.
See the example below to see how a value can be added or changed programmatically. To update a value of a property editor you need the .
Although the use of a GUID is preferable, you can also use the numeric ID to get the page:
If Models Builder is enabled you can get the alias of the desired property without using a magic string:
Schema Alias: Umbraco.MultipleTextstring
UI Alias: Umb.PropertyEditorUi.MultipleTextString
Returns: array of strings
The Repeatable textstrings property editor enables a content editor to make a list of text items. For best use with an unordered-list.
See the example below to see how a value can be added or changed programmatically. To update a value of a property editor you need the .
Although the use of a GUID is preferable, you can also use the numeric ID to get the page:
If Models Builder is enabled you can get the alias of the desired property without using a magic string:
Schema Alias: Umbraco.Integer
UI Alias: Umb.PropertyEditorUi.Integer
Returns: Integer
Numeric is an HTML input control for entering numbers. Since it's a standard HTML element the options and behaviour are all controlled by the browser and therefore is beyond the control of Umbraco.
This allows you to set up a minimum value. If you will always need a minimum value of 10 this is where you set it up and whenever you use the datatype the value will always start at 10. It's not possible to change the value to anything lower than 10. Only higher values will be accepted.
This allows you to control by how much value should be allowed to increase/decrease when clicking the up/down arrows. If you try to enter a value that does not match with the step setting then it will not be accepted.
This allows you to set up a maximum value. If you will always need a maximum value of 100 this is where you set it up. It's not possible to change the value to anything higher than 100. Only lower values will be accepted.
By casting the output as an int it's possible for you to do mathematical operations with the value.
You can also render the output by casting it to a string, which means you will not be able to do mathematical operations
See the example below to see how a value can be added or changed programmatically. To update a value of a property editor you need the .
Although the use of a GUID is preferable, you can also use the numeric ID to get the page:
If Models Builder is enabled you can get the alias of the desired property without using a magic string:
Schema Alias: Umbraco.RadioButtonList
UI Alias: Umb.PropertyEditorUi.RadioButtonList
Returns: string
Pretty much like the name indicates this Data type enables editors to choose from list of radio buttons and returns the value of the selected item as string.
See the example below to see how a value can be added or changed programmatically. To update a value of a property editor you need the .
Although the use of a GUID is preferable, you can also use the numeric ID to get the page:
If Models Builder is enabled you can get the alias of the desired property without using a magic string:
How to use the TextBox property editors in Umbraco CMS.
Schema Alias: Umbraco.TextBox
UI Alias: Umb.PropertyEditorUi.TextBox
Returns: String
Textbox is an HTML input control for text. It can be configured to have a fixed character limit. The default maximum amount of characters is 512 unless it's specifically changed to a lower amount.
See the example below to see how a value can be added or changed programmatically. To update a value of a property editor you need the .
Although the use of a GUID is preferable, you can also use the numeric ID to get the page:
If Models Builder is enabled you can get the alias of the desired property without using a magic string:
Schema Alias: Umbraco.UserPicker
UI Alias: Umb.PropertyEditorUi.UserPicker
Returns: IPublishedContent
The user picker opens a panel to pick a specific user from the Users section. The value saved is of type IPublishedContent.
See the example below to see how a value can be added or changed programmatically. To update a value of a property editor you need the .
Although the use of a GUID is preferable, you can also use the numeric ID to get the page:
If Models Builder is enabled you can get the alias of the desired property without using a magic string:
Information on how to work with Tiptap extensions in the rich text editor.
The Rich Text Editor (RTE) in Umbraco is based on the open-source editor .
Out of the box, Tiptap has limited capabilities and everything is an extension by design. Basic text formatting features such as bold, italic, and underline are their own extensions. This offers great flexibility, making the rich text editor highly configurable. The implementation in Umbraco offers a wide range of built-in extensions to enhance the Tiptap editor capabilities.
Using the same extension points, this article will show you how to add a custom extension to the rich text editor.
Tiptap has a library of supported native extensions. You can find a list of these extensions on the . While many of these are open source, there are also available for commercial subscriptions.
There are two types of extension: tiptapExtension
and tiptapToolbarExtension
.
The tiptapExtension
extension is used to register a native . These will enhance the capabilities of the rich text editor itself. For example, to enable text formatting, drag-and-drop functionality and spell-checking.
The tiptapToolbarExtension
extension adds a toolbar action that interacts with the Tiptap editor (and native Tiptap extensions).
In this example, you will take the native Tiptap open-source extension . Then register it with the rich text editor and add a toolbar button to invoke the Task List action.
Install the Highlight extension from the npm registry.
Create the code to register the native Tiptap extensions in the rich text editor.
Create the toolbar action to invoke the Highlight extension.
Once you have the above code in place, they can be referenced using a .
Upon restarting Umbraco, the new extension and toolbar action will be available in the Tiptap Data Type configuration settings.
On this page you will find the media types and Data Types in Umbraco. These types are not created automatically after an upgrade. If you want to use the new types, you can create them yourself.
The UploadArticle
Data Type has the following configuration:
Property editor: FileUpload
Accepted file extensions: pdf
, docx
, doc
The UploadAudio
Data Type has the following configuration:
Property editor: FileUpload
Accepted file extensions: mp3
, weba
, oga
, opus
The UploadVectorGraphics
Data Type has the following configuration:
Property editor: FileUpload
Accepted file extensions: svg
The UploadVideo
Data Type has the following configuration:
Property editor: FileUpload
Accepted file extensions: mp4
, webm
, ogv
The UmbracoMediaArticle
media type has the following properties:
umbracoFile
- Upload File
umbracoExtension
- Label (string)
umbracoBytes
- Label (bigint)
The UmbracoMediaAudio
media type has the following properties:
umbracoFile
Upload Audio
umbracoExtension
Label (string)
umbracoBytes
Label (bigint)
The UmbracoMediaVectorGraphics
media type has the following properties:
umbracoFile
- Upload Vector Graphics
umbracoExtension
Label (string)
umbracoBytes
Label (bigint)
The UmbracoMediaVideo
media type has the following properties:
umbracoFile
- Upload Video
umbracoExtension
- Label (string)
umbracoBytes
- Label (bigint)
Learn about the data types in Umbraco.
A Data Type defines the type of input for a property. So when adding a property (on Document Types, Media Types and Members) and selecting the Type you are selecting a Data Type. There are preconfigured Data Types available in Umbraco and more can be added in the Settings section.
A Data Type can be something basic such as TextString, Number, True/False and so on. Or it can be more complex such as Multi Node Tree Picker, Image Cropper, Block Grid and so on.
The Data Type references a Property Editor and if the Property Editor has settings these are configured on the Data Type. This means you can have multiple Data Types referencing the same Property Editor.
An example of this could be to have two dropdown Data Types both referencing the same dropdown Property Editor. One configured to show a list of cities, the other a list of countries.
Follow these steps to create a new Dropdown Data Type:
Go to the Settings section within the backoffice.
Select the + icon to the right of the Data Types folder.
Choose New Data Type....
Name the Data Type.
Click on Select a property editor.
Find and click on the Dropdown editor.
Click Select.
Choose whether to enable multiple selections.
Add options.
Save the Data Type once you have added the required configuration.
When you're happy with the list press Save. It is now possible to select this Data Type for a property on Document Types, Media Types, and Members. Doing this will then create a dropdown list for the editor to choose from and save the choice as a string.
To customize an existing Data Type go to the Settings section, expand the Data Types folder and select the Data Type you want to edit.
Besides the Data Types that are available out of the box there are some additional Property Editors. For example, think of the Slider and Block List.
To view the Data Type reference, go to the Settings section and expand the Data Types folder. Select the Data Type you wish to view the reference for and click the Info tab.
This gives you an overview of the Types that currently use the Data Type.
Learn more about viewing references or implementing tracking in the article.
Learn about the default data types in Umbraco.
Here's a list of the default Data Types that come installed with Umbraco. There are plenty more that you can create based on the installed .
Adds a list of approved colors. The approved colors are added as hex values by using the color picker. Optionally, you can enable labels to give the colors different names.
Displays a list of preset options as a list of checkbox controls. The preset options are added when configuring a Property Editor using the Data Type. Alternatively, the options can also be updated in the Settings section under Data Types. The value saved is a comma-separated string of IDs.
The Content Picker opens a modal to pick a specific page from the content structure. The value saved is the selected page's ID.
Displays a calendar UI for selecting date and time. The value saved is a standard DateTime value but does not contain time information.
Displays a calendar UI for selecting date and time. The value saved is a standard DateTime value.
Displays a list of preset options as a list where only a single value can be selected. The default Data Type does not contain any predefined options. The value saved is the selected value as a string.
Displays a list of preset options as a list where multiple values can be selected. The default Data Type does not contain any predefined options. The value saved is a comma-separated string of IDs.
Allows to upload and crop images by using a focal point. Specific crop definitions can also be added. This Data Type is used by default on the Image Media Type.
The Image Media Picker opens a modal to pick images from the Media tree or images from your Computer. The value saved is the selected media node UDI.
Is a non-editable control and can be used to only display the value. It can also be used in the Media section to load in values related to the node, such as width, height and file size.
There are six Label Data Types:
Label (bigint) - Allows to save a big integer value for a Label.
Label (datetime) - Allows to set a DateTime value for a Label.
Label (decimal) - Allows to set a decimal value for a Label.
Label (integer) - Allows to set an integer value for a Label.
Label (string) - Allows to set a long string value for a Label.
Label (time) - Allows to set time for a Label
This Data Type is used by Document Types that are set to display as a Collection.
This Data Type is used by Media Types that is set to display as a Collection.
This Data Type is used by Member Types that is set to display as a Collection.
The picker opens a modal to pick a specific media item from the Media tree. The value saved is the selected media node UDI.
Displays a dropdown with all the available members. A single member can be selected. The value saved is the ID of the member.
This Data Type allows an editor to add an array of links. These can either be internal Umbraco pages external URLs or links to media in the Media section. The Data Type can be configured by limited number of links it is possible to add.
The picker opens a modal to pick multiple images from the Media tree. The value saved is a comma separated string of media node UDIs.
The picker opens a modal to pick multiple media items from the Media tree. The value saved is a comma separated string of media node UDIs.
A textbox to input a numeric value.
This Data type enables editors to choose from a list of radiobuttons.
A TipTap-based What You See Is What You Get (WYSIWYG) editor. This is the standard editor used to edit a larger amount of text. The editor has a lot of settings, which can be changed on the Richtext editor Data Type in the Settings section.
Learn more about the configuration options in the .
A textbox that allows you to use multiple tags on a Document Type. You can specify a Tag Group for the Data Type, if you need to use Tags on different sections of your site.
A textarea provides a multi-line plain-text editing control. You can set the maximum allowed characters for the textarea and the number of rows, if any.
A normal HTML input text field.
A checkbox which saves either 0 or 1, depending on the checkbox being checked or not. A common use is to create a property with the 'umbracoNaviHide' alias and the Data Type True/False. This will provide editors with the option to hide nodes in the navigation menu on the website.
Adds an upload field, which allows documents or images to be uploaded to Umbraco. This does not add them to the media library, they are added to the document data.
There are five Upload Data Types:
Upload Article - Used for uploading and storing documents.
Upload Audio - Used for uploading and storing digital audio files.
Upload File - Used for uploading and storing different types of files in the Media section
Upload Vector Graphics - Used for uploading and storing Scalable Vector Graphics (svg) files which are text files containing source code to draw the desired image.
Upload Video - Used for uploading and storing video files.
In this section, an overview is given of how to add and reorder tabs, convert a group to a tab and manage the “Generic” tab.
Using tabs, you can organize properties in the backoffice to provide a tailored and efficient workflow for editors creating and maintaining Content, Media and Members.
Tabs allow you to add horizontal organization in your Document Types, Media Types and Member Types. This is handy for types that need a more defined hierarchy or have many properties and groups.
To add a tab, follow these steps:
Go to Settings.
Create or select a Document Type/Media Type/Member Type and click Add tab.
To reorder tabs, follow these steps:
Go to Settings.
Select a Document Type/Media Type/Member Type.
Select Reorder.
You can drag the tab where you want, manually add a numeric value next to the tab name or use the arrows to set a value.
This is important when using compositions, as you want to always display a tab/group at a certain position by setting a manual numeric value.
Select I am done reordering.
Click Save.
To convert a group to a tab, follow these steps:
Go to Settings.
Select a Document Type/Media Type/Member Type.
Select Reorder.
You can drag the group to the Convert to tab option.
Select I am done reordering.
Click Save.
Once you start adding tabs, you might see a “Generic” tab appear. This is done to hold groups and properties that are not assigned to a tab. For example, a group of properties coming from a composition that has no tab. In order to display the groups and properties correctly and have a solid data structure, they will be displayed under the “Generic” tab.
To manage the Generic tab on a Document Type/Media Type:
Go to the Composition Document Type/Media Type.
Click Add tab and enter the Name for the tab. All existing groups and properties are added to the tab.
Go to the Document Type/Media Type, the Generic tab will now be replaced by the tab from the composition.
Each document in Umbraco can be scheduled for publishing and unpublishing on a pre-defined date and time.
Each document in Umbraco can be scheduled for publishing and unpublishing on a pre-defined date and time.
You can find the options to do this click on the arrow next to the Save and publish button and pick Schedule...
This will open a Schedule Publishing dialog where you can specify dates and time.
Your server may be in a different timezone than where you are located. You are able to select a date and time in your timezone and Umbraco will make sure that the item gets published at that time. So, if you select 12 PM then the item will be published at 12PM in the timezone you are in. This may be 8 PM on the server, which is indicated when you select the date and time.
If you are in the same timezone as the server, this message will not appear under the date picker.
All users with access to the Content section in the Umbraco backoffice are able to schedule content for publishing/unpublish.
In some cases you will need to adjust your configuration to ensure that scheduled publishing/unpublishing works. The schedule works by the server sending an HTTP(S) request to itself.
If you are in a load balanced environment special care must be given to ensure you've configured this correctly,
If you are not load balancing, the way that Umbraco determines the base URL to send the scheduled HTTP(S) request to is as follows:
umbracoSettings:settings/web.routing/@umbracoApplicationUrl if it exists (see for details)
Else umbracoSettings:settings/scheduledTasks/@baseUrl if it exits (deprecated)
Else umbracoSettings:distributedCall/servers if we have the server in there (deprecated, see load balance docs)
Else it's based on the first request that the website receives and uses the base URL of this request (default)
If the umbracoApplicationUrl
is used, the value also specifies the scheme (either HTTP or HTTPS). The request for scheduled publishing will always be sent over HTTPS if the appSettings umbracoUseSSL
is set to true
.
If your scheduled publishing/unpublishing is not working as expected it is probably an issue that your server cannot communicate with the scheduled publishing endpoint. This can be caused by a number of reasons such as:
Url rewrites in place that prevent the endpoint from being reached
DNS misconfiguration not allowing the server to communicate to the base URL used in the first request that the website receives - which could be directly affected by a firewall/Network Address Translation (NAT)/load balancer that your server sites behind
Secure Sockets Layer (SSL) and/or umbracoUseSSL misconfiguration not allowing the server to communicate to the scheduled publishing endpoint on the correct http/https scheme
To better diagnose the issue you can temporarily change your log4net config settings to be DEBUG
instead of INFO
. This will give you all sorts of information including being able to see whether or not the scheduled publishing endpoint is being reached or not.
In some cases it might be easiest to specify the setting. This is to ensure that your server is communicating to itself on the correct URL.
Learn about relations and how to create and manage them.
Umbraco sections are built around the concept of 'trees' and there is an implicit relationship between items in a section tree.
We refer to these relationships in the manner of a 'Family Tree'. One content item might be the 'Parent' of some content items, and those items would be referred to as the 'Children' of that parent. Items within the same branch of the tree can also be described as 'Ancestors' or 'Descendants' of an item.
There are methods available to support querying content items by their relative position to the current page. This is possible using the following concepts: Model.Ancestors()
, Model.Children()
, or Model.Descendants()
.
In some cases there are no direct relationships between two items in a tree, but they are still somehow 'related'. This could be the alternate language translation pages of a content page.
In other cases there is a 'relation' between different types of entities. This could be a relation between Content and Member, or Member and MediaFolder. You might need to be able to retrieve and display the uploaded images from a specific logged-in Member.
These are the scenarios where the concept of Umbraco Relations provides a solution.
Umbraco Relations allow you to relate almost any object in Umbraco to almost any other Umbraco object. This is done by defining a new Relation Type.
With a Content, Member, or Media picker the relationship only works as a 1-way street. The content item knows it has 'picked' another content item but that other content item does not know where it has been picked.
Umbraco Relations works as a 2-way street. When creating a relation between two different types of entities, it will be possible to find one entity from the other and vice versa. As an example this provides the option to list out all the pages that a content banner had been picked on.
A Relation Type specifies how two types of entities are related. Two items might be related under multiple Relation Types, and you might only be interested in your 'Related Language Page' Relation Type.
It is possible to view the existing Relation Types from the Umbraco backoffice:
Access the Umbraco Backoffice.
Navigate to the Settings section.
Locate the Advanced group in the sidebar.
Select Relations.
On the dashboard all defined relations will be listed. Select a Relation to view a list of all the objects that have been related for that specific Relation Type.
You can create Relations using the RelationService API via code.
You might want to create a 'Relation' between two objects either as:
A response to a backoffice event. For example, a content item being published that has picked other content items. Storing a relationship between these items would make querying between them easier. Perhaps show all the pages on which a particular 'banner' has been picked.
A logged-in member on the front end of an Umbraco website might have the facility to upload images. In response, the implementation could store the photos programmatically in the Media Section and at the same time, create a Relation to record the relationship between the member and their uploaded pictures. On an image gallery page, it would be possible to display all the gallery images for the current logged-in Member using the relations.
Some of the community packages that use Relations are listed below:
- a content picker that automatically creates Relations.
- allows you to relate two items via the Backoffice.
- Provides a LinkedPages context item to show, edit, and add relations between content pages.
A new version is created whenever you save and publish a content item in Umbraco. This is how you can roll back to a previous version. Every saved version stores a record in the database, not only for the version but also for each content item property for that version. In a multi-lingual site, further rows are added for every culture variation. Over time this amount of data can build and swallow up the capacity of your SQL Server and slow the performance of the Umbraco backoffice.
The default cleanup policy will:
Not delete any versions created over the previous 4 days. The recent version history is preserved. See the KeepAllVersionsNewerThanDays
setting.
'Prune' versions 4 days after they are created. The last version of a content item saved on a particular day will be kept but earlier versions from that day will be deleted.
Delete all versions older than 90 days. See the KeepLatestVersionPerDayForDays
setting.
Never delete any versions that are currently 'published'.
Never delete any specific versions marked as 'Prevent Cleanup' in the Backoffice version history.
The feature can be configured in the appSettings.json
:
For sites with stricter requirements, it is possible to opt-out of both options globally, see and by Document Type.
Additionally, it is possible to keep the feature enabled but mark specific versions to keep forever.
It is worth noting that whilst we delete rows, we do not shrink database files or rebuild indexes. For upgraded sites with a lot of history you may wish to perform these tasks. If they are not part of your regular database maintenance plan already.
It is possible to override the global settings per Document Type in the backoffice to prevent unwanted cleanup. This can be managed in the "permissions" Content App for each Document Type.
It is possible to mark important content versions as "prevent cleanup" to ensure they are never removed. This happens via the new and improved rollback modal which can be found on the "info" content app for each document.
Open rollback modal.
Click Prevent cleanup button for each important version.
Since Umbraco 9 it has been possible to run Umbraco CMS natively on Linux or macOS High Sierra 10.13 and newer.
With Umbraco CMS on .NET Core, Linux and macOS is natively supported with SQLite as the database.
In the below section, we describe how to get started with running Umbraco CMS on Linux or macOS.
To get started with Umbraco CMS first have a look at the .
Once you've made sure you meet the requirements it is time to install the Umbraco Templates on your system.
To do this follow the guide.
With the templates installed on your system, it is now possible to create Umbraco projects.
To create a project, there are two options:
Continue creating projects using the .NET CLI.
Create new projects using Visual Studio (only macOS).
To create new projects using Visual Studio, you can use the guide.
Once you create a new project it will use SQLite by default on Linux/macOS.
If you want to use an SQL server database, you will need to .
using Umbraco.Cms.Core.Composing;
using Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_15_0_0;
namespace UmbracoDocs.Samples;
public class DisableBlockEditorMigrationComposer : IComposer
{
[Obsolete]
public void Compose(IUmbracoBuilder builder)
=> builder.Services.Configure<ConvertBlockEditorPropertiesOptions>(options =>
{
// setting this to true will parallelize the migration of all Block Editors
options.ParallelizeMigration = true;
});
}
using Umbraco.Cms.Core.Composing;
using Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_15_0_0;
namespace UmbracoDocs.Samples;
public class DisableBlockEditorMigrationComposer : IComposer
{
[Obsolete]
public void Compose(IUmbracoBuilder builder)
=> builder.Services.Configure<ConvertBlockEditorPropertiesOptions>(options =>
{
// setting this to true will skip the migration of all Block List properties
options.SkipBlockListEditors = false;
// setting this to true will skip the migration of all Block Grid properties
options.SkipBlockGridEditors = false;
// setting this to true will skip the migration of all Rich Text Editor properties
options.SkipRichTextEditors = false;
});
}
"Umbraco": {
"CMS": {
"HealthChecks" : {
"DisabledChecks": [
{
"Id": "E2048C48-21C5-4BE1-A80B-8062162DF124"
}
]
},
{...}
using Umbraco.Cms.Core.Composing;
using Umbraco.Cms.Infrastructure.Runtime.RuntimeModeValidators;
namespace MySite;
public class DockerChecksRemover : IComposer
{
public void Compose(IUmbracoBuilder builder)
=> builder.RuntimeModeValidators().Remove<UseHttpsValidator>();
}
npm install @tiptap/extension-highlight
import { UmbTiptapExtensionApiBase } from '@umbraco-cms/backoffice/tiptap';
import { Highlight } from '@tiptap/extension-highlight';
export default class UmbTiptapHighlightExtensionApi extends UmbTiptapExtensionApiBase {
getTiptapExtensions = () => [Highlight];
}
import { UmbTiptapToolbarElementApiBase } from '@umbraco-cms/backoffice/tiptap';
import type { Editor } from '@umbraco-cms/backoffice/external/tiptap';
export default class UmbTiptapToolbarHighlightExtensionApi extends UmbTiptapToolbarElementApiBase {
override execute(editor?: Editor) {
editor?.chain().focus().toggleHighlight().run();
}
}
export const manifests: Array<UmbExtensionManifest> = [
{
type: 'tiptapExtension',
kind: 'button',
alias: 'My Highlight Tiptap Extension',
name: 'My.Tiptap.Highlight',
api: () => import('./highlight.tiptap-api.js'),
meta:{
icon: "icon-thumbnail-list",
label: "Highlight",
group: "#tiptap_extGroup_formatting"
}
},
{
type: 'tiptapToolbarExtension',
kind: 'button',
alias: 'My.Tiptap.Toolbar.Highlight',
name: 'My Highlight Tiptap Toolbar Extension',
js: () => import('./highlight.tiptap-toolbar-api.js'),
forExtensions: ["My.Tiptap.Highlight"],
meta:{
alias: "highlight",
icon: "icon-brush",
label: "Highlight"
}
}
]
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:40264",
"sslPort": 44360
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Umbraco.Web.UI.NetCore": {
"commandName": "Project",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:44360;http://localhost:40264"
}
}
}
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iis": {
"applicationUrl": "https://testsite.local",
"sslPort": 0
},
"iisExpress": {
"applicationUrl": "http://localhost:40264",
"sslPort": 44360
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS": {
"commandName": "IIS",
"launchBrowser": true,
"launchUrl": "https://testsite.local",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Umbraco.Web.UI.NetCore": {
"commandName": "Project",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:44360;http://localhost:40264"
}
}
}
@{
if (Model.HasValue("superHeros"))
{
<ul>
@foreach (var item in Model.Value<IEnumerable<string>>("superHeros"))
{
<li>@item</li>
}
</ul>
}
}
@{
if (Model.SuperHeros.Any())
{
<ul>
@foreach (var item in Model.SuperHeros)
{
<li>@item</li>
}
</ul>
}
}
@using Umbraco.Cms.Core.Serialization
@using Umbraco.Cms.Core.Services
@inject IContentService ContentService
@inject IJsonSerializer Serializer
@{
// Create a variable for the GUID of the page you want to update
var guid = Guid.Parse("32e60db4-1283-4caa-9645-f2153f9888ef");
// Get the page using the GUID you've defined
var content = ContentService.GetById(guid); // ID of your page
// Set the value of the property with alias 'superHeroes'.
content.SetValue("superHeroes", Serializer.Serialize(new[] { "Umbraco", "CodeGarden"}));
// Save the change
ContentService.Save(content);
}
@{
// Get the page using it's id
var content = ContentService.GetById(1234);
}
@using Umbraco.Cms.Core.PublishedCache
@inject IPublishedContentTypeCache PublishedContentTypeCache
@{
// Set the value of the property with alias 'superHeroes'
content.SetValue(Home.GetModelPropertyType(PublishedContentTypeCache, x => x.SuperHeroes).Alias, Serializer.Serialize(new[] { "Umbraco", "CodeGarden"}));
}
@{
IPublishedContent typedContentPicker = Model.Value<IPublishedContent>("featurePicker");
if (typedContentPicker != null)
{
<p>@typedContentPicker.Name</p>
}
}
@{
IPublishedContent typedContentPicker = Model.FeaturePicker;
if (typedContentPicker != null)
{
<p>@typedContentPicker.Name</p>
}
}
@using Umbraco.Cms.Core
@using Umbraco.Cms.Core.Services
@inject IContentService ContentService
@{
// Create a variable for the GUID of the page you want to update
var guid = Guid.Parse("32e60db4-1283-4caa-9645-f2153f9888ef");
// Get the page using the GUID you've defined
var content = ContentService.GetById(guid); // ID of your page
// Get the page you want to assign to the document picker
var page = Umbraco.Content("665d7368-e43e-4a83-b1d4-43853860dc45");
// Create an Udi of the page
var udi = Udi.Create(Constants.UdiEntityType.Document, page.Key);
// Set the value of the property with alias 'featurePicker'.
content.SetValue("featurePicker", udi.ToString());
// Save the change
ContentService.Save(content);
}
@{
// Get the page using it's id
var content = ContentService.GetById(1234);
}
@using Umbraco.Cms.Core.PublishedCache
@inject IPublishedContentTypeCache PublishedContentTypeCache
@{
// Set the value of the property with alias 'featurePicker'
content.SetValue(Home.GetModelPropertyType(PublishedContentTypeCache, x => x.FeaturePicker).Alias, udi.ToString());
}
@{
if (Model.HasValue("author"))
{
var member = Model.Value<IPublishedContent>("author");
@member.Name
}
}
@{
if (Model.Author != null)
{
var member = Model.Author;
@member.Name
}
}
@using Umbraco.Cms.Core.Services
@inject IContentService ContentService
@{
// Create a variable for the GUID of the page you want to update
var guid = Guid.Parse("32e60db4-1283-4caa-9645-f2153f9888ef");
// Get the page using the GUID you've defined
var content = ContentService.GetById(guid); // ID of your page
// Create a variable for the GUID of the member ID
var authorId = Guid.Parse("ed944097281e4492bcdf783355219450");
// Set the value of the property with alias 'author'.
content.SetValue("author", authorId);
// Save the change
ContentService.Save(content);
}
@{
// Get the page using it's id
var content = ContentService.GetById(1234);
}
@using Umbraco.Cms.Core.PublishedCache
@inject IPublishedContentTypeCache PublishedContentTypeCache
@{
// Set the value of the property with alias 'author'
content.SetValue(Home.GetModelPropertyType(PublishedContentTypeCache, x => x.Author).Alias, udi);
}
@{
if (Model.Value<string[]>("keyFeatureList").Length > 0)
{
<ul>
@foreach (var item in Model.Value<string[]>("keyFeatureList"))
{
<li>@item</li>
}
</ul>
}
}
@{
if (Model.KeyFeatureList.Any())
{
<ul>
@foreach (var item in Model.KeyFeatureList)
{
<li>@item</li>
}
</ul>
}
}
@using Umbraco.Cms.Core.Services
@inject IContentService ContentService
@{
// Create a variable for the GUID of the page you want to update
var guid = new Guid("32e60db4-1283-4caa-9645-f2153f9888ef");
// Get the page using the GUID you've defined
var content = ContentService.GetById(guid); // ID of your page
// Set the value of the property with alias 'keyFeatureList'
content.SetValue("keyFeatureList", "Awesome" + Environment.NewLine + "Super");
// Save the change
ContentService.Save(content);
}
@{
// Get the page using it's id
var content = ContentService.GetById(1234);
}
@using Umbraco.Cms.Core.PublishedCache
@inject IPublishedContentTypeCache PublishedContentTypeCache
@{
// Set the value of the property with alias 'keyFeatureList'
content.SetValue(Home.GetModelPropertyType(PublishedContentTypeCache, x => x.KeyFeatureList).Alias, "Awesome" + Environment.NewLine + "Super");
}
@{
int students = Model.HasValue("students") ? Model.Value<int>("students") : 0;
int teachers = Model.HasValue("teachers") ? Model.Value<int>("teachers") : 0;
int totalTravellers = students + teachers;
<p>@totalTravellers</p>
}
@{
if(Model.HasValue("students")){
<p>@(Model.Value<string>("students"))</p>
}
}
@{
int students = Model.Students;
int teachers = Model.Teachers;
int totalTravellers = students + teachers;
<p>@totalTravellers</p>
}
@using Umbraco.Cms.Core.Services
@inject IContentService ContentService
@{
// Create a variable for the GUID of the page you want to update
var guid = new Guid("32e60db4-1283-4caa-9645-f2153f9888ef");
// Get the page using the GUID you've defined
var content = ContentService.GetById(guid); // ID of your page
// Set the value of the property with alias 'students'
content.SetValue("students", 20);
// Save the change
ContentService.Save(content);
}
@{
// Get the page using it's id
var content = ContentService.GetById(1234);
}
@using Umbraco.Cms.Core.PublishedCache
@inject IPublishedContentTypeCache PublishedContentTypeCache
@{
// Set the value of the property with alias 'students'
content.SetValue(Home.GetModelPropertyType(PublishedContentTypeCache, x => x.Students).Alias, 20);
}
@if (Model.HasValue("colorTheme"))
{
var value = Model.Value("colorTheme");
<p>@value</p>
}
@if (Model.ColorTheme != null)
{
var value = Model.ColorTheme;
<p>@value</p>
}
@using Umbraco.Cms.Core.Services
@inject IContentService ContentService
@{
// Create a variable for the GUID of the page you want to update
var guid = new Guid("796a8d5c-b7bb-46d9-bc57-ab834d0d1248");
// Get the page using the GUID you've defined
var content = ContentService.GetById(guid); // ID of your page
// Set the value of the property with alias 'colorTheme'
content.SetValue("colorTheme", "water");
// Save the change
ContentService.Save(content);
}
@{
// Get the page using it's id
var content = ContentService.GetById(1234);
}
@using Umbraco.Cms.Core.PublishedCache
@inject IPublishedContentTypeCache PublishedContentTypeCache
@{
// Set the value of the property with alias 'colorTheme'
content.SetValue(Home.GetModelPropertyType(PublishedContentTypeCache, x => x.ColorTheme).Alias, "water");
}
@{
// Perform an null-check on the field with alias 'pageTitle'
if (Model.HasValue("pageTitle")){
// Print the value of the field with alias 'pageTitle'
<p>@(Model.Value("pageTitle"))</p>
}
}
@{
// Perform an null-check on the field with alias 'pageTitle'
@if (!Model.HasValue(Model.PageTitle))
{
// Print the value of the field with alias 'pageTitle'
<p>@Model.PageTitle</p>
}
}
@using Umbraco.Cms.Core.Services
@inject IContentService ContentService
@{
// Create a variable for the GUID of the page you want to update
var guid = new Guid("32e60db4-1283-4caa-9645-f2153f9888ef");
// Get the page using the GUID you've defined
var content = ContentService.GetById(guid); // ID of your page
// Set the value of the property with alias 'pageTitle'
content.SetValue("pageTitle", "Umbraco Demo");
// Save the change
ContentService.Save(content);
}
@{
// Get the page using it's id
var content = ContentService.GetById(1234);
}
@using Umbraco.Cms.Core.PublishedCache
@inject IPublishedContentTypeCache PublishedContentTypeCache
@{
// Set the value of the property with alias 'pageTitle'
content.SetValue(Home.GetModelPropertyType(PublishedContentTypeCache, x => x.PageTitle).Alias, "Umbraco Demo");
}
@using Umbraco.Cms.Core.Services;
@inject IUserService UserService;
@{
if (Model.Value("userPicker") != null)
{
var us = UserService;
var username = us.GetUserById(Model.Value<int>("userPicker")).Name;
<p>This is the chosen person: @username</p>
<p>This returns the id value of chosen person: @Model.Value("userPicker")</p>
}
}
@using Umbraco.Cms.Core.Services;
@inject IUserService UserService;
@{
if (Model.UserPicker != null)
{
var us = UserService;
var user = us.GetUserById((int)Model.UserPicker);
<p>This is the chosen person: @user.Name</p>
<p>This returns the id value of chosen person: @user.Id)</p>
}
}
@using Umbraco.Cms.Core.Services
@inject IContentService ContentService
@{
// Create a variable for the GUID of the page you want to update
var guid = new Guid("796a8d5c-b7bb-46d9-bc57-ab834d0d1248");
// Get the page using the GUID you've defined
var content = ContentService.GetById(guid); // ID of your page
// Set the value of the property with alias 'userPicker'. The value is the specific ID of the user
content.SetValue("userPicker", -1);
// Save the change
ContentService.Save(content);
}
@{
// Get the page using it's id
var content = ContentService.GetById(1234);
}
@using Umbraco.Cms.Core.PublishedCache
@inject IPublishedContentTypeCache PublishedContentTypeCache
@{
// Set the value of the property with alias 'userPicker'
content.SetValue(Home.GetModelPropertyType(PublishedContentTypeCache, x => x.UserPicker).Alias, -1);
}
{
"Umbraco": {
"CMS": {
"Content": {
"ContentVersionCleanupPolicy": {
"EnableCleanup": true,
"KeepLatestVersionPerDayForDays": 90,
"KeepAllVersionsNewerThanDays": 4
}
}
}
}
}
Running Umbraco on docker locally using docker compose
This article shows how to run Umbraco locally in Docker using Docker Compose. You can use either SQL Server or SQLite for development.
Before you can run Umbraco in Docker, make sure the following are installed:
.NET SDK with Umbraco Templates v16 or higher
Docker Desktop
To install Umbraco using the provided Dockerfile and Docker Compose setup, follow these steps:
Create a folder and navigate into it:
mkdir MyDockerProject
cd MyDockerProject
Create a new Umbraco project with Docker support:
dotnet new umbraco -n MyDockerProject --add-docker
Add Docker Compose files:
dotnet new umbraco-compose -P "MyDockerProject"
The -P
flag is required to specify the correct paths in the docker-compose file. The project is now ready to run with Docker Compose.
The folder structure should now look like this:
MyDockerProject/
Database/
Dockerfile
healthcheck.sh
setup.sql
startup.sh
MyDockerProject/
Your project files
Dockerfile
.dockerignore
.env
docker-compose.yml
The project now includes docker files for both Umbraco and the SQL server database.
It also includes additional scripts to launch and configure the database and a .env
file with the database password.
Run the following command from the root folder (where docker-compose.yml
is located):
docker compose up
Access the site at http://localhost:44372
.
Create a new folder and navigate into it:
mkdir MyDockerSqliteProject
cd MyDockerSqliteProject
Create a new Umbraco project:
dotnet new umbraco -n MyDockerSqliteProject
Add a Dockerfile
FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS base
WORKDIR /app
EXPOSE 8080
FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src
COPY ["MyDockerSqliteProject/MyDockerSqliteProject.csproj", "MyDockerSqliteProject/"]
RUN dotnet restore "MyDockerSqliteProject/MyDockerSqliteProject.csproj"
COPY . .
WORKDIR "/src/MyDockerSqliteProject"
RUN dotnet build "MyDockerSqliteProject.csproj" -c $BUILD_CONFIGURATION -o /app/build
FROM build AS publish
RUN dotnet publish "MyDockerSqliteProject.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "MyDockerSqliteProject.dll"]
Build the container:
docker build -t umbraco-sqlite .
Run the container:
docker run -p 8080:8080 umbraco-sqlite
Access the site at http://localhost:8080
.
There are some useful commands you can use to manage the docker containers:
docker compose down --volumes
: Deletes containers and the volumes they use. This is useful if you want to start from scratch.
Be careful with this command, as it deletes your database and all data in it.
docker compose up --build
: Rebuild the images and start the containers. This is useful if you have made changes to the project and want to see them reflected on the running site.
docker compose watch
: Start the containers and watch the default models folder. This means that if the project uses a source-code models builder the images are automatically rebuilt and restarts when you change the models.
The docker compose file uses bind mounts for the following folders:
/wwwroot/media
/wwwroot/scripts
/wwwroot/css
/Views
/models
This is not meant to be used in production.
For local development, however, this means that the files necessary for development are available from outside the container in your IDE. This allows development even though the project is running in docker.
The umbraco-compose
template supports:
-P
or --project-name
: The name of the project. This is required and used to set the correct paths in the docker-compose file.
-dbpw
or --DatabasePassword
: Used to specify the database password. This is stored in the .env
file and defaults to: Password1234
.
-p
or --Port
: Used to specify the port the site will run on. Defaults to 44372
.
If the file system on your servers isn't performing any file replication then no Umbraco configuration file changes are necessary. However Media will need to be configured to use a shared location such as Blob storage or S3.
Depending on the configuration and performance of the environment's local storage you might need to consider Examine Directory Factory Options and the Umbraco temporary storage location.
If the file system on your servers is performing file replication then the Umbraco temporary folder (~/umbraco/Data/TEMP
) must be excluded from replication.
If the file system on your servers is located on shared storage you will need to configure Umbraco to locate the Umbraco temporary folder outside of the shared storage.
A common way to replicate files on Windows Server is to use [DFS](https://msdn.microsoft.com/en-us/library/windows/desktop/bb540031(v=vs.85), which is included with Windows Server.
Additional DFS resources:
There are other alternatives for file replication out there, some free and some licensed. You'll need to decide which solution is best for your environment.
When deploying Umbraco in a load balanced scenario using file replication, it is important to ensure that not all files are replicated - otherwise you will experience file locking issues. Here are the folders and files that should not be replicated:
~/umbraco/Data/TEMP/*
~/umbraco/Logs/*
This is optional and depends on how you want your logs configured (see below)
If for some reason your file replication solution doesn't allow you to not replicate specific files folders (which it should!!) then you can use an alternative approach by using virtual directories.
The following is not the recommended setup but it is a viable alternative:
Copy the ~/umbraco/Data/TEMP
directory to each server, outside of any replication areas or to a unique folder for each server.
Create a virtual directory (not a virtual application) in the ~/umbraco/Data/
folder, and name it TEMP
. Point the virtual directory to the folder you created in step 2.
You may delete the ~/umbraco/Data/TEMP
folder from the file system - not IIS as this may delete the virtual directory - if you wish.
IIS configuration is pretty straightforward with file replication. IIS is only reading files from its own file system like a normal IIS website.
In some scenarios you have a mixture of standalone and synchronised file systems. An example of this is Azure Web Apps where the file system isn't replicated between backoffice and front end servers but is replicated between all front end servers, in this configuration you should follow the steps for synchronised file systems.
There is a specific documentation for load balancing with Azure Web Apps
The TempFileSystemDirectoryFactory
allows Examine to store indexes directly in the environment temporary storage directory, and should be used instead of SyncTempEnvDirectoryFactory
mentioned above.
{
"Umbraco": {
"CMS": {
"Examine": {
"LuceneDirectoryFactory" : "TempFileSystemDirectoryFactory"
}
}
}
}
The SyncedTempFileSystemDirectoryFactory
enables Examine to sync indexes between the remote file system and the local environment temporary storage directory, the indexes will be accessed from the temporary storage directory. This setting is needed because Lucene has issues when working from a remote file share so the files need to be read/accessed locally. Any time the index is updated, this setting will ensure that both the locally created indexes and the normal indexes are written to. This will ensure that when the app is restarted or the local environment temp files are cleared out that the index files can be restored from the centrally stored index files.
{
"Umbraco": {
"CMS": {
"Examine": {
"LuceneDirectoryFactory" : "SyncedTempFileSystemDirectoryFactory"
}
}
}
}
Once you are familiar with how flexible load balancing works, you might be interested in some advanced techniques.
This describes some more advanced techniques that you could achieve with flexible load balancing
The election process that runs during the startup of an Umbraco instance determines the server role that instance will undertake.
There are two server roles to be aware of for flexible load balancing:
SchedulingPublisher
- The Umbraco instance usually used for backoffice access, responsible for running scheduled tasks.
Subscriber
- A scalable instance that subscribes to content updates from the SchedulingPublisher server, not recommended to be used for backoffice access.
It is recommended to configure an explicit SchedulingPublisher server since this reduces the amount of complexity that the election process performs.
The first thing to do is create a couple of small classes that implement IServerRoleAccessor
one for each of the different server roles:
public class SchedulingPublisherServerRoleAccessor : IServerRoleAccessor
{
public ServerRole CurrentServerRole => ServerRole.SchedulingPublisher;
}
public class SubscriberServerRoleAccessor : IServerRoleAccessor
{
public ServerRole CurrentServerRole => ServerRole.Subscriber;
}
then you'll need to replace the default IServerRoleAccessor
for the your custom registrars. You'll can do this by using the SetServerRegistrar()
extension method on IUmbracoBuilder
from a Composer.
// This should be executed on your single `SchedulingPublisher` server
builder.SetServerRegistrar<SchedulingPublisherServerRoleAccessor>();
// This should be executed on your `Subscriber` servers
builder.SetServerRegistrar<SubscriberServerRoleAccessor>();
Now that your subscriber servers are using your custom SubscriberServerRoleAccessor
class, they will always be deemed 'Subscriber' servers and will not attempt to run the automatic server role election process or task scheduling.
By setting your SchedulingPublisher server to use your custom SchedulingPublisherServerRoleAccessor
class, it will always be deemed the 'SchedulingPublisher' and will always be the one that executes all task scheduling.
In some cases infrastructure admins will not want their front-end servers to have write access to the database. By default front-end servers will require write full access to the following tables:
umbracoServer
umbracoNode
This is because by default each server will inform the database that they are active and more importantly it is used for task scheduling. Only a single server can execute task scheduling and these tables are used for servers to use a server role election process without the need for any configuration. So in the case that a subscriber server becomes the SchedulingPublisher task scheduler, it will require write access to all of the Umbraco tables.
In order to have read-only database access configured for your front-end servers, you need to implement the Explicit SchedulingPublisher server configuration mentioned above.
Now that your subscriber servers are using your custom SubscriberServerRoleAccessor
class, they will always be deemed 'Subscriber' servers and will not attempt to run the automatic server role election process or task scheduling. Because you are no longer using the default ElectedServerRoleAccessor
they will not try to ping the umbracoServer table.
The configurations can be adjusted to control how often the load balancing instructions from the database are processed and pruned.
Below is shown how to do this from a JSON configuration source.
{
"Umbraco": {
"CMS": {
"Global": {
"DatabaseServerMessenger": {
"MaxProcessingInstructionCount": 1000,
"TimeBetweenPruneOperations": "00:01:00",
"TimeBetweenSyncOperations": "00:00:05",
"TimeToRetainInstructions": "2.00:00:00"
}
}
}
}
}
Options:
TimeToRetainInstructions
- The timespan to keep instructions in the database; records older than this number will be pruned.
MaxProcessingInstructionCount
- The maximum number of instructions that can be processed at startup; otherwise the server cold-boots (rebuilds its caches)
TimeBetweenSyncOperations
- The timespan to wait between each sync operations
TimeBetweenPruneOperations
- The timespan to wait between each prune operation
These setting would normally be applied to all environments as they are added to the global app settings. If you need these settings to be environment specific, we recommend using environment specific appSetting
files.
A guide displaying the options available in the Settings section in Umbraco CMS backoffice.
The Settings section of the Umbraco backoffice has its own set of default dashboards. In this article, you can get an overview of each dashboard available in the Settings section:
How to perform common logical tasks in Razor like if/else, foreach loops, switch statements and using the @ character to separate code and markup
Shows how to perform common logical tasks in Razor like if/else, foreach loops, switch statements and using the @ character to separate code and markup.
The @ symbol is used in Razor to initiate code, and tell the compiler where to start interpreting code, instead of returning the content of the file as text. Using a single character for this separation, results in cleaner, compact code which is easier to read.
@* Writing a value inside a html element *@
<p>@Model.Name</p>
@* Inside an attribute *@
<a href="@Model.Url()">@Model.Name</a>
@* Using it to start logical structures *@
@if (selection?.Length > 0)
{
<ul>
@foreach (var item in selection)
{
<li>
<a href="@item.Url(PublishedUrlProvider)">@item.Name</a>
</li>
}
</ul>
}
Commenting your code is important, use comments to explain what the code does. @* *@
indicates a comment, which will not be visible in the rendered output.
@* Here we check if the name is equal to foobar *@
@if (Model.Name == "foobar")
{
@foreach (var child in Model.Children())
{
@* here we write stuff for each child page *@
<p>write stuff</p>
}
}
If/else statements perform one task if a condition is true, and another if the condition is not true
@if (Model.Name == "home")
{
<p>This is the homepage!</p>
}
@if (Model.NodeTypeAlias == "TextPage")
{
<p>This is a textpage</p>
}
else
{
<p>This is NOT a textpage</p>
}
A foreach loop goes through a collection of items, typically a collection of pages and performs an action for each item
@foreach (var item in Model.Children())
{
<p>The item name is: @Item.Name</p>
}
A Switch block is used when testing a large number of conditions
@switch (Model.WeekDay)
{
case "Monday":
"<p>It is Monday</p>";
break;
case "Tuesday":
"<p>It is Tuesday</p>";
break;
case "Wednesday":
"<p>It is Wednesday</p>";
break;
default:
"<p>It's some day of the week</p>";
break;
}
Umbraco HQ offers a training course covering the basic concepts and features needed for building an Umbraco CMS website. The course targets frontend and backend developers, designers, and technical users who want to build a website from scratch in Umbraco,
Explore the Fundamentals Training Course to learn more about the topics covered and how they can enhance your Umbraco development skills.
A guide to install Umbraco CMS using Visual Studio.
Install the newest Umbraco dotnet templates.
In Visual Studio 2022, the .NET CLI templates are enabled to appear, by default. For information on how to enable .NET CLI templates in Visual Studio 2019, see the .NET CLI Templates in Visual Studio article.
Check the Requirements to ensure you have everything you need to start your Umbraco project.
This is an abbreviated version of the installation steps. Jump to the Create a new project section for a more thorough guide.
Open Visual Studio.
Go to File
> New
> Project
, search for Umbraco.
Choose Umbraco Project (Umbraco HQ) then click Next.
Choose or specify the parameters, leave the default or leave them all empty.
Click Create.
Use CTRL+F5 to run the project and start the Umbraco installer.
To install Umbraco we first need to install Umbraco's dotnet new templates.
For more information check the first 2 steps of Install Umbraco with .NET CLI.
Go to File > New > Project and search for Umbraco
in the Search for templates field.
Once you select Umbraco Project (Umbraco HQ) navigate to the next step by clicking Next.
In this step, you will be able to give your project a name specific to the project you are creating.
In the next step, you are able to specify some additional parameters like the Target framework. The rest are optional.
You can then click the Create button and your Umbraco Project will be ready for you.
You can now run the site through Visual Studio using F5 or the Debug button.
Follow the installation wizard and after a few steps, you will get a message saying the installation was a success.
You are now ready to start building your Umbraco project. Have a look below for different resources on the next steps.
In this article you can learn more about the various sections you can find within the Umbraco Backoffice.
A section in Umbraco is where you perform specific tasks related to a particular area of Umbraco. For example, Content, Settings, and Users are all sections. You can navigate between the different sections by clicking the corresponding icon in the section menu positioned at the top of the Backoffice.
Below is a short overview of the default sections in Umbraco CMS:
The Content section contains the content nodes that make up the website. Content is displayed as nodes in the Content tree.
Nodes in Umbraco can display the following content states:
Grayed-out nodes are not published yet.
Nodes that are currently locked using the Public Access feature.
Content nodes that contain a collection of nodes.
To create content, you must define it using Document Types.
For more information, see the Defining Content article.
The Media section contains the media for the website. You can create folders and upload media files, such as images and PDFs. Additionally, you can customize the existing Media Types or define your own from the Settings section.
For more information, see the Creating Media article.
The Settings section allows you to manage website layout files, languages, media, and content types. It also gives you access to more advanced features such as the Log Viewer and extension insights.
The Settings section consists of:
Structure
Document Types
Media Types
Member Types
Data Types
Languages
Document Blueprints
Templating
Templates (.cshtml
files)
Partial views (.cshtml
files)
Stylesheets (.css
files)
Scripts (.js
files)
Advanced
Relations
Log Viewer
Extension Insights
Webhooks
The Settings section in the Umbraco backoffice has its own set of default dashboards.
For more information, see the Settings Dashboards article.
In this section, you can browse the different packages available for your Umbraco solution. You can also get an overview of all the packages you have installed or created.
For more information, see the Packages article.
The Users section allows administrators to manage user accounts, assign permissions, set user roles, and monitor user activity within the backoffice. It provides control over who can access and modify content, media, and settings in the CMS.
For more information, see the Users article.
The Members section allows to create and manage member profiles, set up member groups, and control Member's access to restricted content on the website.
For more information, see the Members article.
The Dictionary section is where you create and manage Dictionary Items. By managing these dictionary items, you can ensure consistent and efficient content translation and maintenance across different languages.
For more information, see the Dictionary Items article.
To enhance Umbraco's functionality, you can integrate plugins and extensions tailored to specific needs. These add-ons expand Umbraco's capabilities, allowing for a more customized and powerful content management experience.
For example, you can start with core Umbraco features and later decide to integrate additional products. Currently, Umbraco supports add-on products like:
Forms: Simplifies the creation and management of Forms.
Deploy: Facilitates smooth deployment processes.
Workflow: Enhances content workflows and approval processes.
Commerce: Adds e-commerce capabilities to your site.
UI Builder: Helps in designing and customizing the user interface.
When you add an add-on product to Umbraco, it appears in the Backoffice as a new section, seamlessly extending your content management capabilities.
If you wish to explore the unique features and use cases of Umbraco products, see the Exploring the Umbraco Products article.
For more information about extending the Umbraco platform through packages and integrations, see the Umbraco DXP documentation.
The Help section in Umbraco provides documentation and resources to assist in understanding and effectively using the Umbraco CMS. It typically includes the following in the Getting Started Dashboard:
Documentation: Comprehensive guides, tutorials, and references covering different aspects of Umbraco.
Community Forums: Access to forums where you can ask questions, share knowledge, and seek assistance from other Umbraco community members.
Resources: Stay updated with the latest news, access documentation, watch free video tutorials, and register for live demos.
Training: Learn how to effectively use Umbraco through structured courses, webinars, and hands-on tutorials designed to enhance your proficiency with the CMS.
The Help section serves as a valuable resource hub in navigating and leveraging the capabilities of the Umbraco CMS effectively.
Along with the default sections that come with Umbraco, you can create your own Custom Sections.
A User can access a particular section based on the User Group permissions.
Learn more about how to configure the permissions in the article about backoffice users.
Schema Alias: Umbraco.ColorPicker
UI Alias: Umb.PropertyEditorUi.ColorPicker
Returns: String (Hexadecimal)
Returns: Umbraco.Cms.Core.PropertyEditors.ValueConverters.ColorPickerValueConverter.PickedColor (When using labels)
The Color picker allows you to set some predetermined colors that the editor can choose between.
It is possible to add a label to use with the color.
@{
// Model has a property called "Color" which holds a Color Picker editor
var hexColor = Model.Color;
// Define the label if you've included it
String colorLabel = Model.Color.Label;
if (hexColor != null)
{
<div style="background-color: #@hexColor">@colorLabel</div>
}
}
@using Umbraco.Cms.Core.PropertyEditors.ValueConverters
@{
// Model has a property called "Color" which holds a Color Picker editor
var hexColor = Model.Value("Color");
// Define the label if you've included it
var colorLabel = Model.Value<ColorPickerValueConverter.PickedColor>("Color").Label;
if (hexColor != null)
{
<div style="background-color: #@hexColor">@colorLabel</div>
}
}
See the example below to see how a value can be added or changed programmatically. To update a value of a property editor you need the Content Service.
@using Umbraco.Cms.Core.Services
@inject IContentService ContentService
@{
// Create a variable for the GUID of the page you want to update
var guid = Guid.Parse("32e60db4-1283-4caa-9645-f2153f9888ef");
// Get the page using the GUID you've defined
var content = ContentService.GetById(guid); // ID of your page
// Set the value of the property with alias 'color'.
// The value set here, needs to be one of the colors on the Color Picker
content.SetValue("color", "38761d");
// Save the change
ContentService.Save(content);
}
@using Umbraco.Cms.Core.Services
@inject IContentService ContentService
@{
// Create a variable for the GUID of the page you want to update
var guid = Guid.Parse("32e60db4-1283-4caa-9645-f2153f9888ef");
// Get the page using the GUID you've defined
var content = ContentService.GetById(guid); // ID of your page
// Set the value of the property with alias 'color'.
// The value set here, needs to be one of the colors on the Color Picker
content.SetValue("color", "{'value':'000000', 'label':'Black', 'sortOrder':1, 'id':'1'}");
// Save the change
ContentService.Save(content);
}
Although the use of a GUID is preferable, you can also use the numeric ID to get the page:
@{
// Get the page using it's id
var content = ContentService.GetById(1234);
}
If Models Builder is enabled you can get the alias of the desired property without using a magic string:
@using Umbraco.Cms.Core.PublishedCache
@inject IPublishedContentTypeCache PublishedContentTypeCache
@{
// Set the value of the property with alias 'color'
content.SetValue(Home.GetModelPropertyType(PublishedContentTypeCache, x => x.Color).Alias, "38761d");
}
Schema Alias: Umbraco.UploadField
UI Alias: Umb.PropertyEditorUi.UploadField
Returns: string
Adds an upload field, which allows documents or images to be uploaded to Umbraco.
You can define which file types should be accepted through the upload field.
In code, the property is a string, which references the location of the file.
Example: "/media/o01axaqu/guidelines-on-remote-working.pdf"
@using System.IO;
@{
if (Model.HasValue("myFile"))
{
var myFile = Model.Value<string>("myFile");
<a href="@myFile">@System.IO.Path.GetFileName(myFile)</a>
}
}
@if (!Model.HasValue(Model.MyFile))
{
<a href="@Model.MyFile">@System.IO.Path.GetFileName(Model.MyFile)</a>
}
See the example below to see how a value can be added or changed programmatically. To update a value of this property editor you need the Content Service and the Media Service.
@using Umbraco.Cms.Core.IO
@using Umbraco.Cms.Core.Serialization
@using Umbraco.Cms.Core.Strings
@inject MediaFileManager MediaFileManager
@inject IShortStringHelper ShortStringHelper
@inject IContentTypeBaseServiceProvider ContentTypeBaseServiceProvider
@inject IContentService ContentService
@inject IMediaService MediaService
@inject IJsonSerializer Serializer
@inject MediaUrlGeneratorCollection MediaUrlGeneratorCollection
@{
// Create a variable for the GUID of the parent where you want to add a child item
var guid = Guid.Parse("32e60db4-1283-4caa-9645-f2153f9888ef");
// Get the page using the GUID you've defined
var content = ContentService.GetById(guid); // ID of your page
// Create a variable for the file you want to upload, in this case the Our Umbraco logo
var imageUrl = "https://our.umbraco.com/assets/images/logo.svg";
// Create a request to get the file
var request = WebRequest.Create(imageUrl);
var webResponse = request.GetResponse();
var responseStream = webResponse.GetResponseStream();
// Get the file name
var lastIndex = imageUrl.LastIndexOf("/", StringComparison.Ordinal) + 1;
var filename = imageUrl.Substring(lastIndex, imageUrl.Length - lastIndex);
// Create a media file
var media = MediaService.CreateMediaWithIdentity("myImage", -1, "File");
media.SetValue(MediaFileManager, MediaUrlGeneratorCollection, ShortStringHelper, ContentTypeBaseServiceProvider, Constants.Conventions.Media.File, filename, responseStream);
// Save the created media
MediaService.Save(media);
// Get the published version of the media (IPublishedContent)
var publishedMedia = Umbraco.Media(media.Id);
// Set the value of the property with alias 'myFile'
content.SetValue("myFile", publishedMedia.Url());
// Save the child item
ContentService.Save(content);
}
Although the use of a GUID is preferable, you can also use the numeric ID to get the page:
@{
// Get the page using it's id
var content = ContentService.GetById(1234);
}
If Models Builder is enabled you can get the alias of the desired property without using a magic string:
@using Umbraco.Cms.Core.PublishedCache
@inject IPublishedContentTypeCache PublishedContentTypeCache
@{
// Set the value of the property with alias 'myFile'
content.SetValue(Home.GetModelPropertyType(PublishedContentTypeCache, x => x.MyFile).Alias, publishedMedia.Url();
}
Schema Alias: Umbraco.MarkdownEditor
UI Alias: Umb.PropertyEditorUi.MarkdownEditor
Returns: System.Web.HtmlString
This built-in editor allow the user to use the markdown formatting options, from within a rich text editor-like interface.
There are three settings available for manipulating the Markdown editor property.
Preview toggles if a preview of the markdown should be displayed beneath the editor in the content view.
Default value is inserted if no content has been saved to the Document Type using this property editor.
Overlay Size is used to select the width of the link picker overlay in the content view.
toggle bold text
Ctrl + B
toggle italic text
Ctrl + I
insert link
Ctrl + L
This opens the Select Link interface.
toggle quote
Ctrl + Q
toggle code block
Ctrl + K
insert image
Ctrl + G
This opens the Select Media interface.
toggle ordered list
Ctrl + O
toggle unordered list
Ctrl + U
toggle heading
Ctrl + H
This toggles between h1, h2 and off.
toggle a hr
undo
Ctrl + Z
redo
Ctrl + Y
select all
Ctrl + A
copy
Ctrl + C
paste
Ctrl + V
@Model.MyMarkdownEditor
@Model.Value("MyMarkdownEditor")
See the example below to see how a value can be added or changed programmatically. To update a value of a property editor you need the Content Service.
@using Umbraco.Cms.Core.Services
@inject IContentService ContentService
@{
// Create a variable for the GUID of the page you want to update
var guid = Guid.Parse("32e60db4-1283-4caa-9645-f2153f9888ef");
// Get the page using the GUID you've defined
var content = ContentService.GetById(guid); // ID of your page
// Create markdown value
var markdownValue = new HtmlString("#heading \n**strong text**");
// Set the value of the property with alias 'myMarkdownEditor'.
content.SetValue("myMarkdownEditor", markdownValue);
// Save the change
ContentService.Save(content);
}
Although the use of a GUID is preferable, you can also use the numeric ID to get the page:
@{
// Get the page using it's id
var content = ContentService.GetById(1234);
}
If Models Builder is enabled you can get the alias of the desired property without using a magic string:
@using Umbraco.Cms.Core.PublishedCache
@inject IPublishedContentTypeCache PublishedContentTypeCache
@{
// Set the value of the property with alias 'myMarkdownEditor'
content.SetValue(Home.GetModelPropertyType(PublishedContentTypeCache, x => x.MyMarkdownEditor).Alias, markdownValue);
}
Schema Alias: Umbraco.MultiUrlPicker
UI Alias: Umb.PropertyEditorUi.MultiUrlPicker
Returns: IEnumerable<Link> or Link
Multi Url Picker allows an editor to pick and sort multiple urls. This property editor returns a single item if the "Maximum number of items" Data Type setting is set to 1 or a collection if it is 0. These can either be internal, external or media.
@using Umbraco.Cms.Core.Models
@{
var links = Model.Value<IEnumerable<Link>>("footerLinks");
if (links.Any())
{
<ul>
@foreach (var link in links)
{
<li><a href="@link.Url" target="@link.Target">@link.Name</a></li>
}
</ul>
}
}
If Max number of items
is configured to 1
@using Umbraco.Cms.Core.Models
@{
var link = Model.Value<Link>("link");
if (link != null)
{
<a href="@link.Url" target="@link.Target">@link.Name</a>
}
}
See the example below to see how a value can be added or changed programmatically. To update a value of a property editor you need the Content Service.
@using Umbraco.Cms.Core
@using Umbraco.Cms.Core.Serialization
@using Umbraco.Cms.Core.Services
@using Umbraco.Cms.Core.Models
@inject IContentService ContentService
@inject IJsonSerializer Serializer
@{
// Create a variable for the GUID of the page you want to update
var guid = Guid.Parse("32e60db4-1283-4caa-9645-f2153f9888ef");
// Get the page using the GUID you've defined
var content = ContentService.GetById(guid); // ID of your page
// Get the media you want to assign to the footer links property
var media = Umbraco.Media("bca8d5fa-de0a-4f2b-9520-02118d8329a8");
// Create an Udi of the media
var mediaUdi = Udi.Create(Constants.UdiEntityType.Media, media.Key);
// Get the content you want to assign to the footer links property
var contentPage = Umbraco.Content("665d7368-e43e-4a83-b1d4-43853860dc45");
// Create an Udi of the Content
var contentPageUdi = Udi.Create(Constants.UdiEntityType.Document, contentPage.Key);
// Create a list with different link types
var externalLinks = new List<Link>
{
// External Link
new Link
{
Target = "_blank",
Name = "Our Umbraco",
Url = "https://our.umbraco.com/",
Type = LinkType.External
},
// Media
new Link
{
Target = "_self",
Name = media.Name,
Url = media.MediaUrl(),
Type = LinkType.Media,
Udi = mediaUdi
},
// Content
new Link
{
Target = "_self",
Name = contentPage.Name,
Url = contentPage.Url(),
Type = LinkType.Content,
Udi = contentPageUdi
}
};
// Serialize the list with links to JSON
var links = Serializer.Serialize(externalLinks);
// Set the value of the property with alias 'footerLinks'.
content.SetValue("footerLinks", links);
// Save the change
ContentService.Save(content);
}
Although the use of a GUID is preferable, you can also use the numeric ID to get the page:
@{
// Get the page using it's id
var content = ContentService.GetById(1234);
}
If Models Builder is enabled you can get the alias of the desired property without using a magic string:
@using Umbraco.Cms.Core.PublishedCache
@inject IPublishedContentTypeCache PublishedContentTypeCache
@{
// Set the value of the property with alias 'footerLinks'
content.SetValue(Home.GetModelPropertyType(PublishedContentTypeCache, x => x.FooterLinks).Alias, links);
}
Schema Alias: Umbraco.Tags
UI Alias: Umb.PropertyEditorUi.Tags
Returns: IEnumerable<string>
The Tags property editor allows you to add multiple tags to a node.
The Tag group setting provides a way to categorize your tags in groups. So for each category you will create a new instance of the Tags property editor and setup the unique category name for each instance. Whenever a tag is added to an instance of the tags property editor it's added to the tag group, which means it will appear in the Typeahead list when you start to add another tag. Only tags that belong to the specified group will be listed. If you have a "Frontend" group and a "Backend" group the tags from the "Frontend" group will only be listed if you're adding a tag to the Tags property editor configured with the "Frontend" group name and vice versa.
Data can be saved in either Comma-Separated Values (CSV) format or in JSON format. By default data is saved in JSON format. The difference between using CSV and JSON is that with JSON you can save a tag, which includes comma separated values.
There are built-in property value converters, which means you don't need to worry about writing them yourself or parse the JSON output when choosing "JSON" in the storage type field. Therefore the last code example on this page will work out of the box without further ado.
Whenever a tag has been added it will be visible in the typeahead when you start typing on other pages.
@if(Model.Tags.Any()){
<ul>
@foreach(var tag in Model.Tags){
<li>@tag</li>
}
</ul>
}
@if(Model.HasValue("tags"))
{
var tags = Model.Value<IEnumerable<string>>("tags");
<ul>
@foreach(var tag in tags)
{
<li>@tag</li>
}
</ul>
}
You can use the ContentService to create and update Umbraco content from c# code, when setting tags there is an extension method (SetTagsValue) on IContentBase that helps you set the value for a Tags property. Remember to add the using statement for Umbraco.Core.Models
to take advantage of it.
@using Umbraco.Cms.Core.Serialization
@using Umbraco.Cms.Core.Services
@inject IContentService ContentService
@inject IJsonSerializer Serializer
@{
// Create a variable for the GUID of the page you want to update
var guid = Guid.Parse("9daf8585-6ab6-4ac2-98f0-28bf83aeea6e");
// Get the page using the GUID you've defined
var content = ContentService.GetById(guid); // ID of your page
// Set the value of the property with alias 'tags'.
content.SetValue("tags", Serializer.Serialize(new[] { "News", "Umbraco", "Example", "Setting Tags", "Helper" }));
// Save the change
ContentService.Save(content);
}
Although the use of a GUID is preferable, you can also use the numeric ID to get the page:
@{
// Get the page using it's id
var content = ContentService.GetById(1234);
}
If Models Builder is enabled, you can get the alias of the desired property without using a magic string:
@using Umbraco.Cms.Core.PublishedCache
@inject IPublishedContentTypeCache PublishedContentTypeCache
@{
// Set the value of the property with alias 'tags'
content.SetValue(Home.GetModelPropertyType(PublishedContentTypeCache, x => x.Tags).Alias, Serializer.Serialize(new[] { "News", "Umbraco", "Example", "Setting Tags" }));
}
More on working with Tags (query all of them) can be found at the UmbracoHelper reference page
Schema Alias: Umbraco.RichText
UI Alias: Umb.PropertyEditorUi.Tiptap
Returns: HTML
With the release of Umbraco 16, the TinyMCE UI option for the Rich Text Editor is removed.
The Rich Text Editor property editor is highly configurable and based on Tiptap. Depending on the configuration setup, it provides editors a lot of flexibility when working with content.
Customize everything from toolbar options to editor size to where pasted images are saved.
Define a cascading text formatting and style menu for the Rich Text Editor toolbar.
Use Blocks to define specific parts that can be added as part of the markup of the Rich Text Editor.
Extend the functionality of the Rich Text Editor with extensions.
@{
if (!string.IsNullOrEmpty(Model.RichText.ToString()))
{
<p>@Model.RichText</p>
}
}
@{
if (Model.HasValue("richText")){
<p>@(Model.Value("richText"))</p>
}
}
See the example below to see how a value can be added or changed programmatically. To update a value of a property editor you need the Content Service.
@using Umbraco.Cms.Core.Services
@inject IContentService ContentService
@{
// Create a variable for the GUID of the page you want to update
var guid = Guid.Parse("32e60db4-1283-4caa-9645-f2153f9888ef");
// Get the page using the GUID you've defined
var content = ContentService.GetById(guid); // ID of your page
// Create a variable for the desired value
var htmlValue = new HtmlString("Add some text <strong>here</strong>");
// Set the value of the property with alias 'richText'.
content.SetValue("richText", htmlValue);
// Save the change
ContentService.Save(content);
}
Although the use of a GUID is preferable, you can also use the numeric ID to get the page:
@{
// Get the page using it's id
var content = ContentService.GetById(1234);
}
If Models Builder is enabled you can get the alias of the desired property without using a magic string.
@using Umbraco.Cms.Core.PublishedCache
@inject IPublishedContentTypeCache PublishedContentTypeCache
@{
// Set the value of the property with alias 'richText'
content.SetValue(Home.GetModelPropertyType(PublishedContentTypeCache, x => x.RichText).Alias, htmlValue);
}
A Style Menu is a configurable extension that adds a cascading menu to the toolbar for applying text styles and formatting.
In this article, you can find an example of how to set up a Style Menu using the package manifest file.
{
"name": "Name of your package",
"alias": "My.Package",
"extensions": [
{
"type": "tiptapToolbarExtension",
"kind": "styleMenu",
"alias": "MyCustom.Tiptap.StyleMenu",
"name": "My Custom Tiptap Style Menu",
"meta": {
"alias": "myCustomStyleMenu",
"icon": "icon-palette",
"label": "My custom styles"
},
"items": [
{
"label": "Headings",
"items": [
{
"label": "Heading 2",
"data": { "tag": "h2" },
"appearance": { "icon": "icon-heading-2" }
},
{
"label": "Heading 3",
"data": { "tag": "h3" },
"appearance": { "style": "font-size: large;" }
},
{
"label": "Heading 4",
"data": { "tag": "h4" }
}
]
},
{
"label": "Attributes",
"items": [
{
"label": "Classes",
"data": { "class": "foo" }
},
{
"label": "IDs",
"data": { "id": "bar" }
},
{
"label": "Mixed",
"data": { "tag": "span", "class": "foo", "id": "bar" }
}
]
}
]
}
]
}
The items
property defines the structure of the style menu. Each menu item has the following options:
label
: (required) The label of the menu item. This supports localization keys.
appearance
: This defines the appearance of the menu item. The value has 2 optional properties:
icon
: To prefix an icon to the menu item.
style
: To apply CSS rules to the menu item.
data
: To configure the function of the style menu item. The value has 3 optional properties:
tag
: A supported HTML tag name. This will be applied to the selected text.
class
: Applies a class attribute with the defined class name to the containing tag of the selected text.
id
: Applies an ID attribute with the defined ID value to the containing tag of the selected text.
separatorAfter
: When true
, it will add a line separator after the menu item.
items
: To enable a cascading menu, an array of nested menu items may be added.
Once configured, all custom style menus will appear in the Rich Text Editor toolbar options, as described in the Rich Text Editor Configuration article.
Since the Tiptap has a strict rich-text schema, only supported HTML tags can be used in the style menu, (arbitrary markup will be excluded). The following HTML tag names are supported:
h1
h2
h3
h4
h5
h6
p
blockquote
code
codeBlock
div
em
(italic)
ol
strong
(bold)
s
(strike-through)
span
u
(underline)
ul
Learn how to create and use Document Blueprints in Umbraco.
A Document Blueprint allows editors to preconfigure a content node. It serves as a reusable starting point when creating new content.
Before using this method, make sure you have already created some content.
Go to the Content section and select an existing content node.
Click the ... menu next to the node and choose Create Document Blueprint.
Enter a Name for the new blueprint.
Click Save.
The new blueprint will appear under the Document Blueprints folder in the Settings section.
Go to the Settings section.
Click the ... menu next to the Document Blueprints tree.
Select Create....
Choose the Document Type you want to base the blueprint on.
You can only create Document Blueprints from Document Types or Document Types with Templates.
Enter a Name for the blueprint.
Click Save.
The new blueprint will appear under the Document Blueprints folder in the Settings section.
To edit an existing document blueprint, follow these steps:
Go to the Settings section.
Open the Document Blueprints folder.
Select the blueprint you want to edit.
Make your changes.
Click Save.
Once you have created a document blueprint, you can use it to create new content nodes.
To use a document blueprint, follow these steps:
Go to the Content section.
Click the ... menu next to the root node and select Create.
Select the Document Type that has an associated blueprint.
Choose how to create the new content:
Use the Document Blueprint
Start with a blank node
Learn how to use language variants to output your content in multiple languages.
Language Variants allows you to vary content by culture, so you can allow a content node to exist in multiple languages.
This article will cover the different aspects of enabling and working with language variants on your Umbraco website.
To work with Language Variants you need to have more than one language enabled. This can be done from the Settings
section:
Now that there are two languages to vary the content with, it needs to be enabled on the Document Types. To do so:
Go to the Document Type in the structure section.
Open the settings page.
Toggle Allow vary by culture.
To allow a property on the Document Type to be varied it will have to be enabled for the property:
When you return to your content node you will notice two things:
At the top of the Content tree there will now be a dropdown so you can show the Content tree in the language of your choice.
To the right of the content name there is now a dropdown where you can select a language. You can also open a split view so you can see two languages at once.
Each Property Editor that does not allow variants (an Invariant Property) will by default need to be unlocked in order to be edited. The lock exists to make it clear that this change will affect more languages. Since the value of the invariant properties are shared between all variants on the website.
To read about how you render variant content in Templates, check out the rendering content section.
Culture and hostnames must be added to your language sites before the content can be tested for variants:
Click ... next to the Home node and select Culture and Hostnames.
Add a specific URL per language and save. For eg: An English language variant with English (United States) as the language can be given a specific URL https://yourwebsite.com/en-us
and a Danish language variant can be given a specific URL https://yourwebsite.com/dk
.
The Info content app should now show specific URLs for your language variants.
When you are working with a multilingual site you might want to control who can edit the different variations of the content on the website.
This can be controlled on a User Group level. All default User Groups, except the Sensitive data group, have access to all languages out of the box.
When "Allow access to all languages" is not checked, languages can be added and/or removed. This is to determine which variants the users in the user group have access to.
Here you will learn how to apply localization for Document Types in Umbraco.
This article is a work in progress and may undergo further revisions, updates, or amendments. The information contained herein is subject to change without notice.
The Umbraco backoffice is localized to match the user's configured language.
When defining a Document Type, you can apply localization to:
Document Type name and description.
Property names and descriptions.
Custom property validation messages.
Tab and group names.
Setting up localization for Document Types is a two-step process:
Create the localizations in user defined backoffice localization file.
Apply the localizations to the Document Type.
Once you have registered a backoffice localization file, you can add your localization texts for use in Document Types. The following localizations are used for the samples in this article:
export default {
contentTypes: {
article: 'Article page',
'article-desc': 'A textual, article-like page on the site. Use this as the main type of content.',
landing: 'Landing page',
'landing-desc': 'An inviting, very graphical page. Use this as an entry point for a campaign, and supplement with Articles.'
},
tabs: {
content: 'Page content',
seo: 'SEO configuration',
},
groups: {
titles: 'Page titles'
},
properties: {
title: 'Main title',
'title-desc': 'This is the main title of the page.',
'title-message': 'The main title is required for this page.',
subTitle: 'Sub title',
'subTitle-desc': 'This is the sub title of the page.',
}
};
The localizations are applied by using the syntax #{area alias}_{key alias}
.
Create a Document Type with template called #contentTypes_article
with alias: articlePage
.
Under the newly created Document Type follow these steps:
Name the description to #contentTypes_article-desc
.
Create a new tab called #tabs_content
.
Add a new group called #groups_titles
.
Add a property called #properties_title
with alias title
.
Set description to {#properties_title-desc}
.
Use a TextString
editor.
Enable to Set this field as mandatory
.
Under validation add #properties_title-message
.
Add a property called #properties_subTitle
with alias subTitle
.
Set description to {#properties_subTitle-desc}
.
Use a TextString
editor.
Enable Allow at root
in the Structure tab.
When creating and editing the content, you will see that the backoffice now uses the configured localizations.
Create a new "Article" content:
When trying to save the content without adding the mandatory content, you will see a warning as expected:
In some cases, you might need to install Umbraco instances automatically without having to run through the installation wizard to configure the instance.
You can use the Unattended installs feature to allow for quick installation and set up of Umbraco instances on something like Azure Web Apps.
This article will give you the details you need to install Umbraco unattended.
In order to get a clean instance of Umbraco, follow our installation guide for how to .
As you will not be running through the installation wizard when using this feature, you need to manually tell Umbraco which database to use.
Set up and configure a new database - see for details.
Add the connection string using configuration.
A value is configured for the keyumbracoDbDSN_ProviderName
to ensure usage of the Microsoft.Data.SQLite
ADO.NET provider.
It is recommended that you make use of the values shown below for the Cache
, Foreign Keys
and Pooling
keywords on your connection string.
The unattended installs feature is disabled by default. In order to enable it, you need to add the following JSON object to a JSON configuration source.
Remember to set the value of InstallUnattended
to true
.
Alternatively you may set your configuration with Environment Variables or other means. Learn more about this in the .
The keys for this would then be as follows:
After completing the steps above you can now initialize the installation by booting up the Umbraco instance.
Once it has completed, you should see the following when visiting the frontend of the site.
Depending on your preferences, you can use any type of configuration to specify the connection string and login information, as well as enable unattended install. With the extending configuration functionality, it is possible to read from all kinds of sources. One example can be using a JSON file or environment variables.
Program.cs has a condition, which if met, an appsettings.Local.json file will be added and configured as a configuration source.
Having intellisense will help you to add your connection string and information needed for the unattended install.
We have added support for unattended installs with Name, Email and Password, and Connection String as CLI params, which are also available in Visual Studio. There you can fill in your information as follows:
Learn how to upgrade your Umbraco 8 project to Umbraco 10.
It is currently not possible to upgrade directly from Umbraco 8 to the latest version.
The recommended approach for upgrading from version 8 to the latest version is to use this guide to upgrade from Umbraco 8 to Umbraco 10. Umbraco 10 contains the that must be upgraded from Umbraco 8. You can then use the steps to upgrade from Umbraco 10 to the latest version.
Since the underlying framework going from Umbraco 8 to the latest version has changed, there is no direct upgrade path. That said, it is possible to re-use the database from your Umbraco 8 project on your new project in order to maintain the content.
It is not possible to migrate the custom code as the underlying web framework has been updated from ASP.NET to ASP.NET Core. All templates and custom code will need to be reimplemented.
You also need to make sure that the packages you are using are available on the latest version.
A Umbraco 8 project running the latest version of Umbraco 8.
A backup of your Umbraco 8 project database.
A clean installation of the latest version of Umbraco.
The video below shows how to complete the upgrade on an Umbraco Cloud project. Most of the process is the same, however, the video does contain some Cloud-specific elements.
If you use Umbraco Forms, make sure to have to True
before step 1.
Create a backup of the database from your Umbraco 8 project (after you have upgraded to the latest version of v8). For this, you can use the .
Import the database backup into SQL Server Management Studio.
Update the connection string in the new projects appsettings.json
file so that it connects to the Umbraco 8 database:
Run the new project and login to authorize the upgrade.
Select "Upgrade" when the upgrade wizard appears.
Once the upgrade has been completed, it's recommended to login to the backoffice to verify if your project is upgraded to new version.
This is only content migration and the database will be migrated.
You need to manually update the view files and custom code implementation. For more information, see Step 3 of this guide.
The following files/folders need to be copied from the Umbraco 8 project into the new project:
~/Views
- Do not overwrite the default Macro and Partial View Macro files unless changes have been made to these.
~/Media
- Media folder from v8 needs to be copied over into the wwwroot - media
folder
Any files/folders related to Stylesheets and JavaScript.
Migrate custom configuration from the Umbraco 8 configuration files (.config
) into the appsettings.json
file on the new project.
As of Umbraco version 9, the configuration no longer lives in the Web.Config
file and has been replaced by the appsettings.json
file. Learn more about this in the article.
, if relevant.
As of Umbraco Forms version 9, it is only possible to store Forms data in the database. If Umbraco Forms was used on the Umbraco 8 project, the files need to be migrated to the database.
Run the new project.
It will give you an error screen on the frontend as none of the Template files have been updated. Follow Step 3 to resolve the errors.
The latest version of Umbraco is different from Umbraco 8 in many ways. With all the files and data migrated it is now time to rewrite and re-implement all custom code and templates.
One of the changes is how published content is rendered through Template files. Due to this, it will be necessary to update all the Template files (.cshtml
) to reflect these changes.
Read more about these changes in the section of the Umbraco CMS documentation.
Template files need to inherit from Umbraco.Cms.Web.Common.Views.UmbracoViewPage<ContentModels.HomePage>
instead of Umbraco.Web.Mvc.UmbracoViewPage<ContentModels.HomePage>
Template files need to use ContentModels = Umbraco.Cms.Web.Common.PublishedModels
instead of ContentModels = Umbraco.Web.PublishedModels
Depending on the extent of the project and the amount of custom code and implementations, this step is going to require a lot of work.
Once the new project runs without errors on a local setup it is time to deploy the website to production.
This concludes this tutorial. Find related information and further reading in the section below.
This article provides details on how to upgrade to the next minor version when using Umbraco 7.
Sometimes there are exceptions to these guidelines, which are listed in the .
It is necessary to run the upgrade installer on each environment of your Umbraco site. If you want to update your staging and live site then you need to repeat the steps below and make sure that you click through the install screens to complete the upgrade.
In this article you will find instructions for 2 different ways of upgrading:
Open up the Package Console and type: Update-Package UmbracoCms
Choose "No to All" by pressing the "L" when prompted.
If there are any specific configuration changes required for the version you are upgrading to then they will be noted in the .
Alternatively, you can use the Visual Studio NuGet Package Manager to upgrade:
Open the NuGet Package Manager and select the Updates pane to get a list of available updates.
Choose the package called UmbracoCms and select update.
The upgrade will run through all the files and make sure you have the latest changes while leaving the files you have updated.
If you're not upgrading to 7.2.0 or higher then you should follow these extra instructions. If you are upgrading to 7.2.0+ then you can skip this and go to .
You will be asked to overwrite your web.config file and the files in /config, make sure to answer No to those questions.
For some inexplicable reason, the installation will fail if you click "No to All" (in the GUI) or answer "L" (in the package manager console) to the question: "File 'Web.config' already exists in project 'MySite'. Do you want to overwrite it?" So make sure to only answer "No" (in the GUI) or "N" (in the package manager console).
We will overwrite the web.config
file. We'll back it up so don't worry. You can find the backup in App_Data\NuGetBackup\20140320-165450\
. The 20140320-165450
bit is the date and time when the backup occurred, which varies. You can then merge your config files and make sure they're up to date.
Download the .zip file for the new version you are upgrading to from
Copy the following folders from inside the .zip file over the existing folders in your site:
/bin
/Umbraco
/Umbraco_Client
You can expect some changes to the following configuration files:
Any file in the /Config
folder
The /Global.asax
file
The web.config
file in the root of your site (Important: make sure to copy back the version number, and the connection string as they were.)
In rare cases, the web.config
file in the Views folder
Use a tool like to check changes between all of the config files. Depending on when you last did this there may have been updates to a few of them.
There's also the possibility that files in the /Config
folder are new or have been removed(we note this in the release notes). WinMerge (and other diff tools) is able to compare folders as well so you can spot these differences.
Up until version 6.0.0 it was necessary to change the version number in ClientDependency.config
. This was to clear the cached HTML/CSS/JS files in the backoffice. Change the current version number to one that's higher than that. Make sure not to skip this step as you might get strange behavior in the backoffice otherwise.
Some packages (like Contour and Umbraco Forms) add dialogs to the UI.xml
. Make sure to merge those changes back in from your backup during the upgrade so that the packages continue to work. This file can be found in: /Umbraco/Config/Create/UI.xml
.
Packages like Contour, Umbraco Forms, and Courier also make changes to the language files located in: /Umbraco/Config/Lang/*.xml
(typically en.xml
).
After copying the files and making the config changes, you can open your site. You should see the installer which will guide you through the upgrade.
The installer will do two things:
Update the version number in the web.config
Upgrade your database in case there are any changes
We are aware that, currently, the installer is asking you for the database details of a blank database while upgrading. In the near future this will be pre-filled with your existing details and the wording will be updated. So no need to be scared. Enter the details of your existing database and Umbraco will upgrade it to the latest version when necessary.
One important recommendation is to always remove the install
folder immediately after upgrading Umbraco and never to upload it to a live server.
Google Chrome has notoriously aggressive caching. If something doesn't seem to work well in the backoffice, make sure to clear cache and cookies thoroughly (for other browsers as well). Normally the browser cache problem is automatically handled in an Umbraco upgrade by modifying the config/ClientDependency.config version number. If you wish to re-force this update you can increment this version number. This will ensure that any server-side cache of JavaScript and stylesheets gets cleared as well.
One way to nudge the cache in Chrome is to open the developer tools (F12) and go to the settings (the cog icon). There will be a checkbox that says "Disable cache (while DevTools is open)". Once this checkbox is on you can refresh the page and the cache should be invalidated. To force it even more, the "reload" button next to your address bar now has extra options when you right-click it. It should have "Normal reload", "Hard reload" and "Empty cache and hard reload" now. The last option is the most thorough and you might want to try that.
This section describes best practices with running Umbraco on Azure Web Apps
They have been called a few names in the past, many people still know Azure Web Apps as Azure Web Sites.
App Service is a fully Managed Platform for professional developers that brings a rich set of capabilities to web, mobile and integration scenarios. Quickly create and deploy mission critical web Apps that scale with your business by using Azure App Service.
Umbraco will run on Azure Web Apps but there are some configuration options and specific Azure Web Apps environment limitations to be aware of.
You need to add these configuration values. E.g in a json configuration source like appSettings.json
:
You can also copy the following JSON directly into your Azure Web App configuration via the Advanced Edit feature.
Remember to add an ASPNETCORE_ENVIRONMENT
variable with values Development
, Staging
, or Production
.
The minimum recommended Azure SQL Tier is "S2", however noticeable performance improvements are seen in higher Tiers
If you are load balancing or require the scaling ("scale out") ability of Azure Web Apps then you need to consult the . This is due to the fact that a lot more needs to be configured to support scaling/auto-scaling.
It is important to know that Azure Web Apps uses a remote file share to host the files to run your website. This is due to the files running your website do not exist on the machine running your website. In many cases this isn't an issue. It can become one if you have a large amount of IO operations running over remote file-share.
Although Umbraco can be configured to use environmental storage it still requires its working-directory to be writable. If Umbraco is deployed to a read-only file system it will .
For example, Azure's is not supported by Umbraco. To check if your web app is using this feature you can check the WEBSITE_RUN_FROM_PACKAGE
environment variable.
If you require the scaling ("scale out") ability of Azure Web Apps you need to consult the . This is due to the fact that a lot more needs to be configured to support scaling/auto-scaling.
It's important to know that Azure Web Apps may move your website between their 'workers' at any given time. This is normally a transparent operation. In some cases you may be affected by it if any of your code or libraries use the following variables:
Environment.MachineName
(or equivalent)
When your site is migrated to another worker, these variables will change. You cannot rely on these variables remaining static for the lifetime of your website.
The quickest way to get to your logs is using the following URL template and replacing {app}
with your Web App name:
https://{app}.scm.azurewebsites.net/api/logstream
You can also find this in the KUDU console by clicking Advanced Tools > Log Stream on the Web App in the Azure Portal.
Consult the if you would like to directly reference Azure Key Vault Secrets to your Azure Web App.
Ensure you read the and general documentation before you begin - you will need to ensure that your ASP.NET Core & logging configurations are correct.
2 x App service plans with 1 x web app in each:
One for the backoffice (Administrative) environment
One for your scalable public-facing environment (Public)
1 x SQL server that is shared with these 2 web apps
The setup above will allow for the proper scaling of the Administrative and Public web apps.
The App Service plan with the Administrative web app should only be scaled up. The reason for this is that the web app needs to stay as a single instance.
The App Service plan with the Public web app can be scaled both out and up.
The single instance Backoffice Administrative Web App should be set to use .
The multi-instance Scalable Public Web App should be set to use .
When an instance of Umbraco starts up it generates some 'temporary' files on disk. In a normal IIS environment, these would be created within the folders of the Web Application. In an Azure Web App, we want these to be created in the local storage of the actual server that Azure happens to be used for the Web App. So we set this configuration setting to 'true' and the temporary files will be located in the environment temporary folder. This is required for both the performance of the website as well as to prevent file locks from occurring due to the nature of Azure Web Apps shared files system.
Umbraco runs within a .
When a host restarts, the current host 'winds down' while another host is started. This means there can be more than one live host during a restart. Restarts can occur in many scenarios including when an Azure Web App auto-transitions between hosts, you scale the instances or you utilize slot swapping.
Some file system based services in Umbraco such as the Published Cache and Lucene files can only be accessed by a single host at once. Umbraco manages this synchronization by an object called IMainDom
.
By default Umbraco v9.4 & 9.5 uses a system-wide semaphore locking mechanism. This mechanism only works on Windows systems and doesn't work with multi-instance Azure Web Apps. We need to swap it out for an alternative file system based locking mechanism by using the following appSetting. With Umbraco v10+ FileSystemMainDomLock
is the default setting.
Apply this setting to both the SCHEDULINGPUBLISHER Administrative server and the SUBSCRIBER scalable public-facing servers.
You can also copy the following JSON directly into your Azure Web App configuration via the Advanced Edit feature.
Create an Azure SQL database
Install Umbraco on your backoffice administrative environment and ensure to use your Azure SQL Database
Install Umbraco on your scalable public-facing environment and ensure to use your Azure SQL Database
Test: Perform some content updates on the administrative environment, ensure they work successfully in that environment, then verify that those changes appear on the scalable public-facing environment
Fix the backoffice environment to be the SCHEDULINGPUBLISHER scheduling server and the scalable public-facing environment to be SUBSCRIBERs - see
Do not scale your backoffice administrative environment this is not supported and can cause issues.
The public-facing subscriber Azure Web Apps can be manually or automatically scaled up or down and is supported by Umbraco's load balancing.
Since you have 2 x web apps, when you deploy you will need to deploy to both places - There are various automation techniques you can use to simplify the process. That is outside the scope of this article.
Schema Alias: Umbraco.Slider
UI Alias: Umb.PropertyEditorUi.Slider
Returns: decimal
or Umbraco.Core.Models.Range<decimal>
Pretty much like the name indicates this Data type enables editors to choose a value with a range using a slider.
There are two flavors of the slider. One with a single value picker. One with a minimum and maximum value.
See the example below to see how a value can be added or changed programmatically. To update a value of a property editor you need the .
Although the use of a GUID is preferable, you can also use the numeric ID to get the page:
If Models Builder is enabled you can get the alias of the desired property without using a magic string:
Members are used for registering and authentication external / frontend users of an Umbraco installation. This could be Forum members and Intranet members.
Members are used for registering and authenticating external users of an Umbraco installation (ie. forum members, intranet users and so forth).
This guide will explain how to define and create members in the backoffice. If you want to work with members using the service APIs, links can be found at the end of the document.
There is a default Member Type that can be used to create members. You can customize this to fit your needs or create your own Member Type from scratch.
Go to the Members section and click Create.
Members have a number of mandatory properties that need to be filled in before a member can be saved. Some of the properties are Username, Email, two Password fields and so on.
There are also a number of default properties which are stored in the database in the tables Member
andTwoFactorLogin
:
umbracoMemberFailedPasswordAttempts
umbracoMemberApproved
umbracoMemberLockedOut
umbracoTwoFactorLogin
umbracoMemberLastLockoutDate
umbracoMemberLastLogin
umbracoMemberLastPasswordChangeDate
Once the Member is created and saved you can access it by expanding the Members tree and clicking All Members to get a collection. You can also view members of a specific type by selecting the member type in the Members tree.
Sensitive properties on a members data will not be displayed to backoffice users unless they have appropriate permissions. In order to see the values of the default properties in the Member tab you need to have the Sensitive data User Group. By having this group added to a user they will also have the option to mark member type properties as sensitive.
More information can be found under .
You can create your own Member Types and add tabs, groups and properties as you would with Document Types.
Go to the Settings section, click ... next to Member Types and select Create. You will now be taken to the Member Type editor that is used to define and edit the Member Type. Name the new Member Type and click Save.
Once created, the Member Type will have no properties, so you have the freedom to add your own properties or compositions.
When creating a Member Type you can assign compositions. Compositions allow you to inherit tabs and properties from existing member types instead of creating them from scratch.
For example on the member type that you have created, click on Composition. Then you can choose the existing Member type which then you will inherit its tabs, groups, and properties.
The default Member type has a Membership group which includes umbracoMemberComments
property along with the other default properties. The other properties can be seen only in the Member tab when creating a member.
It is possible to add more groups and more properties to each of the Member Types you create, as well as the default Member Type.
Member Groups define roles for your members that can be used for role-based protection. A member can be in multiple groups.
To create a new Member Group click the menu icon next to the Member Groups node in the Members section. Choose Create, name the group, and save the group.
To assign a member to a specific group find the member you wish to assign and find the Properties group. Here you can see which groups the member is already part of. You can also add the member to more groups or remove the member from already assigned groups:
As a developer you are able to leverage your website when you build on the Members section of Umbraco. The member's section is by default in the Umbraco backoffice, but you can still use it to implement some work on your front end. Members are created using ASP.NET Core Identity, so there are some provider settings that can be set in appsettings.json - here are the defaults:
You can find out more about the services methods in the reference section of the documentation by following the links below.
Video:
Video:
Video:
Schema Alias: Umbraco.TrueFalse
UI Alias: Umb.PropertyEditorUi.Toggle
Returns: Boolean
Toggle is a standard checkbox which saves either 0 or 1, depending on the checkbox being checked or not.
The Toggle property has a setting which allows you to set the default value of the checkbox, either checked (true) or unchecked (false).
It is also possible to define a label, that will be displayed next to the checkbox on the content.
See the example below to see how a value can be added or changed programmatically. To update a value of a property editor you need the .
Although the use of a GUID is preferable, you can also use the numeric ID to get the page:
If Models Builder is enabled you can get the alias of the desired property without using a magic string:
{
"ConnectionStrings": {
"umbracoDbDSN": "server=localhost;database=UmbracoUnicore;user id=sa;password='P@ssw0rd'",
"umbracoDbDSN_ProviderName": "System.Data.SqlClient"
}
}
{
"ConnectionStrings": {
"umbracoDbDSN": "Data Source=|DataDirectory|/Umbraco.sqlite.db;Cache=Private;Foreign Keys=True;Pooling=True",
"umbracoDbDSN_ProviderName": "Microsoft.Data.Sqlite"
}
}
{
"Umbraco": {
"CMS": {
"Unattended": {
"InstallUnattended": true,
"UnattendedUserName": "FRIENDLY_NAME",
"UnattendedUserEmail": "EMAIL",
"UnattendedUserPassword": "PASSWORD"
}
}
}
}
Umbraco__CMS__Unattended__InstallUnattended
Umbraco__CMS__Unattended__UnattendedUserName
Umbraco__CMS__Unattended__UnattendedUserEmail
Umbraco__CMS__Unattended__UnattendedUserPassword
#if DEBUG
.ConfigureAppConfiguration(config
=> config.AddJsonFile(
"appsettings.Local.json",
optional: true,
reloadOnChange: true))
#endif
{
"ConnectionStrings": {
"umbracoDbDSN": "server=localhost;database=UmbracoUnicore;user id=sa;password='P@ssw0rd'"
},
"Umbraco": {
"CMS": {
"Unattended": {
"InstallUnattended": true,
"UnattendedUserName": "FRIENDLY_NAME",
"UnattendedUserEmail": "EMAIL",
"UnattendedUserPassword": "PASSWORD"
}
}
}
}
dotnet new umbraco -n MyNewProject --friendly-name "Friendly User" --email [email protected] --password password1234 --connection-string "Server=(localdb)\Umbraco;Database=MyDatabase;Integrated Security=true" --version 10.0.0
{
"Umbraco": {
"CMS": {
"Examine": {
"LuceneDirectoryFactory" : "TempFileSystemDirectoryFactory"
}
}
}
}
{
"Umbraco": {
"CMS": {
"Hosting": {
"LocalTempStorageLocation" : "EnvironmentTemp"
}
}
}
}
{
"Umbraco": {
"CMS": {
"Global": {
"MainDomLock" : "FileSystemMainDomLock"
}
}
}
}
{
"name": "UMBRACO__CMS__Global__MainDomLock",
"value": "FileSystemMainDomLock",
"slotSetting": false
},
{
"name": "UMBRACO__CMS__Hosting__LocalTempStorageLocation",
"value": "EnvironmentTemp",
"slotSetting": false
},
{
"name": "UMBRACO__CMS__Examine__LuceneDirectoryFactory",
"value": "TempFileSystemDirectoryFactory",
"slotSetting": false
}
@if (Model.HasValue("singleValueSlider"))
{
var value = Model.Value<decimal>("singleValueSlider");
<p>@value</p>
}
@if (Model.HasValue("multiValueSlider"))
{
var value = Model.Value<Umbraco.Cms.Core.Models.Range<decimal>>("multiValueSlider");
<p>@(value.Minimum) and @(value.Maximum)</p>
}
// with a range off
@if (Model.SingleValueSlider != null)
{
var value = Model.SingleValueSlider;
<p>@value</p>
}
// with a range on
@if (Model.MultiValueSlider != null)
{
var minValue = Model.MultiValueSlider.Minimum;
var maxValue = Model.MultiValueSlider.Maximum;
<p>@minValue and @maxValue</p>
}
@using Umbraco.Cms.Core.Services
@inject IContentService ContentService
@{
// Create a variable for the GUID of the page you want to update
var guid = Guid.Parse("32e60db4-1283-4caa-9645-f2153f9888ef");
// Get the page using the GUID you've defined
var content = ContentService.GetById(guid); // ID of your page
// Set the value of the property with alias 'singleValueSlider'.
content.SetValue("singleValueSlider", 10);
// Save the change
ContentService.Save(content);
}
@using Umbraco.Cms.Core.Models
@using Umbraco.Cms.Core.Services
@inject IContentService ContentService
@{
// Create a variable for the GUID of the page you want to update
var guid = Guid.Parse("32e60db4-1283-4caa-9645-f2153f9888ef");
// Get the page using the GUID you've defined
var content = ContentService.GetById(guid); // ID of your page
// Create a variable for the desired value of the 'multiValueSlider' property
var range = new Range<decimal> {Minimum = 10, Maximum = 12};
// Set the value of the property with alias 'multiValueSlider'.
content.SetValue("multiValueSlider", range);
// Save the change
ContentService.Save(content);
}
@{
// Get the page using it's id
var content = ContentService.GetById(1234);
}
@using Umbraco.Cms.Core.PublishedCache
@inject IPublishedContentTypeCache PublishedContentTypeCache
@{
// Set the value of the property with alias 'singleValueSlider'
content.SetValue(Home.GetModelPropertyType(PublishedContentTypeCache, x => x.SingleValueSlider).Alias, 10);
// Set the value of the property with alias 'multiValueSlider'
content.SetValue(Home.GetModelPropertyType(PublishedContentTypeCache, x => x.MultiValueSlider).Alias, new Range<decimal> {Minimum = 10, Maximum = 12});
}
{
"$schema": "appsettings-schema.json",
"Umbraco": {
"CMS": {
"Security": {
"AllowPasswordReset": true,
"AuthCookieDomain": "(No default, but takes a string)",
"AuthCookieName": "UMB_UCONTEXT",
"KeepUserLoggedIn": false,
"UsernameIsEmail": true,
"HideDisabledUsersInBackoffice": false,
"AllowedUserNameCharacters": "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+\\",
"MemberPassword": {
"RequiredLength": 10,
"RequireNonLetterOrDigit": false,
"RequireDigit": false,
"RequireLowercase": false,
"RequireUppercase": false,
"MaxFailedAccessAttemptsBeforeLockout": 5,
"HashAlgorithmType": "HMACSHA256"
}
}
}
}
}
@{
if (!Model.Value<bool>("myCheckBox"))
{
<p>The Checkbox is not checked!</p>
}
}
@{
if (!Model.MyCheckbox)
{
<p>The Checkbox is not checked!</p>
}
}
@using Umbraco.Cms.Core.Services
@inject IContentService ContentService
@{
// Create a variable for the GUID of the page you want to update
var guid = new Guid("796a8d5c-b7bb-46d9-bc57-ab834d0d1248");
// Get the page using the GUID you've defined
var content = ContentService.GetById(guid); // ID of your page
// Set the value of the property with alias 'myCheckBox'
content.SetValue("myCheckBox", true);
// Save the change
ContentService.Save(content);
}
@{
// Get the page using it's id
var content = ContentService.GetById(1234);
}
@using Umbraco.Cms.Core.PublishedCache
@inject IPublishedContentTypeCache PublishedContentTypeCache
@{
// Set the value of the property with alias 'myCheckBox'
content.SetValue(Home.GetModelPropertyType(PublishedContentTypeCache, x => x.MyCheckBox).Alias, true);
}
"ConnectionStrings": {
"umbracoDbDSN": "Server=YourLocalSQLServerHere;Database=NameOfYourDatabaseHere;User Id=NameOfYourUserHere;Password=YourPasswordHere;TrustServerCertificate=True"
}
{
"Umbraco": {
"CMS": {
"Global": {
"MainDomLock" : "FileSystemMainDomLock"
},
"Hosting": {
"LocalTempStorageLocation": "EnvironmentTemp"
},
"Examine": {
"LuceneDirectoryFactory": "SyncedTempFileSystemDirectoryFactory"
}
}
}
}
{
"name": "UMBRACO__CMS__Global__MainDomLock",
"value": "FileSystemMainDomLock",
"slotSetting": false
},
{
"name": "UMBRACO__CMS__Hosting__LocalTempStorageLocation",
"value": "EnvironmentTemp",
"slotSetting": false
},
{
"name": "UMBRACO__CMS__Examine__LuceneDirectoryFactory",
"value": "SyncedTempFileSystemDirectoryFactory",
"slotSetting": false
}
Information on using the Umbraco log viewer
Umbraco ships with a built-in Log Viewer feature. This allows you to filter, view log entries, perform complex search queries, and analyze logs for debugging. You can find the Log viewer in the Settings section of the Umbraco backoffice.
Ever needed to find all log entries containing the same request ID? Or locate all logs where a property called Duration
exceeds 1000ms?
With structured logging and a query language, you can efficiently search and identify log items for specific scenarios. This helps in debugging and finding patterns in your logs, making it easier to resolve issues.
Here are some example queries to help you get started. For more details on the syntax, see the https://github.com/serilog/serilog-filters-expressions project.
Find all logs that are from the namespace 'Umbraco.Core'StartsWith(SourceContext, 'Umbraco.Core')
Find all logs that have the property 'Duration' and the duration is greater than 1000msHas(Duration) and Duration > 1000
Find all logs where the message has localhost in it with SQL like@Message like '%localhost%'
If you frequently use a custom query, you can save it for quick access. Type your query in the search box and click the heart icon to save it with a friendly name. Saved queries are stored in the umbracoLogViewerQuery
table in the database.
Umbraco allows you to implement a customn ILogViewer
to fetch logs from alternative sources, such as Azure Table Storage.
To fetch logs from Azure Table Storage, implement the SerilogLogViewerSourceBase
class from Umbraco.Cms.Core.Logging.Viewer
.
using Azure;
using Azure.Data.Tables;
using Serilog.Events;
using Serilog.Formatting.Compact.Reader;
using Serilog.Sinks.AzureTableStorage;
using Umbraco.Cms.Core.Logging.Viewer;
using ITableEntity = Azure.Data.Tables.ITableEntity;
namespace My.Website;
public class AzureTableLogViewer : SerilogLogViewerSourceBase
{
public AzureTableLogViewer(ILogViewerConfig logViewerConfig, Serilog.ILogger serilogLog, ILogLevelLoader logLevelLoader)
: base(logViewerConfig, logLevelLoader, serilogLog)
{
}
public override bool CanHandleLargeLogs => true;
// This method will not be called - as we have indicated that this 'CanHandleLargeLogs'
public override bool CheckCanOpenLogs(LogTimePeriod logTimePeriod) => throw new NotImplementedException();
protected override IReadOnlyList<LogEvent> GetLogs(LogTimePeriod logTimePeriod, ILogFilter filter, int skip, int take)
{
//Replace ACCOUNT_NAME and KEY with your actual Azure Storage Account details. The "Logs" parameter refers to the table name where logs will be stored and retrieved from.
var client =
new TableClient(
"DefaultEndpointsProtocol=https;AccountName=ACCOUNT_NAME;AccountKey=KEY;EndpointSuffix=core.windows.net",
"Logs");
// Table storage does not support skip, only take, so the best we can do is to not fetch more entities than we need in total.
// See: https://learn.microsoft.com/en-us/rest/api/storageservices/writing-linq-queries-against-the-table-service#returning-the-top-n-entities for more info.
var requiredEntities = skip + take;
IEnumerable<AzureTableLogEntity> results = client.Query<AzureTableLogEntity>().Take(requiredEntities);
return results
.Skip(skip)
.Take(take)
.Select(x => LogEventReader.ReadFromString(x.Data))
// Filter by timestamp to avoid retrieving all logs from the table, preventing memory and performance issues
.Where(evt => evt.Timestamp >= logTimePeriod.StartTime.Date &&
evt.Timestamp <= logTimePeriod.EndTime.Date.AddDays(1).AddSeconds(-1))
.Where(filter.TakeLogEvent)
.ToList();
}
public override IReadOnlyList<SavedLogSearch>? GetSavedSearches()
{
//This method is optional. If you store saved searches in Azure Table Storage, implement fetching logic here.
return base.GetSavedSearches();
}
public override IReadOnlyList<SavedLogSearch>? AddSavedSearch(string? name, string? query)
{
//This method is optional. If you store saved searches in Azure Table Storage, implement adding logic here.
return base.AddSavedSearch(name, query);
}
public override IReadOnlyList<SavedLogSearch>? DeleteSavedSearch(string? name, string? query)
{
//This method is optional. If you store saved searches in Azure Table Storage, implement deleting logic here.
return base.DeleteSavedSearch(name, query);
}
}
public class AzureTableLogEntity : LogEventEntity, ITableEntity
{
public DateTimeOffset? Timestamp { get; set; }
public ETag ETag { get; set; }
}
Azure Table Storage requires entities to implement the ITableEntity
interface. Since Umbraco’s default log entity does not implement this, a custom entity (AzureTableLogEntity
) must be created to ensure logs are correctly fetched and stored.
Umbraco needs to be made aware that there is a new implementation of an ILogViewer
to register. We also need to replace the default JSON LogViewer that we ship in the core of Umbraco.
using Umbraco.Cms.Core.Composing;
using Umbraco.Cms.Infrastructure.DependencyInjection;
namespace My.Website;
public class LogViewerSavedSearches : IComposer
{
public void Compose(IUmbracoBuilder builder) => builder.SetLogViewer<AzureTableLogViewer>();
}
With the above two classes, the setup is in place to view logs from an Azure Table. However, logs are not yet persisted into the Azure Table Storage account. To enable persistence, configure the Serilog logging pipeline to store logs in Azure Table Storage.
Install Serilog.Sinks.AzureTableStorage
from NuGet.
Add a new sink to appsettings.json
with credentials to persist logs to Azure.
The following sink needs to be added to the Serilog:WriteTo
array.
{
"Name": "AzureTableStorage",
"Args": {
"storageTableName": "LogEventEntity",
"formatter": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact",
"connectionString": "DefaultEndpointsProtocol=https;AccountName=ACCOUNT_NAME;AccountKey=KEY;EndpointSuffix=core.windows.net"}
}
For more in-depth information about logging and how to configure it, see the Logging article.
Compact Log Viewer. A desktop tool is available for viewing and querying JSON log files in the same way as the built-in Log Viewer in Umbraco.
Creating Dictionary Items in Umbraco
Depending on how your site is set up, not all content is edited through the Content section. There might be some text in your templates that needs translation. Using Dictionary Items, you can store a value for each language. Dictionary Items have a unique key that is used to fetch the value of the Dictionary Item.
Dictionary Items can be managed from the Translation section. Let's take a look at an example. In this example, we will translate "Welcome to Umbraco" from within the template and add it to the dictionary:
To add a Dictionary Item:
Go to the Translation section.
Click on Dictionary in the Translation tree and select Create.
Enter the Name for the dictionary item. Let's say Welcome.
Enter the values for the different language versions.
Click Save.
To group dictionary items:
Go to the Translation section.
Click on Dictionary in the Translation tree and select Create.
Enter the Name for the dictionary item. Let's say Contact.
Click Create.
Click on Contact and select Create.
Enter the Name of the item to be created under the Contact group.
Click Create.
Enter the values for the different language versions.
Click Save.
To edit a dictionary item, follow these steps:
Go to the Translation section.
Use the Dictionary tree to locate the item you need to update/edit.
Alternatively, you can use the search field in the top-right corner.
Make the edits you need to make.
Click Save to save the changes.
To fetch dictionary values in the template, replace the text with the following snippet:
@Umbraco.GetDictionaryValue("Welcome")
Alternatively, you can specify an altText
which will be returned if the dictionary value is empty.
@Umbraco.GetDictionaryValueOrDefault("Welcome", "Another amazing day in Umbraco")
In some cases, you might want to use the same Dictionary Items on multiple Umbraco websites. For this, you can use the export and import functionality to quickly copy the items from one website to another.
Go to the Translation section in the Umbraco backoffice.
Locate the Dictionary Item (or group) you want to copy in the section tree.
Click ... next to the Dictionary item (or group).
Select Export....
Decide whether you want to also include descendants.
Click Export.
This will download a .udt
file which you can use to import the Dictionary items on another Umbraco website.
Go to the Translation section in the Umbraco backoffice.
Click ... next to the Dictionary tree.
Select Import....
Click on Import.
Find and select the .udt
file containing the Dictionary Items.
Click Open in the file browser.
Review the Dictionary Items for import.
Choose where to import the items.
Click on Import.
The Dictionary Items have now been added to your website.
To use Dictionary Items in a multilingual website, see the Creating a Multilingual Site article.
We have made custom Umbraco templates that are available for use with dotnet new
. The steps below will demonstrate the minimum amount of actions required to get you going and set up an Umbraco project from the command line using .NET templates.
Install the latest .
Run dotnet new install Umbraco.Templates
to install the project templates.The solution is packaged up into the NuGet package and can be installed into the dotnet CLI.
To get help on a project template with dotnet new
run the following command:
dotnet new umbraco -h
From that command's output, you will get a better understanding of what are the default template options, as well as those command-line flags specific to Umbraco that you can use (as seen below):
Create a new empty Umbraco solution:
dotnet new umbraco -n MyCustomUmbracoProject
You will now have a new project with the name MyCustomUmbracoProject, or the name you chose to use. The new project can be opened and run using your favorite IDE or you can continue using the CLI commands.
Navigate to the newly created project folder:
cd MyCustomUmbracoProject
Build and run the new Umbraco .Net Core project:
dotnet build
dotnet run
The project is now running on the and has assigned a free available port to run it on. Look in the terminal window after the dotnet run
command to see the URLs.
The next step is to run through the Umbraco CMS installation. If you chose to use MS SQL Server/Azure you will need to add your connection string during this setup process to get access to the Umbraco backoffice.
Learn more about the Umbraco backoffice which is the admin side of your Umbraco website
In this article you can learn more about the common terms and concepts that are used throughout the Umbraco backoffice.
When you go to the backoffice for the first time, you're presented with the login screen.
.
A section in Umbraco is where you do specific tasks related to that section. For example Content, Settings and Users. You can navigate between the different sections of the backoffice by clicking the corresponding icon in the section menu.
The Section menu is the horizontal menu located on the top of the backoffice.
.
A tree is a hierarchical list of items related (and usually restricted) to a specific concept, like for example content or media.
You can expand trees by clicking the side arrow to the left of the node.
A node is an item in a tree. Media section items appear as nodes in the Media tree, while pages and content are displayed in the Content tree, and so on.
A dashboard is the main view you are presented with when entering a section within the backoffice. It can be used to show valuable information to the users of the system.
An editor is what you use to edit different items within the backoffice. There are editors specific to editing stylesheets, there are editors for editing Partial Views, and so forth.
Content is what you find in the Content section. Each item in the tree is called a content node. Each content node in the content tree consists of different fields, and each of them is defined by a Document Type.
Document Types define the types of content nodes that backoffice users can create in the content tree. Each Document Type contains different properties. Each property has a specific Data Type for example text or number.
Every Document Type has properties. These are the fields that the content editor is allowed to edit for the content node.
Each Document Type property has a Data Type that defines the type of input of that property. Data Types reference a Property Editor and are configured in the Umbraco backoffice in the Settings section. A Data Type can be something basic (text string, number, true/false) or more complex (multi-node tree picker, image cropper, etc).
A property editor is a view used by Data Types to insert content into Umbraco. An example of a property editor is the Textarea. It's possible to have many Textarea Data Types with different settings that all use the Textarea property editor.
Media items are used to store assets like images and video within the Media section and can be referenced from your content.
Media Types are similar to Document Types in Umbraco, except they are specifically for media items in the Media section.
Umbraco includes the following default Media Types - Article, Audio, File, Folder, Image, Vector Graphics (SVG), and Video.
A member is someone who has access to signup, register, and login into your public website and is not to be confused with Users.
Similar to a Document Type and a Media Type. You are able to define custom properties to store on a member such as Twitter username or website URL.
A Template is where you define the HTML markup of your website and also where you output the data from your content nodes.
A package is the Umbraco term for an add-on or plugin used to extend the core functionalities in Umbraco. The packages can be found on the , and the can also be browsed directly in the backoffice of the Umbraco CMS.
A user is someone who has access to the Umbraco backoffice and is not to be confused with Members. When Umbraco has been installed a user will automatically be generated with the login (email) and password entered during installation. Users can be created, edited, and managed in the User section.
Document Blueprint provide a blueprint for content nodes based on an existing node.
Schema Alias: Umbraco.MediaPicker3
UI Alias: Umb.PropertyEditorUi.MediaPicker
Returns: IEnumerable<MediaWithCrops>
or MediaWithCrops
This property editors returns one of the following:
A collection (IEnumerable<MediaWithCrops>
) if the Pick multiple items setting is enabled.
A single MediaWithCrops
item if the Pick multiple items setting is disabled.
Use setting to limit the picker to only select Media Items of these types.
Use this setting to enable the property to contain multiple items. When this is enabled the property editor returns an IEnumerable<MediaWithCrops>
.
You can still set the maximum amount to 1. Do so when you want to retrieve a collection but only allow the Content Editors to select one Media Item.
Use this setting to enforce a minimum and/or maximum amount of selected Media Items.
This setting is used to limit the Media Picker to certain parts of the Media Tree.
Use this setting to overrule user permissions, to enable any user of this property to pick any Media Item of the chosen Start node.
When this setting is enabled, a user can access the media available under the selected "Start Node" (/Design in this case). This applies even if they normally lack access. The access is granted specifically when using this particular Media Picker.
Enable the focal point setter, do only enable this if the focal point is used or if you have Image crops defined.
Define local image crops. Local image crop data is stored on the document in this property. This means it can differentiate between documents.
This is different from Global crops as they are defined on the Media Item, making the crops shared between all usage of that Media Item.
Global crops are configured on the Image Cropper property of the Image Media Type
Both local and global crops are retrieved using the method GetCropUrl
. If crops with identical aliases are defined both locally and globally, the locally defined crops are always prioritized by GetCropUrl
.
The following is an example of how to retrieve a crop from a MediaWithCrops
entry:
You can retrieve globally defined crops explicitly by using GetCropUrl
on the UrlHelper
:
See the example below to see how a value can be added or changed programmatically. To update a value of a property editor you need the .
The following sample will update a single image in a Media Picker.
Although the use of a GUID is preferable, you can also use the numeric ID to get the page:
If Models Builder is enabled you can get the alias of the desired property without using a magic string:
Learn how to create, manage, and assign permissions to users in the Umbraco backoffice.
Users are people who have access to the Umbraco backoffice (not to be confused with ). These could include Content Editors, Translators, Web Designers, and Developers.
This guide will walk you through how to create and invite users, manage user profiles, work with User Groups and permissions in the backoffice.
To create or invite a User:
Go to the Users section in the backoffice.
Select Create -> User. Alternatively, click Invite....
Enter the Name and Email of the new user.
Select which User group the new user should be added to.
[Optional] Enter a Message for the invitation.
Click Create user or Send invite.
Once you have created the user, the new user will receive a system-generated password for their initial login. This password needs to be used to access the account.
Open a user’s profile from the Users section to update:
Profile photo.
Email address of the user.
UI Culture (sets the backoffice language of the user account).
User Group (determines the scope of access in the backoffice).
Start nodes for both Content and Media sections to limit access.
When working with multiple users in Umbraco, the user screen provides tools to help you quickly locate and manage users using filters and layout options.
At the top of the Users section, use the search bar to quickly find a user by typing their name or email address.
Use the Status filter to narrow down users based on their current state:
Active – Users who have logged in and are enabled.
Disabled – Users whose access has been explicitly turned off.
Locked out - User has been automatically blocked from logging in after too many failed login attempts.
Invited - User has been invited to access the Umbraco backoffice.
Inactive – Users who haven't logged in or have been disabled.
The Groups filter lets you view users based on the user groups they belong to. For example, Administrators, Editors, Sensitive data, Translators, and Writers.
Use Order by to sort users by:
Name (A–Z)
Name (Z-A)
Newest
Oldest
Last Login
Users are displayed in Grid format by default, showing:
Initials, full name, and group membership.
Login status (for example, “Inactive” label).
Last login time (if applicable).
Click the table/grid icon (top-right corner) to switch to a more compact, column-based layout.
By default, the User Groups available to new users are Administrators, Editors, Sensitive Data, Translators, and Writers.
Administrators: Can do anything when editing nodes in the content section (has all permissions).
Editors: Allowed to create and publish content items or nodes on the website without approval from others or restrictions (has permissions to Public Access, Rollback, Browse Node, Create Content Template, Delete, Create, Publish, Unpublish, Update, Copy, Move and Sort).
Sensitive data: Any users added to this User group will have access to view any data marked as sensitive. Learn more about this feature in the article.
Translators: These are used for translating your website. Translators are allowed to browse and update nodes as well as grant dashboard access. Translations of site pages must be reviewed by others before publication (has permissions to Browse Node and Update).
Writers: Allowed to browse nodes, create nodes, and request for publication of items. Not allowed to publish directly without someone else's approval like an Editor (has permissions to Browse Node, Create, Send to Publish, and Update).
You can also create your own custom User Groups and add properties and tabs as you would with Document Types and Member Types.
Go to the Users section.
Select User Groups.
Click Create.
Enter the information about the User Group and settings for custom properties:
Name: The name of the User Group.
Alias: Used to reference the User Group in code - the alias will be auto-generated based on the name.
Assign access: Define which sections and languages the users will have access to. Also, if the users should have access to only some or all content and media.
Default Permissions: Select the default permissions granted to users of the User Group.
Granular permissions: Define a specific node the users in the group should have access to.
Depending on which User Group a user is added to, each user has a set of permissions associated with their accounts. These permissions either enable or disable a user's ability to perform their associated function.
The available user Permissions are defined under Default Permissions in the User group.
As an addition to the Default Permissions, it is also possible to add more granular permissions on a User Group level.
With the Documents permission, you can define granular permissions on specific documents. This is useful when a User Group should only have limited access to a certain page on the website. Clicking Add opens a dialog where you can choose between documents from the Content section.
With the Document Property Values permission, you can define both read and write permissions for individual properties on a Document Type. This is useful if a User Group should have limited access to edit the content on a specific type of document. Clicking Add opens a dialog where you select a Document Type, choose a Property, and, finally, set the read and write permissions.
When a new user is created, you can set specific permissions for that user on different domains and subdomains. You can also set permissions on different User Groups, even for the default types.
As a developer, you are only able to leverage your website from the backoffice when you build on the Users section of Umbraco. This is because the Users section is restricted to the Umbraco backoffice.
Umbraco Forms has a backoffice security model integrated with Umbraco Users. You can manage the details in the Users section of the backoffice, within a tree named Forms Security.
@using Umbraco.Cms.Core.Models
@{
var typedMultiMediaPicker = Model.Value<IEnumerable<MediaWithCrops>>("medias");
foreach (var entry in typedMultiMediaPicker)
{
<img src="@entry.MediaUrl()" style="width:200px" />
}
}
@using Umbraco.Cms.Core.Models
@{
var listOfImages = Model.Value<IEnumerable<IPublishedContent>>("medias");
foreach (var image in listOfImages)
{
<img src="@image.Url()" alt="@image.Name" />
}
}
@{
var typedMultiMediaPicker = Model.Medias;
foreach (var entry in typedMultiMediaPicker)
{
<img src="@entry.MediaUrl()" style="width:200px" />
}
}
@using Umbraco.Cms.Core.Models
@{
var typedMediaPickerSingle = Model.Value<MediaWithCrops>("media");
if (typedMediaPickerSingle != null)
{
<img src="@typedMediaPickerSingle.MediaUrl()" style="width:200px" alt="@typedMediaPickerSingle.Value("alt")" />
}
}
@using Umbraco.Cms.Core.Models
@{
var typedMediaPickerSingle = Model.Media;
if (typedMediaPickerSingle is MediaWithCrops mediaEntry)
{
<img src="@mediaEntry.MediaUrl()" style="width:200px"/>
}
}
@{
foreach (var entry in Model.Medias)
{
<img src="@entry.GetCropUrl("cropAlias")"/>
}
}
@{
foreach (var entry in Model.Medias)
{
<img src="@Url.GetCropUrl(entry, "cropAlias")"/>
}
}
@using Umbraco.Cms.Core
@using Umbraco.Cms.Core.Services
@inject IContentService ContentService
@{
// Create a variable for the GUID of the page you want to update
var guid = Guid.Parse("32e60db4-1283-4caa-9645-f2153f9888ef");
// Get the page using the GUID you've defined
var content = ContentService.GetById(guid); // ID of your page
// Get the media you want to assign to the media picker
var media = Umbraco.Media("bca8d5fa-de0a-4f2b-9520-02118d8329a8");
// Create an Udi of the media
var udi = Udi.Create(Constants.UdiEntityType.Media, media.Key);
// Set the value of the property with alias 'featuredBanner'.
content.SetValue("featuredBanner", udi.ToString());
// Save the change
ContentService.Save(content);
}
@{
// Get the page using it's id
var content = ContentService.GetById(1234);
}
@using Umbraco.Cms.Core.PublishedCache
@inject IPublishedContentTypeCache PublishedContentTypeCache
@{
// Set the value of the property with alias 'featuredBanner'
content.SetValue(Home.GetModelPropertyType(PublishedContentTypeCache, x => x.FeaturedBanner).Alias, udi.ToString());
}
This article provides details on how to upgrade to the next minor version when using Umbraco 8.
Sometimes there are exceptions to these guidelines, which are listed in the version-specific guide.
It is necessary to run the upgrade installer on each environment of your Umbraco site. If you want to update your staging and live site you need to repeat the steps below. Make sure you click through the install screens so that your upgrade is complete.
In this article you will find instructions for 3 different ways of upgrading:
Open up the Package Console and type: Update-Package UmbracoCms
Choose "No to All" by pressing the "L" when prompted.
If there are any specific configuration changes required for the version you are upgrading to then they will be noted in the version-specific guide.
Alternatively, you can use the Visual Studio NuGet Package Manager to upgrade:
Open the NuGet Package Manager and select the Updates pane to get a list of available updates.
Choose the package called UmbracoCms and select update.
The upgrade will run through all the files and make sure you have the latest changes while leaving files you have updated.
Download the .zip
file for the new version you are upgrading to from https://our.umbraco.com/download
Copy the following folders from inside the .zip
file over the existing folders in your site:
/bin
/Umbraco
You can expect some changes to the following configuration files:
Any file in the /Config
folder
The /Global.asax
file
The web.config
file in the root of your site (Important: make sure to copy back the version number, and the connection string as they were.)
In rare cases, the web.config
file in the /Views
folder
Use a tool like WinMerge to check changes between all of the config files. Depending on when you last did this there may have been updates to few of them.
There's also the possibility that some files in the /Config
folder are new or some have been removed (we do make a note of this in the release notes). WinMerge (and other diff tools) can compare folders as well so you can spot these differences.
Some packages like Umbraco Forms add dialogs to the UI.xml
. Make sure to merge those changes back in from your backup during the upgrade so that the packages continue to work. This file can be found in: /Umbraco/Config/Create/UI.xml
.
Packages like Umbraco Forms and Courier also make changes to the language files located in: /Umbraco/Config/Lang/*.xml
(typically en.xml
).
After copying the files and making the config changes, you can open your site. You should see the installer which will guide you through the upgrade.
The installer will do two things:
Update the version number in the web.config
Upgrade your database in case there are any changes
We are aware that, currently, the installer is asking you for the database details of a blank database while upgrading. In the near future this will be pre-filled with your existing details and the wording will be updated. So no need to be scared. Enter the details of your existing database and Umbraco will upgrade it to the latest version when necessary.
When upgrading your Umbraco project to Umbraco v8.12+ it is possible to enable the upgrade to run unattended. This means that you will not need to run through the installation wizard when upgrading.
Below you will find the steps you need to take in order to upgrade your project unattended.
Add the Umbraco.Core.RuntimeState.UpgradeUnattended
key to appSettings
in your web.config file.
Set the value of the key to true
.
<add key="Umbraco.Core.RuntimeState.UpgradeUnattended" value="true" />
ConfigurationStatus
In order to trigger the actual upgrade, the correct version number needs to be set.
It is important to use the version number of the version that you are upgrading to. If this is not set, the upgrade will not run even if the UpgradeUnattended
key has been set to true
.
Locate the ConfigurationStatus
key in the appSettings
section in your web.config file.
Update the value to match the Umbraco version that you are upgrading to.
<add key="Umbraco.Core.ConfigurationStatus" value="x.x.x"/>
With the correct configuration applied, the project will be upgraded on the next boot.
The Runtime level will use Run
instead of Upgrade
in order to allow the website to continue to boot up directly after the migration is run, instead of initiating the otherwise required restart.
Follow the steps outlined below to use run unattended upgrades in a load balanced setup.
Upgrade Umbraco via NuGet in Visual Studio. Make sure the Umbraco.Core.ConfigurationStatus
key in appSetting
in the web.config
file is updated to match the target version.
Deploy to all environments, including the updated appSetting
for Umbraco.Core.ConfigurationStatus
.
Set the Umbraco.Core.RuntimeState.UpgradeUnattended
key in appSetting
in the web.config
to true
for the Main server only.
Request a page on the Main server and the upgrade will run automatically.
Wait for the upgrade to complete.
Browse the Read-Only servers and make sure they do not show the “upgrade required” screen.
One important recommendation is to always remove the install
folder immediately after upgrading Umbraco and never to upload it to a live server.
Google Chrome has notoriously aggressive caching, so if something doesn't seem to work well in the backoffice, make sure to clear cache and cookies thoroughly (for other browsers as well). Normally the browser cache problem is automatically handled in an Umbraco upgrade by modifying the config/ClientDependency.config version number. If you however wish to re-force this update you can increment this version number which will ensure that any server-side cache of JavaScript and stylesheets gets cleared as well.
One way to nudge the cache in Chrome is to open the developer tools (F12) and go to the settings (the cog icon). There will be a checkbox that says "Disable cache (while DevTools is open)". Once this checkbox is on you can refresh the page and the cache should be invalidated. To force it even more, the "reload" button next to your address bar now has extra options when you right-click it. It should have "Normal reload", "Hard reload" and "Empty cache and hard reload" now. The last option is the most thorough and you might want to try that.
Templates Short Name Language Tags
------------------------------------------------------------------------------------------------------
Umbraco Project umbraco [C#] Web/CMS/Umbraco
Umbraco Extension umbraco-extension [C#] Web/CMS/Umbraco/Extension/Plugin/Razor Class Library
Umbraco Docker Compose umbraco-compose Web/CMS/Umbraco
Umbraco Project (C#)
Author: Umbraco HQ
Description: An empty Umbraco project ready to get started.
Usage:
dotnet new umbraco [options] [template options]
Options:
-n, --name <name> The name for the output being created. If no name is specified, the name of the output directory is used.
-o, --output <output> Location to place the generated output.
--dry-run Displays a summary of what would happen if the given command line were run if it would result in a template
creation.
--force Forces content to be generated even if it would change existing files.
--no-update-check Disables checking for the template package updates when instantiating a template.
--project <project> The project that should be used for context evaluation.
-lang, --language <C#> Specifies the template language to instantiate.
--type <project> Specifies the template type to instantiate.
Template options:
-r, --release <Latest|LTS> The Umbraco release to use, either latest or latest long term supported
Type: choice
Latest The latest umbraco release
LTS The most recent long term supported version
Default: Latest
--use-https-redirect Adds code to Startup.cs to redirect HTTP to HTTPS and enables the UseHttps setting.
Type: bool
Default: false
-da, --use-delivery-api Enables the Delivery API
Type: bool
Default: false
--add-docker Adds a docker file to the project.
Type: bool
Default: false
--no-restore If specified, skips the automatic restore of the project on create.
Type: bool
Default: false
--exclude-gitignore Whether to exclude .gitignore from the generated template.
Type: bool
Default: false
--minimal-gitignore Whether to only include minimal (Umbraco specific) rules in the .gitignore.
Type: bool
Default: false
--connection-string <connection-string> Database connection string used by Umbraco.
Type: string
--connection-string-provider-name Database connection string provider name used by Umbraco.
<connection-string-provider-name> Type: string
Default: Microsoft.Data.SqlClient
--development-database-type <choice> Database type used by Umbraco for development.
Type: choice
None Do not configure a database for development.
SQLite Use embedded SQLite database.
LocalDB Use embedded LocalDB database (requires SQL Server Express with Advanced
Services).
Default: None
--friendly-name <friendly-name> Used to specify the name of the default admin user when using unattended install on
development (stored as plain text).
Type: string
--email <email> Used to specify the email of the default admin user when using unattended install on
development (stored as plain text).
Type: string
--password <password> Used to specify the password of the default admin user when using unattended install on
development (stored as plain text).
Type: string
--no-nodes-view-path <no-nodes-view-path> Path to a custom view presented with the Umbraco installation contains no published
content.
Type: string
-dm, --development-mode <choice> Choose the development mode to use for the project.
Type: choice
BackofficeDevelopment Enables backoffice development, allowing you to develop from
within the backoffice, this is the default behaviour.
IDEDevelopment Configures appsettings.Development.json to Development runtime
mode and SourceCodeAuto models builder mode, and configures appsettings.json to
Production runtime mode, Nothing models builder mode, and enables UseHttps
Default: BackofficeDevelopment
-mm, --models-mode <choice> Choose the models builder mode to use for the project. When development mode is set to
IDEDevelopment this only changes the models builder mode appsetttings.development.json
Type: choice
Default Let DevelopmentMode determine the models builder mode.
InMemoryAuto Generate models in memory, automatically updating when a content
type change, this means no need for app rebuild, however models are only available in
views.
SourceCodeManual Generate models as source code, only updating when requested
manually, this means a interaction and rebuild is required when content type(s) change,
however models are available in code.
SourceCodeAuto Generate models as source code, automatically updating when a
content type change, this means a rebuild is required when content type(s) change,
however models are available in code.
Nothing No models are generated, this is recommended for production assuming
generated models are used for development.
Default: Default
-sk, --starter-kit <choice> Choose a starter kit to install.
Type: choice
None No starter kit.
Umbraco.TheStarterKit The Umbraco starter kit.
Default: None
This section describes how to use the runtime mode setting to optimize Umbraco for the best development experience or optimal production environment.
You can configure the runtime mode to optimize Umbraco for different development experiences and environments by setting Umbraco:CMS:Runtime:Mode
to one of the available modes:
BackofficeDevelopment
(default)
Development
Production
This can be done via the appsettings.json
file, environment variables, or any other .NET configuration provider (like Azure Key Vault/App Configuration). Although this setting affects how Umbraco behaves at runtime, some modes have prerequisites on how the project is built/published. Make sure to read the descriptions of each mode before changing this setting from the default BackofficeDevelopment
mode, as incorrect configuration can result in your application not starting (by throwing a BootFailedException
).
The BackofficeDevelopment
mode is the default behavior for Umbraco: it does not optimize Umbraco for any specific environment and does not have any prerequisites. This mode allows for rapid development (without having to recompile/rebuild your project), including all development from within the backoffice.
The Development
mode can be used when you're developing from an IDE (like Visual Studio, VS Code, or Rider) or the dotnet CLI (e.g. using dotnet watch
). It is a recommended prerequisite if you want to use the Production
mode in your production environment.
This mode disables in-memory ModelsBuilder generation and validates the following setting:
Umbraco:CMS:ModelsBuilder:ModelsMode
is not set to InMemoryAuto
.
If you want to use the generated models, use SourceCodeAuto
or SourceCodeManual
. These require manually recompiling the project after the models have changed (for example after updating Document Types, Media Types, Member Types, or Data Types). Razor views (cshtml
files) will still be automatically compiled at runtime. They allow you to quickly iterate on the rendered output from templates, partial views, and view components.
The recommended approach to enable Development
mode is to update the appsettings.json
file with the following settings:
{
"Umbraco": {
"CMS": {
"Runtime": {
"Mode" : "Development"
},
"ModelsBuilder":{
"ModelsMode": "SourceCodeAuto"
}
}
}
}
Ensure your models are generated by running Umbraco and navigating to Settings > Models Builder > Generate models. You can remove the following properties from your csproj
project file to enable the compilation of Razor views (which also ensures your views do not contain compilation errors and is a prerequisite for enabling Production
mode):
<RazorCompileOnBuild>false</RazorCompileOnBuild>
<RazorCompileOnPublish>false</RazorCompileOnPublish>
Fix any compilation errors you might get after this, e.g. if you accidentally referenced deleted models or properties. Running the application will still show the rendered content and you're now ready to optionally enable Production
mode on your production environment.
Use Production
mode to ensure your production environment is running optimally by disabling development features and validating whether specific settings are configured to their recommended production values.
This mode disables both in-memory ModelsBuilder generation (see Development mode) and Razor (cshtml) runtime compilation. Production mode requires you to compile your views at build/publish time and enforces the following settings for optimal performance/security:
The application is built/published in Release mode (with JIT optimization enabled), e.g. using dotnet publish --configuration Release
;
Umbraco:CMS:WebRouting:UmbracoApplicationUrl
is set to a valid URL;
Umbraco:CMS:Global:UseHttps
is enabled;
Umbraco:CMS:ModelsBuilder:ModelsMode
is set to Nothing
.
The recommended approach to enable Production
mode is to update the appsettings.Production.json
file (or create one) with the following settings:
{
"Umbraco": {
"CMS": {
"Runtime": {
"Mode": "Production"
},
"Hosting": {
"Debug": false
},
"Global": {
"UseHttps": true
},
"ModelsBuilder": {
"ModelsMode": "Nothing"
},
"WebRouting": {
"UmbracoApplicationUrl": "https://<REPLACE_WITH_YOUR_PRIMARY_DOMAIN>/"
},
"RuntimeMinification": {
"UseInMemoryCache": true,
"CacheBuster": "AppDomain"
}
}
}
}
Although you can still edit document types and views (if not running from the published output), changes won't be picked up until you've rebuilt your project or republished the application.
Also ensure the UmbracoApplicationUrl
is updated to the primary URL of your production environment, as this is used when sending emails (password reset, notifications, health check results, etc.).
Validation of the above-mentioned settings is done when determining the runtime level during startup using the new IRuntimeModeValidationService
and when it fails, causes a BootFailedException
to be thrown. The default implementation gets all registered IRuntimeModeValidators
to do the validation, making it possible to remove default checks and/or add your own (inherit from RuntimeModeProductionValidatorBase
, if you only want to validate against the production runtime mode). The following validators are added by default:
JITOptimizerValidator
- Ensure the application is built/published in Release mode (with JIT optimization enabled) when in production runtime mode, e.g. using dotnet publish --configuration Release
;
UmbracoApplicationUrlValidator
- ensure Umbraco:CMS:WebRouting:UmbracoApplicationUrl
is configured when in production runtime mode;
UseHttpsValidator
- ensure Umbraco:CMS:Global:UseHttps
is enabled when in production runtime mode;
ModelsBuilderModeValidator
- ensure Umbraco:CMS:ModelsBuilder:ModelsMode
is not set to InMemoryAuto
when in development runtime mode and set to Nothing
when in production runtime mode.
The following example removes the default UmbracoApplicationUrlValidator
and adds a new custom DisableElectionForSingleServerValidator
:
using System.Diagnostics.CodeAnalysis;
using Microsoft.Extensions.Options;
using Umbraco.Cms.Core.Composing;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Infrastructure.Runtime;
using Umbraco.Cms.Infrastructure.Runtime.RuntimeModeValidators;
public class RuntimeModeValidatorComposer : IComposer
{
public void Compose(IUmbracoBuilder builder)
=> builder.RuntimeModeValidators()
.Remove<UmbracoApplicationUrlValidator>()
.Add<DisableElectionForSingleServerValidator>();
}
public class DisableElectionForSingleServerValidator : IRuntimeModeValidator
{
private readonly IOptionsMonitor<GlobalSettings> _globalSettings;
public DisableElectionForSingleServerValidator(IOptionsMonitor<GlobalSettings> globalSettings) => _globalSettings = globalSettings;
public bool Validate(RuntimeMode runtimeMode, [NotNullWhen(false)] out string? validationErrorMessage)
{
if (runtimeMode == RuntimeMode.Production && _globalSettings.CurrentValue.DisableElectionForSingleServer == false)
{
validationErrorMessage = "Disable primary server election (and support for load balancing) to improve startup performance.";
return false;
}
validationErrorMessage = null;
return true;
}
}
Information on how to deploy Umbraco in a Load Balanced scenario and other details to consider when setting up Umbraco for load balancing
Configuring and setting up a load balanced server environment requires planning, design and testing. This document should assist you in setting up your servers, load balanced environment and Umbraco configuration.
This document assumes that you have a fair amount of knowledge about:
Umbraco
IIS 10+
Networking & DNS
Windows Server
.NET5+
These instructions make the following assumptions:
All web servers can communicate with the database where Umbraco data is stored
You are running Umbraco 9.0.0 or above
You will designate a single server to be the backoffice server for which your editors will log into for editing content. Umbraco will not work correctly if the backoffice is behind the load balancer.
There are three design alternatives you can use to effectively load balance servers:
You use cloud based auto-scaling appliances like Microsoft's Azure Web Apps
Each server hosts copies of the load balanced website files and a file replication service is running to ensure that all files on all servers are up to date
The load balanced website files are located on a centralized file share (SAN/NAS/Clustered File Server/Network Share)
You will need a load balancer to do your load balancing.
In order to understand how to host your site it is best to understand how Umbraco's flexible load balancing works.
The following diagram shows the data flow/communication between each item in the environment:
The process is as follows:
Administrators and editors create, update, delete data/content on the backoffice server
These events are converted into data structures called "instructions" and are stored in the database in a queue
Each front-end server checks to see if there are any outstanding instructions it hasn't processed yet
When a front-end server detects that there are pending instructions, it downloads them and processes them and in turn updates it's cache, cache files and indexes on its own file system
There can be a delay between content updates and a front-end server's refreshing, this is expected and normal behaviour.
Although there is a backoffice server designated for administration, by default this is not explicitly set as the "Scheduling server". In Umbraco there can only be a single scheduling server which performs the following tasks:
Scheduled tasks - to initiate any configured scheduled tasks
Scheduled publishing - to initiate any scheduled publishing for documents
Umbraco will automatically elect a "Scheduling server" to perform the above services. This means that all of the servers will need to be able to resolve the URL of either: itself, the Backoffice server, the internal load balancer, or the public address.
There are two server roles:
SchedulingPublisher
- Usually this is the backoffice instance.
Subscriber
- These are the scalable front-end instances - not recommended to be used for backoffice access.
Each instance will be allocated a role by the automatic server role election process, but they can also be set explicitly (recommended)
For example, In the following diagram the node f02.mysite.local is the elected "Scheduling server". In order for scheduling to work it needs to be able to send requests to itself, the Backoffice server, the internal load balancer or the public address. The address used by the "Scheduling server" is called the "umbracoApplicationUrl".
By default, Umbraco will set the "umbracoApplicationUrl" to the address made by the first accepted request when the AppDomain starts. It is assumed that this address will be a DNS address that the server can resolve.
For example, if a public request reached the load balancer on www.mysite.com
, the load balancer may send the request on to the servers with the original address: www.mysite.com
. By default the "umbracoApplicationUrl" will be www.mysite.com
. However, load balancers may route the request internally under a different DNS name such as "f02.mysite.local" which by default would mean the "umbracoApplicationUrl" is "f02.mysite.local". In any case the elected "Scheduling server" must be able to resolve this address.
In many scenarios this is fine, but in case this is not adequate there's a few of options you can use:
Recommended: set your front-end(s) (non-admin server) to be explicit subscriber servers by creating a custom IServerRegistrar
, this means the front-end servers will never be used as the SchedulingPublisher server role.
Set the UmbracoApplicationUrl
property in the WebRouting section of the CMS config
The below section applies to all ASP.NET load balancing configurations.
This section describes the configuration options depending on your hosting setup:
Azure Web Apps - You use cloud based auto-scaling appliances like Microsoft's Azure Web Apps
File Replication - Each server hosts copies of the load balanced website files and a file replication service is running to ensure that all files on all servers are up to date
Centralized file share - The load balanced website files are located on a centralized file share (SAN/NAS/Clustered File Server/Network Share)
Full documentation is available here
The replacement for Machine Keys in ASP.NET Core are called Data Protection. You will need to setup data protection to the same keys on all servers, without this you will end up with view state errors, validation errors and encryption/decryption errors since each server will have its own generated key.
ASP.NET Core supports multiple ways to share keys. Use the official docs to find a description that fits your setup the best.
It is required to setup a distributed cache, like DistributedSqlServerCache
or an alternative provider (see https://docs.microsoft.com/en-us/aspnet/core/performance/caching/distributed for more details). The distributed cache is used by the session in your application, which is used by the default TempDataProvider in MVC.
Because Umbraco in some cases uses TempData, your setup needs to be configured with a distributed cache.
There are some logging configurations to take into account no matter what type of load balancing environment you are using.
Full documentation is available here
Your staging environment should also be load balanced so that you can see any issues relating to load balancing in that environment before going to production.
You'll need to test this solution a lot before going to production. You need to ensure there are no windows security issues, etc... The best way to determine issues is have a lot of people testing this setup and ensuring all errors and warnings in your application/system logs in Windows are fixed.
Ensure to analyze logs from all servers and check for any warnings and errors.
When upgrading it is possible to run the upgrades unattended.
Find steps on how to enable the feature for a load balanced setup in the General Upgrades article.
Here's some common questions that are asked regarding Load Balancing with Umbraco:
Question> Why do I need to have a single web instance for Umbraco admin?
TL:DR You must not load balance the Umbraco backoffice, you will end up with data integrity or corruption issues.
The reason you need a single server is because there is no way to guarantee transactional safety between servers. This is because we don't currently use database level locking, we only use application (c#) level locks to guarantee transactional data integrity which is only possible to work on one server. If you have multiple admins saving and publishing at once between servers then the order in which this data is read and written to the database absolutely must be consistent otherwise you will end up with data corruption.
Additionally, the order in which cache instructions are written to the cache instructions table is important for LB, this order is guaranteed by having a single admin server.
Question> Can my SchedulingPublisher backoffice admin server also serve front-end requests?
Yes. There are no problems with having your SchedulingPublisher backoffice admin server also serve front-end request.
However, if you wish to have different security policies for your front-end servers and your back office servers, you may choose to not do this.
Schema Alias: Umbraco.DropDown.Flexible
UI Alias: Umb.PropertyEditorUi.Dropdown
Returns: String
or IEnumerable<string>
Displays a list of preset values. Either a single value or multiple values (formatted as a collection of strings) can be returned.
If enabled, editors will be able to select multiple values from the dropdown otherwise only a single value can be selected.
Options are the values which are shown in the dropdown list. You can add, edit, or remove values here.
@if (Model.HasValue("category"))
{
<p>@(Model.Value<string>("category"))</p>
}
@if (Model.HasValue("categories"))
{
var categories = Model.Value<IEnumerable<string>>("categories");
<ul>
@foreach (var category in categories)
{
<li>@category</li>
}
</ul>
}
@if (!Model.HasValue(Model.Category))
{
<p>@Model.Category</p>
}
@if (Model.Categories.Any())
{
<ul>
@foreach (var category in Model.Categories)
{
<li>@category</li>
}
</ul>
}
See the example below to see how a value can be added or changed programmatically. To update a value of a property editor you need the Content Service.
@using Umbraco.Cms.Core.Serialization
@using Umbraco.Cms.Core.Services
@inject IContentService ContentService
@inject IJsonSerializer Serializer
@{
// Create a variable for the GUID of the page you want to update
var guid = Guid.Parse("32e60db4-1283-4caa-9645-f2153f9888ef");
// Get the page using the GUID you've defined
var content = ContentService.GetById(guid); // ID of your page
// Set the value of the property with alias 'categories'.
content.SetValue("categories", Serializer.Serialize(new[] { "News" }));
// Save the change
ContentService.Save(content);
}
Although the use of a GUID is preferable, you can also use the numeric ID to get the page:
@{
// Get the page using it's id
var content = ContentService.GetById(1234);
}
If Models Builder is enabled you can get the alias of the desired property without using a magic string:
@using Umbraco.Cms.Core.PublishedCache
@inject IPublishedContentTypeCache PublishedContentTypeCache
@{
// Set the value of the property with alias 'categories'
content.SetValue(Home.GetModelPropertyType(PublishedContentTypeCache, x => x.Categories).Alias, Serializer.Serialize(new[] { "News" }));
}
This is the guide for upgrading existing installations in general.
In this article, you will find everything you need to upgrade your Umbraco CMS project.
You will find instructions on how to upgrade to a new minor or major version as well as how to run upgrades unattended.
The following lists a few things to be aware of before initiating an upgrade of your Umbraco CMS project.
Sometimes, there are exceptions to general upgrade guidelines. These are listed in the . Be sure to read this article before moving on.
Ensure your setup meets the for the new versions you will be upgrading your project to.
Things may go wrong for different reasons. Be sure to always keep a backup of both your site's files and the database. This way, you can always return to a version that you know works.
Before upgrading to a new major version, check if the packages you're using are compatible with the version you're upgrading to. On the package's download page, in the Project compatibility area, click View details to check version-specific compatibility.
The steps outlined in this article apply to Umbraco version 10 and later versions.
Are you upgrading to a minor version for Umbraco 6, 7, or 8? You can find the appropriate guide below:
You can upgrade to a new major version of Umbraco CMS directly by using NuGet.
You must upgrade to the closest version before upgrading to the latest version. For Umbraco 10, the closest long-term support version is Umbraco 13. Once the project is on Umbraco 13, you can move on to Umbraco 14.
Switching to a new major version of Umbraco CMS also means switching to a new .NET version. Ensure that any packages used on your site are compatible with this version before upgrading.
The package compatibility can be checked on the package's download page. Locate the Project compatibility area and select View details to check version-specific compatibility.
Use the table below to determine which .NET version to upgrade to when going through the steps below.
It's recommended that you upgrade the site offline and test the upgrade fully before deploying it to the production environment.
Stop your site in IIS to prevent any changes from being made while you are upgrading.
Open your Umbraco project in Visual Studio.
Right-click on the project name in the Solution Explorer and select Properties.
Select the .NET version from the Target Framework drop-down.
Go to Tools > NuGet Package Manager > Manage NuGet Packages for Solution...
Go to the Installed tab in the NuGet Package Manager.
Upgrade Umbraco.Cms.
a. Select the correct version from the Version drop-down.
b. Click Install to upgrade your project.
Make sure that your connection string has TrustServerCertificate=True
to complete the upgrade successfully:
Restart your site in IIS, then build and run your project to finish the installation.
If your database experiences timeout issues after an upgrade, it might be due to the startupTimeLimit
configuration.
To fix the issue, try increasing the in the web.config
file. Additionally, you can set the value in the in the appsettings.json
file.
NuGet installs the latest version of the package when you use the dotnet add package
command unless you specify a package version:
dotnet add package Umbraco.Cms --version <VERSION>
Add a package reference to your project by executing the dotnet add package Umbraco.Cms
command in the directory that contains your project file.
Run dotnet restore
to install the package.
For Umbraco 9
If you are using SQL CE in your project, you need to run dotnet add package Umbraco.Cms.SqlCe --version <VERSION>
before the dotnet restore
command. From Umbraco 10, SQL CE has been replaced with SQLite, so a dotnet restore
should be sufficient. If this is not working, then you need to run dotnet add package Umbraco.Cms.Persistence.Sqlite --version <VERSION>
, and then dotnet restore
.
When the command completes, open the .csproj
file to make sure the package reference was updated:
When upgrading your Umbraco project, it is possible to enable the upgrade to run unattended. This means that you will not need to run through the installation wizard when upgrading.
Below you will find the steps you need to take in order to upgrade your project unattended.
Add the Umbraco:Cms:Unattended:UpgradeUnattended
configuration key.
Set the value of the key to true
.
With the correct configuration applied, the project will be upgraded on the next boot.
The Runtime level uses Run
instead of Upgrade
to allow the website to continue to boot up directly after the migration is run. This happens instead of initiating the otherwise required restart.
Follow the steps outlined below to use unattended upgrades in a load-balanced setup.
.
Deploy to all environments.
Set the Umbraco:CMS:Unattended:UpgradeUnattended
configuration key to true
for the Main server only.
Boot the Main server, and the upgrade will run automatically.
Wait for the upgrade to complete.
Boot the Read-Only servers and ensure they do not show the “upgrade required” screen.
Learn how to work with different types of Media content on your Umbraco website.
Media in Umbraco CMS is handled the same way as content. You define Media Types that act as a base for media items. The following default Media Types are available:
Article - used for uploading and storing documents.
Audio - used for uploading and storing digital audio files.
File - used for uploading and storing different types of files in the Media section.
Folder - a container for organizing media items in the Media section tree.
Image - used for uploading and storing images.
Vector Graphics (SVG) - used for uploading and storing Scalable Vector Graphics (SVG) files which are text files containing source code to draw the desired image.
Video - used for uploading and storing video files.
The default Media Types aim to cover most needs for media on a website. You do not need to define your Media Types to start using the Media section. The tools for organizing and uploading the media are already in place.
You can upload media in two different ways:
and
From the Media section in the Umbraco backoffice, you can add new media items by following either of the approaches defined below:
Use the Create dialog to create a new Media item in the Media section
The Media item will be created based on the type you choose.
Upload the image or file, give the Media item a name, and click Save.
Use the Drag and drop feature to add your files to the Media section.
Umbraco will automatically detect the Media Type and create the Media item.
You can drop entire folder structures to recreate that same structure in the Media section.
New media items can be added to your site without interrupting the content creation flow. This can be done following either of the two approaches outlined below.
Drag and drop the image(s) from your file explorer directly into the Media Picker property on the Content page.
Images added this way is automatically added to the user's start node in the Media section of the Umbraco backoffice.
Select the "+" icon to open the "Select media" dialog where you can add images from your file explorer directly or using drag and drop.
It is always a good idea to start by creating a folder for your media items. It can be a good idea to align these folders with the content on your website. This will give the editors a better overview of the files and enable them to upload media items in the correct place.
Follow these steps to create a folder in the Media section:
Go to the Media section.
Select ... next to Media.
Select Create.
Select Folder.
Enter a name for the folder and select Save in the bottom-right corner.
The Image Media Type has 5 properties: Upload Image, Width, Height, Size, and Type. These are populated once the image is uploaded. The properties can be viewed in the Media section and accessed in your Templates.
Except for the Folder Media Type, the other Media Types have 3 properties: Upload Image, Type, and Size.
Learn more about each Media Type in .
The default view for the Media section is a card view that lets you preview the different files that have been uploaded.
By selecting multiple media items it is possible to perform bulk operations like moving or deleting the items.
To edit properties on a single media item, click the name of the item, which you will see once you hover over the item.
From the top-right corner of the Media section, you can toggle between the list and grid view. There is also an option to search for the items in the Media section.
By adding a Media Picker property to a Document Type the editor will have the ability to select media items when creating content.
You can create custom Media Types and control the structure of the Media tree as you would with Document Types. This means you can store information that is specific to the media on the item itself.
A Media Type is created in the Settings section using the Media Type editor.
Go to the Settings section.
Click ... next to Media Types.
Click Create > New Media Type.
Name the new Media Type Employee Image.
Choose an icon by selecting the icon left of the name field.
You will now see the Media Type editor. It is similar to the editor used for creating Document Types.
Before we start adding properties to the Media Type we need to add a group to put these in.
Click on Add group.
Call the group Image.
We need to add the same properties as on the default Image Media Type. These are:
umbracoFile
umbracoWidth
umbracoHeight
umbracoBytes
umbracoExtension
Follow the steps outlined below to add the properties to the Media Type:
Click Add property.
Name it Upload image.
Change the alias to umbracoFile.
Click Select property editor.
Select Image cropper.
Rename the editor Employee Image Cropper.
Add two new crops called Thumbnail (200px x 350px) and wideThumbnail (350px x 200px).
8. Click Save. 9. Click Add. 10. Name the remaining four properties Width, Height, Size, and Type, and give them the aliases as mentioned above. They should all use the Label editor.
As mentioned before these properties will automatically be populated once an image has been uploaded.
Next up, we will create a folder to hold the employee images. We could use the existing Folder Media Type but that would mean editors can upload employee images to any folder of that type. If we create a folder specifically for employee images there is only one place to put them.
Go back to the Settings section and create a new Media Type.
Name it Employee Images.
Select the folder icon by clicking the icon to the left of the name.
Navigate to the Structure tab.
Click Configure as a Collection under Presentation.
Choose List view - Media.
7. Click Save.
The new folder is created under the Media Types folder. We also need to only allow the Employee Image Media Type in our new folder. Both of these configurations can be set on the Structure tab.
Go to the Structure tab of the Employee Images folder.
Toggle the Allow at root.
Click Choose in the Allowed Child Node Types.
Select Employee Image.
Click Choose.
Go to the Media section.
Select ... next to Media.
Click Create > Employee Images folder.
Name it Employee Images.
Click Save.
If you select an image that has been uploaded to the folder you will see the full image and the two defined crops.
Moving the focal point circle on the image will update the crops to focus accordingly. You can also edit the individual crops by selecting them and moving the image or adjusting the slider to zoom.
This document should be used as a reference, not a step by step guide. Upgrading will largely depend on what version of Umbraco you are currently running, what packages you have installed and the many
The standard upgrade instructions still apply to this process as well.
It is critical that you back up your website and database before upgrading. There are database changes made during installation and you cannot revert an Umbraco 7 database to an Umbraco 6 database.
Umbraco 7 is built on .Net 4.5 and your development environment will require this version installed in order to operate. Visual Studio users may require 2012 or higher.
Umbraco 7 requires browsers with proper HTML 5 support, these include Chrome, Firefox, IE10+
Before you upgrade be sure to read the list of breaking changes. This is especially recommended if you have removed or modified code in the core or if one of these breaking changes directly affects your installation.
See the list of breaking changes for more details.
It is recommended to rebuild all Examine indexes after completing the upgrade.
You should re-generate the XML cache. This can be done by following the prompts when visiting the following URL:
your-domain.com/umbraco/dialogs/republish.aspx?xml=true
It is recommended that you use a Diff tool to compare the configuration file changes with your own current configuration files.
/web.config
updates
Details are listed here: https://issues.umbraco.org/issue/U4-2900
You will need to compare the new Umbraco 7 web.config
with your current web.config
. Here is a quick reference of what needs to change:
Remove the section name="BaseRestExtensions"
section
Remove the section name="FileSystemProviders"
section
Remove the sectionGroup name="system.web.webPages.razor"
section
Remove the <FileSystemProviders>
element
Remove the BaseRestExtensions
element
Remove the add key="umbracoUseMediumTrust"
element
Remove the system.web.extensions
element
Removes the xhtmlConformance
element
Remove the system.codedom
element
Remove the compilation
assemblies, /compilation
Remove the system.web.webPages.razor
element
New: sectionGroup name="umbracoConfiguration"
section
New: umbracoConfiguration
element
Ensure that the targetFramework="4.5"
is added to the httpRuntime
element
Add add key="ValidationSettings:UnobtrusiveValidationMode" value="None"
to the appSettings
element
/config/clientdependency.config
changes
remove add name="CanvasProvider"
element
/views/web.config
updates
New macroscripts/web.config
config/umbracoSettings.config
Umbraco is now shipped with minimal settings but the full settings are still available
umbracoSettings
is now a true ASP.NET configuration section https://issues.umbraco.org/issue/U4-58
Remove the EnableCanvasEditing
element
Remove the webservices
element
Removed xsltExtensions.config
/config/applications.config
and /config/trees.config
have some icon paths and names updated. You need to merge the new changes into your existing config files.
/config/tinyMceConfig.config
The inlinepopups
is compatible and supported in Umbraco 7. You need to remove these elements: plugin loadOnFrontend="true"
, inlinepopups/plugin
;
The plugins element that is shipped with Umbraco 7 looks like this:
<plugins>
<plugin loadOnFrontend="true">code</plugin>
<plugin loadOnFrontend="true">paste</plugin>
<plugin loadOnFrontend="true">umbracolink</plugin>
<plugin loadOnFrontend="true">anchor</plugin>
<plugin loadOnFrontend="true">charmap</plugin>
<plugin loadOnFrontend="true">table</plugin>
<plugin loadOnFrontend="true">lists</plugin>
</plugins>
You need to merge the changes from the new tinyMceConfig
file into yours. The command
elements that have changed are: JustifyCenter
, JustifyLeft
, JustifyRight
, JustifyFull
, umbracomacro
, umbracoembed
, mceImage
, subscript
, superscript
, styleselect
Remove the command: mceSpellCheck
/config/dashboard.config
You need to merge the changes from the new dashboard.config
into yours. Some of the original dashboard entries that were shipped with Umbraco 6 have been replaced or removed.
Umbraco 7+ will no longer support medium trust environments. There are now some assemblies used in the core that do not support medium trust but are used extensively. Plugin scanning now also allows for scanning Umbraco's internal types which requires full trust.
Content, Media, Members, and Data Type trees will no longer raise the legacy tree events (based on BaseTree). It is recommended to change all tree event handlers to use the new tree events that fire for every tree in Umbraco including legacy trees. The new tree events are static events and are found in the class Umbraco.Web.Trees.TreeControllerBase
:
MenuRendering
RootNodeRendering
TreeNodesRendering
The Content, Media, Member, and Data Type editors have been re-created and are solely using the new Umbraco Services data layer. This means that operations performed in the backoffice will no longer raise the legacy business logic events (for example, events based on umbraco.cms.businesslogic.web.Document
). It is recommended to change your event handlers to subscribe to the new Services data layer events. These are static events and are found in the services. For example: Umbraco.Core.Services.ContentService.Saved
.
Legacy property editors (pre-Umbraco 7) will not work with Umbraco 7. During the upgrade installation process, Umbraco will generate a report showing you which legacy property editors are installed. These will all be converted to a readonly
Label property editor. No data loss will occur but you'll need to re-assign your existing data types to use a new compatible Umbraco 7 property editor.
Most Umbraco core property editors shipped will be mapped to their equivalent Umbraco 7 editors. The Image cropper editor has not been completed for v7.0.
Since the Related Links property is an advanced property editor, the data format has changed from XML to JSON. This should not have any effect when retrieving the data from razor. If you are outputting Related Links data with XSLT you will need to update your XSLT snippet. Making use of the new library method umbraco.library:JsonToXml
and taking into account that the xml structure has also slightly changed.
One of the database changes made in Umbraco 7 is the change of referencing a property editor from a GUID to a string alias. In order to map a legacy property editor to a new Umbraco 7 version you can add your custom "GUID -> Alias" map during application startup. To do this you would add your map using this method: Umbraco.Core.PropertyEditors.LegacyPropertyEditorIdToAliasConverter.CreateMap
Legacy parameter editors (pre-Umbraco 7) will not work with Umbraco 7. If Umbraco detects legacy parameter editor aliases that do not map to a Umbraco 7 parameter editor it will render a textbox in its place. You will need to update your macros to use a compatible Umbraco 7 parameter editor as those that aren't supported.
Previously, parameter editors were registered in an Umbraco database table: cmsMacroPropertyType
which no longer exists. Parameter editors in Umbraco 7 are plugins like property editors. During the Umbraco 7 upgrade installation process it will update the new cmsMacroProperty.editorAlias
column with the previous parameter editor alias. During this process it will look into the Umbraco.Core.PropertyEditors.LegacyParameterEditorAliasConverter
for a map between a legacy alias to a new Umbraco 7 alias.
Custom legacy parameters can be mapped to new Umbraco 7 parameter editor aliases during installation. This can be done by modifying the mapping during application startup using this method: Umbraco.Core.PropertyEditors.LegacyParameterEditorAliasConverter.CreateMap
.
All database changes will be taken care of during the upgrade installation process.
For database change details see (including all child tasks):
See above for the database updates made for better tag support.
Tags can now be assigned to a nodes property and not only a node
Multiple tag controls can exist on one page with different data
The legacy API does not support this, the legacy API will effectively, add/update/remove tags for the first property found for the document that is assigned a tag property editor.
There is a new ITagService that can be used to query tags
Querying for tags in a view (front-end) can be done via the new TagQuery class which is exposed from the UmbracoHelper. For example: @Umbraco.TagQuery.GetTagsForProperty
You should check with the package creator for all installed packages to ensure they are compatible with Umbraco 7.
We see common errors that we cannot fix for you, but we do have recommendations you can follow to fix them:
Could not load type umbraco.BusinessLogic.Utils.TypeFinder from assembly businesslogic, Version=1.0.5031.21336, Culture=neutral, PublicKeyToken=null.
The TypeFinder has been deprecated since 4.10 and is now found under Umbraco.Core.TypeFinder
.
While you need to have JavaScript inside menu actions to trigger a response, it is highly recommended that you use the recommended UmbClientMgr
methods. You should not try to override parent.right.document
and similar tricks to get to the right-hand frame.
If you have a webforms page, it is recommended to use the built-in ASP.NET controls to render panels, properties and so on. If you use the raw HTML or try to style it to match the backoffice, you will get out of sync. Follow the guidelines set by Umbraco's internal editors and use the ASP.NET custom controls for UI.
16
9.0
15
9.0
14
8.0
13
8.0
12
7.0
11
7.0
10
6.0.5
"ConnectionStrings": {
"umbracoDbDSN": "Server=YourLocalSQLServerHere;Database=NameOfYourDatabaseHere;User Id=NameOfYourUserHere;Password=YourPasswordHere;TrustServerCertificate=True"
}
<ItemGroup>
<PackageReference Include="Umbraco.Cms" Version="x.x.x" />
</ItemGroup>
{
"Umbraco": {
"CMS": {
"Unattended": {
"UpgradeUnattended": true
}
}
}
}
This guide will show you how to migrate the content from your Umbraco 7 site to a site running Umbraco 8.
Umbraco 8 contains a lot of breaking changes and a lot of code has been cleaned up compared to Umbraco 7. Due to this, it will not be possible to do a direct upgrade from Umbraco 7 to Umbraco 8. You need to migrate your content from your Umbraco 7 site into your Umbraco 8 site and then recreate the rest in the new version.
A content migration tool has been implemented in Umbraco 8.1.0, to help you with the transition.
In this guide you can read more about the tool, its limitations, and how to use it in practice.
In the following section, you can learn more about the limitations of migrating content from Umbraco 7 to Umbraco 8.
The content migration tool is a database migration, which is made for the database schema of Umbraco 7.14+. This means that in order to do the migration you need to ensure your Umbraco 7 site is running at least Umbraco 7.14.
Umbraco 8 does not support MySQL databases. This means that the migration will not work when moving from an Umbraco 7 site using MySQL to Umbraco 8 on SQL Server
The database types that are supported are SQL Server and SQL CE.
Feedback from user testing has shown that some databases are harder to migrate than others.
We are collecting a list of these known issues on our GitHub Issue Tracker. There is a community package: Pre-migration health checks that you can install on your Umbraco 7 site before migration. This will help identify and resolve some of these common issues before triggering the migration steps detailed below.
The migration will transform the data stored in third party editors as well. However, it will be stored as it was in Umbraco 7. If the structure has changed or the property editor doesn't exist, you will still be able to find the data in the database. It will, however, not be available in the backoffice.
When the migrations are running, Umbraco will go through your entire Umbraco 7 database and update it to the format required for Umbraco 8. The schema will be remodeled and transformed into the correct format and your existing compatible data will be transformed to fit with Umbraco 8.
These migrations will be running directly on your database. They are transforming schema and data - not transferring. Therefore always ensure that you have a backup before attempting to do this. In case something goes wrong, you will be able to rollback and try again.
It is highly recommended to clean up your site before running this as it will be quicker.
Empty Content recycle bin
Empty Media recycle bin
Clean up the database version history (can be done with a script or a package like Unversion)
In the following guide we will migrate the content of an Umbraco 7.13.1 site to Umbraco 8.1.0.
Before the content migration can start the site has to run Umbraco 7.14+. Make sure to always take a backup of the database before doing an upgrade, and then check the version specific upgrade instructions.
The site in this example is an Umbraco 7.13.1 site, and we will use Nuget to update it.
Following the general upgrade instructions we will now upgrade via Nuget until we get to this point:
When upgrading an old website, check if you are using obsolete properties in your Data Types. These should be changed to their updated counterparts. The migration will fail if you are still using obsolete properties.
The updated properties are:
Content Picker
Media Picker
Member Picker
Multinode Treepicker
Nested Content
Folder Browser
Related Links
You can see if your site is using the obsolete properties from the (Obsolete)
prefix in their name.
Install the Pre-migration health checks plugin, and run it health check from the Developer section of the backoffice. This is done to identify and resolve some common database schema issues before migration.
Once it is upgraded and you have verified everything is working, move on to the next step.
The first thing to do is to spin up a fresh new Umbraco 8.1+ site. Make sure everything works and that no content is there.
If you have customized the UsersMembershipProvider
on your Umbraco 7 site you need to copy that over to the 8.1 web.config
as well. Additionally you need to update the type
attribute to be type="Umbraco.Web.Security.Providers.UsersMembershipProvider, Umbraco.Web"
.
This also includes the attribute useLegacyEncoding
value. Make sure that this setting is copied into your new Umbraco 8 site, as it is needed in order to log in.
Take a backup of your database from the Umbraco 7.14 site. Take the information for the backup database and add that to the connectionstring for the Umbraco 8.1 site. If you are running SQL CE, you will have to copy the database over to the new site as well.
Once the connectionstring is set, the final step is to change the Umbraco version number in the web.config
on the Umbraco 8.1 site. Chang it to 7.14.0
. This will indicate that there is an upgrade pending and it needs to run the migration.
The version will be set to 8.1.0, and you need to change it to the version you are currently migrating from.
When you start the site it will ask you to login and then show you this screen:
From here, the automatic migration will take over, and after a little bit you can log in and see your content:
Before moving on to this step, make sure that the Umbraco 8 project is no longer running.
The following files/folders need to be copied into the Umbraco 8 project:
~/Views
- do not overwrite the default Macro and Partial View Macro files, unless changes have been made to these.
~/Media
Any files/folders related to Stylesheets and JavaScripts.
Any custom files/folders the Umbraco 7 project uses, that aren't in the ~/Config
or ~/bin
.
~/App_Data/UmbracoForms
- in the case Umbraco Forms was used on the Umbraco 7 site.
Merge the configuration files carefully to ensure any custom settings are migrated while none of the default configurations for Umbraco 8 is overwritten.
You'll have to revisit all templates and custom implementations to get the site up and running, as all markup is still Umbraco 7-specific.
As you are updating your template files and custom implementation, you should also verify your configuration files and settings.
Umbraco 8 contains a few changes regarding the Sections in the Umbraco Backoffice. Because of this, you should also check your User Groups and make sure they have access to the appropriate sections.
Learn more about the Section in the Sections article
Schema Alias: Umbraco.ImageCropper
UI Alias: Umb.PropertyEditorUi.ImageCropper
Returns: MediaWithCrops
Returns a path to an image, along with information about focal point and available crops.
When the Image Cropper is used on a Media Type the crops are shared between all usages of a Media Item. This is called global crops.
If the Image Cropper is used on a Document Type, the file and crops will be local to the Document.
Notice that it is possible make local crops on shared Media Items via the Media Picker Property Editor.
You can add, edit & delete crop presets the cropper UI can use.
The Image Cropper provides a UI to upload an image, set a focal point on the image, and use predefined crops.
By default, images in the Image Cropper will be shown based on a set focal point and only use specific crops if they are available.
The Image Cropper comes with 3 modes:
Uploading an image
Setting a focal point
Cropping the image to predefined crops
The editor exposes a drop area for files. Select it to upload an image.
By default, the Image Cropper allows the editor to set a focal point on the uploaded image.
All the preset crops are shown to give the editor a preview of what the image will look like on the frontend.
The editor can fit the crop to the image to ensure that the image is presented as intended.
ImageSharp.Web is image processing middleware for ASP.NET.
We bundle this package with Umbraco and you can therefore take full advantage of all its features for resizing and format changing. Learn more about the built in processing commands in the official ImageSharp documentation.
The Image Cropper comes with an API to generate crop URLs. You can also access the raw data directly as a dynamic object.
For rendering a cropped media item, the .GetCropUrl
is used:
<img src="@Url.GetCropUrl(Model.Photo,"square", true)" />
The third parameter is HtmlEncode
and is by default set to true. This means you only need to define the parameter if you want to disable HTML encoding.
<img src="@Url.GetCropUrl(Model.SecondaryPhoto, "customCropper", "banner")" />
Or, alternatively using the MediaWithCrops
extension method:
<img src="@Model.SecondaryPhoto.GetCropUrl("customCropper", "banner")" />
@if (Model.Photo is not null)
{
<img src="@Url.GetCropUrl(Model.Photo, height: 300, width: 400)" alt="@Model.Photo.Name" />
}
Set the htmlEncode
to false so that the URL is not HTML encoded
@if (Model.Photo is not null)
{
var cropUrl = Url.GetCropUrl(Model.Photo, "square", false);
<style>
.myCssClass {
background-image: url("@cropUrl");
height: 400px;
width: 400px;
}
</style>
<div class="product-image-container myCssClass"></div>
}
To update a content property value you need the Content Service.
The following sample demonstrates how to add or change the value of an Image Cropper property programmatically. The sample creates an API controller with an action, which must be invoked via a POST request to the URL written above the action.
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.PropertyEditors;
using Umbraco.Cms.Core.PropertyEditors.ValueConverters;
using Umbraco.Cms.Core.Serialization;
using Umbraco.Cms.Core.Services;
namespace Umbraco.Docs.Samples.Web.Property_Editors_Add_Values;
[ApiController]
[Route("/umbraco/api/createimagecroppervalues")]
public class CreateImageCropperValuesController : Controller
{
private readonly IContentService _contentService;
private readonly IMediaService _mediaService;
private readonly MediaUrlGeneratorCollection _mediaUrlGeneratorCollection;
private readonly IJsonSerializer serializer;
public CreateImageCropperValuesController(
IContentService contentService,
IMediaService mediaService,
MediaUrlGeneratorCollection mediaUrlGeneratorCollection, IJsonSerializer serializer)
{
_contentService = contentService;
_mediaService = mediaService;
_mediaUrlGeneratorCollection = mediaUrlGeneratorCollection;
this.serializer = serializer;
}
// /Umbraco/Api/CreateImageCropperValues/CreateImageCropperValues
[HttpPost("createimagecroppervalues")]
public ActionResult<bool> CreateImageCropperValues()
{
// Create a variable for the GUID of the page you want to update
var contentKey = Guid.Parse("89974f8b-e213-4c32-9f7a-40522d87aa2f");
// Get the page using the GUID you've defined
IContent? content = _contentService.GetById(contentKey);
if (content == null)
{
return false;
}
// Create a variable for the GUID of the media item you want to use
var mediaKey = Guid.Parse("b6d4e98a-07c0-45f9-bfcc-52994f2806b6");
// Get the desired media file
IMedia? media = _mediaService.GetById(mediaKey);
if (media == null)
{
return false;
}
// Create a variable for the image cropper and set the source
var imageCropperValue = new ImageCropperValue
{
Src = media.GetUrl("umbracoFile", _mediaUrlGeneratorCollection)
};
// Serialize the image cropper value
var propertyValue = serializer.Serialize(imageCropperValue);
// Set the value of the property with alias "cropper"
// - remember to add the "culture" parameter if "cropper" is set to vary by culture
content.SetValue("cropper", propertyValue);
return _contentService.Save(content).Success;
}
}
If you use Models Builder to generate source code (modes SourceCodeAuto
or SourceCodeManual
), you can use nameof([generated property name])
to access the desired property without using a magic string:
// Set the value of the "Cropper" property on content of type MyContentType
// - remember to add the "culture" parameter if "cropper" is set to vary by culture
content.SetValue(nameof(MyContentType.Cropper).ToFirstLowerInvariant(), propertyValue);
Crop URLs are not limited to usage within a view. IPublishedContent
has a GetCropUrl
extension method, which can be used to access crop URLs anywhere.
The following sample demonstrates how to use GetCropUrl
to retrieve URLs for all crops defined on a specific image:
public Dictionary<string, string> GetCropUrls(IPublishedContent image)
{
// Get the Image Cropper property value for property with alias "umbracoFile"
ImageCropperValue? imageCropperValue = image.Value<ImageCropperValue>("umbracoFile");
if (imageCropperValue?.Crops == null)
{
return new Dictionary<string, string>();
}
// Return all crop aliases and their corresponding crop URLs as a dictionary
var cropUrls = new Dictionary<string, string>();
foreach (ImageCropperValue.ImageCropperCrop crop in imageCropperValue.Crops)
{
// Get the cropped URL and add it to the dictionary that I will return
var cropUrl = crop.Alias != null
? image.GetCropUrl(crop.Alias)
: null;
if (cropUrl != null)
{
cropUrls.Add(crop.Alias!, cropUrl);
}
}
return cropUrls;
}
Below the example to output a PNG using ImageSharp.Web format command.
<img src="@Url.GetCropUrl(Model.Photo, 500, 300, furtherOptions: "&format=png")" />
Templating in Umbraco builds on the concept of Razor Views from ASP.NET MVC.
Templates are the files that control the look and feel of the frontend of your Umbraco websites. Building on the concept of MVC Razor Views, template files enable you to structure your websites using HTML, CSS, and JavaScript. When tied to a Document Type, templates are used to render your Umbraco content on the frontend.
You can manage and work with your templates directly from the Settings section in the Umbraco backoffice. Each Template can also be found as a cshtml
file in the Views
folder in your project directory.
When building an Umbraco website you can automatically generate Templates when you create a new Document Type. This will ensure the connection between the two and you can jump straight from defining the content to structuring it.
Choose the option called Document Type with Template when you create a new Document Type to automatically create a Template as well.
In some cases, you might want to create independent Templates that don't have a direct connection to a Document Type. You can follow the steps below to create a new blank Template:
Go to the Settings section inside the Umbraco backoffice.
Click ... next to the Templates folder.
Choose Create.
Enter a template name.
Click the Save button.
You will now see the default template markup in the backoffice template editor.
To use a Template on your content, you must first allow it on the content Document Type.
Open the Document Type you want to use the template.
Open the Templates Workspace View.
Select your Template under the Allowed Templates section.
A Template can inherit content from a "Master Template". This is done by using the ASP.NET views Layout feature.
Let's say you have a Template called MainView, containing the following HTML:
@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage
@{
Layout = null;
}
<!DOCTYPE html>
<html lang="en">
<body>
<h1>Hello world</h1>
@RenderBody()
</body>
</html>
This file contains the structural HTML tags for your website.
By using the Template as the "Master Template" on your other Templates, you can ensure that they inherit the same structural HTML.
Follow these steps to use a Template file as a Master Template:
Open one of your Template files.
Select the Master template: No master button above the editor.
Select the Template that should be defined as the Master Template.
Click Choose.
Alternatively, you can manually change the value of the Layout
variable in the Template using the name of the Template file.
The updated markup will look something like the snippet below and the Template is now referred to as a Child Template:
@inherits Umbraco.Web.Mvc.UmbracoViewPage
@{
Layout = "MainView.cshtml";
}
<p>My content</p>
When a page that uses a Template with a Master Template defined is rendered, the HTML of the two templates is merged.
The code from the Template replaces the @RenderBody()
tag in the Master Template. Following the examples above, the final HTML will look like the code in the snippet below:
@inherits Umbraco.Web.Mvc.UmbracoViewPage
@{
Layout = null;
}
<!DOCTYPE html>
<html lang="en">
<body>
<h1>Hello world</h1>
<p>My content</p>
</body>
</html>
Template Sections give you added flexibility when building your templates. Use the Template Section together with a Master Template setup, to decide where sections of content are placed.
If a Child Template needs to add code to the <head>
tag a Section must be defined and then used in the Master Template. This is made possible by Named Sections.
The following steps will guide you through defining and using a Named Section:
Open your Template.
Select the Sections option.
Choose Define a named section.
Give the section a name and click Submit.
The following code will be added to your Template:
@section SectionName {
}
Add your code between the curly brackets.
Save the changes.
Open the Master Template.
Choose a spot for the section and set the cursor there.
Select the Sections option.
Choose Render a named section.
Enter the name of the section you want to add.
Click Submit.
For instance, if you want to be able to add HTML to your <head>
tags, you would add the tag there:
@inherits Umbraco.Web.Mvc.UmbracoViewPage
@{
Layout = null;
}
<html>
<head>
<title>Title</title>
@RenderSection("SectionName", false)
</head>
<body>
</body>
</html>
You can decide whether a section should be mandatory or not. Making a section mandatory means that any template using the Master Template is required to have the section defined.
To make the section mandatory, you have two options:
Add true
to the code tag: @RenderSection("SectionName", true)
.
Check the Section is mandatory field when using the Sections dialog in the backoffice.
Another way to reuse HTML is to use partial views - which are small reusable views that can be injected into another view.
Like templates, you can create a partial view, by clicking ... next to the Partial Views folder and selecting Create. You can then either create an empty partial view or a partial view from a snippet.
The created partial view can now be injected into any template by using the @Html.Partial()
method like so:
@inherits Umbraco.Web.Mvc.UmbracoViewPage
@{
Layout = "MasterView.cshtml";
}
<h1>My new page</h1>
@Html.Partial("a-new-view")
Information on hosting Umbraco on IIS
Download the .NET Core Runtime from the .
Ensure you download the version that matches your project’s requirements, which can be found in the article.
Download the to enable IIS to run ASP.NET Core applications.
After installing .NET Core Runtime, restart IIS to ensure the changes are applied.
Open Command Prompt as Administrator.
Run the following commands:
Next, create a new site in IIS for hosting Umbraco.
Open IIS Manager.
Right-click on Application Pools in the Connections panel.
Select Add Application Pool.
Enter the Name.
Ensure the .NET Common Language Runtime (CLR) version is set to No Managed Code.
Click Ok.
Open IIS Manager.
Right-click on Sites in the Connections panel.
Select Add Website.
Fill in the Site Name, Physical Path (to your Umbraco installation), and the Port.
Click Ok.
You can either use the dotnet CLI or Visual Studio to publish your Umbraco website.
Open the Command Prompt in the directory of your Umbraco project.
Run the following command:
Open your project in Visual Studio.
Right-click on the Umbraco project in Solution Explorer.
Select Publish....
In IIS, you can configure environment variables for Umbraco to store sensitive data such as your connection string.
Open IIS Manager and select your Umbraco site.
Double-click Configuration Editor in the Management section.
Select system.webServer/aspNetCore
in the Section dropdown.
Select ApplicationHost.config <location path='[YOUR-SITENAME]'>
in the From dropdown.
This ensures your settings will be stored in a machine specific file. The configuration files might end in a public repository and should not contain sensitive data like Connection Strings or Simple Mail Transfer Protocol (SMTP) credentials. Additionally, by default the configuration file will be overwritten during each publish processes.
Locate the environmentVariables line and open the dialog to add environment variables.
Enter the values for ASPNETCORE_ENVIRONMENT
and ConnectionStrings__umbracoDbDSN
.
Click Add.
Click Apply.
Restart IIS to apply the changes after updating the environment variables.
IIS can host .NET applications using two different hosting models: In-process (default) and Out-of-process.
runs the .NET application within the same process as the IIS worker process.
This is the default hosting model and is more efficient, as there is no inter-process communication between IIS and the application.
No changes are required to your application configuration for in-process hosting. It works automatically with the default IIS settings.
allows the .NET application to run separately from the IIS worker process. IIS acts as a reverse proxy to the Kestrel server, which hosts the .NET application.
This model is useful when you need to run a .NET application in a separate process, for example, when the application requires more isolated resources or needs to scale independently from IIS.
To enable out-of-process hosting:
Open your Umbraco project.
Locate the .csproj
file.
Add the following line:
Save the .csproj
file.
Rebuild your application.
Issue: A 405 error may occur when attempting to save content items in Umbraco, due to the WebDAV module blocking PUT requests.
Solution: If you encounter this issue, it may be because the WebDAV module in IIS is blocking the necessary PUT requests. This issue is not present on all IIS setups, but if you do have WebDAV installed, try disabling the WebDAV module.
Workaround:
Open the web.config
file.
Add the following code to remove the WebDAV module:
Restart IIS.
net stop was /y
net start w3svc
dotnet publish -o ../deployment-artefacts -f net9.0
<PropertyGroup>
<AspNetCoreHostingModel>OutOfProcess</AspNetCoreHostingModel>
</PropertyGroup>
<modules runAllManagedModulesForAllRequests="false">
<remove name="WebDAVModule" />
</modules>
Umbraco HQ offers a training course covering the basics of working with Umbraco CMS in a load-balanced setup. The course targets backend developers and operations engineers.
Explore the Load Balancing Training Course to learn more about the topics covered and get more details about the course.
In this article you can learn the various ways of customizing the Umbraco backoffice login screen and form.
To access the backoffice, you will need to login. You can do this by adding /umbraco
at the end of your website URL, for example http://mywebsite.com/umbraco
.
You will be presented with a login form similar to this:
The login screen contains a short greeting, a login form and an optional Forgotten password link.
Below, you will find instructions on how to customize the login screen.
The login screen features a greeting text: The "Welcome" headline. This can be personalized by overriding the existing language translation keys.
To do this follow the steps below:
Register a 'localization' manifest for the default language of your Umbraco site, (usually en-US) to override the greetings.
{
"alias": "login.extensions",
"name": "Login extensions",
"version": "1.0.0",
"allowPublicAccess": true,
"extensions": [
{
"type": "localization",
"alias": "Login.Localize.EnUS",
"name": "English",
"js": "/App_Plugins/Login/en-us.js",
"meta": {
"culture": "en-US"
}
}
]
}
Add an en-us.js
file containing the following:
export default {
auth: {
instruction: "Log in again to continue",
greeting0: "Is is Sunday",
greeting1: "Is is Monday",
greeting2: "Is is Tuesday",
greeting3: "Is is Wednesday",
greeting4: "Is is Thursday",
greeting5: "Is is Friday",
greeting6: "Is is Saturday",
}
}
This will override the default greetings with the ones you provide. The login screen will now display "It is Sunday" instead of "Welcome" for example.
You can customize other text on the login screen as well. First, grab the default values and keys from the en.ts in the Umbraco CMS GitHub repository. Thereafter copy the ones you want to translate into ~/App_Plugins/Login/umbraco-package.json
file.
The Forgotten password? link allows your backoffice users to reset their password. To use this feature, you will need to add the following key to the Umbraco.Cms.Security
section in the appsettings.json
file:
"Umbraco": {
"CMS": {
"Security": {
"AllowPasswordReset": true
}
}
}
Set it to true
to enable the password reset feature, and false
to disable the feature.
You will also need to configure a Simple Mail Transfer Protocol (SMTP) server in your appsettings.json
file. When you get a successful result on the SMTP configuration when running a health check in the backoffice, you are good to go!
An example:
"Umbraco": {
"CMS": {
"Global": {
"Id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"Smtp": {
"From": "[email protected]",
"Host": "127.0.0.1",
"Username": "username",
"Password": "password"
}
}
}
}
It is possible to customize the background image and the logo for the backoffice login screen by adding the "Content"
section in the appsettings.json
file:
"Umbraco": {
"CMS": {
"Content": {
"LoginBackgroundImage": "../myImagesFolder/myLogin.jpg",
"LoginLogoImage": "../myImagesFolder/myLogo.svg",
"LoginLogoImageAlternative": "../myImagesFolder/myLogo.svg"
}
}
}
The LoginBackgroundImage
, LoginLogoImage
, and LoginLogoImageAlternative
are referenced from the /wwwroot/umbraco/
folder.
The LoginLogoImage
is displayed on top of the LoginBackgroundImage
and the LoginLogoImageAlternative
is displayed when the LoginLogoImage
is not available, for example on small resolutions.
You can also customize the login screen by adding a custom CSS file. To do this, you will need to add a new file inside the ~/App_Plugins
folder, for example ~/App_Plugins/Login/my-custom-login-screen.css
.
You can then add your custom CSS to the file:
:root {
--umb-login-curves-color: rgba(0, 0, 0, 0.1);
}
This will change the color of the SVG graphics (curves) shown on the login screen. You can also hide the curves by adding the following CSS:
:root {
--umb-login-curves-display: none;
}
To tell Umbraco about your custom CSS file, you will need to add a umbraco-package.json
file. The umbraco-package.json
file should look like this:
{
"alias": "login.extensions",
"name": "Login extensions",
"version": "1.0.0",
"allowPublicAccess": true,
"extensions": [
{
"type": "appEntryPoint",
"alias": "MyCustomLoginScreen",
"name": "My Custom Login Screen",
"js": "/App_Plugins/Login/my-custom-login-screen.js"
}
]
}
Next add a JavaScript file, for example ~/App_Plugins/Login/my-custom-login-screen.js
, and add the following code to load the custom CSS file:
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = '/App_Plugins/Login/my-custom-login-screen.css';
document.head.appendChild(link);
This will load the custom CSS file into Umbraco.
Be aware that the custom CSS file will be loaded on all Umbraco screens, not only the login screen.
The following CSS properties are available for customization:
--umb-login-background
The background of the layout
#f4f4f4
--umb-login-primary-color
The color of the headline
#283a97
--umb-login-text-color
The color of the text
#000
--umb-login-header-font-size
The font-size of the headline
3rem
--umb-login-header-font-size-large
The font-size of the headline on large screens
4rem
--umb-login-header-secondary-font-size
The font-size of the secondary headline
2.4rem
--umb-login-image
The background of the image wrapper
The value of the setting
--umb-login-image-display
The display of the image wrapper
flex
--umb-login-image-border-radius
The border-radius of the image wrapper
38px
--umb-login-content-background
The background of the content wrapper
none
--umb-login-content-display
The display of the content wrapper
flex
--umb-login-content-width
The width of the content wrapper
100%
--umb-login-content-height
The height of the content wrapper
100%
--umb-login-content-border-radius
The border-radius of the content wrapper
0
--umb-login-align-items
The align-items of the main wrapper
unset
--umb-login-button-border-radius
The border-radius of the buttons
45px
--umb-login-curves-color
The color of the curves
#f5c1bc
--umb-login-curves-display
The display of the curves
inline
The CSS custom properties may change in future versions of Umbraco. You can always find the latest values in the login layout element in the Umbraco CMS GitHub repository.
The time out screen is displayed when the user has been inactive for a certain amount of time. The screen resembles the login screen in many ways and the two are sometimes confused. The most notable difference is that the time out screen does not have a login form. It only has a message and a button to log in again with Umbraco.
If you have added more than one login provider, the users will also see this screen first. This is because they need to choose which provider to use first. In that case, the screen is also referred to as the Choose provider screen.
You can customize the time out screen in the same way as the login screen. The time out screen uses the same localization files as the rest of the Backoffice and not those of the login screen. The notable difference is that the time out screen is scoped to the login
section. The login screen is scoped to the auth
section of the localization files.
To update the greeting message on this screen, you will have to change the section to login
:
{
"alias": "login.extensions",
"name": "Login extensions",
"version": "1.0.0",
"allowPublicAccess": true,
"extensions": [
{
"type": "localization",
"alias": "Login.Localize.EnUS",
"name": "English",
"js": "/App_Plugins/Login/en-us.js",
"meta": {
"culture": "en-US"
}
}
]
}
The en-us.js
file should contain the following:
export default {
auth: {
instruction: "Log in again to continue",
greeting0: "Is is Sunday",
greeting1: "Is is Monday",
greeting2: "Is is Tuesday",
greeting3: "Is is Wednesday",
greeting4: "Is is Thursday",
greeting5: "Is is Friday",
greeting6: "Is is Saturday",
}
}
The instruction
key is shown when the user has timed out, and the greeting0..6
keys are shown when the user has to choose a login provider.
You can update the image on the time out screen through a custom CSS variable. The default value is --umb-login-image
and it is set to the same value as the login screen. You can override this value in your custom CSS file:
:root {
--umb-login-image: url(../myImagesFolder/myTimeout.jpg);
}
Instructions on installing nightly builds of Umbraco.
In this article, we'll explain how you can get the latest builds of Umbraco. You can do this in three steps:
The NuGet feed containing the nightly builds is https://www.myget.org/F/umbraconightly/api/v3/index.json
.
You can either add this feed through the command line or use an IDE of your choice. In this article, we'll provide steps for:
To add the nightly feed using the command line:
Open a command prompt of your choice.
Run the following command:
Now the feed is added as a source named Umbraco Nightly
.
To add the nightly feed using Visual Studio:
Open Visual Studio.
Go to Tools > NuGet Package Manager > Package Manager Settings.
The Options window open.
Select the Package Sources option in the NuGet Package Manager section.
Click the +
icon.
A new Package source will be added automatically and highlighted.
Enter the desired name for the feed in the Name field.
Enter the link https://www.myget.org/F/umbraconightly/api/v3/index.json
into the Source field.
Click OK.
Now the feed is added as a source named Umbraco Nightly
.
To add the nightly feed using Rider:
Open Rider.
Go to View > Tool Windows > NuGet.
Go to Sources tab.
Choose the C:\Users\Úmbraco\AppData\Roaming\NuGet\NuGet.Config
to add the feed globally.
Cick the green +
button in the New Feed field.
The New feed dialog opens.
Enter the desired name in the Name field.
Enter https://www.myget.org/F/umbraconightly/api/v3/index.json
in the URL field.
Click OK.
Now the feed is added as a source named Umbraco Nightly
.
In the previous steps, we've added the feed and are now ready to install the nightly build.
However, which version should we install? This is, in particular, an issue if we want to create a new site using the dotnet template. The dotnet command does not allow us to use wildcard characters to install the newest version.
Using IDE, we can see a list of available versions in both Visual Studio and Rider. We can then use that version to install the template.
Here we're going to assume that you want to create a brand new site with the dotnet template. The approach is the same if you're updating an existing site. You'll click the Update button for the Umbraco.Cms
package instead of installing the template through the terminal.
Let's look at how we can find the latest version of the nightly build:
You can use the package manager in Visual Studio to browse the available template versions.
Open Visual Studio.
Go to Tools > NuGet Package Manager > Manage NuGet Packages For Solution...
Select Umbraco Nightly from the Package source dropdown in the NuGet - Solution window.
Check the Include prerelease checkbox.
Search for Umbraco.Templates in the Browse field.
Choose that package.
Click on the Version dropdown and see the available nightly builds.
Choose the applicable version and note down the version number.
You can use the NuGet window in Rider to browse the available template versions.
Open Rider.
Go to the Packages tab in the NuGet window..
Select Umbraco Nightly from the All Feeds dropdown.
Check the Prerelase checkbox.
Search for Umbraco.Templates in the Search field.
Choose that package.
Click on the Version drop down and see the available nightly builds.
Choose the applicable version and note down the version number
Now that our feed is added and we know the exact version we're ready to install our template.
To install the latest nightly version template:
Open your command prompt.
Run the following command using the latest version:
With that, we've successfully installed the latest nightly build of Umbraco.
All we have to do now is to create a site using the dotnet new umbraco -n MyAwesomeNightlySite
command.
For more information about installing Umbraco, see the article.
dotnet nuget add source "https://www.myget.org/F/umbraconightly/api/v3/index.json" -n "Umbraco Nightly"
dotnet new install Umbraco.Templates
Here you'll find an explanation of how content is defined in Umbraco
Before a piece of content can be created in the Umbraco backoffice, first it needs to be defined. That is why, when opening a blank installation of Umbraco, it is not possible to create content in the Content section.
All content needs a blueprint that holds information about what kind of data can be stored on the content node or which editors are used.
Additionally, it also needs information on how it is organized, where in the structure it is allowed, and so forth. This blueprint or definition is called a Document Type.
Document Types define what kind of content can be created in the Content section and what an end-user sees and can interact with.
It can define entire pages or more limited content that can be reused on other nodes ie. a Search Engine Optimization (SEO) group. This means that you are in complete control of what type of content can be created and where.
Another example is if there is a "Blog post
" Document Type that has some properties containing a thumbnail, a name, and an author image. Then all blog posts using the "Blog post
" Document Type, will allow the end user to fill in a thumbnail, author name, and an author image.
A Document Type contains fieldsets (or groups) where you can apply rules about where the content can be created, allowed template(s), backoffice icons, etc.
A Document Type is created using the Document Type editor in the Settings section.
Go to the Settings section in the backoffice.
On the Document Types node click the menu icon (•••) to bring up the context menu.
Here choose Document Type with Template. This will create a new Document Type with a template. The Template can be found under Templates in the Settings section which will be assigned as the default template for the Document Type.
You can also choose to create a Document Type without a template and create Folders to organize your Document Types. Other options are to create Compositions and Element types, which you can read more about in the Default Document Types section.
First, we're prompted to give the Document Type a name. This first Document Type will be the root node for our content, name it "Home
".
Having a root node lets you quickly query content as you know everything will be under the root node.
Choosing appropriate icons for your content nodes is a good way to give editors a better overview of the content tree.
To set an icon for the Document Type click the document icon in the top left corner. This will open the icon select dialog. Search for "Home"
and select the icon. This icon will be used in the content tree.
This will allow this Document Type to be created as the first content in the Content section.
Go to the Structure tab
Tick the Allow as root toggle
Save the Document Type by clicking save in the bottom right corner.
Now that we have the Document Type in place, we can create the content.
Go to the Content section
Click on the menu icon next to Content
Select the "Home
" Document Type. We'll name it "Home
"
Then click the Save and Publish button.
As we haven't created our properties, all we can see on the "Home
" node is the Properties tab. This tab contains the default properties that are available on all content nodes in Umbraco.
Let's add some properties of our own.
In order to add the option to create different content on the same Document Type, some groups and properties need to be added.
Groups
Groups are a way to organize and structure the properties within the content, making it more manageable. It also makes it more user-friendly for content editors when creating or editing content on a website.
A name can be added to the group and after properties can be added.
Properties
Each field on a Document Type is called a property. The property is given a name, an alias (used to output the properties contained in a template), and an editor.
The editor determines what type of data the property will store and the input method. There is a wide range of default property editors available and you can customize additional editors.
Some editors require configuration where a configured editor is saved as a Data Type and can be reused for multiple properties and document types. These can be seen in the Settings section under Data Types.
Go to the Settings section
Expand Document Types by clicking the arrow to the left
Select the "Home
" Document Type.
Before we start adding properties to the Document Type we need to create a group to hold the property.
Click Add group and name the group "Content
".
To convert a group to a tab, see the Convert a group to a tab section in the Using Tabs article.
Now that we have created a group we can start adding properties. Let's add a Rich Text editor to the Content group.
Click the Add property link in the Content group. This opens the property settings dialog. Here you can set the metadata for each property (name, alias, description)
Choose which Data Type/property editor to use, and add validation if needed.
Give the property a name. The name will be shown to the editor to make it relevant and understandable. Notice the alias is automatically generated based on the name. We'll name this "Body Text
".
Clicking Select Editor will open the Select Editor dialog. Here, you can choose between all the available editors on the Create a new Configuration tab. This will create a new configuration or already configured editors in the Available Configurations tab.
To make it easier to find what you need use the search field to filter by typing "Rich
". Filtering will display configured properties first (under Available configurations) and all available editors under that.
Select the Rich Text editor under Create new. This will let you configure the editor settings - the Rich Text editor for this property.
Let's rename it to "Basic Rich Text editor
" and only select the most necessary options.
bold
italic
alignLeft
alignCenter
link
umbMediaPicker
When you are happy with the settings click Submit.
Save the Document Type.
If you go to the Content section and click on the Home node
you will now see the Content
group with the Body Text
property.
The description of the property is not necessary, but it´s a best practice as it guides the editor to use the property correctly. The property description supports some markdown and one custom collapse syntax:
Now if we put it all together we get something like this:
This is **bold**
This is *italic*
[This is an absolute link](https://google.com)
[This is a relative link](/umbraco#/media)
--

Next up we'll create a text page Document Type that will be used for subpages on the site.
Go back to the Settings section
Create a new Document Type
Name it "Text Page
".
Add a group called "Content
"
This time we'll add two properties:
First, make a property called "Summary
" using the Textarea editor
Secondly, create a property called "Body Text
" and reuse the Rich Text Editor Data Type.
Before creating a Text Page in Content section, allow the Text Page Document Type to be created as a child node to the Home node.
Select the "Home
" Document Type
Go to the Structure group.
Click Add child
Select "Text Page
".
Go to the Content section
Click the menu icon (•••) next to the "Home
" node
Select the "Text page
" Document Type. We'll name the page "About us
". We now have a basic content structure.
Document Types are flexible and can be used for defining pieces of reusable content or an entire page, to act as a container or repository.
You can also export document types from an already existing project/installation and import them into another project/installation.
Go to the Settings section
Click ... next to the Document type
Select Export. When you click on the Export button, the Document Type is saved as a *.udt file.
To import a Document Type:
Go to the Settings section
Click ... next to the Document type
Select Import Document Type
Click on the Import button and browse to the Document Type you exported. The Name and Alias of the Document Type are displayed.
Click Import to complete the process.
Schema Alias: Umbraco.BlockList
UI Alias: Umb.PropertyEditorUi.BlockList
Returns: IEnumerable<BlockListItem>
This article is a work in progress and may undergo further revisions, updates, or amendments. The information contained herein is subject to change without notice.
Block List is a list editing property editor, using to define the list item schema.
The Block List property editor is configured in the same way as any standard property editor, via the Data Types admin interface.
To set up your Block List Editor property, create a new Data Type and select Block List from the list of available property editors.
Then you will see the configuration options for a Block List as shown below.
The Data Type editor allows you to configure the following properties:
Available Blocks - Here you will define the Block Types to be available for use in the property. Read more on how to set up Block Types below.
Amount - Sets the minimum and/or maximum number of blocks that should be allowed in the list.
Single block mode - When in Single block mode, the output will be BlockListItem<>
instead of BlockListModel
Live editing mode - Enabling this will make editing of a block happening directly to the document model, making changes appear as you type.
Inline editing mode - Enabling this will change editing experience to inline, meaning that editing the data of blocks happens at sight as accordions.
Property editor width - Overwrite the width of the property editor. This field takes any valid css value for "max-width".
Block Types are Element Types which need to be created before you can start configuring them as Block Types. This can be done either directly from the property editor setup process, or you can set them up beforehand and add them to the block list after.
Once you have added an element type as a Block Type on your Block List Data Type you will have the option to configure it further.
Each Block has a set of properties that are optional to configure. They are described below.
By configuring the properties in the group you can customize the user experience for your content editors when they work with the blocks in the Content section.
Label - Define a label for the appearance of the Block in the editor. The label uses to display values of properties. The label is also used for search in the Add Block dialog during content editing. If no label is defined, the block will not be searchable. The search does not fall back to the block’s name.
Overlay editor size - Set the size for the Content editor overlay for editing this block.
It is possible to use two separate Element Types for your Block Types. Its required to have one for Content and optional to add one for Settings.
Content model - This presents the Element Type used as model for the content section of this Block. This cannot be changed, but you can open the Element Type to perform edits or view the properties available. Useful when writing your Label.
Settings model - Add a Settings section to your Block based on a given Element Type. When picked you can open the Element Type or choose to remove the settings section again.
These properties refer to how the Block is presented in the Block catalogue, when editors choose which Blocks to use for their content.
Background color - Define a background color to be displayed beneath the icon or thumbnail. Eg. #424242
.
Icon color - Change the color of the Element Type icon. Eg. #242424
.
Thumbnail - Pick an image or SVG file to replace the icon of this Block in the catalogue.
The thumbnails for the catalogue are presented in the format of 16:10, and we recommend a resolution of 400px width and 250px height.
These properties are relevant when you work with custom views.
Force hide content editor - If you made a custom view that enables you to edit the content part of a block and you are using default editing mode (not inline) you might want to hide the content-editor from the block editor overlay.
When viewing a Block List editor in the Content section for the first time, you will be presented with the option to Add content.
Clicking the Add content button brings up the Block Catalogue.
The Block Catalogue looks different depending on the amount of available Blocks and their catalogue appearance.
Click the Block Type you wish to create and a new Block will appear in the list.
Depending on whether your Block List Editor is setup to use default or inline editing mode you will see one of the following things happening:
In default mode you will enter the editing overlay of that Block:
In inline editing mode the new Blocks will expand to show its inline editor:
More Blocks can be added to the list by clicking the Add content button or using the inline Add content button that appears on hover between or above existing Blocks.
To reorder the Blocks, click and drag a Block up or down to place in the desired order.
To delete a Block click the trash-bin icon appearing on hover.
Rendering the stored value of your Block List property can be done in two ways.
You can choose to use the built-in rendering mechanism for rendering blocks via a Partial View for each block.
The default rendering method is named GetBlockListHtml()
and comes with a few options to go with it. The typical use could be:
"MyBlocks" above is the alias for the Block List editor.
If using ModelsBuilder the example can be simplified:
Example:
To make this work you will need to create a Partial View for each block, named by the alias of the Element Type that is being used as Content Model.
These partial views must be placed in this folder: Views/Partials/BlockList/Components/
. Example: Views/Partials/BlockList/Components/MyElementTypeAliasOfContent.cshtml
.
A Partial View will receive the model of Umbraco.Core.Models.Blocks.BlockListItem
. This gives you the option to access properties of the Content and Settings section of your Block.
In the following example of a Partial view for a Block Type, please note that the MyElementTypeAliasOfContent
and MyElementTypeAliasOfSettings
should correspond with the selected Element Type Alias for the given model in your case.
Example:
With ModelsBuilder:
A built-in value converter is available to use the data as you like. Call the Value<T>
method with a generic type of IEnumerable<BlockListItem>
and the stored value will be returned as a list of BlockListItem
entities.
Example:
Each item is a BlockListItem
entity that contains two main properties Content
and Settings
. Each of these is a IPublishedElement
which means you can use all the value converters you are used to using.
Example:
In some cases, you might want to use the Block List Editor to hold some data and not necessarily render a view since the data should be presented in different areas on a page. An example could be a product page with variants stored in a Block List Editor.
In this case, you can extract the variant's data using the following, which returns IEnumerable<IPublishedElement>
.
Example:
If using ModelsBuilder the example can be simplified:
Example:
If you know the Block List Editor only uses a single block, you can cast the collection to a specific type T
using .OfType<T>()
otherwise the return value will be IEnumerable<IPublishedElement>
.
Building Custom Views for Block representations in Backoffice is the same for all Block Editors.
@Html.GetBlockListHtml(Model, "MyBlocks")
@Html.GetBlockListHtml(Model.MyBlocks)
@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage<Umbraco.Cms.Core.Models.Blocks.BlockListItem>;
@using ContentModels = Umbraco.Cms.Web.Common.PublishedModels;
@{
var content = (ContentModels.MyElementTypeAliasOfContent)Model.Content;
var settings = (ContentModels.MyElementTypeAliasOfSettings)Model.Settings;
}
// Output the value of field with alias 'heading' from the Element Type selected as Content section
<h1>@content.Value("heading")</h1>
// Output the value of field with alias 'heading' from the Element Type selected as Content section
<h1>@content.Heading</h1>
@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage;
@using Umbraco.Cms.Core.Models.Blocks;
@{
var blocks = Model.Value<IEnumerable<BlockListItem>>("myBlocksProperty");
foreach (var block in blocks)
{
var content = block.Content;
@Html.Partial("MyFolderOfBlocks/" + content.ContentType.Alias, block)
}
}
@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage;
@using ContentModels = Umbraco.Cms.Web.Common.PublishedModels;
@using Umbraco.Cms.Core.Models.Blocks;
@{
var blocks = Model.Value<IEnumerable<BlockListItem>>("myBlocksProperty");
foreach (var block in blocks)
{
var content = (ContentModels.MyAliasOfContentElementType)block.Content;
var settings = (ContentModels.MyAliasOfSettingsElementType)block.Settings;
<h1>@content.MyExampleHeadlinePropertyAlias</h1>
}
}
@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage;
@using ContentModels = Umbraco.Cms.Web.Common.PublishedModels;
@using Umbraco.Cms.Core.Models.Blocks;
@{
var variants = Model.Value<IEnumerable<BlockListItem>>("variants").Select(x => x.Content);
foreach (var variant in variants)
{
<h4>@variant.Value("variantName")</h4>
<p>@variant.Value("description")</p>
}
}
@inherits Umbraco.Web.Mvc.UmbracoViewPage
@using ContentModels = Umbraco.Web.PublishedModels;
@{
var variants = Model.Variants.Select(x => x.Content).OfType<ProductVariant>();
foreach (var variant in variants)
{
<h4>@variant.VariantName</h4>
<p>@variant.Description</h4>
}
}
Schema Alias: Umbraco.ContentPicker
UI Alias: Umb.PropertyEditorUi.DocumentPicker
Returns: IEnumerable<IPublishedContent>
The Content Picker enables choosing the type of content tree to display and which specific part to render. It also allows you to set a dynamic root node for the content based on the current document using the Content Picker.
Define a limit on the number of items allowed to be selected.
Checking this field allows users to choose nodes they normally cannot access.
This option allows for configuring what type of content is available when using the Data Type. The available types of content are Content, Members, or Media items.
When selecting Content from the dropdown, the option to specify a root node, also called the origin, becomes available.
When picking the origin there are several different options available:
The following options are available when picking the origin:
Root: The root is the first level item of the sub-tree of the current node.
Parent: The parent is the nearest ancestor of the current node.
Current: The current node.
A picker that uses the current node, cannot pick anything when the current node is created, as it will not have any children.
Site: The nearest ancestor of the current node with a domain assigned.
Specific node: A specific node selected from the existing content.
When an origin has been specified, it becomes possible to continue to build a Dynamic Root by adding additional query steps.
Navigate the content tree relative to the specified origin to execute multiple query steps and find the root node needed.
The following options are available:
Nearest Ancestor or Self: Find the nearest ancestor or current item that fits with one of the configured Document Types.
Furthest Ancestor or Self: Find the furthest ancestor or current item that fits with one of the configured Document Types.
Nearest Descendant or Self: Find the nearest descendant or current item that fits with one of the configured Document Types.
Furthest Descendant or Self: Find the furthest descendant or current item that fits with one of the configured Document Types.
The options above are all based on navigating the document hierarchy by locating ancestors and descendants. It is possible to execute custom steps to build even more complex queries. Once a custom query is available it will be added to the bottom of the Append steps to query dialog. Learn more about .
Each query step takes the output from the origin or the previous step as input. It is only ever the result of the last query step that is passed to the next step.
Custom query steps can be used to solve specific use cases, such as traversing sibling documents or matching property values. Before the custom query steps can be selected in the Data Type settings, they must be defined via code.
When implementing a query step it requires a collection of origins and information about the query step. The collection is taken from where the name specified in the UI can be found.
Specifying the origin is required for the custom query step to become available.
Read the above to learn more about this.
You can inject dependencies into the constructor. These dependencies could be custom repositories or the IVariationContextAccessor
, if you want to use the current culture.
The ExecuteAsync
method receives a set of content keys from the last executed query step or the origin. It has to return a new set of content keys.
To register the custom query step, append it to the existing query steps, DynamicRootSteps()
. This is done from a composer as shown below.
Finally, register the custom query step on the client side and provide a brief description.
You can do this in an umbraco-package.json
file, as shown below:
Choose which types of content should be available to pick using the Content Picker.
This is done by selecting one or more Document Types.
Consider the following tree structure where the Document Type alias is presented in square brackets.
Codegarden
2023 [year
]
Talks [talks
]
...
Umbraco anno MMXXIII [talk
]
Stages [stages
]
Social Space [stage
]
No 10 [stage
]
No 16 [stage
]
The Theatre [stage
]
2022 [year
]
Talks [talks
]
...
Stages [stages
]
Main Stage [stage
]
The Barn [stage
]
The Theatre [stage
]
Consider configuring a Content Picker on the talk
Document Type to select a stage
for the talk
. Here, you want to display only the stages for the actual year. To do this, you need to set the parent as the origin.
For instance, if you are on the Umbraco anno MMXXIII
node, the collection of content keys passed into the first query step will only contain the Talks
content node.
First, query for the nearest ancestors of the type year
. This will return 2023
.
Second, query for the nearest descendants of the type stages
.
When opening the picker on the Umbraco anno MMXXIII
node, it will now show the children of the node on the path Codegarden > 2023 > Stages
.
See the example below to see how a value can be added or changed programmatically. To update the value of a property editor you need the .
Although the use of a GUID is preferable, you can also use the numeric ID to get the page:
If Models Builder is enabled you can get the alias of the desired property without using a magic string:
public class MyCustomDynamicRootQueryStep : IDynamicRootQueryStep
{
private readonly IMyCustomRepository _myCustomRepository;
public MyCustomDynamicRootQueryStep(IMyCustomRepository myCustomRepository)
{
_myCustomRepository = myCustomRepository;
}
// The string below is what you specify in the UI to execute this custom query step.
public virtual string SupportedDirectionAlias { get; set; } = "MyCustomStep";
public async Task<Attempt<ICollection<Guid>>> ExecuteAsync(ICollection<Guid> origins, DynamicRootQueryStep filter)
{
if (filter.Alias != SupportedDirectionAlias)
{
return Attempt<ICollection<Guid>>.Fail();
}
if (origins.Any() is false)
{
return Attempt<ICollection<Guid>>.Succeed(Array.Empty<Guid>());
}
// Replace the following with your custom logic
var result = await _myCustomRepository.GetWhateverIWantAsync(origins);
return Attempt<ICollection<Guid>>.Succeed(result);
}
}
public class CustomQueryStepComposer : IComposer
{
public void Compose(IUmbracoBuilder builder)
{
builder.DynamicRootSteps().Append<MyCustomDynamicRootQueryStep>();
}
}
{
"$schema": "../../umbraco-package-schema.json",
"name": "My.Test.Extension",
"version": "0.1.0",
"extensions": [
{
"type": "dynamicRootQueryStep",
"alias": "Umb.DynamicRootQueryStep.MyCustomStep",
"name": "Dynamic Root Query Step: My Custom Step",
"meta": {
"queryStepAlias": "MyCustomStep",
"label": "My Custom Step",
"description": "My custom step description.",
"icon": "icon-coffee"
},
"weight": 0
}
]
}
@{
var typedContentPicker = Model.Value<IEnumerable<IPublishedContent>>("featuredArticles");
if (typedContentPicker != null) {
foreach (var item in typedContentPicker)
{
<p>@item.Name</p>
}
}
@{
var typedContentPicker = Model.FeaturedArticles;
foreach (var item in typedContentPicker)
{
<p>@item.Name</p>
}
}
@using Umbraco.Cms.Core
@using Umbraco.Cms.Core.Services
@inject IContentService ContentService
@{
// Create a variable for the GUID of the page you want to update
var guid = Guid.Parse("32e60db4-1283-4caa-9645-f2153f9888ef");
// Get the page using the GUID you've defined
var content = ContentService.GetById(guid); // ID of your page
// Get the pages you want to assign to the Content Picker
var page = Umbraco.Content("665d7368-e43e-4a83-b1d4-43853860dc45");
var anotherPage = Umbraco.Content("1f8cabd5-2b06-4ca1-9ed5-fbf14d300d59");
// Create Udi's of the pages
var pageUdi = Udi.Create(Constants.UdiEntityType.Document, page.Key);
var anotherPageUdi = Udi.Create(Constants.UdiEntityType.Document, anotherPage.Key);
// Create a list of the page udi's
var udis = new List<string>{pageUdi.ToString(), anotherPageUdi.ToString()};
// Set the value of the property with alias 'featuredArticles'.
content.SetValue("featuredArticles", string.Join(",", udis));
// Save the change
ContentService.Save(content);
}
@{
// Get the page using it's id
var content = ContentService.GetById(1234);
}
@using Umbraco.Cms.Core.PublishedCache
@inject IPublishedContentTypeCache PublishedContentTypeCache
@{
// Set the value of the property with alias 'featuredArticles'
content.SetValue(Home.GetModelPropertyType(PublishedContentTypeCache, x => x.FeaturedArticles).Alias, string.Join(",", udis));
}
Schema Alias: Umbraco.BlockGrid
UI Alias: Umb.PropertyEditorUi.BlockGrid
Returns: BlockGridModel
The Block Grid property editor enables editors to layout their content in the Umbraco backoffice. The content is made of Blocks that can contain different types of data.
This article is a work in progress and may undergo further revisions, updates, or amendments. The information contained herein is subject to change without notice.
When testing out the property editor, you can use a set of predefined Blocks. The option will only be possible when there are no other Data Types using the Block Grid property editor.
Create a new Data Type.
Select the Block Grid as the Property editor.
Install the "Sample Configuration".
4 Blocks will be added to the property, ready for testing.
The Block Grid property editor is configured via the Data Types backoffice interface.
To set up the Block Grid property editor, follow these steps:
Navigate to the Settings section in the Umbraco backoffice.
Click ... next to the Data Types folder.
Select Create -> New Data Type.
Select Block Grid from the list of available property editors.
You will see the configuration options for a Block Grid property editor as shown below:
The Data Type editor allows you to configure the following properties:
Blocks - Defines the Block Types available for use in the property. For more information, see Setup Block Types.
Amount - Sets the minimum and/or the maximum number of Blocks that should be allowed at the root of the layout.
Live editing mode - Enabling this option will allow you to see the changes as you are editing them.
Editor width - Overwrites the width of the property editor. This field takes any valid CSS value for "max-width". For example: 100% or 800px.
Grid Columns - Define the number of columns in your Block Grid. The default is 12 columns.
Layout Stylesheet - Replaces the built-in Layout Stylesheet. Additionally, you can retrieve the default layout stylesheet to use as a base for your own inspiration or for writing your own stylesheet.
Create Button Label - Overwrites the label on the Create button.
Block Types are based on Element Types. These can be created beforehand or while setting up your Block Types.
Once you have added an Element Type as a Block Type on your Block Grid Data Type you have the option to configure it.
Blocks can also be grouped. This is visible in the Block Catalogue and can also be used to allow a group of Blocks in an Area.
Each Block has a set of properties that are optional to configure. These are described below.
Customize the user experience for your content editors when they work with the Blocks in the Content section.
Label - Defines a label for the appearance of the Block in the editor. The label can use AngularJS template-string-syntax to display values of properties. The label is also used for search in the Add Block dialog during content editing. If no label is defined, the block will not be searchable. The search does not fall back to the block’s name.
Content model - Presents the Element Type used as model for the Content section of this Block. This cannot be changed but you can open the Element Type to perform edits or view the properties available. Useful when writing your Label.
Settings model - Adds a Settings section to your Block based on a given Element Type. When selected you can open the Element Type or choose to remove the Settings section again.
Customize the Blocks size in the Grid. If you define multiple options, the Block becomes scalable.
By default, a Block takes up the available width.
A Block can be resized in two ways:
When a Block is placed in an Area, it will fit to the Areas width. Learn more about Areas.
A Block can have one or more Column Span options defined.
A Column Span option is used to define the width of a Block. With multiple Column Span options defined, the Content Editor can scale the Block to fit specific needs.
Additionally, Blocks can be configured to span rows, this enables one Block to be placed next to a few rows containing other Blocks.
Available column spans - Defines one or more columns, the Block spans across. For example: in a 12 columns grid, 6 columns is equivalent to half width. By enabling 6 columns and 12 columns, the Block can be scaled to either half width or full width.
Available row spans - Defines the amount of rows the Block spans across.
See the scaling blocks section of this article for an example of how scaling works.
These properties refer to how the Block is presented in the Block catalogue when editors choose which Blocks to use for their content.
Background color - Defines a background color to be displayed beneath the icon or thumbnail. Example: #424242
.
Icon color - Changes the color of the Element Type icon. Example: #242424
.
Thumbnail - Pick an image or Scalable Vector Graphics (SVG) file to replace the icon of the Block in the catalogue.
The thumbnails for the catalogue are presented in the format of 16:10. We recommend a resolution of 400px width and 250px height.
Allow in root - Determines whether the Block can be created at the root of your layout. Turn this off if you only want a Block to appear within Block Areas.
Allow in areas - Determines whether the Block can be created inside Areas of other Blocks. If this is turned off it can still be allowed in Block Areas by defining specific allowed Blocks.
Blocks can nest other Blocks to support specific compositions. These compositions can be used as a layout for other Blocks.
To achieve nesting, a Block must have one or more Areas defined. Each Area can contain one or more Blocks.
Each Area has a size, defined by column and rows spans. The grid for the Areas are based on the same amount of columns as your root grid, unless you choose to change it.
To scale an Area, click and drag the scale-button in the bottom-right corner of an Area.
Grid Columns for Areas - Overwrites the amount of columns used for the Area grid.
Areas - Determines whether the Block can be created inside Areas of other Blocks.
Alias - The alias is used to identify this Area. It is being printed by GetBlockGridHTML()
and used as name for the Area slot in Custom Views. The alias is also available for CSS Selectors to target the HTML-Element representing an Area.
Create Button Label - Overwrites the Create Button Label of the Area.
Number of blocks - Determines the total number of Blocks in an Area.
Allowed block types - When this is empty, all Blocks with Permissions for creation in Areas, will be available. This can be overwritten by specifying the allowed Blocks. Define the types of Blocks or Groups of Blocks that are allowed. Additionally, you can also set how many Blocks of each type/group should be present.
When allowing a Group of Blocks, you might want to require a specific amount for a certain Block of that Group. This can be done by adding that Block Type to the list as well and set the requirements.
These properties are relevant when working with custom views or complex projects.
Custom view - Overwrites the AngularJS view for the block presentation in the Content editor. Use this view to make a more visual presentation of the Block or make your own editing experience by adding your own AngularJS controller to the view.
Custom stylesheet - Pick your own stylesheet to be used by the Block in the Content editor.
Overlay editor size - Sets the size for the Content editor overlay for editing this block.
Hide content editor - Hides the UI for editing the content in a Block Editor. This is only relevant if you made a custom view that provides the UI for editing of content.
When viewing a Block Grid property editor in the Content section for the first time, you will be presented with the option to Add content.
Clicking the Add content button opens up the Block Catalogue.
The Block Catalogue looks different depending on the amount of available Blocks and their catalogue appearance.
Click the Block Type you wish to create and a new Block will appear in the layout.
More Blocks can be added to the layout by clicking the Add content button. Alternatively, use the Add content button that appears on hover to add new Blocks between, besides, or above the existing Blocks.
To delete a Block, click the trash icon which appears on the mouse hover.
Blocks can be rearranged using the click and drag feature. Move them up or down to place them in the desired order.
Moving a Block from one Area to another is done in the same way. If a Block is not allowed in the given position, the area will display a red color and not allow the new position.
If a Block has multiple size options it can be scaled via the UI. This appears in the bottom left corner of the Block.
The Block is resized using a click-and-drag feature. Moving the mouse will change the size to the size options closest to the mouse pointer.
Rendering the stored value of your Block Grid property editor can be done in two ways:
You can choose to use the built-in rendering mechanism for rendering Blocks using a Partial View for each block.
The default rendering method is named GetBlockGridHtmlAsync()
and comes with a few options - for example:
@await Html.GetBlockGridHtmlAsync(Model, "myGrid")
In the sample above "myGrid"
is the alias of the Block Grid editor.
If you are using ModelsBuilder, the example will look like this:
@await Html.GetBlockGridHtmlAsync(Model.MyGrid)
To use the GetBlockGridHtmlAsync()
method, you will need to create a Partial View for each Block Type. The Partial View must be named using the alias of the Element Type that is being used as Content Model for the Block Type.
These Partial View files need to go into the Views/Partials/blockgrid/Components/
folder.
Example: Views/Partials/blockgrid/Components/MyElementTypeAliasOfContent.cshtml
.
The Partial Views will receive a model of type Umbraco.Cms.Core.Models.Blocks.BlockGridItem
. This model contains Content
and Settings
from your block, as well as the configured RowSpan
, ColumnSpan
, and Areas
of the Block.
The Partial View for the Block is responsible for rendering its own Block Areas. This is done using another built-in rendering mechanism:
@await Html.GetBlockGridItemAreasHtmlAsync(Model)
Here you will need to create a Partial View for each Block Type within the Block Area. For the name, use the alias of the Element Type that is being used as Content Model for the Block Type.
These Partial Views must be placed in the same folder as before, (Views/Partials/blockgrid/Components/
), and will receive a model of type Umbraco.Cms.Core.Models.Blocks.BlockGridItem
.
The following is an example of a Partial View for a Block Type of type MyElementTypeAliasOfContent
.
@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage<Umbraco.Cms.Core.Models.Blocks.BlockGridItem>;
@* Render the value of field with alias 'heading' from the Element Type selected as Content section *@
<h1>@Model.Content.Value("heading")</h1>
@* Render the block areas *@
@await Html.GetBlockGridItemAreasHtmlAsync(Model)
If you are using ModelsBuilder, you can make the property rendering strongly typed by letting your view accept a model of type BlockGridItem<T>
. For example:
@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage<Umbraco.Cms.Core.Models.Blocks.BlockGridItem<ContentModels.MyElementTypeAliasOfContent>>;
@using ContentModels = Umbraco.Cms.Web.Common.PublishedModels;
@* Render the Heading property from the Element Type selected as Content section *@
<h1>@Model.Content.Heading</h1>
@* Render the block areas *@
@await Html.GetBlockGridItemAreasHtmlAsync(Model)
Using the default rendering together with your layout stylesheet will provide what you need for rendering the layout.
To use the Default Layout Stylesheet, copy the stylesheet to your frontend. You can download the default layout stylesheet from the link within the DataType, we recommend putting the file in the css
folder, example: wwwroot/css/umbraco-blockgridlayout.css
.
<link rel="stylesheet" href="@Url.Content("~/css/blockgridlayout.css")" />
The built-in value converter for the Block Grid property editor lets you use the block data as you like. Call the Value<T>
method with a type of BlockGridModel
to have the stored value returned as a BlockGridModel
instance.
BlockGridModel
contains the Block Grid configuration (like the number of columns as GridColumns
) whilst also being an implementation of IEnumerable<BlockGridItem>
(see details for BlockGridItem
above).
The following example mimics the built-in rendering mechanism for rendering Blocks using Partial Views:
@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage
@using Umbraco.Cms.Core.Models.Blocks
@{
var grid = Model.Value<BlockGridModel>("myGrid");
// get the number of columns defined for the grid
var gridColumns = grid.GridColumns;
// iterate the block items
foreach (var item in grid)
{
var content = item.Content;
@await Html.PartialAsync("PathToMyFolderOfPartialViews/" + content.ContentType.Alias, item);
}
}
If you do not want to use Partial Views, you can access the block item data directly within your rendering:
@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage
@using Umbraco.Cms.Core.Models.Blocks
@{
var grid = Model.Value<BlockGridModel>("myGrid");
// get the number of columns defined for the grid
var gridColumns = grid.GridColumns;
// iterate the block items
foreach (var item in grid)
{
// get the content and settings of the block
var content = item.Content;
var settings = item.Settings;
// get the areas of the block
var areas = item.Areas;
// get the dimensions of the block
var rowSpan = item.RowSpan;
var columnSpan = item.ColumnSpan;
// render the block data
<div style="background-color: #@(settings.Value<string>("color"))">
<h2>@(content.Value<string>("title"))</h2>
<span>This block is supposed to span <b>@rowSpan rows</b> and <b>@columnSpan columns</b></span>
</div>
}
}
The default layout stylesheet is using CSS Grid. This can be modified to fit your implementation and your project.
To make additions or overwrite parts of the default layout stylesheet, import the default stylesheet at the top of your own file.
@import 'css/umbblockgridlayout.css';
You need to copy the Default Layout Stylesheet to your frontend. You can download the default layout stylesheet from the link within the DataType, we recommend putting the file in the css
folder, example: wwwroot/css/umbraco-blockgridlayout.css
.
In this case, you would have to write the layout from scratch.
You are free to pick any style, meaning there is no requirement to use CSS Grid. It is, however, recommended to use CSS Grid to ensure complete compatibility with the Umbraco backoffice.
When extending or writing your own layout, you need to know the structure and what data is available.
For example: You can use the below HTML structure:
<div class="umb-block-grid"
style="--umb-block-grid--grid-columns: 12;"
>
<!-- Notice this is the same markup used every time we will be printing a list of blocks: -->
<div class="umb-block-grid__layout-container">
<!-- repeated for each layout entry -->
<div
class="umb-block-grid__layout-item"
data-content-element-type-alias="MyElementTypeAlias"
data-content-element-type-key="00000000-0000-0000-0000-000000000000"
data-element-udi="00000000-0000-0000-0000-000000000000"
data-col-span="6"
data-row-span="1"
style="
--umb-block-grid--item-column-span: 6;
--umb-block-grid--item-row-span: 1;
"
>
<!-- Here the Razor View or Custom View for this block will be rendered. -->
<!-- Each razor view must render the 'area-container' them self.
This can be done by the Razor helper method:
@await Html.GetBlockGridItemAreasHtmlAsync(Model)
The structure will be as printed below,
Do notice targeting the 'area-container' needs a double selector as markup will be different in Backoffice.
Here is an example of the CSS selector:
.umb-block-grid__area-container, .umb-block-grid__block--view::part(area-container) {
position: relative;
}
-->
<div
class="umb-block-grid__area-container"
style="--umb-block-grid--area-grid-columns: 9;"
>
<!-- repeated for each area for this block type. -->
<div
class="umb-block-grid__area"
data-area-col-span="3"
data-area-row-span="1"
data-area-alias="MyAreaAlias"
style="
--umb-block-grid--grid-columns: 3;
--umb-block-grid--area-column-span: 3;
--umb-block-grid--area-row-span: 1;
">
<!-- Notice here we print the same markup as when we print a list of blocks(same as the one in the root of this structure..):
<div class="umb-block-grid__layout-container">
...
</div>
End of notice. -->
</div>
<!-- end of repeat -->
</div>
</div>
<!-- end of repeat -->
</div>
</div>
Building Custom Views for Block representations in Backoffice is based on the same API for all Block Editors.
Read about building a Custom View for Blocks here
In this example, we will be creating content programmatically for a "spot" Blocks in a Block Grid.
On a Document Type add a property called blockGrid.
Then add as editor Block Grid.
In the Block Grid add a new block and click to Create new Element Type
Name this element type spotElement with the following properties:
A property called title with the editor of Textstring
A property called text with the editor of Textstring
Then on the Settings model click to add a new Setting.
Then click to Create new Element Type.
Name this element type spotSettings with the following properties:
A property called featured with the editor of True/false.
The raw input data for the spots looks like this:
new[]
{
new { Title = "Item one", Text = "This is item one", Featured = false, ColumnSpan = 12, RowSpan = 1 },
new { Title = "Item two", Text = "This is item two", Featured = true, ColumnSpan = 6, RowSpan = 2 }
}
The resulting JSON object stored for the Block Grid will look like this:
{
"layout": {
"Umbraco.BlockGrid": [{
"contentUdi": "umb://element/bb23fe28160941efa506da7aa314172d",
"settingsUdi": "umb://element/9b832ee528464456a8e9a658b47a9801",
"areas": [],
"columnSpan": 12,
"rowSpan": 1
}, {
"contentUdi": "umb://element/a11e06ca155d40b78189be0bdaf11c6d",
"settingsUdi": "umb://element/d182a0d807fc4518b741b77c18aa73a1",
"areas": [],
"columnSpan": 6,
"rowSpan": 2
}
]
},
"contentData": [{
"contentTypeKey": "0e9f8609-1904-4fd1-9801-ad1880825ff3",
"udi": "umb://element/bb23fe28160941efa506da7aa314172d",
"title": "Item one",
"text": "This is item one"
}, {
"contentTypeKey": "0e9f8609-1904-4fd1-9801-ad1880825ff3",
"udi": "umb://element/a11e06ca155d40b78189be0bdaf11c6d",
"title": "Item two",
"text": "This is item two"
}
],
"settingsData": [{
"contentTypeKey": "22be457c-8249-42b8-8685-d33262f7ce2a",
"udi": "umb://element/9b832ee528464456a8e9a658b47a9801",
"featured": "0"
}, {
"contentTypeKey": "22be457c-8249-42b8-8685-d33262f7ce2a",
"udi": "umb://element/d182a0d807fc4518b741b77c18aa73a1",
"featured": "1"
}
]
}
For each item in the raw data, we need to create:
One contentData
entry with the title and text.
One settingsData
entry with the featured value (the checkbox expects "0"
or "1"
as data value).
One layout
entry with the desired column and row spans.
All contentData
and layoutData
entries need their own unique Udi
as well as the ID (key) of their corresponding Element Types. In this sample, we only have one Element Type for content (spotElement
) and one for settings (spotSettings
). In a real life scenario, there could be any number of Element Type combinations.
First and foremost, we need models to transform the raw data into Block Grid compatible JSON. Create a class called Model.cs containing the following:
using Umbraco.Cms.Core;
using System.Text.Json.Serialization;
namespace My.Site.Models;
// this is the "root" of the block grid data
public class BlockGridData
{
public BlockGridData(BlockGridLayout layout, BlockGridElementData[] contentData, BlockGridElementData[] settingsData)
{
Layout = layout;
ContentData = contentData;
SettingsData = settingsData;
}
[JsonPropertyName("layout")]
public BlockGridLayout Layout { get; }
[JsonPropertyName("contentData")]
public BlockGridElementData[] ContentData { get; }
[JsonPropertyName("settingsData")]
public BlockGridElementData[] SettingsData { get; }
}
// this is a wrapper for the block grid layout, purely required for correct serialization
public class BlockGridLayout
{
public BlockGridLayout(BlockGridLayoutItem[] layoutItems) => LayoutItems = layoutItems;
[JsonPropertyName("Umbraco.BlockGrid")]
public BlockGridLayoutItem[] LayoutItems { get; }
}
// this represents an item in the block grid layout collection
public class BlockGridLayoutItem
{
public BlockGridLayoutItem(Udi contentUdi, Udi settingsUdi, int columnSpan, int rowSpan)
{
ContentUdi = contentUdi;
SettingsUdi = settingsUdi;
ColumnSpan = columnSpan;
RowSpan = rowSpan;
}
[JsonPropertyName("contentUdi")]
public Udi ContentUdi { get; }
[JsonPropertyName("settingsUdi")]
public Udi SettingsUdi { get; }
[JsonPropertyName("areas")]
// areas are omitted from this sample for abbreviation
public object[] Areas { get; } = { };
[JsonPropertyName("columnSpan")]
public int ColumnSpan { get; }
[JsonPropertyName("rowSpan")]
public int RowSpan { get; }
}
// this represents an item in the block grid content or settings data collection
public class BlockGridElementData
{
public BlockGridElementData(Guid contentTypeKey, Udi udi)
{
ContentTypeKey = contentTypeKey;
Udi = udi;
}
[JsonPropertyName("contentTypeKey")]
public Guid ContentTypeKey { get; }
[JsonPropertyName("udi")]
public Udi Udi { get; }
[JsonExtensionData]
public Dictionary<string, object>? Data { get; set;}
}
By injecting ContentService and ContentTypeService into an API controller, we can transform the raw data into Block Grid JSON. It can then be saved to the target content item. Create a class called BlockGridTestController.cs containing the following:
using Microsoft.AspNetCore.Mvc;
using My.Site.Models;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Serialization;
using Umbraco.Cms.Core.Services;
namespace My.Site.Controllers;
[ApiController]
[Route("/umbraco/api/blockgridtest")]
public class BlockGridTestController : Controller
{
private readonly IContentService _contentService;
private readonly IContentTypeService _contentTypeService;
private readonly IJsonSerializer _serializer;
public BlockGridTestController(IContentService contentService, IContentTypeService contentTypeService, IJsonSerializer serializer)
{
_contentService = contentService;
_contentTypeService = contentTypeService;
_serializer = serializer;
}
// POST: /umbraco/api/blockgridtest/create
[HttpPost("create")]
public ActionResult Create()
{
// get the item content to modify
IContent? content = _contentService.GetById(Guid.Parse("efba7b97-91b6-4ddf-b2cc-eef89ff48c3b"));
if (content == null)
{
return NotFound("Could not find the content item to modify");
}
// get the element types for spot blocks (content and settings)
IContentType? spotContentType = _contentTypeService.Get("spotElement");
IContentType? spotSettingsType = _contentTypeService.Get("spotSettings");
if (spotContentType == null || spotSettingsType == null)
{
return NotFound("Could not find one or more content types for block data");
}
// this is the raw data to insert into the block grid
var rawData = new[]
{
new { Title = "Item one", Text = "This is item one", Featured = false, ColumnSpan = 12, RowSpan = 1 },
new { Title = "Item two", Text = "This is item two", Featured = true, ColumnSpan = 6, RowSpan = 2 }
};
// build the individual parts of the block grid data from the raw data
var layoutItems = new List<BlockGridLayoutItem>();
var spotContentData = new List<BlockGridElementData>();
var spotSettingsData = new List<BlockGridElementData>();
foreach (var data in rawData)
{
// generate new UDIs for block content and settings
var contentUdi = Udi.Create(Constants.UdiEntityType.Element, Guid.NewGuid());
var settingsUdi = Udi.Create(Constants.UdiEntityType.Element, Guid.NewGuid());
// create a new layout item
layoutItems.Add(new BlockGridLayoutItem(contentUdi, settingsUdi, data.ColumnSpan, data.RowSpan));
// create new content data
spotContentData.Add(new BlockGridElementData(spotContentType.Key, contentUdi)
{
Data = new Dictionary<string, object>
{
{ "title", data.Title },
{ "text", data.Text },
}
});
// create new settings data
spotSettingsData.Add(new BlockGridElementData(spotSettingsType.Key, settingsUdi)
{
Data = new Dictionary<string, object>
{
{ "featured", data.Featured ? "1" : "0" },
}
});
}
// construct the block grid data from layout, content and settings
var blockGridData = new BlockGridData(
new BlockGridLayout(layoutItems.ToArray()),
spotContentData.ToArray(),
spotSettingsData.ToArray());
// serialize the block grid data as JSON and save it to the "blockGrid" property on the content item
var propertyValue = _serializer.Serialize(blockGridData);
content.SetValue("blockGrid", propertyValue);
_contentService.Save(content);
return Ok("Saved");
}
}
For the above code IContent? content = _contentService.GetById(1203);
change the id with your content node that is using the Block Grid.
In order to test this implementation, run the project and add /umbraco/api/blockgridtest/create
after your domain name. If the result shows as Saved then check your content node and you will see the 2 spotElement contents.
This can also be tested via Postman as well if preffered.
This document covers specific upgrade steps if a version requires them. Most versions do not require specific upgrade steps and you will be able to upgrade directly from your current version.
Use the information below to learn about any potential breaking changes and common pitfalls when upgrading your Umbraco CMS project.
If any specific steps are involved with upgrading to a specific version they will be listed below.
Use the general upgrade guide to complete the upgrade of your project.
You can find a list of all the released Umbraco versions on Our Umbraco website. When you visit Our Umbraco website, click on the version number to view the changes made in that specific version.
Are you looking to upgrade an Umbraco Cloud project from 9 to 10? Follow the guide made for Upgrading your project from Umbraco 9 to 10 instead, as it requires a few steps specific to Umbraco Cloud.
:root {
--umb-header-logo-display: none;
}
{
...
"ConnectionStrings": {
"umbracoDbDSN": "Data Source=|DataDirectory|/Umbraco.sqlite.db;Cache=Private;Foreign Keys=True;Pooling=True",
"umbracoDbDSN_ProviderName": "Microsoft.Data.Sqlite",
"umbracoCommerceDbDSN": "Data Source=|DataDirectory|/Umbraco.Commerce.sqlite.db;Mode=ReadWrite;Foreign Keys=True;Pooling=True;Cache=Private",
"umbracoCommerceDbDSN_ProviderName": "Microsoft.Data.Sqlite"
},
...
}
{
"type": "mfaLoginProvider",
"alias": "my.2fa.provider",
"name": "My 2fa Provider",
"forProviderName": "UmbracoUserAppAuthenticator",
"meta": {
"label": "Authenticate with a 2FA code"
}
}
{
"type": "authProvider",
"alias": "My.AuthProvider.Google",
"name": "Google Auth Provider",
"forProviderName": "Umbraco.Google",
"meta": {
"label": "Google",
"defaultView": {
"icon": "icon-google"
},
"linking": {
"allowManualLinking": true
}
}
}
<PropertyGroup>
<RazorCompileOnBuild>false</RazorCompileOnBuild>
<RazorCompileOnPublish>false</RazorCompileOnPublish>
</PropertyGroup>