Category Archives: Page Types

Slight update on the Tool for Page Type Classes from Page Types in EPiServer 7 CMS

I made a small mistake on the Page Type Class Tool for EPiServer 7 CMS. This was on the SetDefaultValues method where the ChildOrderRule was set to FilterSortOrder.None.

If a Page have a ChildOrderRule set to None, EPiServer won’t be able to find the Children of that Page since the Stored Procedure does not know how to handle that ChildOrderRule.

Therefore I have added a check whether pageType.Defaults.ChildOrderRule is not FilterSortOrder.None before setting the value.

Some information behind the scenes

FilterSortOrder.None is basically a value that means that there is no specific default value setting for this Page Type stored in tblPropertyDefinitionDefault.

If the ChildOrderRule is set to None, the default values provided by PageDataBuilder.SetPropertyValues() will be set, which means that the default value is 1 (CreatedDescending).

Even the class PageData where SetDefaultValues() is defined have a check for ChildOrderRule.

if (pageType.Defaults.ChildOrderRule != FilterSortOrder.None)
    property["PageChildOrderRule"].Value = (object) pageType.Defaults.ChildOrderRule;

What should I do if I have used the faulty version?

All you need to do is to remove the following row from all your Page Type Classes:

this[MetaDataProperties.PageChildOrderRule] = FilterSortOrder.None;

And run following in your database to fix all pages that have already been created with wrong ChildOrderRule:

UPDATE [tblContent] SET ChildOrderRule = 1 WHERE ChildOrderRule = -1

I am sorry for the inconvenience, if you find more bugs or have suggestions on how to improve, please tell me.

Resolve PageType & ContentType from Class

In PageTypeBuilder for EPiServer CMS 6 we had a lovely feature called PageTypeResolver which could be used to find the Id of a PageType based on your implementation of TypedPageData. All you needed to do is run PageTypeResolver.Instance.GetPageTypeID(typeof(MyPageType)) and you would get a Nullable Int which represents the Id of your PageType, or null if no PageType could be found. In EPiServer 7 CMS this has been built into the main functionality of Page Types / Content Types and all you need to do is this:

  • Find the implementation of IContentTypeRepository you’re looking for:
    var repository = ServiceLocator.Current.GetInstance<IContentTypeRepository<PageType>>();
    var repository = ServiceLocator.Current.GetInstance<IContentTypeRepository<BlockTypeType>>();
    var repository = ServiceLocator.Current.GetInstance<PageTypeRepository>();
    var repository = ServiceLocator.Current.GetInstance<BlockTypeRepository>();
  • Load the page type based on your implementation of BlockData/PageData:
    var contentType = repository.Load(typeof(MyPageType));

If you’re locating the PageTypeRepository or BlockTypeRepository implementations directly you can also find the shortcut:

var contentType = repository.Load<MyPageType>();

If you try to load an instance of ContentData that does not exist, Load() will return null.

Creating Page Type Classes from Page Types in EPiServer CMS 7

After my upgrade of Stockholm Pride to EPiServer 7 CMS (blog post coming soon) I wanted the project to be a bit more shiny with some Code Managed Page Types.

I forked Erik Nordin’s utility to create classes for PageTypeBuilder in an existing project. Did some research on what attributes I needed to create a similar thing with EPiServer 7 CMS.

As a bonus I also gave it a little more EPiServer look-and-feel:

create pt

Since I don’t know if I should commit this back to Erik Nordin’s GitHub or not, you can download it from GitHub.

Current status

I would see this as a first draft of the creation tool that worked quite good for my upgrade of Stockholm Pride.

It creates Properties for the most common properties in EPiServer but gives a template where you can decide if you want to go with a BackingTypeAttribute or using EditorDescriptors/UIHints instead (see below).

Attributes and value types

I’ve tried to cover all correct DataTypes Attributes such as replacing PropertyImageUrl with Url and setting UIHints but I still thinks it needs some more cleaning.

Note that since I only check for what’s in the database, avoid running this tool while already having Page Types Classes in your project.

Custom Properties

For now, the support for Custom Properties are not that great. I try to read out what kind of Data Value the Properties are meant to return but leave a code comment to those Properties I don’t know what to do with.

This way you can make a search for //DefinitionType= and decide for yourself if you want to use the UIHintAttribute or the BackingFieldAttribute to solve this problem.

Some of the older EPiServer Properties are obsolete which mean that they should not be used as a BackingField.

UILanguageProperty is one of them which luckily is only a property that returns a string, but the Editor may select among all activated Languages.

By reflection I can find out exactly how that list is populated.

Example of EditorDescriptor

This means that UILanguageProperty can easily be replaced with an EditorDescriptor that gives the same functionality:

//DefinitionType=EPiServer.SpecializedProperties.PropertyUILanguage
//[BackingType(typeof(PropertyUILanguage))] -- PropertyUILanguage has been obsoleted and will be removed in a future release.
[UIHint("UILanguage")]
[Display(Name = "Content Language")]
public virtual string ContentLanguage { get; set; }

[EditorDescriptorRegistration(TargetType = typeof(string), UIHint = "UILanguage")]
public class UILanguageEditorDescriptor : EditorDescriptor
{
   public override void ModifyMetadata(ExtendedMetadata metadata, IEnumerable<Attribute> attributes)
   {
      SelectionFactoryType = typeof(UILanguageSelectionFactory);
      ClientEditingClass = "epi.cms.contentediting.editors.SelectionEditor";

      base.ModifyMetadata(metadata, attributes);
   }
}

public class UILanguageSelectionFactory : ISelectionFactory
{
   public IEnumerable<ISelectItem> GetSelections(ExtendedMetadata metadata)
   {
      var languages = new List<SelectItem>();
      foreach (System.Globalization.CultureInfo info in LocalizationService.Current.AvailableLocalizations)
      {
         string nativeName = info.NativeName;
         if (info.TextInfo.ANSICodePage != 0x4e4)
         {
            nativeName = nativeName + string.Format(" ({0})", info.EnglishName);
         }
         languages.Add(new SelectItem { Value = info.Name, Text = nativeName });
      }
      return languages;
   }
}