Auto create sub page(s) when a page is created
There are times when I want to make a structure of pages when one page is created. Sometimes it would be easy to just add an attributes to your page type, so each time a page of that type is created we will auto magically add a sub page.
First I made myself a attribute
- [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
- public class EnsureSubPageAttribute : Attribute
- {
- public Type PageType { get; set; }
- public string PageName { get; set; }
- public string URLSegment { get; set; }
- public int SortIndex { get; set; }
- public string SetReferenceToProperty { get; set; }
- public string[] SetPropertyNames { get; set; }
- public string[] SetPropertyValues { get; set; }
- }
Then I add myself to the Created Page event. I do this stuff there since created page is only triggered once, and if I change my attributes I will ensure my sub pages on startup.
- [ModuleDependency(typeof(PageTypeBuilder.Initializer))]
- public class EnsureSubPages : IInitializableModule
- {
- #region IInitializableModule Members
- public void Initialize(EPiServer.Framework.Initialization.InitializationEngine context)
- {
- EPiServer.DataFactory.Instance.CreatedPage += new EPiServer.PageEventHandler(Instance_CreatedPage);
- EnsureAllExistingPages();
- }
- public void Preload(string[] parameters) { }
- public void Uninitialize(EPiServer.Framework.Initialization.InitializationEngine context)
- {
- EPiServer.DataFactory.Instance.CreatedPage -= new EPiServer.PageEventHandler(Instance_CreatedPage);
- }
- #endregion
The method for created page looks like this
- void Instance_CreatedPage(object sender, EPiServer.PageEventArgs e)
- {
- EnsureSubPagesForPage(e.Page);
- }
- static void EnsureSubPagesForPage(PageData page)
- {
- var type = page.GetType();
- PageDataCollection subPages = null;
- foreach (var attribute in type.GetCustomAttributes(true))
- {
- var myAttribute = (attribute as EnsureSubPageAttribute);
- if (myAttribute != null && !string.IsNullOrEmpty(myAttribute.URLSegment))
- {
- if (subPages == null)
- subPages = EPiServer.DataFactory.Instance.GetChildren(page.PageLink, LanguageSelector.MasterLanguage());
- var result = (from subPage in subPages where subPage.URLSegment == myAttribute.URLSegment select subPage).ToList();
- if (result.Count == 0)
- page = CreatePage(page, myAttribute);
- else
- UpdatePage(myAttribute, result[0]);
- }
- }
- if (page.IsModified)
- EPiServer.DataFactory.Instance.Save(page, EPiServer.DataAccess.SaveAction.ForceCurrentVersion | EPiServer.DataAccess.SaveAction.Publish, EPiServer.Security.AccessLevel.NoAccess);
- }
but the cool (and dangerous ) task is the method that checks all the page types and find all that uses the attribute.Then finds all pages of that type and ensure them.
- private static void EnsureAllExistingPages()
- {
- foreach (var pagetype in EPiServer.DataAbstraction.PageType.List())
- {
- var typedPageType = PageTypeResolver.Instance.GetPageTypeType(pagetype.ID);
- if (typedPageType != null && typedPageType.GetCustomAttributes(typeof(EnsureSubPageAttribute), true).Length > 0)
- {
- var pages = FindPagesByPageType(typedPageType, PageReference.StartPage);
- foreach (var page in pages)
- EnsureSubPagesForPage(page);
- }
- }
- }
So now one can in the code behind mark page types with attributes like this
- [PageType(Name = "Department structur", Filename = "/Custom/Pages/Department.aspx", DefaultSortIndex = 10)]
- [EnsureSubPage(
- PageType = typeof(AttachPageProviderPageType),
- PageName = "Community pages",
- SetPropertyNames=new string[] {"AttachChildrenFrom"},
- SetPropertyValues=new string[] {"22"},
- SetReferenceToProperty = "OneClubPage",
- URLSegment = "CommunityPages",
- SortIndex = 10)]
- [EnsureSubPage(
- PageType = typeof(UDPageType),
- PageName = "dummy page",
- URLSegment = "DummyPage",
- SortIndex=20)]
- [EnsureSubPage(
- PageType = typeof(UDPageType),
- PageName = "dummy page 2",
- URLSegment = "DummyPage2",
- SortIndex = 30)]
- public class DepartmentPageType : TypedPageData, OnCreatedPage, IClubRoot
Full code is here. Its just one file :)
Neat solution.
I think I'll have to replace my global event handlers with your code.