Introduction

When working with page properties there are some things you need to know in order to get good performance. This document describes what happens when you work with properties and also covers some best practice when working with page properties.

What Happens When You Access a Property?

Accessing a property for a page in read-only mode.

When you have loaded a page from the EPiServer.DataFactory it is delivered in read-only mode. The normal way to access a property that resides on the EPiServer.DataFactory.CurrentPage property through code is like this:

CopyC#
Object propertyValue = CurrentPage["PropertyName"];

The first thing that will happen is that the accessor will see if the property with the name "propertyname" is a native page property. If it is the property is returned. If the property is not a native page property a delegate will be called to see if the property can be found elsewhere. The default delegate will first of all look for the property from the "fetch data from" function if that has been activated on the current page. Last of all the delegate will check the dynamic properties for the page. It is possible to write your own delegate and change this behavior.

Accessing a property for a page that is in write mode.

If the page you are working with is in write enabled mode the Property accessor will only return properties that are native to the page. This means that you will never get dynamic properties or fetch data from properties when the page is in write mode.

Best Practice Examples When Working With Properties

If you are accessing a property and you want to use the property several times in your code we recommend you to save a reference to the property as we need to fetch it from the internal collection for each call otherwise. It may also result in several unnecessary calls to the delegate if the property is not native for the page. For instance, use:

CopyC#
PropertyData property = CurrentPage.Property["PropertyName"];
if (property != null && !property.IsNull)
{
    DoSomething();
}

instead of:

CopyC#
if (CurrentPage.Property["PropertyName"] != null && !CurrentPage.Property["PropertyName"].IsNull)
{
    DoSomething()
}

Null values

EPiServer properties with an empty value are never stored in the database. If you access it from code, it will always be null - not an empty string, 0 or false as you maybe expected. Why null? It is by design and is very convenient if you want to check if something is not set by an editor or does not exist on this page. You just have to compare with null regardless of data type.

Examples - DOs and DON'Ts

The following will throw NullReferenceException if value is empty or missing:

CopyC#
StringBuilder sb = new StringBuilder();
sb.Append(CurrentPage["PropertyName"].ToString());

StringBuilder.Append accepts null objects so this is better:

CopyC#
sb.Append(CurrentPage["PropertyName"]);

The following will throw NullReferenceException if value is empty or missing:

CopyC#
<%= CurrentPage.Property["PropertyName"].Value.ToString()%>

Markup will accept any type and convert to string so cast is not needed:

CopyC#
<%= CurrentPage["PropertyName"] %>

An example fallback for src-attributes

CopyC#
<img src='<%= CurrentPage["ImageUrl"] ?? "/Missing.png" %>' />

Other examples with fallback

If a string must be returned use the ?? operator:

CopyC#
string x = CurrentPage["StringProperty"] as string ?? string.Empty;

And for Value Type it is written like this:

CopyC#
DateTime x = (DateTime)(CurrentPage[”DateProperty”] ?? DateTime.Now);
int i = (int)(CurrentPage[”IntegerProperty”] ?? 0);

Another fallback in the markup using the ?? Operator:

CopyC#
<%= CurrentPage[“Heading”] ?? CurrentPage.PageName %>

Accessing property values

When accessing a property's value there are some different ways to do this depending on what you know about the actual property. If you have no knowledge about the property or if you want to access several properties, for instance in a loop, you can access the value directly through its object representation.

CopyC#
Object propertyValue = CurrentPage["PropertyName"];
If you know the type of your value you can cast it directly
CopyC#
string propertyValue = (string)CurrentPage["PropertyName"];
If you are not sure of the actual type and want to avoid an exception being thrown you might want to assign the property value with the "as" key word:
CopyC#
String propertyValue = CurrentPage["PropertyName"] as string;
if (!String.IsNullOrEmpty(propertyValue))
{
    DoSomething();
}

Updating Values For a Page

If you want to update properties for an existing page you need to make sure that you have a writable version of the page. This can be done in the following way:

CopyC#
PageData writablePage = CurrentPage.CreateWritableClone();
To set new values you just need to assign them directly to the writablePage object. This can be done either by working against the properties for the most common page properties or by accessing the values directly:
CopyC#
writablePage.PageName = "somevalue";
is the same as
CopyC#
writablePage["Pagename"] = "somevalue";
When we are done with the page we simply save it by using DataFactory.Instance:
CopyC#
DataFactory.Instance.Save(writablePage, EPiServer.DataAccess.SaveAction.Publish);

HTML encoding and EPiServer page properties

HTML encoding

HTML has special handling for characters such as <> and symbols ?, &,/, etc. Spaces for example may be truncated or corrupted by some browsers, problems can arise when displaying these types of characters in various browsers. In order for your Web site to be XHTML valid use the HtmlEncode method - the HttpUtility.HtmlEncode Method - is part of the .NET framework. The HtmlEncode method encodes a string that is to be displayed in a Web browser.

When rendering EPiServer page properties it is often recommended that this function is used - particularly when rendering inline. Calling the HttpUtility.HtmlEncode method on strings that you inject with inline expressions is recommended.

Example

If you wish to display the EPiServer pagename property (for example) it is often a good idea to use the HttpUtility.HtmlEncode method. To safe guard the output when rendering inline use the HttpUtility.HtmlEncode method, see below for an example:

CopyC#
<%= HttpUtility.HtmlEncode(CurrentPage.PageName) %>

Note: It is not possible to save dynamic properties or properties that reside on other pages when you are working against DataFactory.Save.