There has been quite a lot of talk about strongly typed property access lately. There has also been a few very interesting blog posts about how to achieve both strongly typed property access and page type inheritance. Fredrik Tjärnberg has developed a Visual Studio plugin first described here and later here. Daniel Rodin and Mikael Nordberg has described another solution here and here.
And yes, here’s yet another solution. It is actually very similar to the one that Daniel Rodin and Mikael Nordberg described. As I found their solution very interesting but couldn’t find any downloadable source code attached to their blog entries, and as I also so an opportunity to utilize the new features in R2 Sp2 RC that Fredrik Tjärnberg described in his second blog entry about his Page Type Tool, I decided to write my own.
You are very much welcome to download the source code, as well as the resulting assembly, from here. Please do keep in mind that at this stage it’s just an experiment. Quite a lot of work remains to be done and the whole idea needs to be tested more before I can even be sure it’s viable.
How to use it – A hello world
The hello world of using this tool is referencing the assembly (PageTypeBuilder.dll), creating a new class that inherits from PageData with a PageTypeDefinition attribute and making a request to the site. This will create a new page type with the name of the newly created class.
Allow me to illustrate. We begin by referencing the PageTypeBuilder assembly, or the project, in a EPiServer web project. We then create a new class like this:
using EPiServer.Core;
using PageTypeBuilder;
namespace SP2RC.PageTypes
{
[PageTypeDefinition]
public class MyPageType : PageData
{
}
}
Finally we compile the project and head on over to EPiServers admin mode where we find that a new page type has been created.
The settings for sort index and availability in edit mode is set to the default values. The file name is also set to a default value. That one is however not set by the CMS but by the page builder tool and we can easily change it by modifying the PageTypeDefinition attribute. The attribute also allows us to specify a name for the page type other than the class name. It might look something like this:
[PageTypeDefinition(Filename = "/MyPageTemplate.aspx",
Name="MyVeryOwnPageType")]
public class MyPageType : PageData
{
}
Specifying the file name will only result in the file name property of the page type being updated. Specifying a different name for the page type will however lead to a new page type being created, and the old one won’t get removed. I have some ideas on how to handle this better in the future but would very much like to hear ideas and opinions about this subject.
Specifying properties
We can add a property to our page type by creating a new property in the class and adding a PropertyDefinition attribute to it.
[PageTypeDefinition]
public class MyPageType : PageData
{
[PropertyDefinition]
public string MainBody { get; set; }
}
This will result in a new XHtml property being added to the page type.

Let’s also add a headline. We want that to be a string but on the page type we don’t want it to be a XHtml string (what the tool defaults to for strings) but a short string. We accomplish that by specifying that it should be a PropertyString by setting the PropertyDefinition’s Type property.
[PropertyDefinition(Type = typeof(PropertyString))]
public string Headline { get; set; }
The result will look like this:

The PropertyDefinition attribute also allows us to specify which tab the property should be placed under (it will default to the first one), the edit caption (it will default to the property name) and the help text.
How to handle sort order, default values etc is another thing I’d love some input on.
Implementing the property data access
The properties that we just created in our page type class results in properties being added to the page type, but they won’t actually retrieve or store values. We could implement the properties like this:
[PropertyDefinition(Type = typeof(PropertyString))]
public string Headline
{
get
{
return GetValue("Headline") as string;
}
set
{
this["Headline"] =value;
}
}
The above code would work fine but it looks a bit nasty. Luckily there’s a class in the PageTypeBuilder assembly called PropertyValueUtility which adds two extension methods to the PageData class and it’s descendants, GetPropertyValue and SetPropertyValue. These two will look quite familiar to anyone who has read Daniel Rodins blog entry. They have really come up with a smart solution. Hats off!
By using the two extension methods we can implement the properties like this:
[PropertyDefinition(Type = typeof(PropertyString))]
public string Headline
{
get
{
return this.GetPropertyValue<MyPageType, string>(
page => page.Headline);
}
set
{
this.SetPropertyValue<MyPageType, string>(
page => page.Headline, value);
}
}
[PropertyDefinition]
public string MainBody
{
get
{
return this.GetPropertyValue<MyPageType, string>(
page => page.MainBody);
}
set
{
this.SetPropertyValue<MyPageType, string>(
page => page.MainBody, value);
}
}
While we might loose a little readability the implementation is now strongly typed.
Using the page type
By inheriting from the new TypedPageBase class in R2 SP2 using the page type class is a joy. We inherit from TypedPageBase<MyPageType> and can then access our properties in a strongly typed way by getting the current page object, as a MyPageType, from the (new) CurrentTypedPage property.
public partial class MyPageTemplate : TypedPageBase<MyPageType>
{
protected void Page_Load(object sender, EventArgs e)
{
LiteralHeadline.Text = CurrentTypedPage.Headline;
LiteralMainBody.Text = CurrentTypedPage.MainBody;
}
}
We could also retrieve an instance of our page type class by using the new generic GetPage method in Datafactory:
DataFactory.Instance.GetPage<MyPageType>(aPageReference);
Source code and request for feedback
The source code for the PageTypeBuilder can be downloaded here. Remenber that you will need to EPiServer CMS R2 SP2 RC or higher to fully be able to use it.
Any feedback and ideas for improvement are very, very welcome. Please keep in mind however that this is just a little weekend project so far and should be considered an experiment :)