The Umbraco backoffice is great for managing things like content types and data types. Using the backoffice is both user friendly and Umbraco will ensure that everything is saved correctly.
But as a developer, we'd sometimes need to create or manage content types and data types programmatically, which can be a bit tricky to get all the different parts right - especially since not all of this is documented.
This article will walk through the steps to create or update an content type, as well as provide examples on how to create new data types using many of Umbraco's build-in property editors.
Programmatically creating and editing content and media are generally well documented, so I won't focus much on this for this article. But working with media and medias is not super well documented, so the article therefore finishes off with a few examples on this as well.
Content Types
Umbraco contains an IContentTypeService
interface for working with content types through your own code. You can inject the interface in your class constructor or using @inject
in a Razor view.
@using Umbraco.Cms.Core.Services
@inherits UmbracoViewPage
@inject IContentTypeService ContentTypeService
You can then use ContentTypeService
to access the injected IContentTypeService
.
Creating a new content type
To get started creating a simple content type, you can create a new instance of Umbraco's ContentType
class. Genererally content types are represented by the IContentType
interface, but when creating a new content type, we have to use the ContentType
class directly (the class implements the IContentType
interface.
The ContentType
constructor takes an instance of IShortStringHelper
, and then the numeric parent ID of where in the content type tree the new content type should be located.
Umbraco internally uses the IShortStringHelper
service to convert names to safe aliases. The implementation of this service isn't all that important for this article, so I won't go in detail about it. You can inject it via @inject IShortStringHelper ShortStringHelper
and then pass in on to the constructor via it's first parameter.
The second parameter is the parent ID. If you wish to create your content type under a specific folder in the content type tree, you can set this parameter to the parent's ID. To create your content type in the root of the content type tree, you can pass on -1
instead.
@using Umbraco.Cms.Core.Services
@using Umbraco.Cms.Core.Models
@using Umbraco.Cms.Core.Strings
@inherits UmbracoViewPage
@inject IShortStringHelper ShortStringHelper
@inject IContentTypeService ContentTypeService
@{
// Create a new content type in memory
ContentType contentType = new ContentType(ShortStringHelper, -1)
{
Alias = "settingsComp",
Name = "Settings",
Icon = "icon-defrag"
};
// Save the content type
ContentTypeService.Save(contentType);
}
Adding a property group
The example above only creates the content type, but we haven't added any properties to it yet. In order to add properties, we should first add one or more property groups.
A property group represents either a tab or a property group under a tab. A property group is shown under a tab, but in code, tabs and groups are represented by a flat collection of PropertyGroup
.
A new tab or property can be added like shown as below:
// Initialize a "Settings" tab
var settingsTab = new PropertyGroup(new PropertyTypeCollection(contentType.SupportsPublishing))
{
Alias = "settings",
Name = "Settings",
Type = PropertyGroupType.Tab,
SortOrder = 100
};
// Add a new tab to the content type
contentType.PropertyGroups.Add(settingsTab);
And a property group such as:
// Initialize a "Settings" tab
var seoGroup = new PropertyGroup(new PropertyTypeCollection(contentType.SupportsPublishing))
{
Alias = "settings/seo",
Name = "SEO",
Type = PropertyGroupType.Info
};
// Add a new tab to the content type
contentType.PropertyGroups.Add(settingsTab);
Notice the group alias. A group with the alias seo
will be created under a Generic tab, whereas a group with the alias settings/seo
will be created under the tab with the alias settings
.
Adding a property type
A property of a content type is referred to a property type, and as such represented by the PropertyType
class.
// Add a new property type to the "Settings" tab
propertyGroup.PropertyTypes!.Add(new PropertyType(ShortStringHelper, trueFalse)
{
Alias = "umbracoNaviHide",
Name = "Hide from navigation?",
Description = "Select whether the page should be hidden from navigation."
});
Similar to when creating a content type, the PropertyType
's first constructor should be an instance of IShortStringHelper
. The second parameter is an instance of IDateType
. In this case, trueFalse
refers to Umbraco's True/false data type.
Adding content type compositions
A content type is made up of property groups and property types added directly to the content type, and then property groups and property types added to one or more composition types the content type is using.
In code, content type compositions can be added via the ContentTypeComposition
property:
// Get a reference to our "Settings" composition type
IContentType? settingsComposition = ContentTypeService.Get("settingsComp");
if (settingsComposition is null) throw new Exception("Oh noes!");
// Set the new content type's compositions
contentType.ContentTypeComposition = new List
{
settingsComposition
};
Notice that the ContentTypeComposition
property is of the type IEnumerable<IContentTypeComposition>
. As we're in the process of creating a new content type, we can simply replace the existing with a new List<IContentTypeComposition>
. If editing an existing content type, you should take existing composition types into account.
Creating a settings
content type composition
The full example for creating a Settings composition type is illustrated with the snippet below:
@using Umbraco.Cms.Core.Services
@using Umbraco.Cms.Core.Models
@using Umbraco.Cms.Core.Strings
@inherits UmbracoViewPage
@inject IShortStringHelper ShortStringHelper
@inject IContentTypeService ContentTypeService
@inject IDataTypeService DataTypeService
@{
// Gets a reference to Umbraco's default "True/false" data type
IDataType? trueFalse = DataTypeService.GetDataType(-49);
if (trueFalse is null) throw new Exception("Oh noes!");
// Create a new content type in memory
ContentType contentType = new ContentType(ShortStringHelper, -1)
{
Alias = "settingsComp",
Name = "Settings",
Icon = "icon-defrag",
IsElement = true
};
// Initialize a new property group
var propertyGroup = new PropertyGroup(new PropertyTypeCollection(contentType.SupportsPublishing))
{
Alias = "settings",
Name = "Settings",
Type = PropertyGroupType.Tab,
SortOrder = 100
};
// Add a new property type to the "Settings" tab
propertyGroup.PropertyTypes!.Add(new PropertyType(ShortStringHelper, trueFalse)
{
Alias = "umbracoNaviHide",
Name = "Hide from navigation?",
Description = "Select whether the page should be hidden from navigation."
});
// Add a new tab to the content type
contentType.PropertyGroups.Add(propertyGroup);
// Save the content type
ContentTypeService.Save(contentType);
<pre>@contentType.Id</pre>
<pre>@contentType.Key</pre>
}
When creating a new Composition via Umbraco's UI, it's marked as an element type by default. Whether this should be the case might be a bit debateable. If a composition type is only used by non-element types, I'd argue that the composition shouldn't be an element type either.
This may not matter that much, but when using ModelsBuilder, it determines whether the generated model for the composition inherits from IPublishedContent
or IPublishedElement
.
Creating a contentPage
content type
The example belows illistrates a Content Page content type, which would represent a basic page - eg. using Umbraco's block list for the content. Such a page would likely share a few setting with other page types, so it uses the above settingsComp
composition while also having the title
and teaser
properties on it's own.
The title
and teaser
properties are added to a Intro property group, which is again added to a Content tab.
@using Umbraco.Cms.Core.Services
@using Umbraco.Cms.Core.Models
@using Umbraco.Cms.Core.Strings
@inherits UmbracoViewPage
@inject IShortStringHelper ShortStringHelper
@inject IContentTypeService ContentTypeService
@inject IDataTypeService DataTypeService
@{
// Gets a reference to Umbraco's default "Textstring" data type
IDataType? textstring = DataTypeService.GetDataType(-88);
if (textstring is null) throw new Exception("Oh noes!");
// Gets a reference to Umbraco's default "Textarea" data type
IDataType? textarea = DataTypeService.GetDataType(-89);
if (textarea is null) throw new Exception("Oh noes!");
// Get a reference to our "Settings" composition type
IContentType? settingsComposition = ContentTypeService.Get("settingsComp");
if (settingsComposition is null) throw new Exception("Oh noes!");
// Create a new content type in memory
ContentType contentType = new ContentType(ShortStringHelper, -1)
{
Alias = "contentPage",
Name = "Content Page",
Icon = "icon-document"
};
// Set the new content type's compositions
contentType.ContentTypeComposition = new List<IContentTypeComposition>
{
settingsComposition
};
// Initialize a new "Content" tab
var contentPropertyGroup = new PropertyGroup(new PropertyTypeCollection(false))
{
Alias = "content",
Name = "Content",
Type = PropertyGroupType.Tab
};
// Initialize a new "Intro" group
var introPropertyGroup = new PropertyGroup(new PropertyTypeCollection(false))
{
Alias = contentPropertyGroup.Alias + "/intro",
Name = "Intro",
Type = PropertyGroupType.Group,
};
// Add a new "Title" property type to the "Settings" tab
introPropertyGroup.PropertyTypes!.Add(new PropertyType(ShortStringHelper, textstring)
{
Alias = "title",
Name = "Title",
Description = "The title of the page."
});
// Add a new "Description" property type to the "Settings" tab
introPropertyGroup.PropertyTypes!.Add(new PropertyType(ShortStringHelper, textstring)
{
Alias = "teaser",
Name = "Teaser",
Description = "The teaser of the page."
});
// Append the "Content" tab to the content type
contentType.PropertyGroups.Add(contentPropertyGroup);
// Append the "Intro" group to the content type
contentType.PropertyGroups.Add(introPropertyGroup);
// Save and persist the content type to the database
ContentTypeService.Save(contentType);
<pre>@contentType.Id</pre>
<pre>@contentType.Key</pre>
}
Property Editors
When working with data types, it's also relevant to talk about property editors. A data type is based on a property editor, and multiple data types may be using the same property editor. But a property editor may also exist without any data types using it.
Programmatically property editors can be accessed via the PropertyEditorCollection
class in the Umbraco.Cms.Core.PropertyEditors
namespace. The class represents a collection of all the property editors registered in your Umbraco installation.
The class has an indexer property, so if you are looking for a particular property editor, you can get the property as shown below:
@using Umbraco.Cms.Core.PropertyEditors
@using Umbraco.Cms.Core
@inject PropertyEditorCollection PropertyEditors
@{
IDataEditor? editor = PropertyEditors[Constants.PropertyEditors.Aliases.TextBox];
}
Or you can use the TryGet
method instead:
@using Umbraco.Cms.Core.PropertyEditors
@using Umbraco.Cms.Core
@inject PropertyEditorCollection PropertyEditors
@{
if (!PropertyEditors.TryGet(Constants.PropertyEditors.Aliases.TextBox, out IDataEditor? editor)) {
<div>Computer says no!</div>
return;
}
}
Notice that Umbraco has constants for the aliases of all the build-in property editors.
Value Editor
A property editor declares a value editor, which represents what the users see for properties of a given property editor. For one, a value editor specifies the a value type - which determines how the value editor's value is saved to the database. This is relevant when creating a new data type.
Getting the value type programmatically could look like:
@using Umbraco.Cms.Core.PropertyEditors
@using Umbraco.Cms.Core
@inject PropertyEditorCollection PropertyEditors
@{
// Try to get a reference to the "Umbraco.TextBox" property editor
if (!PropertyEditors.TryGet(Constants.PropertyEditors.Aliases.TextBox, out IDataEditor? editor)) {
<div>Computer says no!</div>
return;
}
// Get the value editor for the property editor
var valueEditor = editor.GetValueEditor();
// Write out the value type
<pre>@valueEditor.ValueType</pre>
}
In this case, the textbox property editor has the value type STRING. Also, here we're calling the parameterless GetValueEditor
method. Most property editors have the same value type regardless of the configuration, but the method has an overload with a parameter representing a configuration object.
Data Types
Data types can be accessed by injecting the IDataTypeService
interface. Individual data types are represented by the IDataTye
interface, and specifically the DataType
class. Normally you'd only need to work with data types via the interface, but when creating a new data type, you need to use the class directly.
Database Type
Each data type specifies how property values using the given data type should be saved in the database. The database type is based on the property editor's value type, although the two doesn't represent exactly the same.
Umbraco uses the ValueStorageType
enum class for representing the supported database types. And the ValueTypes
class features a static ToStorageType
method for converting the property editor's value type to a ValueStorageType
:
// Get the default database type
ValueStorageType databaseType = ValueTypes
.ToStorageType(editor.GetValueEditor().ValueType);
Creating a new data type
New data types can be created via the DataType
class' constructor. This will not persist the data type to the database, but it lets us further modify the data type in C#, and then save the data type via IDataTypeService
's Save
method:
<code@using Umbraco.Cms.Core.Models @using Umbraco.Cms.Core.PropertyEditors @using Umbraco.Cms.Core.Serialization @using Umbraco.Cms.Core.Services @inject PropertyEditorCollection PropertyEditors @inject IDataTypeService DataTypeService @inject IConfigurationEditorJsonSerializer ConfigurationEditorJsonSerializer @{ // Get ID of the folder in which the new data type will be created int parentId = 1122; // Get a reference to the property editor IDataEditor editor = PropertyEditors .Single(x => x.Alias == "myEditor"); // Initialize a new data type IDataType dataType = new DataType(editor, ConfigurationEditorJsonSerializer, parentId); // Create/save the data type to the database DataTypeService.Save(dataType); }
The first parameter for the constructor is an instance of IDataEditor
with the property editor that should be used for the data type. The second parameter should be an instance of IConfigurationEditorJsonSerializer
- which you can inject as shown in the example above. The third parameter is optional, and if specified, should be the numeric ID of the folder in which the data type should be created. If not specified, the data type is created at the root of the data type tree.
Before saving the data type, you should ideally also set some on the other properties of the IDataType
instance - in particular the Name
, DatabaseType
and Configuration
properties.
Creating a new checkbox list data type
The Checkbox list property editor (alias: Umbraco.CheckBoxList
) let's users select between a pre-defined list of items configured for each data type using this property editor.
The data type configuration is represented by the ValueListConfiguration
class, which let's you define the items that should be available in the value editor. Each item is represented by the ValueListConfiguration.ValueListItem
nested class.
What value you set for the ID of each item is not really super important, although they have to be unique within the data type. Umbraco's seems to be using forthcoming numbers, so the example below follows this approach.
@using Umbraco.Cms.Core.Services
@using Umbraco.Cms.Core.PropertyEditors
@using Umbraco.Cms.Core
@using Umbraco.Cms.Core.Models
@using Umbraco.Cms.Core.Serialization
@inherits UmbracoViewPage
@inject PropertyEditorCollection PropertyEditors
@inject IDataTypeService DataTypeService
@inject IConfigurationEditorJsonSerializer ConfigurationEditorJsonSerializer
@{
// Get ID of the folder in which the new data type will be created
int parentId = 1122;
// Get a reference to the property editor
IDataEditor editor = PropertyEditors
.Single(x => x.Alias == Constants.PropertyEditors.Aliases.CheckBoxList);
// Initialize the configuration object
ValueListConfiguration config = new ValueListConfiguration {
Items = new List<ValueListConfiguration.ValueListItem> {
new ValueListConfiguration.ValueListItem {
Id = 1,
Value = "Hello World"
},
new ValueListConfiguration.ValueListItem {
Id = 2,
Value = "Hej Verden"
}
}
};
// Get the database type for "editor" and "config"
ValueStorageType databaseType = ValueTypes
.ToStorageType(editor.GetValueEditor(config).ValueType);
// Initialize a new data type
IDataType dataType = new DataType(editor, ConfigurationEditorJsonSerializer, parentId) {
Name = "My checkbox list",
DatabaseType = databaseType,
Configuration = config
};
// Create/save the data type to the database
DataTypeService.Save(dataType);
// Print out the ID
<pre>@dataType.Id</pre>
}
Creating a new color picker data type
The Color Picker property editor (alias: Umbraco.ColorPicker
) let's users select between a list of pre-defined colors configured through the data type options.
The data type configuration is represented by the ColorPickerConfiguration
class. The class features an Items
property that you can use to configure the available colors/items. Each item (color) is represented by the ValueListConfiguration.ValueListItem
nested class.
Notice that the Value
for each item should be a JSON object with both the value
(HEX value) and name
(label) of the item.
@using Umbraco.Cms.Core.Services
@using Umbraco.Cms.Core.Models
@using Umbraco.Cms.Core.PropertyEditors
@using Umbraco.Cms.Core.Serialization
@using Umbraco.Cms.Core
@inherits UmbracoViewPage
@inject PropertyEditorCollection PropertyEditorCollection
@inject IDataTypeService DataTypeService
@inject IConfigurationEditorJsonSerializer ConfigurationEditorJsonSerializer
@{
// Get ID of the folder in which the new data type will be created
int parentId = 1122;
// Get a reference to the property editor
IDataEditor colorPicker = PropertyEditorCollection
.Single(x => x.Alias == Constants.PropertyEditors.Aliases.ColorPicker);
// Initialize the configuration object
ColorPickerConfiguration config = new ColorPickerConfiguration {
UseLabel = true,
Items = new List<ValueListConfiguration.ValueListItem> {
new ValueListConfiguration.ValueListItem {
Id = 1,
Value = "{\"value\":\"ed1212\",name:\"Red\"}"
},
new ValueListConfiguration.ValueListItem {
Id = 2,
Value = "{\"value\":\"8fce00\",name:\"Green\"}"
}
}
};
// Get the database type for "editor" and "config"
ValueStorageType databaseType = ValueTypes
.ToStorageType(colorPicker.GetValueEditor(config).ValueType);
// Initialize a new data type
IDataType dataType = new DataType(colorPicker, ConfigurationEditorJsonSerializer, parentId) {
Name = "My color picker",
DatabaseType = databaseType,
Configuration = config
};
// Create/save the data type to the database
DataTypeService.Save(dataType);
// Print out the ID
<pre>@dataType.Id</pre>
}
Creating a new content picker data type
The Content Picker property editor (alias: Umbraco.ContentPicker
) let's users select a single content node. The data type can be configured to control what content nodes users will be able to select.
The data type configuration is represented by the ContentPickerConfiguration
class. Like when editing a content picker data type in the backoffice, it has a few different options - all of them being optional.
@using Umbraco.Cms.Core.PropertyEditors
@using Umbraco.Cms.Core.Services
@using Umbraco.Cms.Core
@using Umbraco.Cms.Core.Models
@using Umbraco.Cms.Core.Serialization
@inherits UmbracoViewPage
@inject PropertyEditorCollection PropertyEditors
@inject IDataTypeService DataTypeService
@inject IConfigurationEditorJsonSerializer ConfigurationEditorJsonSerializer
@{
// Get ID of the folder in which the new data type will be created
int parentId = 1122;
// Get a reference to the property editor
IDataEditor editor = PropertyEditors
.Single(x => x.Alias == Constants.PropertyEditors.Aliases.ContentPicker);
// Initialize the configuration
ContentPickerConfiguration config = new ContentPickerConfiguration {
ShowOpenButton = false,
StartNodeId = new GuidUdi("document", new Guid("db25f0d0-f80f-4262-b279-c2e6568b325a")),
IgnoreUserStartNodes = false
};
// Initialize a new data type
IDataType dataType = new DataType(editor, ConfigurationEditorJsonSerializer, parentId) {
Name = "My content picker",
Configuration = config,
DatabaseType = ValueTypes.ToStorageType(editor.GetValueEditor(config).ValueType)
};
// Create/save the data type to the database
DataTypeService.Save(dataType);
// Print out the ID
<pre>@dataType.Id</pre>
}
Creating a new date time data type
The Date/Time property editor (alias: Umbraco.DateTime
) let's user select a point in time consisting of both a date and time.
The data type configuration is represented by the DateTimeConfiguration
class. For one, it let's you set the format being used by the value editor.
@using Umbraco.Cms.Core.PropertyEditors
@using Umbraco.Cms.Core.Services
@using Umbraco.Cms.Core
@using Umbraco.Cms.Core.Models
@using Umbraco.Cms.Core.Serialization
@inherits UmbracoViewPage
@inject PropertyEditorCollection PropertyEditors
@inject IDataTypeService DataTypeService
@inject IConfigurationEditorJsonSerializer ConfigurationEditorJsonSerializer
@{
// Get ID of the folder in which the new data type will be created
int parentId = 1122;
// Get a reference to the property editor
IDataEditor editor = PropertyEditors
.Single(x => x.Alias == Constants.PropertyEditors.Aliases.DateTime);
// Get the default database type
ValueStorageType databaseType = ValueTypes
.ToStorageType(editor.GetValueEditor(null).ValueType);
// Initialize a new data type
IDataType dataType = new DataType(editor, ConfigurationEditorJsonSerializer, parentId) {
Name = "My DateTime",
DatabaseType = databaseType
};
// Set the configuration
dataType.Configuration = new DateTimeConfiguration {
Format = "YYYY-MM-DD HH:mm:ss",
OffsetTime = false
};
// Set the database type
dataType.DatabaseType = ValueTypes
.ToStorageType(editor.GetValueEditor(dataType.Configuration).ValueType);
// Create/save the data type to the database
DataTypeService.Save(dataType);
// Print out the ID
<pre>@dataType.Id</pre>
}
Creating a new decimal type
The data type for the Decimal property editor (alias: Umbraco.Decimal
) doesn't have it's own configuration class, so it instead relies on a Dictionary<string, object>
instance instead. You may add values for min
, step
and max
, but all of them are optional.
@using Umbraco.Cms.Core.PropertyEditors
@using Umbraco.Cms.Core.Services
@using Umbraco.Cms.Core
@using Umbraco.Cms.Core.Models
@using Umbraco.Cms.Core.Serialization
@inherits UmbracoViewPage
@inject PropertyEditorCollection PropertyEditors
@inject IDataTypeService DataTypeService
@inject IConfigurationEditorJsonSerializer ConfigurationEditorJsonSerializer
@{
// Get ID of the folder in which the new data type will be created
int parentId = 1122;
// Get a reference to the property editor
IDataEditor editor = PropertyEditors
.Single(x => x.Alias == Constants.PropertyEditors.Aliases.Decimal);
// Initialize the configuration
var config = new Dictionary<string, object> {
{"min", -1},
{"step", 1},
{"max", 10}
};
// Initialize a new data type
IDataType dataType = new DataType(editor, ConfigurationEditorJsonSerializer, parentId) {
Name = "My decimal",
Configuration = config,
DatabaseType = ValueTypes.ToStorageType(editor.GetValueEditor(config).ValueType)
};
// Create/save the data type to the database
DataTypeService.Save(dataType);
// Print out the ID
<pre>@dataType.Id</pre>
}
Creating a new dropdown list data type
The Dropdown property editor (alias: Umbraco.DropDown.Flexible
) let's users select between a list of pre-defined items configured in the data type.
The configuration is represented by the DropDownFlexibleConfiguration
class, and similar to other item based data types, each item is represented by the ValueListConfiguration.ValueListItem
nested class.
@using Umbraco.Cms.Core.Services
@using Umbraco.Cms.Core.PropertyEditors
@using Umbraco.Cms.Core
@using Umbraco.Cms.Core.Models
@using Umbraco.Cms.Core.Serialization
@inherits UmbracoViewPage
@inject PropertyEditorCollection PropertyEditors
@inject IDataTypeService DataTypeService
@inject IConfigurationEditorJsonSerializer ConfigurationEditorJsonSerializer
@{
// Get ID of the folder in which the new data type will be created
int parentId = 1122;
// Get a reference to the property editor
IDataEditor editor = PropertyEditors
.Single(x => x.Alias == Constants.PropertyEditors.Aliases.DropDownListFlexible);
// Initialize the configuration
var config = new DropDownFlexibleConfiguration {
Multiple = false,
Items = new List<ValueListConfiguration.ValueListItem> {
new ValueListConfiguration.ValueListItem {
Id = 1,
Value = "Hello World"
},
new ValueListConfiguration.ValueListItem {
Id = 2,
Value = "Hej Verden"
}
}
};
// Initialize a new data type
IDataType dataType = new DataType(editor, ConfigurationEditorJsonSerializer, parentId) {
Name = "My dropdown list",
Configuration = config,
DatabaseType = ValueTypes.ToStorageType(editor.GetValueEditor(config).ValueType)
};
// Create/save the data type to the database
DataTypeService.Save(dataType);
// Print out the ID
<pre>@dataType.Id</pre>
}
Creating a new eye dropper data type
The Eye Dropper Color Picker property editor (alias: Umbraco.ColorPicker.EyeDropper
) let's users select a single RGB color.
Thedata type's configuration is represented by the EyeDropperColorPickerConfiguration
class. For one, you may set the ShowAlpha
property to true
to allow alpha values.
@using Umbraco.Cms.Core.Services
@using Umbraco.Cms.Core.PropertyEditors
@using Umbraco.Cms.Core
@using Umbraco.Cms.Core.Models
@using Umbraco.Cms.Core.Serialization
@inherits UmbracoViewPage
@inject PropertyEditorCollection PropertyEditors
@inject IDataTypeService DataTypeService
@inject IConfigurationEditorJsonSerializer ConfigurationEditorJsonSerializer
@{
// Get ID of the folder in which the new data type will be created
int parentId = 1122;
// Get a reference to the property editor
IDataEditor editor = PropertyEditors
.Single(x => x.Alias == Constants.PropertyEditors.Aliases.ColorPickerEyeDropper);
// Initialize the configuration
var config = new EyeDropperColorPickerConfiguration {
ShowAlpha = true,
ShowPalette = true
};
// Initialize a new data type
IDataType dataType = new DataType(editor, ConfigurationEditorJsonSerializer, parentId) {
Name = "Eye Dropper",
Configuration = config,
DatabaseType = ValueTypes.ToStorageType(editor.GetValueEditor(config).ValueType)
};
// Create/save the data type to the database
DataTypeService.Save(dataType);
// Print out the ID
<pre>@dataType.Id</pre>
}
Creating a new file upload data type
The File upload property editor let's user upload a file to a property rather than in the media archive. The data type's configuration is represented by the FileExtensionConfigItem
class, which allows you to configure the accepted file extensions via the FileExtensions
property.
@using Umbraco.Cms.Core.Services
@using Umbraco.Cms.Core.PropertyEditors
@using Umbraco.Cms.Core
@using Umbraco.Cms.Core.Models
@using Umbraco.Cms.Core.Serialization
@inherits UmbracoViewPage
@inject PropertyEditorCollection PropertyEditors
@inject IDataTypeService DataTypeService
@inject IConfigurationEditorJsonSerializer ConfigurationEditorJsonSerializer
@{
// Get ID of the folder in which the new data type will be created
int parentId = 1122;
// Get a reference to the property editor
IDataEditor editor = PropertyEditors
.Single(x => x.Alias == Constants.PropertyEditors.Aliases.UploadField);
// Initialize the configuration
var config = new FileUploadConfiguration {
FileExtensions = new List<FileExtensionConfigItem> {
new FileExtensionConfigItem {
Id = 1, // Umbraco always set the IDs to zero (0)
Value = "cs"
},
new FileExtensionConfigItem {
Id = 2,
Value = "cshtml"
}
}
};
// Initialize a new data type
IDataType dataType = new DataType(editor, ConfigurationEditorJsonSerializer, parentId) {
Name = "Upload Field",
Configuration = config,
DatabaseType = ValueTypes.ToStorageType(editor.GetValueEditor(config).ValueType)
};
// Create/save the data type to the database
DataTypeService.Save(dataType);
// Print out the ID
<pre>@dataType.Id</pre>
}
Creating a label data type
The Label property editor (alias: Umbraco.Label
) may be used to store readonly data that users are not supposed to edit. The data type configuration is represented by the LabelConfiguration
class, it let's you configure which value type will be used when storing property values using this data type in the database.
In the example below, I'm creating a new Label data type with the value type ValueTypes.Text
(constant with the value TEXT
).
@using Umbraco.Cms.Core.PropertyEditors
@using Umbraco.Cms.Core.Services
@using Umbraco.Cms.Core
@using Umbraco.Cms.Core.Models
@using Umbraco.Cms.Core.Serialization
@inherits UmbracoViewPage
@inject PropertyEditorCollection PropertyEditors
@inject IDataTypeService DataTypeService
@inject IConfigurationEditorJsonSerializer ConfigurationEditorJsonSerializer
@{
// Get ID of the folder in which the new data type will be created
int parentId = 1122;
// Get a reference to the property editor
IDataEditor editor = PropertyEditors
.Single(x => x.Alias == Constants.PropertyEditors.Aliases.Label);
// Initialize the configuration
LabelConfiguration config = new LabelConfiguration {
ValueType = ValueTypes.Text
};
// Initialize a new data type
IDataType dataType = new DataType(editor, ConfigurationEditorJsonSerializer, parentId) {
Name = "My label",
Configuration = config,
DatabaseType = ValueTypes.ToStorageType(editor.GetValueEditor(config).ValueType)
};
// Create/save the data type to the database
DataTypeService.Save(dataType);
// Print out the ID
<pre>@dataType.Id</pre>
}
Creating a new member group picker data type
The Member Group Picker property editor (alias: Umbraco.MemberGroupPicker
) doesn't have any configuration, so in the example below, I'm passing null
to the editor.GetValueEditor
method.
@using Umbraco.Cms.Core.PropertyEditors
@using Umbraco.Cms.Core.Services
@using Umbraco.Cms.Core
@using Umbraco.Cms.Core.Models
@using Umbraco.Cms.Core.Serialization
@inherits UmbracoViewPage
@inject PropertyEditorCollection PropertyEditors
@inject IDataTypeService DataTypeService
@inject IConfigurationEditorJsonSerializer ConfigurationEditorJsonSerializer
@{
// Get ID of the folder in which the new data type will be created
int parentId = 1122;
// Get a reference to the property editor
IDataEditor editor = PropertyEditors
.Single(x => x.Alias == Constants.PropertyEditors.Aliases.MemberGroupPicker);
// Initialize a new data type
IDataType dataType = new DataType(editor, ConfigurationEditorJsonSerializer, parentId) {
Name = "My member group picker",
DatabaseType = ValueTypes.ToStorageType(editor.GetValueEditor(null).ValueType)
};
// Create/save the data type to the database
DataTypeService.Save(dataType);
// Print out the ID
<pre>@dataType.Id</pre>
}
Creating a new member picker data type
The Member Picker property editor (alias: Umbraco.MemberPicker
) works very similar to Umbraco.MemberGroupPicker
as shown above. This property editor also doesn't have any configuration:
@using Umbraco.Cms.Core.PropertyEditors
@using Umbraco.Cms.Core.Services
@using Umbraco.Cms.Core
@using Umbraco.Cms.Core.Models
@using Umbraco.Cms.Core.Serialization
@inherits UmbracoViewPage
@inject PropertyEditorCollection PropertyEditors
@inject IDataTypeService DataTypeService
@inject IConfigurationEditorJsonSerializer ConfigurationEditorJsonSerializer
@{
// Get ID of the folder in which the new data type will be created
int parentId = 1122;
// Get a reference to the property editor
IDataEditor editor = PropertyEditors
.Single(x => x.Alias == Constants.PropertyEditors.Aliases.MemberPicker);
// Initialize a new data type
IDataType dataType = new DataType(editor, ConfigurationEditorJsonSerializer, parentId) {
Name = "My member picker",
DatabaseType = ValueTypes.ToStorageType(editor.GetValueEditor(null).ValueType)
};
// Create/save the data type to the database
DataTypeService.Save(dataType);
// Print out the ID
<pre>@dataType.Id</pre>
}
Creating a new multi URL picker data type
The Multi URL Picker property editor (alias: Umbraco.MultiUrlPicker
) let's users add either a single or a list of URL items. The configuration for data types created using this property editor is represented by the MultiUrlPickerConfiguration
class, and it allows you to configure the following properties:
-
Minimum number of items (
MinNumber
)
Indicates the minimum amount of allowed items. Default is0
. -
Maximum number of items (
MaxNumber
)
Indicates the maximum amount of allowed items. Default is0
(no limit). -
Overlay Size (
OverlaySize
)
Sets the size of the link picker overlay. When creating or editing the data type through the backoffice, possible values are Small (small
), Medium (medium
) and Large (large
). Default issmall
. -
Hide anchor/query string input (
HideAnchor
)
Indicates whether the anchor/query string field of the link picker overlay should be hidden. Default isfalse
. -
Ignore user start nodes (
IgnoreUserStartNodes
)
Indicates whether the link picker overlay should ignore the user's permissions (start nodes). Default isfalse
.
@using Umbraco.Cms.Core.PropertyEditors
@using Umbraco.Cms.Core.Services
@using Umbraco.Cms.Core
@using Umbraco.Cms.Core.Models
@using Umbraco.Cms.Core.Serialization
@inherits UmbracoViewPage
@inject PropertyEditorCollection PropertyEditors
@inject IDataTypeService DataTypeService
@inject IConfigurationEditorJsonSerializer ConfigurationEditorJsonSerializer
@{
// Get ID of the folder in which the new data type will be created
int parentId = 1122;
// Get a reference to the property editor
IDataEditor editor = PropertyEditors
.Single(x => x.Alias == Constants.PropertyEditors.Aliases.MultiUrlPicker);
// Initialize the configuration
MultiUrlPickerConfiguration config = new MultiUrlPickerConfiguration {
MinNumber = 1,
MaxNumber = 10,
OverlaySize = "medium",
HideAnchor = true,
IgnoreUserStartNodes = true
};
// Initialize a new data type
IDataType dataType = new DataType(editor, ConfigurationEditorJsonSerializer, parentId) {
Name = "My Multi URL Picker",
Configuration = config,
DatabaseType = ValueTypes.ToStorageType(editor.GetValueEditor(config).ValueType)
};
// Create/save the data type to the database
DataTypeService.Save(dataType);
// Print out the ID
<pre>@dataType.Id</pre>
}
Creating a new numeric data type
The Numeric (alias: Umbraco.Integer
) property editor allows creating data types for specifying a single number (integer). Data types using this property editor have the following options:
-
Minimum (
min
)
Indicates the minimum allowed value. -
Step Size (
step
)
Indicates the interval amount between each step of number to be entered. -
Maximum (
max
)
Indicates the maximum allowed value.
The configuration is represented by an Dictionary<string, object>
instance. None of the properties have a default value, as options left blank are simply ommitted in the dictionary.
@using Umbraco.Cms.Core.PropertyEditors
@using Umbraco.Cms.Core.Services
@using Umbraco.Cms.Core
@using Umbraco.Cms.Core.Models
@using Umbraco.Cms.Core.Serialization
@inherits UmbracoViewPage
@inject PropertyEditorCollection PropertyEditors
@inject IDataTypeService DataTypeService
@inject IConfigurationEditorJsonSerializer ConfigurationEditorJsonSerializer
@{
// Get ID of the folder in which the new data type will be created
int parentId = 1122;
// Get a reference to the property editor
IDataEditor editor = PropertyEditors
.Single(x => x.Alias == Constants.PropertyEditors.Aliases.Integer);
// Initialize the configuration
Dictionary<string, object> config = new Dictionary<string, object> {
{"min", -10},
{"step", 1},
{"max", 10}
};
// Initialize a new data type
IDataType dataType = new DataType(editor, ConfigurationEditorJsonSerializer, parentId) {
Name = "My integer",
Configuration = config,
DatabaseType = ValueTypes.ToStorageType(editor.GetValueEditor(config).ValueType)
};
// Create/save the data type to the database
DataTypeService.Save(dataType);
// Print out the ID
<pre>@dataType.Id</pre>
}
Creating a new radio button list data type
Data types using the Radio button list property editor (alias: Umbraco.RadioButtonList
) don't have any additional configuration besides being able to specify the available items.
The configuration is represented by the ValueListConfiguration
class, and each item is represented by the ValueListConfiguration.ValueListItem
nested class.
Each item of a ValueListConfiguration
instance should have a unique numeric ID. When creating a new data type through the backoffice, the first item is assigned the ID 1
, the second item 2
and so forth.
Paste@using Umbraco.Cms.Core.Services
@using Umbraco.Cms.Core.PropertyEditors
@using Umbraco.Cms.Core
@using Umbraco.Cms.Core.Models
@using Umbraco.Cms.Core.Serialization
@inherits UmbracoViewPage
@inject PropertyEditorCollection PropertyEditors
@inject IDataTypeService DataTypeService
@inject IConfigurationEditorJsonSerializer ConfigurationEditorJsonSerializer
@{
// Get ID of the folder in which the new data type will be created
int parentId = 1122;
// Get a reference to the property editor
IDataEditor editor = PropertyEditors
.Single(x => x.Alias == Constants.PropertyEditors.Aliases.RadioButtonList);
// Initialize the configuration object
ValueListConfiguration config = new ValueListConfiguration {
Items = new List<ValueListConfiguration.ValueListItem> {
new ValueListConfiguration.ValueListItem {
Id = 1,
Value = "Hello World"
},
new ValueListConfiguration.ValueListItem {
Id = 2,
Value = "Hej Verden"
}
}
};
// Get the default database type
ValueStorageType databaseType = ValueTypes
.ToStorageType(editor.GetValueEditor(config).ValueType);
// Initialize a new data type
IDataType dataType = new DataType(editor, ConfigurationEditorJsonSerializer, parentId) {
Name = "My radio button list",
DatabaseType = databaseType,
Configuration = config
};
// Create/save the data type to the database
DataTypeService.Save(dataType);
// Print out the ID
<pre>@dataType.Id</pre>
}
Creating a new multiple textstring data type
The configuration for data types using the Repeatable textstrings property editor (alias: Umbraco.MultipleTextstring
) is represented by the MultipleTextStringConfiguration
class, and it let's you configure both the minimum and maximum allowed amount of items through the Minimum
and Maximum
properties respectively.
@using Umbraco.Cms.Core.Services
@using Umbraco.Cms.Core.PropertyEditors
@using Umbraco.Cms.Core
@using Umbraco.Cms.Core.Models
@using Umbraco.Cms.Core.Serialization
@inherits UmbracoViewPage
@inject PropertyEditorCollection PropertyEditors
@inject IDataTypeService DataTypeService
@inject IConfigurationEditorJsonSerializer ConfigurationEditorJsonSerializer
@{
// Get ID of the folder in which the new data type will be created
int parentId = 1122;
// Get a reference to the property editor
IDataEditor editor = PropertyEditors
.Single(x => x.Alias == Constants.PropertyEditors.Aliases.MultipleTextstring);
// Initialize the configuration object
MultipleTextStringConfiguration config = new MultipleTextStringConfiguration {
Minimum = 0,
Maximum = 10
};
// Get the default database type
ValueStorageType databaseType = ValueTypes
.ToStorageType(editor.GetValueEditor(config).ValueType);
// Initialize a new data type
IDataType dataType = new DataType(editor, ConfigurationEditorJsonSerializer, parentId) {
Name = "My multiple textstring list",
DatabaseType = databaseType,
Configuration = config
};
// Create/save the data type to the database
DataTypeService.Save(dataType);
// Print out the ID
<pre>@dataType.Id</pre>
}
Creating a new rich text editor data type
Data types using the Rich Text Editor (alias: Umbraco.TinyMCE
) propety editor use the RichTextConfiguration
class for representing their configurations.
The class only has a handful of properties, while users are presented with a lot more options when creating or editing the data type in the backoffice. This is because the individual options for the underlying TinyMCE are presented to the user as individual options as well, while the TinyMCE options represented by the Editor
property on RichTextConfiguration
using a single JSON object.
As such, the data type has the following options:
-
Editor (alias:
Editor
)
A JSON object representing the TinyMCE configuration.-
Toolbar (alias:
toolbar
)
The buttons that will be available in TinyMCE's toolbar. Possible values are:- Source Code Editor (
ace
) - Remove format (
removeformat
) - Undo (
undo
) - Redo (
redo
) - Cut (
cut
) - Copy (
copy
) - Paste (
paste
) - Style select (
styleselect
) - Bold (
bold
) - Italic (
italic
) - Underline (
underline
) - Strikethrough (
strikethrough
) - Justify left (
alignleft
) - Justify center (
aligncenter
) - Justify right (
alignright
) - Justify full (
alignjustify
) - Bullet list (
bullist
) - Numbered list (
numlist
) - Decrease indent (
outdent
) - Increase indent (
indent
) - Insert/edit link (
link
) - Remove link (
unlink
) - Anchor (
anchor
) - Image (
umbmediapicker
) - Macro (
umbmacro
) - Table (
table
) - Embed (
umbembeddialog
) - Horizontal rule (
hr
) - Subscript (
subscript
) - Superscript (
superscript
) - Character map (
charmap
) - Right to left (
rtl
) - Left to right (
ltr
)
- Source Code Editor (
-
-
Stylesheets (alias:
stylesheets
)
The stylesheets that will be included for the Style select button. -
Dimensions (alias:
dimensions
)
The size of the rich text editor. May be omitted. -
Maximum size for inserted images (alias:
maxImageSize
)
Maximum width or height - enter 0 to disable resizing. -
Mode (alias:
mode
)
The mode of the editor. Possible values areclassic
anddistraction-free
. Default isclassic
. -
Overlay Size (
OverlaySize
)
Sets the size of the link picker overlay. When creating or editing the data type through the backoffice, possible values are Small (small
), Medium (medium
) and Large (large
). Default issmall
. -
Hide Label (alias:
HideLabel
)
Whether the label and description of the property should be hidden. -
Image Upload Folder (alias:
MediaParentId
)
The UDI of the folder in which images uploaded through the RTE will be located, if specified. -
Ignore user start nodes (alias:
IgnoreUserStartNodes
)
Indicates whether the link picker overlay should ignore the user's permissions (start nodes). Default isfalse
.
@using Umbraco.Cms.Core.PropertyEditors
@using Umbraco.Cms.Core.Services
@using Umbraco.Cms.Core
@using Umbraco.Cms.Core.Models
@using Umbraco.Cms.Core.Serialization
@using Newtonsoft.Json.Linq
@inherits UmbracoViewPage
@inject PropertyEditorCollection PropertyEditors
@inject IDataTypeService DataTypeService
@inject IConfigurationEditorJsonSerializer ConfigurationEditorJsonSerializer
@{
// Get ID of the folder in which the new data type will be created
int parentId = 1122;
// Get a reference to the property editor
IDataEditor editor = PropertyEditors
.Single(x => x.Alias == Constants.PropertyEditors.Aliases.TinyMce);
// Initialize the configuration for TinyMCE
var tinyMceConfig = new JObject {
{"toolbar", new JArray(
"ace",
"removeformat",
"undo",
"redo",
"cut",
"copy",
"paste",
"styleselect",
"bold",
"italic",
"underline",
"strikethrough",
"alignleft",
"aligncenter",
"alignright",
"alignjustify",
"bullist",
"numlist",
"outdent",
"indent",
"link",
"unlink",
"anchor",
"umbmediapicker",
"umbmacro",
"table",
"umbembeddialog",
"hr",
"subscript",
"superscript",
"charmap",
"rtl",
"ltr"
)},
{"stylesheets", new JArray(
"/css/dev/default.css"
)},
{"maxImageSize", 500},
{"mode", "classic"},
{"dimensions", new JObject {
{"width", 500},
{"height", 400}
}}
};
// Initialize the data type configuration
RichTextConfiguration config = new RichTextConfiguration {
Editor = tinyMceConfig,
OverlaySize = "medium",
HideLabel = true,
MediaParentId = new GuidUdi("media", new Guid("14497f2f-0ed4-435c-ad2c-084c3ad9feb0")),
IgnoreUserStartNodes = true
};
// Initialize a new data type
IDataType dataType = new DataType(editor, ConfigurationEditorJsonSerializer, parentId) {
Name = "My RTE",
Configuration = config,
DatabaseType = ValueTypes.ToStorageType(editor.GetValueEditor(config).ValueType)
};
// Create/save the data type to the database
DataTypeService.Save(dataType);
// Print out the ID
<pre>@dataType.Id</pre>
}
Creating a new block list data type
The configuration for data types using the Block List property editor (alias: Umbraco.BlockList
) is represented by the BlockListConfiguration
class, and it has the following properties:
-
Blocks
The value of this property should be an array containing the configuration for the allowed blocks. Each block configuration is represented by theBlockListConfiguration.BlockConfiguration
class. -
ValidationLimit
Describes the minimum and maximum allowed amount of block items. The value hsould be an instance ofBlockListConfiguration.NumberRange
, where theMin
andMax
properties can be used to control this further. If theMin
property is set tonull
,0
is used instead. If theMax
property is set tonull
, no maximum limit is applied. -
UseSingleBlockMode
Indicates whether the block list should be in single mode or multi mode (default). -
UseLiveEditing
Indicates whether live editing should be enabled. -
UseInlineEditingAsDefault
Indicates whether inline editing should be enabled. -
MaxPropertyWidth
Indicates the maximum width of the block list property editor - eg.800px
or100%
.
Additionally, each block configuration (BlockListConfiguration.BlockConfiguration
) has the following properties:
-
Label
An optional label. The content type name is used as fallback if not specified. -
View
An optional custom view for previewing blocks of this type - eg.~/App_Plugins/BlockList/Views/Quote.html
. -
Stylesheet
A optional custom stylesheet - eg.~/App_Plugins/BlockList/Styles.css
. -
EditorSize
Indicates the size of the overlay that is opened when editing a block. Possible values aresmall
,medium
andnormal
. -
ContentElementTypeKey
The GUID key of the content type that should be used for the content element. This must have a value. -
SettingsElementTypeKey
The GUID key of the content type that should be used for the settings element. -
BackgroundColor
An optional background color used for cards using this block configuration - eg.#000000
. -
IconColor
An optional icon color used for cards using this block configuration - eg.#ffffff
. -
Thumbnail
An optional thumbnail image that is used for cards using this block configuration -~/App_Plugins/BlockList/Thumbnails/Quote.png
.
@using Umbraco.Cms.Core.Services
@using Umbraco.Cms.Core.PropertyEditors
@using Umbraco.Cms.Core
@using Umbraco.Cms.Core.Models
@using Umbraco.Cms.Core.Serialization
@inherits UmbracoViewPage
@inject PropertyEditorCollection PropertyEditors
@inject IDataTypeService DataTypeService
@inject IConfigurationEditorJsonSerializer ConfigurationEditorJsonSerializer
@inject IContentTypeService ContentTypeService
@{
// Get ID of the folder in which the new data type will be created
int parentId = 1122;
// Get a reference to the block list property editor
IDataEditor editor = PropertyEditors
.Single(x => x.Alias == Constants.PropertyEditors.Aliases.BlockList);
// Declare a list for the block configurations
List<BlockListConfiguration.BlockConfiguration> blocks = new();
// Get reference to the content types (element types) that we wish to allow for the block list
IContentType? quoteBlockContentType = ContentTypeService.Get("quoteBlock");
IContentType? rteBlockContentType = ContentTypeService.Get("rteBlock");
IContentType? vimeoBlockContentType = ContentTypeService.Get("vimeoBlock");
if (quoteBlockContentType is null) throw new Exception("Oh noes!");
if (rteBlockContentType is null) throw new Exception("Oh noes!");
if (vimeoBlockContentType is null) throw new Exception("Oh noes!");
// Append the "Quote" block configuration
blocks.Add(new BlockListConfiguration.BlockConfiguration
{
ContentElementTypeKey = quoteBlockContentType.Key
});
// Append the "Text" block configuration
blocks.Add(new BlockListConfiguration.BlockConfiguration
{
ContentElementTypeKey = rteBlockContentType.Key,
Label = "Text"
});
// Append the "Vimeo" block configuration
blocks.Add(new BlockListConfiguration.BlockConfiguration
{
ContentElementTypeKey = vimeoBlockContentType.Key
});
// Initialize the configuration object
BlockListConfiguration config = new BlockListConfiguration
{
Blocks = blocks.ToArray(),
ValidationLimit = new BlockListConfiguration.NumberRange { Min = null, Max = null },
UseSingleBlockMode = false,
UseLiveEditing = false,
UseInlineEditingAsDefault = false,
MaxPropertyWidth = "100%"
};
// Get the default database type
ValueStorageType databaseType = ValueTypes
.ToStorageType(editor.GetValueEditor(config).ValueType);
// Initialize a new data type
IDataType dataType = new DataType(editor, ConfigurationEditorJsonSerializer, parentId)
{
Name = "My block list",
DatabaseType = databaseType,
Configuration = config
};
// Create/save the data type to the database
DataTypeService.Save(dataType);
// Print out the ID
<pre>@dataType.Id</pre>
}
Media
Adding media with physical files are a bit complex. To add a file to a media, you have to use the special IMedia.SetValue
extension method. The extension method that you'll need is located in the Umbraco.Exensions
namespace.
Umbraco has a number of SetValue
methods, but the one you'll need where the first five parameters match the following types:
- MediaFileManager
- MediaUrlGeneratorCollection
- IShortStringHelper
- IContentTypeBaseServiceProvider
Creating a new image from a file on disk
A new media may be created from a file on disk using the following steps:
- map/declare the path to the file
- declare the new filename
- open a new stream to the file on disk
- create a new media in memory
- use the special
.SetValue()
extension method to set the media file - save the media
Using these steps, Umbraco will automatically populate the umbracoWidth
, umbracoHeight
, umbracoBytess
and umbracoExtension
properties with the correct values.
If you for instance are using Azure blob storage, and have configured this correctly for your website, Umbraco will also automatically upload the media file to the blob container rather than saving it to disk.
@using Umbraco.Cms.Core.Services
@using Umbraco.Cms.Core.Models
@using Umbraco.Cms.Core.PropertyEditors
@using Umbraco.Cms.Core.Strings
@using Umbraco.Cms.Core.IO
@using System.IO
@using Umbraco.Cms.Core
@using Microsoft.AspNetCore.Hosting
@using File = System.IO.File
@inherits UmbracoViewPage
@inject IWebHostEnvironment WebHostEnvironment
@inject IMediaService MediaService
@inject MediaFileManager MediaFileManager
@inject MediaUrlGeneratorCollection MediaUrlGeneratorCollection
@inject IShortStringHelper ShortStringHelper
@inject IContentTypeBaseServiceProvider ContentTypeBaseServiceProvider
@{
// Map the path to the image file on disk
string imagePath = WebHostEnvironment.MapPathWebRoot("~/unicorn.jpg");
// Declare the file name of the image
string imageName = "unicorn.jpg";
// Open a stream for the file on disk
await using Stream stream = File.OpenRead(imagePath);
// Create a new media in memory
IMedia media = MediaService.CreateMedia("Unicorn", -1, Constants.Conventions.MediaTypes.Image);
// Set the "umbracoFile" property using the stream
media.SetValue(MediaFileManager, MediaUrlGeneratorCollection, ShortStringHelper, ContentTypeBaseServiceProvider, Constants.Conventions.Media.File, imageName, stream);
// Save and persists the media to the database
MediaService.Save(media);
<pre>@media.Id</pre>
<pre>@media.Key</pre>
}
Creating a new image from an URL
A new media may be created from a file on disk using the following steps:
- map/declare the path to the file
- declare the new filename
- get a new
HttpClient
fromIHttpClientFactory
- open a new stream to the remote file
- create a new media in memory
- use the special
.SetValue()
extension method to set the media file - save the media
@using Umbraco.Cms.Core.Services
@using Umbraco.Cms.Core.Models
@using Umbraco.Cms.Core.PropertyEditors
@using Umbraco.Cms.Core.Strings
@using Umbraco.Cms.Core.IO
@using System.Net.Http
@using Umbraco.Cms.Core
@using System.IO
@inherits UmbracoViewPage
@inject IMediaService MediaService
@inject IHttpClientFactory HttpClientFactory
@inject MediaFileManager MediaFileManager
@inject MediaUrlGeneratorCollection MediaUrlGeneratorCollection
@inject IShortStringHelper ShortStringHelper
@inject IContentTypeBaseServiceProvider ContentTypeBaseServiceProvider
@{
// Declare the URL to the image
string imageUrl = "https://umbraco.com/media/br4ddn0l/umbraco-12-square_dark_500x500px-80.jpg";
// Declare the file name of the image
string imageName = "umbraco12.jpg";
// Create a new HTTP client from the factory
using HttpClient client = HttpClientFactory.CreateClient();
// Download the remote image
await using Stream stream = await client.GetStreamAsync(imageUrl);
// Create a new media in memory
IMedia media = MediaService.CreateMedia("Umbraco 12", -1, Constants.Conventions.MediaTypes.Image);
// Set the "umbracoFile" property using the stream
media.SetValue(MediaFileManager, MediaUrlGeneratorCollection, ShortStringHelper, ContentTypeBaseServiceProvider, Constants.Conventions.Media.File, imageName, stream);
// Save and persists the media to the database
MediaService.Save(media);
<pre>@media.Id</pre>
<pre>@media.Key</pre>
}
Accessing a media file for an existing media
Depending on how a Umbraco installation is configured, media files may either be stored locally on disk or somewhere else (eg. Azure Blob Storage). This means that in order to open a file, we can't rely on File.OpenRead
.
Instead we can use Umbraco's MediaFileManager
class, which exposes an IFileSystem
via the FileSystem
property. The IFileSystem
instance then has a OpenFile
method, that returns a Stream
that we can use.
Notice how I'm using the .TryGetMediaPath()
extension method for getting the relative path of the media. For regular files, the media's umbracoFile
will simply be the relative path to the media file, but for images, the property value will instead be a JSON object including both the relative path as well as various cropping information for the image. Instead of reinventing the wheel, we can rely on Umbraco's extension method to parse and return the relative path for us.
@using Umbraco.Cms.Core.Services
@using Umbraco.Cms.Core.Models
@using Umbraco.Cms.Core.PropertyEditors
@using Umbraco.Cms.Core.IO
@using System.IO
@inject IMediaService MediaService
@inject MediaUrlGeneratorCollection MediaUrlGeneratorCollection
@inject MediaFileManager MediaFileManager
@{
// Get a reference to the media
IMedia? media = MediaService.GetById(1313);
if (media is null)
{
throw new Exception("Oh noes!");
}
// Try to get the relative path to the media file
if (!media.TryGetMediaPath("umbracoFile", MediaUrlGeneratorCollection, out string? mediaFilePath))
{
throw new Exception("Oh noes!");
}
<pre>Relative path: @mediaFilePath</pre>
// Open a new stream to the file
await using Stream stream = MediaFileManager.FileSystem.OpenFile(mediaFilePath);
// Do something with the stream
}