November Happy Hour will be moved to Thursday December 5th.

Dan Matthews
Nov 20, 2013
  6939
(0 votes)

Restricting available page types for Root page

Now that we have strongly typed page types in EPiServer 7, we wonder how we ever lived without it. Actually… we just used the superb Page Type Builder, but that’s not the point. We now want to do everything in code rather than in the Admin mode, and we nearly can. However, there are a couple of little things that we can’t quite do yet, and restricting the available page types for the Root page is one of them. Typically, you will only ever be creating ‘start pages’ under the Root page, and you’ll probably have a specific type for the start page. If we do a ‘New page’ under the Root though, we get all of our page types listed! That’s a bit messy. So what are our options? Well, the Root page is in Admin mode; it’s called ‘Welcome page in Edit Mode’ and it’s type is ‘SysRoot’. We could restrict available page types there. But that’s going back to the dark ages. You can’t commit that to source control like other code and have it picked up by everyone else. A much nicer way would be to use the AvailablePageTypes attribute. No luck there though – the SysRoot has no code definition that I can find (according to Admin mode it doesn’t come from code) and so you can’t use it with the strongly-typed AvailablePageTypes attribute. Possibly you could create a definition for the SysRoot in code, but that’s a pretty scary thing to do and I personally wouldn’t want to go there – I used to do it in Page Type Builder but I wouldn’t want to in EPiServer 7.

So what do we do? I was asked that by a student in a training course recently, and so I had to comeup with an answer. Actually, it’s pretty easy. We use an Initialization Module and the API to do what Admin mode is doing, but automatically and in code. The code to achieve this is shown below. Note that in this example the start page type is ‘StartPage’.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using EPiServer.Framework;
using EPiServer.ServiceLocation;
using EPiServer.DataAbstraction;
using EPiServerZA.Models.Pages;
 
namespace EPiServerZA.Business
{
    [InitializableModule]
    [ModuleDependency(typeof(EPiServer.Data.DataInitialization))]
    public class RestrictRootPages : IInitializableModule
    {
        public void Initialize(EPiServer.Framework.Initialization.InitializationEngine context)
        {
            var sysRoot = ServiceLocator.Current.GetInstance<IContentTypeRepository>().Load("SysRoot") as PageType;
            var startPage = ServiceLocator.Current.GetInstance<IContentTypeRepository>().Load(typeof(StartPage));
 
            var setting = new EPiServer.DataAbstraction.PageTypeAvailability.AvailableSetting();
 
            setting.Availability = EPiServer.DataAbstraction.PageTypeAvailability.Availability.Specific;
            setting.AllowedPageTypeNames.Add(startPage.Name);
 
            ServiceLocator.Current.GetInstance<EPiServer.DataAbstraction.PageTypeAvailability.IAvailableSettingsRepository>().RegisterSetting(sysRoot, setting);
        }
 
        public void Preload(string[] parameters)
        {
           
        }
 
        public void Uninitialize(EPiServer.Framework.Initialization.InitializationEngine context)
        {
           
        }
    }
}

The code simply grabs the SysRoot and StartPage types from the content type repository then makes the StartPage the only available page type on the SysRoot. There is a dependency on DataInitialization so that the repositories should be ready to use when this runs. Any clarifications or easier ways to achieve this are welcome Smile

Nov 20, 2013

Comments

Al Higgs
Al Higgs Nov 21, 2013 03:45 PM

Nice article Dan!

Al Higgs
Al Higgs Nov 21, 2013 03:46 PM

Very useful to know Dan

thomassvensen
thomassvensen Jan 17, 2014 01:16 PM

Very useful, Dan, thank you!

We are using 7.5.409, and I found they've changed things slightly. My coded ended up looking like this:

var locator = ServiceLocator.Current;
var contentTypeRepository = locator.GetInstance();
var sysRoot = contentTypeRepository.Load("SysRoot") as PageType;
var startPage = contentTypeRepository.Load(typeof(StartPage));
var setting = new AvailableSetting {Availability = Availability.Specific};
setting.AllowedContentTypeNames.Add(startPage.Name);
var availabilityRepository = locator.GetInstance();
availabilityRepository.RegisterSetting(sysRoot, setting);

Feb 11, 2014 08:27 AM

Thanks for the update Thomas, yes it makes sense that it is slightly different in 7.5 as they have abstracted some additional things around content!

Oct 15, 2016 07:29 PM

The code will only work if there actually is a startpage created. A null protect on the startpage variable and the code is usable once again!

var locator = ServiceLocator.Current;
var contentTypeRepository = locator.GetInstance();
var sysRoot = contentTypeRepository.Load("SysRoot") as PageType;
var startPage = contentTypeRepository.Load(typeof(StartpagePage));
if (startPage != null)
{
    var setting = new AvailableSetting { Availability = Availability.Specific };
    setting.AllowedContentTypeNames.Add(startPage.Name);
    var availabilityRepository = locator.GetInstance();
    availabilityRepository.RegisterSetting(sysRoot, setting);
}

Thanks for sharing.

Nov 10, 2016 01:22 PM

Thanks for feedback Eric... I presume you mean start page TYPE created, which you might not have on first time load as it's possible I guess that the start page type hasn't synced into your content type repository BEFORE this loads. Maybe you could change your module dependency to a later one (like EPiServer.Web.InitializationModule) which would probably ensure that you have your StartpagePage type (in your example) already synced into the content type repository before this code runs. Otherwise, this will only pick up and run on your second load :)

Please login to comment.
Latest blogs
Optimizely SaaS CMS + Coveo Search Page

Short on time but need a listing feature with filters, pagination, and sorting? Create a fully functional Coveo-powered search page driven by data...

Damian Smutek | Nov 21, 2024 | Syndicated blog

Optimizely SaaS CMS DAM Picker (Interim)

Simplify your Optimizely SaaS CMS workflow with the Interim DAM Picker Chrome extension. Seamlessly integrate your DAM system, streamlining asset...

Andy Blyth | Nov 21, 2024 | Syndicated blog

Optimizely CMS Roadmap

Explore Optimizely CMS's latest roadmap, packed with developer-focused updates. From SaaS speed to Visual Builder enhancements, developer tooling...

Andy Blyth | Nov 21, 2024 | Syndicated blog

Set Default Culture in Optimizely CMS 12

Take control over culture-specific operations like date and time formatting.

Tomas Hensrud Gulla | Nov 15, 2024 | Syndicated blog

I'm running Optimizely CMS on .NET 9!

It works 🎉

Tomas Hensrud Gulla | Nov 12, 2024 | Syndicated blog

Recraft's image generation with AI-Assistant for Optimizely

Recraft V3 model is outperforming all other models in the image generation space and we are happy to share: Recraft's new model is now available fo...

Luc Gosso (MVP) | Nov 8, 2024 | Syndicated blog