EPiServer creation and management of non-common content types

EPiServer creation and management of non-common content types

During the EPiServer Ascend event I attended a lab called external content replication which I though was quite interesting, you can find the instructions here. The lab showed us how to treat external content, integrate it in EPiServer using a job, save it outside of the root site and create these content types in a different tab of the assets pane. What I decided to do is to replicate this lab and explain it more in depth, in special how to create non common content types which do not fit as blocks or pages but should be handled by the CMS anyway.   

epi_server_logo_detail

So, lets begin !!!!

First, I am going to begin creating a content type which in this case it is not going to inherit from BlockData or PageData. From the lab I learned that you can also inherit from other classes which provides several of the functionality of those two classes but can be used in different scenarios like this one. These classes are explained in the link above, but I will show them here for completion purposes: 

Class Name Description 
BasicContent Basic implementation of IContent 
ContentBase Inherits from BasicContent but adds IVersionable and IModifiedTrackable interfaces implementations 
StandardContentBase Inherits from ContentBase but adds ILocalizable and even more EPiServer interfaces implementations  

You can also add more interfaces to your content types as required.  The new content type is going to inherit from StandardContentBase and it will describe a person in a business. The class has the following code

using System.ComponentModel.DataAnnotations; 
using EPiServer.Core; 
using EPiServer.DataAnnotations; 

namespace Foundation.Cms.People 
{ 

    [ContentType(DisplayName = "Person Content", GUID = "c41959cf-efc1-4e5f-b79d-78d3b8e5af13")] 
    public class PersonContent : StandardContentBase // Inherits from a different class PageData or BlockData 
    { 

        [Required] 
        [Display(Name = "First Name", Order = 10)] 
        public virtual string FirstName { get; set; } 

        [Required] 
        [Display(Name = "Last Name", Order = 20)] 
        public virtual string LastName { get; set; } 

        [CultureSpecific] 
        [Required] 
        [Display(Name = "Job Position", Order = 30)] 
        public virtual string JobPosition { get; set; } 

        [Required] 
        [Display(Name = "Age", Order = 40)] 
        public virtual int AddressLine2 { get; set; } 

    } 
}  

Now, I am going to choose where these new content types items are going to live because we do not want this content to be part of our main site tree structure. We will create an initialization module which will create a new folder below the root level where will be saving these new items  

using System; 
using EPiServer.Core; 
using EPiServer.DataAbstraction; 
using EPiServer.Framework; 
using EPiServer.Framework.Initialization;  

namespace Foundation.Cms.People 
{ 
    [InitializableModule]
    [ModuleDependency(typeof(EPiServer.Web.InitializationModule))]
    public class PeopleRootInitialization : IInitializableModule
    {
        public void Initialize(InitializationEngine context)
        {
            var contentRootService = context.Locate.Advanced.GetInstance<ContentRootService>();

            // We create a folder at the root level called People 
            contentRootService.Register<ContentFolder>("People", new Guid("c41959cf-efc1-4e5f-b79d-78d3b8e5af14"), ContentReference.RootPage);
        }

        public void Uninitialize(InitializationEngine context)
        {

        }
    }   
} 

We will also create a new content repository descriptor which will define several aspects of the People content folder created in the initialization module.  The aspects we defined are 

Aspect Description Value 
Key Key for this new content repository descriptor People 
Name Name of the content repository descriptor People 
Roots What is the root where the content repository descriptor is applied People folder from Root 
ContainedTypes Which types can be inside  PersonContent, ContentFolder 
CreatableTypes Which types can be created inside  PersonContent, ContentFolder 
LinkableTypes Which types can be linked inside  PersonContent 
MainNavigationTypes Which types can be used as part of the navigation tree structure  ContentFolder 

What we are trying to say with these properties and values is that we are going to allow only PersonContent and ContentFolder items to be inside the folder People, that we are only allowing to create items of the same two types, that you can only link PersonContent items and that we can only use ContentFolder items as part of our navigation tree. The property Roots is using a variable _root which is initialized in the constructor with the folder we created in the initialization module. The code is the following: 

using System; 
using System.Collections.Generic; 
using EPiServer.Core; 
using EPiServer.DataAbstraction; 
using EPiServer.ServiceLocation; 
using EPiServer.Shell; 

 namespace Foundation.Cms.People 
{ 

    [ServiceConfiguration(typeof(IContentRepositoryDescriptor))]
    public class PeopleContentRepositoryDescriptor : ContentRepositoryDescriptorBase
    {

        private readonly ContentReference _root;

        public PeopleContentRepositoryDescriptor(ContentRootService contentRootService)
        {
            _root = contentRootService.Get("People");
        }

        public override string Key => "people";

        public override string Name => "People";

        public override IEnumerable<ContentReference> Roots => new[] { _root };

        public override IEnumerable<Type> ContainedTypes => new[] { typeof(PersonContent), typeof(ContentFolder) };

        public override IEnumerable<Type> CreatableTypes => new[] { typeof(PersonContent), typeof(ContentFolder) };

        public override IEnumerable<Type> LinkableTypes => new[] { typeof(PersonContent), };

        public override IEnumerable<Type> MainNavigationTypes => new[] { typeof(ContentFolder), };

    }

Finally, we will create a UI component. It will use our content repository descriptor created above to define properties in the editor UI such as: sort order, name (in the UI) and in which area will be shown inside the editor. The properties we defined for this UI component are: 

Property Description Value 
Title Title of the UI component People 
Categories Category of the UI component content 
PlugInAreas Where in the UI is going to be located PlugInArea.AssetsDefaultGroup, PlugInArea.NavigationDefaultGroup 
SortOrder In which position is going to appear 1000 
Settings Settings configuration for the UI Component.  new Setting(“repositoryKey”, “people”) 

We added the repository key setting to the UI component and set it to the content repository descriptor defined in the previous class using its key “people” 

using EPiServer.Shell; 
using EPiServer.Shell.ViewComposition;  

namespace Foundation.Cms.People 
{ 

    [Component] 
    public class PeopleTreeComponent : ComponentDefinitionBase 
    { 

        public PeopleTreeComponent() : base("epi-cms/asset/HierarchicalList") 
        { 
            base.Title = "People"; 
            Categories = new [] { "content" }; 
            PlugInAreas = new [] { PlugInArea.AssetsDefaultGroup, PlugInArea.NavigationDefaultGroup }; 
            SortOrder = 1000; 
            base.Settings.Add(new Setting("repositoryKey", "people")); 
            base.Settings.Add(new Setting("noDataMessages", new { single = "This folder does not contain any locations", multiple = "These folders do not contain any locations" })); 
        } 
    } 
} 

There is an additional setting called “noDataMessages”, this setting is required to make this example work. You can find more details about why is needed in the lab link 

We will now compile the code and run it. Go to the CMS editor and see if the People tab appears in any of the plugin areas, we defined in the UI component 

If the tab or tabs does not appear. You can press the profile icon at the top right corner, press my settings, click in display options and hit the reset view (As stated in the lab link)

You can now create some persons or folders inside the people tab -people folder and use those items anywhere in the CMS 

You can check that these new files are being saved outside of the main site tree structure by going to the admin interface, admin tab, set access rights option 

Written by:

Jorge Cardenas

Developer with several years of experience who is passionate about technology and how to solve problems through it.

View All Posts

5 COMMENTS

comments user
Scott Reed

I’ve followed this to the letter but I can’t anything other than new folder to appear as an option. Working on CMS 11.12.0

comments user
Jorge Cardenas

Greetings Scott. Is there a way you can share part of your code so I can help you with it. Or you can send me an email with the sample code. Please also check the recommendation about resetting the view “You can press the profile icon at the top right corner, press my settings, click in display options and hit the reset view” maybe that would help

    comments user
    Scott Reed

    Thanks, can I check what version you are running on, Maybe you can add your example to a github repo so I can double check my code? I’ve reset my view, that didn’t work.

      comments user
      Jorge Cardenas

      Please review the updated blog. I modified some code to work with the latest version of the CMS. In addition, you can see an example in this GitHub repository https://github.com/dYnAc/EpiExamples. The People implementation classes are inside Models – People

Leave a Reply