Using Web User Controls for EPiServer custom page property types

All content in EPiServer pages are stored in page properties which can be of different types such as short string, XHTML string, date, etc. It is also possible tocreate custom property data types, which can be very useful in many circumstances such as when integrating with other systems or creating content which is not easily representable only in page types.

A custom page property type is created by inheriting from an existing property type such as EPiServer.Core.PropertyLongString and overriding the CreateChildControls() function, and a skeleton looks like this:

[EPiServer.PlugIn.PageDefinitionTypePlugIn(DisplayName = "Stränglista")]
public class StringList : EPiServer.Core.PropertyLongString
{
    public override void CreateChildControls(string RenderType, System.Web.UI.Control Container)
    {
        switch (RenderType.ToLower()) 
        {
            case "edit":  // Edit mode, display controls to let the user edit the value
                ...
            case "dope":  // Direct on-page editing
                ...
            case "default":  // Show the content in view mode
                ...
            default:
                base.CreateChildControls(RenderType, Container);
                break;
        }
    }
}

So far, all of the above is documented in the book Developing Solutions with EPiServer together with a simple example of creating a BgColour type for choosing a color. However, for more complex properties, the techniques described there (creating control instances and calling Container.Controls.Add()) quickly becomes complicated. It’s then better to create a Web User Control and load that in the CreateChildControls() function. Here’s how to do that:

StringListEdit edit = (StringListEdit)Container.Page.LoadControl(
    "~/templates/PropertyDataTypes/StringListEdit.ascx");
edit.ID = Name;

// Initialize the user control with watever value it takes. In this case we happen
// to use a list of strings stored in this.Strings
edit.Strings = this.Strings;

CopyWebAttributes(Container, edit);
Container.Controls.Add(edit);

In the user control we don’t have to know anything about loading or saving the property value. Initializing is done explicitly in the code above, but how is saving accomplished?

If we only use the code above, the user control will be correctly initialized but no change will ever be saved. What’s missing is a code snippet something like this, just after the code above:

edit.Controls.Add(CreateParseValidator(edit.ValueText));

The ValueText property is a hidden TextBox property of our user control that always holds the string representation of the edited value (we’re using a string to store the value since we’re inheriting from PropertyLongString). The CreateParseValidator() method creates a custom validator that takes care of the saving for us.

NOTE: The validator must be created inside the user control, not inside the container!

This is actually the only way I have found to update the property value, and it’s not exacly apparent from the API or the documentation that we need to create an extra control in the user control with the complete value representation and connect a validator to it. 😉

The solution outlined here has worked well for me, but if anyone has other solutions for how to best use user controls with custom property types, please feel free to leave a comment!

/Emil

Forcing ASP.NET to generate valid XHTML code

Ever seen error like these when validating your ASP.NET web site using validator.w3.org?

there is no attribute "name".
<form name="aspnetForm" method="post" action="../shop/StartPage.aspx?id=122" i

document type does not allow element "input" here; missing one of "p", "h1",
"h2", "h3", "h4", "h5", "h6", "div", "pre", "address", "fieldset", "ins", "del" start-tag.
...dkZGQDrhr9OheQO96crtnJaz+8HiO6ew==" />

This will happen if you have the following doctype, indicating that the page content should be XHTML Strict:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

However, using that doctype is not enough for ASP.NET to generate valid XHTML Strict code. To make it do that, make sure that the following is set in the system.web section of Web.config (the default value is “Legacy”):

<xhtmlConformance mode="Strict"/>

Without that setting, ASP.NET will insert invalid attributes on the form tag and place the hidden input fields in invalid contexts. AFAIK, there’s no dialog where you can change this setting, you have to know it’s there. And now you do! 🙂

UPDATE:
The above solution only works in ASP.NET 2.0. Under 1.0 there is no known solution (at least not to me).

Why do I get “Registry access not allowed” error message?

Struggling with this error that occurs the first time the site is viewed after an IIS restart?

epi_reg_error.gif

This problem can be caused by the EPiServer Scheduler service not being installed.

Try this:

C:\Inetpub\wwwroot\bin>C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\InstallUtil.exe EPiServer.SchedulerSvc.exe

(From the EPiServer FAQ: http://www.episerver.com/en/EPiServer_Knowledge_Center/Support/FAQ_EPiServer_4/905/923/)