EPiPattern: How to render valid xhtml (part 1/2)

How do you inject dynamic content into your web page? Following is a list of the most common methods I find when doing quality and code reviews with some comments and dangerous pitfalls.

#1: Inline Expressions with Code Render Blocks

Using inline expressions is a shortcut for calling the Write method.

Example – DONT:

<h2><%= CurrentPage.PageName %></h2>
<img src="<%= CurrentPage["ImageUrl"] %>" alt="<%= CurrentPage["MainIntro"] %>" />
<div class="mainarea">

     <%= CurrentPage["MainBody"] %>
</div>

Since xhtml is just text, writing some more in-between existing static blocks is fast and simple. Probably the easiest way to inject dynamic content but it is also dangerous!

Example – DO always use HtmlEncode:

<h2><%= HttpUtility.HtmlEncode(CurrentPage.PageName) %></h2>

What happens if our PageName property contains a “<” or “&” character in the example above? Your page will not validate and you risk that it breaks down. It can also be exposed to script injection if the content is user generated.

To be on the safe side you should always call HttpUtility.HtmlEncode on all strings that you inject with inline expressions.

Example – DO always use a fallback for src-attributes

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

If your ImageUrl property is empty you would get a img-tag with an empty src-attribute. This can lead to the page being rendered twice. FireFox interpret a null src-attribute a relative url and evaluate it using the page url as base returning the same url.

#2: With EPiServer:Property web control

Using the EPiServer Property Web Controls instead of inline expressions has several benefits. It could be used for rendering the PageName and MainBody in the example above.

Example – DO use EPiServer:Property web control

<h2><EPiServer:Property PropertyName="PageName" runat="server" /></h2>
<EPiServer:Property CssClass="mainarea" PropertyName="MainBody" runat="server" />

1) When rendering EPiServer’s ToWebString() is used. This does almost the same job as always calling HtmlEncode yourself.

public virtual void CreateDefaultControls()
{
    Label target = new Label();
    target.Text = PropertyData.ToWebString();
    CopyWebAttributes(target);
    Controls.Add(target);
}

2) It enables the Simple Edit feature for the editors without any extra work. (If you do not know what “Simple Edit” is, you should read the Editors Manual for EPiServer before doing any more development.)

3) Different types have get different rendering automatically. Commonly used for PageReferences and Url’s that are rendered as a Hyperlink.

Example – DO use EPiServer:Property for rendering links if possible

<EPiServer:PageList PageLinkProperty="NewsArchivePage" MaxCount="5" runat="server" >
  <HeaderTemplate>
    <h3><EPiServer:Property PropertyName="PageLink" runat="server" /></h3>
    <ul>
  </HeaderTemplate>
  <ItemTemplate>
    <li><EPiServer:Property PropertyName="PageLink" runat="server" /></li>
  </ItemTemplate>
  <FooterTemplate>
    </ul>
  </FooterTemplate>
</EPiServer:PageList>

4) Use PageLinkProperty to follow a Page-property to another page and render a value. Takes care of all hassle and calls GetPage() and check for nulls for you.

Example – DO use EPiServer:Property to render values from another page

<h3><EPiServer:Property PageLinkProperty="FeatureArticlePage" PropertyName="PageLink" runat="server" /></h3>
<div><EPiServer:Property PageLinkProperty="FeatureArticlePage" PropertyName="MainIntro" runat="server" /></div>
Bookmark and Share

Tags: , , , , ,

  1. Marcus Lindblom’s avatar

    Great post, and don’t forget that semantics is equally important when producing valid x/html.

    Reply

  2. Fredrik Haglund’s avatar

    Thanks, Eric!
    Will continue with web controls and code behind and more common pitfalls…
    /Fredrik

    Reply

  3. Andreas Ek’s avatar

    A lot of page errors in a EPiServer site relates to missing or corrupt data in EPiServer properties. I think that EPiServer should have a lot to win by providing a common static library for property handling.

    Reply

    1. Fredrik Haglund’s avatar

      Yes, I agree that a library would be usefull… more of a ASP.NET MVC approach where you have better control of rendered html!

      Look at Relate+ templates where they use extension methods a lot. It could also be a good complement…

      Reply

  4. Magnus Paulsson’s avatar

    It seems that EPiServer:Property does not emit valid xhtml in all cases. For example, if the property rendered is a PageReference, the link text will not be HtmlEncoded. The same thing goes for links inside XhtmlString properties. The first one is probably easy to solve by using something other than a Property control, but the second one is much more tricky since it will contain xhtml so it can’t just be HtmlEncoded. Any other suggestions on how to handle these problems?

    Reply

    1. Fredrik Haglund’s avatar

      Hi Magnus!

      1) PropertyPageReferenceControl is rendering PageReferences using a HyperLink component and the Text property is assigned page.Property["PageName"].ToWebString() which should encode it. If this does not work as expected you might found a defect – so please send more details!

      2) Yes, xhtmlString should not be encoded since it should be valid. The messy html from the text editor is washed before it is saved. I guess there is flaws in the process. Could you share a few example what comes through?

      Reply

  5. Hans’s avatar

    You mention .ToWebString() and I prefer that over using HttpUtility.HtmlEncode. HttpUtility.HtmlEncode encodes to much I think, å, ä and ö for example.
    /Hans

    Reply

    1. Fredrik Haglund’s avatar

      Hmm… ToWebString will allow some well known HTML-tags to stay unchanged. You specify what tags this in siteSettings in your web.config.

      I prefer to use HtmlEncode myself. It feels a little bit safer…

      Reply

  6. Diego’s avatar

    Hi Fredrik,

    Great article as usual. I have a question about HtmlEncode a custom property that inherits from XHTMLLongstring. Is it possible to render DOPE on the property wile displaying the property like this:

    or do I need to make my property inherit from the Simplepage class in some way. An example would be much apreciated.
    thx

    Reply