Anders Hattestad
Oct 20, 2011
  4772
(3 votes)

How to create virtual page types

Often I come over some sites where there are many page types. Personally I don’t like it, but one of the reason all these types exists is that one want to set some default values on them. Sometime they also want to change the sequence the properties are listed in edit mode. All of this is fair game.

But one problem I have is that my editors want to create these page types and set the default values. If you use page type builder (as I do thank you Joel)   that can be problematic.

The solution to this is to create virtual page types. These page types is not real ones, but only a set of default values for the type.

I first created myself a admin tool that looks something like this

image

where ContentType and other stuff is default values I have one some page types. What these elements can be will change from project to project. But have hardcoded them in since I don’t want to give my administrators to much options to work with Smile.

I save those row data inside a DSS

Code Snippet
  1. [EPiServerDataStore(AutomaticallyRemapStore = true, AutomaticallyCreateStore = true)]
  2. public class VirtuelPageTypeData : IDynamicData
  3. {
  4.     public EPiServer.Data.Identity Id { get; set; }
  5.     public int Rank { get; set; }
  6.     public string Name { get; set; }
  7.     public string Description { get; set; }
  8.     public string PageTypeID { get; set; }
  9.     /*Hardcoded properties*/
  10.     public string ContentType { get; set; }
  11.     public string PageStopPublishAddMonth { get; set; }
  12.     public string IsTypeEvent { get; set; }
  13.     public string ImportantPage { get; set; }
  14.     public string IsSelectebleAsFag { get; set; }
  15.     public string PageVisibleInMenu { get; set; }

Then I need to change where the page type is selected.

I made myself a PageAdapter that I register in the App_Browser catalog like this.

Code Snippet
  1. <adaptercontrolType="EPiServer.UI.Edit.NewPage"
  2.             adapterType="Itera.VirtualPageTypes.NewPageAdapter" />

The code that is executed is a copy of the original page load code but I have added my virtual page types and removing the original page type from the collection. I also needed to change the return type of ID from int to string since I’m returning another parameter along with the pagetypeID.

Code Snippet
  1. foreach (var item in (VirtuelPageTypeData.Items.OrderBy(p=>p.Rank)) )
  2. {
  3.     var orgType = dataSource2.Find(p => p.ID == item.PageTypeID);
  4.     if ( orgType!= null)
  5.     {
  6.         var v = new {
  7.             ID = item.PageTypeID + "&defaultValues=" + item.Id.ToString(),
  8.             Name = item.Name,
  9.             Description = item.Description };
  10.         dataSource2.Insert(teller, v);
  11.         teller++;
  12.         if (!remove.Contains(item.PageTypeID))
  13.             remove.Add(item.PageTypeID);
  14.     }
  15. }
  16. foreach (var i in remove)
  17. {
  18.     var orgType = dataSource2.Find(p => p.ID == i);
  19.     dataSource2.Remove(orgType);
  20. }

After I have done this the new page dialog looks like this:

image

So far so good Smile, but then I need to actually populate the default values to the page.

I found out that the easiest way was to attach myself to the LoadedDefaultPageData event like this.

Code Snippet
  1. [EPiServer.Framework.ModuleDependency(typeof(PageTypeBuilder.Initializer))]
  2. public class AttachEvent : IInitializableModule
  3. {
  4.     #region IInitializableModule Members
  5.     static EPiServer.PageEventHandler DefaultHandler = new EPiServer.PageEventHandler(Instance_LoadedDefaultPageData);
  6.     public void Initialize(EPiServer.Framework.Initialization.InitializationEngine context)
  7.     {
  8.         EPiServer.DataFactory.Instance.LoadedDefaultPageData += DefaultHandler;
  9.     }
  10.  
  11.     static void Instance_LoadedDefaultPageData(object sender, EPiServer.PageEventArgs e)
  12.     {
  13.         if (HttpContext.Current!=null && !string.IsNullOrEmpty(HttpContext.Current.Request["defaultValues"]))
  14.         {
  15.             try
  16.             {
  17.                 var row = VirtuelPageTypeData.Store.Load<VirtuelPageTypeData>(EPiServer.Data.Identity.Parse(HttpContext.Current.Request["defaultValues"]));
  18.                 UpdatePage(e.Page, "ContentType", row.ContentType);
  19.                 UpdatePage(e.Page, "IsTypeEvent", row.IsTypeEvent);
  20.                 UpdatePage(e.Page, "ImportantPage", row.ImportantPage);
  21.                 UpdatePage(e.Page, "IsSelectebleAsFag", row.IsSelectebleAsFag);
  22.  
  23.                  
  24.                 if (!string.IsNullOrEmpty(row.PageStopPublishAddMonth)) {
  25.  
  26.                     try {
  27.                         int mnd=int.Parse(row.PageStopPublishAddMonth);
  28.                         (e.Page.Property["PageStopPublish"] as PropertyDate).Date=DateTime.Now.AddMonths(mnd);
  29.                     }
  30.                     catch{}
  31.  
  32.                 }
  33.             }
  34.             catch (System.Exception error)
  35.             {
  36.                 var a = error.Message;
  37.             }
  38.                    
  39.         }
  40.     }
  41.     static void UpdatePage(PageData page, string key, string val)
  42.     {
  43.         if (page.Property[key] != null)
  44.             page.Property[key].ParseToSelf(val);
  45.     }

Then a new page Event will have the default properties set like this.

image

image

Then the only problem that is left is to change the edit mode accordingly to one or more properties set on the page.

I have blogged before about Change the edit page for the editors. This one of many the blog post from labs that is not searchable using world since they purge a lot of post Sad smile.

That blog post describe a technic that can be used to change the editor mode. With little effort that code can be modified to take in account an other page property

Code Snippet
  1. string fil = HttpContext.Current.Server.MapPath("/EditLayout/" + this.Name + ".html");
  2. if (this.Parent["ContentType"] != null && !this.Parent["ContentType"].IsNull)
  3. {
  4.     if (File.Exists(HttpContext.Current.Server.MapPath("/EditLayout/" + this.Name + "_" + this.Parent["ContentType"].ToString() + ".html")))
  5.     {
  6.         fil = HttpContext.Current.Server.MapPath("/EditLayout/" + this.Name + "_" + this.Parent["ContentType"].ToString() + ".html");
  7.     }
  8. }

So if a page is tagged with Event I can display the edit mode like this:

image

and if its not I can show another edit mode like this

image

even thou it’s the same page type.

See here for full code sample

Oct 20, 2011

Comments

Oct 21, 2011 08:28 AM

Sorry, but what is "IsSelectebleAsFag"? ;)

Joel Abrahamsson
Joel Abrahamsson Oct 21, 2011 09:01 AM

Hey Anders!

Just want to add that with the very latest release of PTB (1.9.3) you can actually allow editors to change things in admin mode. It does this by only overwriting things that has been explicitly set in code.

Anders Hattestad
Anders Hattestad Oct 21, 2011 09:33 AM

>Joel
I didn't know. Thank you for the tip.

>Toni
Thats just a page property on my page types.

Please login to comment.
Latest blogs
Performance optimization – the hardcore series – part 2

Earlier we started a new series about performance optimization, here Performance optimization – the hardcore series – part 1 – Quan Mai’s blog...

Quan Mai | Oct 4, 2023 | Syndicated blog

Our first steps into local AI

After a consumer of tools like ChatGPT and CoPilot, we as developers like to dive deeper into it. How does it work? Where to start? Can I create my...

Chuhukon | Oct 4, 2023 | Syndicated blog

Update on .NET 8 support

With .NET 8 now in release candidate stage I want to share an update about our current thinking about .NET 8 support in Optimizely CMS and Customiz...

Magnus Rahl | Oct 3, 2023

Adding Block Specific JavaScript and CSS to the body and head of the page

A common requirement for CMS implementations includes the ability to embed third party content into a website as if it formed part of the website...

Mark Stott | Oct 3, 2023

Performance optimization – the hardcore series – part 1

Hi again every body. New day – new thing to write about. today we will talk about memory allocation, and effect it has on your website performance....

Quan Mai | Oct 3, 2023 | Syndicated blog

Next level content delivery with Optimizely Graph

Optimizely introduced a new product called Optimizely Graph earlier this year. We were one of the first partners to adopt this new service in a...

Ynze | Oct 2, 2023 | Syndicated blog