In my previous post I talked about "mapping between PageType attributes in PageTypeBuilder and typed pages in EPiServer 7". In this post I want to complete the series and talk about the mapping of property definitions in typed pages.

The following table shows the mappings for PageTypeBuilder property attributes to typed pages in EPiServer 7:

PageTypeBuilder EPiServer CMS 7
Attribute Property/Field Attribute Property/Field
Namespace: PageTypeBuilder Namespace: System.ComponentModel.DataAnnotations
PageTypeProperty DisplayInEditMode ScaffoldColumnAttribute  
PageTypeProperty EditCaption Display Name
PageTypeProperty HelpText Display Description
PageTypeProperty SortOrder Display Order
PageTypeProperty Tab Display GroupName
PageTypeProperty Required Required  
    Namespace: EPiServer.DataAnnotations
PageTypeProperty Searchable Searchable  
PageTypeProperty Type BackingType  
PageTypeProperty UniqueValuePerLanguage CultureSpecific  
  - Access Users
  - Access Roles
  - Access VisitorGroups

Default property values

Experienced PageType builder users may have noticed that the following attributes are missing in the mapping table above:

  • DefaultValue
  • DefaultValueType

This is because typed pages in EPiServer 7 does not have a direct equivalent. If you want to set default property values when using typed pages in EPiServer 7 then you should override the "SetDefaultValues" method on EPiServer.Core.PageData as follows (this is the same method as described in my previous post):

public override void SetDefaultValues(PageType pageType)
{
    base.SetDefaultValues(pageType);
    //Set up your defaults here
}

Full examples

I wanted to put this together and show two fully worked examples to compare PageTypeBuilder and typed pages in EPiServer 7. I have included the full namespaces of the attributes to show in this examples.

EPiServer 7 implementation

[PageType(
      AvailableInEditMode = true
    , Description = "The description"
    , DisplayName = "My page type"
    , GUID = "F5E708BE-B8D8-11E1-9F05-EE3A6188709B"
    , GroupName = "Public:Example"
    , Order = 1234)]
[EPiServer.DataAnnotations.AvailablePageTypes(
    Include = new[] { typeof(AnotherPageType) }
    )]
public class YourPageType : EPiServer.Core.PageData
{
    public override void SetDefaultValues(DataAbstraction.PageType pageType)
    {
        base.SetDefaultValues(pageType);

        ArchiveLink = new Core.PageReference(1234);
        this.Properties["PageChildOrderRule"].Value = EPiServer.Filters.FilterSortOrder.CreatedDescending;
        this.Properties["PageTargetFrame"].Value = 0;
        this.PageName = "My page name";
        this.Properties["PagePeerOrder"].Value = 9999;
        this.StartPublish = DateTime.Now.AddMinutes(10);
        this.StopPublish = DateTime.Now.AddMinutes(20);
        this.VisibleInMenu = false;

        // Set up property defaults
        this.IntroText = "Default intro text";
        this.BodyText = "Default body text";
    }

    [System.ComponentModel.DataAnnotations.Display(
          Name = "Introduction"
        , Description = "Help on introduction"
        , Order = 1
        , GroupName = "Information"
        )]
    [System.ComponentModel.DataAnnotations.Required()]
    [EPiServer.DataAnnotations.Searchable(true)]
    [System.ComponentModel.DataAnnotations.ScaffoldColumn(true)]
    [EPiServer.DataAnnotations.BackingType(typeof(EPiServer.Core.PropertyString))]
    [EPiServer.DataAnnotations.CultureSpecific(true)]
    public virtual string IntroText { get; set; }


    [System.ComponentModel.DataAnnotations.Display(
          Name = "Body Text"
        , Description = "Help on body text"
        , Order = 2
        , GroupName = "Information"
        )]
    [System.ComponentModel.DataAnnotations.Required()]
    [EPiServer.DataAnnotations.Searchable(true)]
    [System.ComponentModel.DataAnnotations.ScaffoldColumn(true)]
    [EPiServer.DataAnnotations.BackingType(typeof(EPiServer.SpecializedProperties.PropertyXhtmlString))]
    [EPiServer.DataAnnotations.CultureSpecific(true)]
    public virtual string BodyText { get; set; }
}

PageTypeBuilder implementation

[PageTypeBuilder.PageType(
        AvailableInEditMode = true
    , AvailablePageTypes = new Type[] { typeof(AnotherPageType) }
    , SortOrder = 1234
    , Filename = "~/Templates/Public/MyPageType.aspx"
    , Name = "[Public] My page type"
    , Description = "The description"
    , DefaultArchiveToPageID = 2345
    , DefaultChildSortOrder = EPiServer.Filters.FilterSortOrder.CreatedDescending
    , DefaultFrameID = 0
    , DefaultPageName = "My page name"
    , DefaultSortIndex = 9999
    , DefaultStartPublishOffsetMinutes = 10
    , DefaultStopPublishOffsetMinutes = 20
    , DefaultVisibleInMenu = false
)]
public class YourPageType : PageTypeBuilder.TypedPageData
{
    [PageTypeBuilder.PageTypeProperty(
        EditCaption = "Introduction"
      , DefaultValue = "Default intro text"
      , Tab = typeof(InformationTab)
      , DisplayInEditMode = true
      , HelpText = "Help on introduction"
      , Required = true
      , Searchable = true
      , Type = typeof(EPiServer.Core.PropertyString)
      , UniqueValuePerLanguage = true
      , SortOrder = 1)]
    public virtual string IntroText { get; set; }

    [PageTypeBuilder.PageTypeProperty(
        EditCaption = "Body Text"
      , DefaultValue = "Default body text"
      , Tab = typeof(InformationTab)
      , SortOrder = 2)
      , DisplayInEditMode = true
      , HelpText = "Help on body text"
      , Required = true
      , Searchable = true
      , Type = typeof(EPiServer.SpecializedProperties.PropertyXhtmlString)
      , UniqueValuePerLanguage = true
      , SortOrder = 2)
    ]
    public virtual string BodyText { get; set; }
}

Disclaimer

EPiServer 7 Preview is obiously still a preview so this advice all is subject to change. As and when things do change I will update these posts to reflect this.

Conclusion

EPiServer have done a great job of typed pages in EPiServer 7, not only making it easy to migrate from PageTypeBuilder but adding some cool new features to typed pages too (my favourite is the PageType.ExcludeOn and PageType.IncludeOn properties).

From a usage point of view the implementation is remarkably similar to PageTypeBuilder so props should go to Joel Abrahamsson and Lee Crowe for their efforts on PTB!

Feedback

I'd be happy to hear any feedback on the comments below or @davidknipe


Comments