<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">Blog posts by Joel Abrahamsson</title><link href="http://world.optimizely.com" /><updated>2013-09-16T14:08:01.0000000Z</updated><id>https://world.optimizely.com/blogs/Joel-Abrahamsson/</id> <generator uri="http://world.optimizely.com" version="2.0">Optimizely World</generator> <entry><title>Update on my EPiServer book</title><link href="http://joelabrahamsson.com/update-on-my-episerver-book/" /><id>Two new chapters. One of them is the first!
&lt;p&gt;It has been almost a month since I &lt;a href=&quot;/link/b6bac5d89c584dda8ff527bff37b9951.aspx?id=557&amp;amp;epslanguage=en&quot;&gt;announced&lt;/a&gt; that I&#39;m writing &lt;a href=&quot;http://leanpub.com/episerver-7-cms-development/&quot;&gt;a book about EPiServer 7 development&lt;/a&gt;. Since then I&#39;ve received a lot of helpful feedback and comments. Not unexpectedly the EPiServer development community has again proven its awesomeness to me!&lt;/p&gt;
&lt;p&gt;While I&#39;ve made two minor updates to the book since its initial release I&#39;m today happy to announce a more major update. In the recently published version (#4) you&#39;ll find two brand new chapters. Somewhat ironically one of those is actually the first chapter, which up until now hasn&#39;t been done. And, actually it probably still isn&#39;t entirely done.&lt;/p&gt;
&lt;p&gt;You see, the first chapter is something that I&#39;ve been thinking about writing for years. It&#39;s not about EPiServer. Instead it&#39;s an attempt to take a step back and see how a CMS, such as EPiServer, could come to be. In the chapter we follow a site from its infancy with a single static HTML page and see how it evolves into a fairly respectable CMS based sites.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;thumbnail-centered&quot; src=&quot;/PageFiles/678/chapter1.png&quot; alt=&quot;&quot; width=&quot;500&quot; height=&quot;364&quot; /&gt;&lt;/p&gt;
&lt;p&gt;My hope is that this chapter will provide a gentle, understandable introduction for those new to CMS development in general and to EPIServer development in particular. I also hope that it may provide for some interesting reflection for senior EPiServer developers. However, with such ambitions it&#39;s hard to get it right the first time and I hope to improve it based on your feedback.&lt;/p&gt;
&lt;p&gt;Anyway, if you&#39;ve already bought the book, please &lt;a href=&quot;http://leanpub.com/episerver-7-cms-development/&quot;&gt;grab the latest version&lt;/a&gt; and give me feedback. If you haven&#39;t yet bought the book, now may be a good time ;-)&lt;/p&gt;
</id><updated>2013-09-16T14:08:01.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Workaround: On Page Editing broken after rendering a block</title><link href="http://joelabrahamsson.com/workaround-on-page-editing-broken-after-rendering-a-block/" /><id>&lt;p&gt;In patch 3 for EPiServer 7 CMS there&#39;s a nasty little bug that manifests it self on sites built using ASP.NET MVC. After rendering a block that doesn&#39;t have a controller but instead is rendered using only a partial view (which, as we know, is good for performance) other properties that are rendered using the &lt;span class=&quot;code-concept&quot;&gt;PropertyFor&lt;/span&gt; method may not be editable in OPE mode.&lt;/p&gt;
&lt;p&gt;Luckily there&#39;s an easy workaround for that, which we can use until the issue is resolved by EPiServer; create custom display templates for the types &lt;span class=&quot;code-concept&quot;&gt;ContentData&lt;/span&gt; and &lt;span class=&quot;code-concept&quot;&gt;ContentArea&lt;/span&gt;. Implement each display template like the original ones shipped by EPiServer, using &lt;span class=&quot;code-concept&quot;&gt;RenderContentData&lt;/span&gt; and &lt;span class=&quot;code-concept&quot;&gt;RenderContentArea&lt;/span&gt;, but wrap the method calls in code that stores the value of &lt;span class=&quot;code-concept&quot;&gt;ViewContext.RouteData.Values[&quot;currentContent&quot;]&lt;/span&gt; in a variable prior to invoking the method and restores it afterwards.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;/Views/Shared/DisplayTemplates/ContentData.cshtml:&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;@using EPiServer.Web.Mvc.Html&lt;br /&gt;@model EPiServer.Core.IContentData&lt;br /&gt;@{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var original = ViewContext.RouteData.Values[&quot;currentContent&quot;];&lt;br /&gt;}&lt;br /&gt;@{Html.RenderContentData(Model, false);}&lt;br /&gt;@{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ViewContext.RouteData.Values[&quot;currentContent&quot;] = original;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;/Views/Shared/DisplayTemplates/ContentArea.cshtml:&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;@using EPiServer.Web.Mvc.Html&lt;br /&gt;@model EPiServer.Core.ContentArea&lt;br /&gt;@{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var original = ViewContext.RouteData.Values[&quot;currentContent&quot;];&lt;br /&gt;}&lt;br /&gt;@{Html.RenderContentArea(Model);}&lt;br /&gt;@{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ViewContext.RouteData.Values[&quot;currentContent&quot;] = original;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;
</id><updated>2013-08-25T19:55:48.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>A book about EPiServer development</title><link href="http://joelabrahamsson.com/a-book-about-episerver-development/" /><id>After years of blogging about EPiServer CMS I decided it was time to get real.
&lt;p&gt;&lt;img class=&quot;thumbnail-centered&quot; src=&quot;/PageFiles/673/book_devices.png&quot; alt=&quot;The cover of the new EPiServer book displayed in an iPhone and a Kindle.&quot; width=&quot;500&quot; height=&quot;293&quot; /&gt;&lt;/p&gt;
&lt;p&gt;I&#39;m happy to announce a little project that I&#39;ve been working on lately; &lt;a href=&quot;http://leanpub.com/episerver-7-cms-development/&quot;&gt;a book about how to develop EPiServer CMS sites&lt;/a&gt;. I&#39;m publishing it on Leanpub and embracing their motto of publishing early and publishing often. So, while the book is far from done I have published a first version of it and early buyers will be getting it a discounted price.&lt;/p&gt;
&lt;h2&gt;Content - current and planned&lt;/h2&gt;
&lt;p&gt;This is a project that I&#39;ve been thinking about doing for several years but haven&#39;t quite gotten around to, until now. Despite having contemplated writing the book for years the exact table of contents isn&#39;t entirely decided yet, and I hope to get reader feedback to help guide it. However, the plan is roughly to cover:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;General CMS concepts - I actually started writing this chapter about a year ago, but I&#39;m not yet finished with it :)&lt;/li&gt;
&lt;li&gt;Installation - &quot;done&quot;&lt;/li&gt;
&lt;li&gt;Using the CMS - &quot;done&quot;&lt;/li&gt;
&lt;li&gt;Core classes and concepts - &quot;done&quot;&lt;/li&gt;
&lt;li&gt;Tools - &quot;done&quot;&lt;/li&gt;
&lt;li&gt;A hands-on tutorial for building a first, simple site - in progress and a first version is featured in the current version of the book&lt;/li&gt;
&lt;li&gt;Deep dives into content types, properties and templates&lt;/li&gt;
&lt;li&gt;Caching and performance&lt;/li&gt;
&lt;li&gt;How to build large scale sites, such as media sites&lt;/li&gt;
&lt;li&gt;Different ways to build integrations&lt;/li&gt;
&lt;li&gt;Extending the CMS in various ways&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Whether I&#39;ll cover all of the above topics and/or other topics will probably depend on whether there is an interest for the book and on reader feedback.&lt;/p&gt;
&lt;p&gt;The book is, and will be, written as a mix of theory and practical tutorials. The examples will be using MVC, primarily as I felt MVC made it easier to focus on EPiServer&#39;s API. However, there will be asides/notes describing how to achieve the same thing with Web Forms.&lt;/p&gt;
&lt;h2&gt;Pricing&lt;/h2&gt;
&lt;p&gt;Prior to publishing the book interested readers could sign up to be notified when it was published and also suggest a price. The average suggested price was $38 which is actually pretty closed to what I initially thought I&#39;d charge for the book. However, I feel that early readers should be rewarded for taking the &quot;risk&quot; of buying an unfinished product and, even more, be rewarded for providing feedback. Therefor I&#39;ve set the minimum price (buyers can choose their own actual price depending on how much they think it&#39;s worth) at $20 and will probably increase that in the future as the book progresses.&lt;/p&gt;
&lt;h2&gt;An e-book&lt;/h2&gt;
&lt;p&gt;Books on Leanpub are only available as e-books. If there&#39;s a lot of interest in a print version I may look in to that in the future, but for now I&#39;m embracing the fact that it&#39;s possible to continously publish an e-book.&lt;/p&gt;
&lt;p&gt;Leanpub books are published and made available to readers in&amp;nbsp;PDF, EPUB (for iPad) and MOBI (for Kindle).&lt;/p&gt;
</id><updated>2013-08-20T00:34:12.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>EPiServer editing delight challenge - MVC solution</title><link href="http://joelabrahamsson.com/episerver-editing-delight-challenge-mvc-solution/" /><id>Solving a small but tricky problem related to customised rendering of a property in EPiServer 7 with ASP.NET MVC.
&lt;p&gt;Starting with the simple stuff we render each of the properties using the PropertyFor method.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&amp;lt;h1&amp;gt;@Html.PropertyFor(x =&amp;gt; x.Heading)&amp;lt;/h1&amp;gt;
&amp;lt;p&amp;gt;@Html.PropertyFor(x =&amp;gt; x.Intro)&amp;lt;/p&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then we make both properties editable using a text area by adding a UI hint to each of them.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;//using EPiServer.Web;

[UIHint(UIHint.Textarea)]
public virtual string Heading { get; set; }

[UIHint(UIHint.Textarea)]
public virtual string Intro { get; set; }&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Customise the rendering&lt;/h2&gt;
&lt;p&gt;Moving on to the next requirement we create an extension method for strings that replaces line breaks with br tags. We make it return an IHtmlString so that the br tags won&#39;t be encoded.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;public static IHtmlString ToLineBreakString(this string original)
{
    var parsed = string.Empty;
    if (!string.IsNullOrEmpty(original))
    {
        parsed = HttpUtility.HtmlEncode(original);
        parsed = parsed.Replace(&quot;\n&quot;, &quot;&amp;lt;br /&amp;gt;&quot;);
    }

    return new MvcHtmlString(parsed);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, how do we use this method? We could modify the view to render the property&#39;s value directly and add edit attributes to the h1 tag, like this:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&amp;lt;h1 @Html.EditAttributes(x =&amp;gt; x.Heading)&amp;gt;
    @Model.Heading.ToLineBreakString()
&amp;lt;/h1&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At first it may seem like we&#39;ve solved the challenge. Both properties are editable in on-page-edit mode using text areas and a line break in the Heading property is replaced with a br tag. However, let&#39;s look at what happens when we make a change to the Heading property:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;thumbnail-centered&quot; src=&quot;/Global/broken_preview.png&quot; alt=&quot;&quot; width=&quot;769&quot; height=&quot;518&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The line break in the Heading property isn&#39;t replaced with a br when the new value is inserted into the page during editing. We&#39;re not meeting the requirement that both properties should offer a realistic preview at all times.&lt;/p&gt;
&lt;p&gt;This happens because the CMS has no way of knowing that we&#39;re customizing the rendering of the property in our view. Instead it updates the DOM node that represents the property with what would be rendered by the PropertyFor method.&lt;/p&gt;
&lt;h2&gt;Fixing the preview&lt;/h2&gt;
&lt;p&gt;If you&#39;ve read my article about &lt;a href=&quot;/link/97755f93eb134f98b538ec69de3fe450.aspx?id=534&amp;amp;epslanguage=en&quot;&gt;how PropertyFor works&lt;/a&gt; you know that means it will replace it with what the DisplayFor method would return, meaning the default display template for strings.&lt;/p&gt;
&lt;p&gt;To fix this we could create a display template named string or Textarea (matching the UI hint) and render the value with the help of our extension method there. Given that we update the view to again render the Heading property using either PropertyFor or DisplayFor we would then have fixed the preview issue.&lt;/p&gt;
&lt;p&gt;That would however mean that a line break in the Intro property would also be replaced with a br tag, violating the requirement that it should not be.&lt;/p&gt;
&lt;p&gt;What to do then? Seems like the requirements are conflicting. Perhaps all is lost and it&#39;s time to give up?&lt;/p&gt;
&lt;p&gt;Not quite. We just need to sprinkle our code with some magic dust made exactly according to the recipe.&lt;/p&gt;
&lt;p&gt;First we create a display template named LineBreaked that renders a string using our extension method.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;thumbnail-centered&quot; src=&quot;/Global/display_template.png&quot; alt=&quot;&quot; width=&quot;209&quot; height=&quot;71&quot; /&gt;&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;@model string
@Model.ToLineBreakString()&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next we add another UI hint to the Heading property, this time with the name of the display template.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;strong&gt;[UIHint(&quot;LineBreaked&quot;)]&lt;/strong&gt;
[UIHint(UIHint.Textarea)]
public virtual string Heading { get; set; }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That alone doesn&#39;t yield any effect as we now have two UI hints and, at least for me, the Textarea one will be used.&lt;/p&gt;
&lt;p&gt;The final step that makes it all work is to modify the second UI hint so that it won&#39;t be used by PropertyFor or DisplayFor, only by the CMS when locating the approriate editor for the property. To do so we use an overload of the UIHintAttribute class&#39; constructor and pass it a string representing a &quot;presentation layer&quot;. Specifically the string exposed by the Edit constant in EPiServer&#39;s PresentationLayer class.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;[UIHint(&quot;LineBreaked&quot;)]
[UIHint(UIHint.Textarea, &lt;strong&gt;PresentationLayer.Edit&lt;/strong&gt;)]
public virtual string Heading { get; set; }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And with that the challenge is solved.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;thumbnail-centered&quot; src=&quot;/PageFiles/652/fixed_preview.png&quot; alt=&quot;&quot; width=&quot;766&quot; height=&quot;518&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Alternative solution&lt;/h2&gt;
&lt;p&gt;The above solution works and will effect all of the places where the Heading property is rendered. There is however also an alternative, simpler, solution that will only effect the rendering in a specific place.&lt;/p&gt;
&lt;p&gt;Instead of adding the additional UI hint and specifying presentation layer for the Textarea UI hint we can render the property using PropertyFor and specify a tag matching the display templates name.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&amp;lt;h1&amp;gt;@Html.PropertyFor(x =&amp;gt; x.Heading, new { tag = &quot;LineBreaked&quot;})&amp;lt;/h1&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
</id><updated>2013-05-21T06:00:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>EPiServer editing delight challenge - Web Forms solution</title><link href="http://joelabrahamsson.com/episerver-editing-delight-challenge-web-forms-solution/" /><id>Solving a small but tricky problem related to customised rendering of a property in EPiServer 7 with ASP.NET Web Forms.
&lt;p&gt;Starting with the simple stuff we render each of the properties using the Property control.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&amp;lt;EPiServer:Property PropertyName=&quot;Heading&quot; CustomTagName=&quot;h1&quot; runat=&quot;server&quot; /&amp;gt;
&amp;lt;EPiServer:Property PropertyName=&quot;Intro&quot; CustomTagName=&quot;p&quot; runat=&quot;server&quot; /&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then we make both properties editable using a text area by adding a UI hint to each of them.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;//using EPiServer.Web;

[UIHint(UIHint.Textarea)]
public virtual string Heading { get; set; }

[UIHint(UIHint.Textarea)]
public virtual string Intro { get; set; }&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Customise the rendering&lt;/h2&gt;
&lt;p&gt;Moving on to the next requirement, we need to replace line breaks in the Heading property with br tags before rendering it. To do so we can change the rendering of it from using the Property control to using a h1 tag that we turn into a control by adding runat=&quot;server&quot; and an ID to it.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&amp;lt;h1 ID=&quot;headingControl&quot; runat=&quot;server&quot;&amp;gt;&amp;lt;/h1&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, in code behind, we set its InnerHtml to the modified value and make it editable in on-page-editing mode using the ApplyEditAttributes extension method.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;//using EPiServer.Web;
protected override void OnLoad(EventArgs e)
{
    base.OnLoad(e);

    if (!string.IsNullOrEmpty(CurrentPage.Heading))
    {
        headingControl.InnerHtml = CurrentPage.Heading.Replace(&quot;\n&quot;, &quot;&amp;lt;br /&amp;gt;&quot;);
    }

    headingControl.ApplyEditAttributes&amp;lt;StandardPage&amp;gt;(x =&amp;gt; x.Heading);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At first it may seem like we&#39;ve solved the challenge. Both properties are editable in on-page-edit mode using text areas and a line break in the Heading property is replaced with a br tag. However, let&#39;s look at what happens when we make a change to the Heading property:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;thumbnail-centered&quot; src=&quot;/PageFiles/654/broken_preview.png&quot; alt=&quot;&quot; width=&quot;769&quot; height=&quot;518&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The line break in the Heading property isn&#39;t replaced with a br when the new value is inserted into the page during editing. We&#39;re not meeting the requirement that both properties should offer a realistic preview at all times.&lt;/p&gt;
&lt;p&gt;This happens because the CMS has no way of knowing that we&#39;re customizing the rendering of the property in our view. Instead it updates the DOM node that represents the property with what would be rendered by the Property control.&lt;/p&gt;
&lt;h2&gt;Fixing the preview&lt;/h2&gt;
&lt;p&gt;In order to fix the preview we could go back to rendering the property using the Property control and then modify how either all strings or string properties with a Textarea UI hint are rendered.&lt;/p&gt;
&lt;p&gt;That would however violate the requirement that a line break in the Intro property should not be replaced with a br tag. Therefor we&#39;ll have to find a way to customize only the rendering of the Heading property. Luckily there are a few ways to do that.&lt;/p&gt;
&lt;p&gt;One is to first render it using the Property control and specify a tag using RenderSettings:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&amp;lt;EPiServer:Property PropertyName=&quot;Heading&quot; CustomTagName=&quot;h1&quot; runat=&quot;server&quot;&amp;gt;
    &amp;lt;RenderSettings Tag=&quot;LineBreaked&quot; /&amp;gt;
&amp;lt;/EPiServer:Property&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next we create a user control that inherits from PropertyControlBase&amp;lt;string&amp;gt; and add a TemplateDescriptor attribute to it in which we specify the same tag.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;[TemplateDescriptor(TagString = &quot;LineBreaked&quot;)]
public partial class LineBreaked : PropertyControlBase&amp;lt;string&amp;gt;
{
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Still in code behind for our custom property control we create a property that exposes the original value, which we can retrieve through the CurrentData property, modified the way we like.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;protected string Formated
{
    get
    {
        if (string.IsNullOrEmpty(CurrentData))
        {
            return string.Empty;
        }
        return CurrentData.Replace(&quot;\n&quot;, &quot;&amp;lt;br /&amp;gt;&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, in the markup part of the user control we output the return value of the property.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&amp;lt;%= Formated %&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And with that the challenge is solved.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;thumbnail-centered&quot; src=&quot;/PageFiles/654/fixed_preview.png&quot; alt=&quot;&quot; width=&quot;766&quot; height=&quot;518&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Alternative solution&lt;/h2&gt;
&lt;p&gt;Above we change how the Heading property is rendered by specifying a tag when rendering it with the Property control. This works well but it only modifies how the property is rendered, including preview, in a single place.&lt;/p&gt;
&lt;p&gt;If we instead wanted to change how it&#39;s rendered everywhere where the Property control is used we could use an alternative approach - using UI hints.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;strong&gt;[UIHint(&quot;LineBreaked&quot;)]&lt;/strong&gt;
[UIHint(UIHint.Textarea&lt;strong&gt;, PresentationLayer.Edit&lt;/strong&gt;)]
public virtual string Heading { get; set; }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the above code we&#39;ve added a second UIHint attribute to the Heading property. This UI hint has the same value as the tag that our custom property control supports, meaning that it will be rendered using our custom control.&lt;/p&gt;
&lt;p&gt;However, we also want the property to be edited using a text area meaning we need to keep the existing UI hint, creating a conflict. To fix that we&amp;nbsp;use an overload of the UIHintAttribute class&#39; constructor and pass it a string representing a &quot;presentation layer&quot;. Specifically the string exposed by the Edit constant in EPiServer&#39;s PresentationLayer class.&lt;/p&gt;
</id><updated>2013-05-21T05:00:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>EPiServer editing delight challenge</title><link href="http://joelabrahamsson.com/episerver-editing-delight-challenge/" /><id>Do you consider yourself to be an EPiServer development ninja? Or do you aspire to become one? Then here&#39;s a challenge for you.
&lt;p&gt;In EPiServer 7 On-Page-Editing is the default way of editing a page. An editor clicks on a part of the page that represents a property and can update it using whatever type of editor (textbox, textarea, Tiny MCE etc) is configured for the property. All while almost instantly seeing the updated result on the page.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;For us developers&lt;/strong&gt; the live-preview way of editing pages in EPiServer 7 can present challenges. Especially when the design requires us to somehow modify whatever the editor has entered before rendering it.&lt;/p&gt;
&lt;p&gt;In order to preserve our vocational pride and keep customers happy we need to ensure that the editors get a correct preview of the content.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Putting ourselves&lt;/strong&gt; in the editors shoes, imagine that we edit a page and modify a couple of properties. All while checking how the page looks. Then we publish the page, only to find ourselves looking at something different from what the preview showed us. That wouldn&#39;t be very fun and we&#39;d lose trust in the system.&lt;/p&gt;
&lt;p&gt;On this topic and based on a simple case that I ran into not long ago, here&#39;s a challenge that will test your EPiServer development skills when it comes to rendering properties and your understanding of how EPiServer 7 CMS works.&lt;/p&gt;
&lt;h2&gt;The challenge&lt;/h2&gt;
&lt;p&gt;You have a page type class with two properties:&lt;/p&gt;
&lt;table class=&quot;table table-striped table-bordered&quot; border=&quot;0&quot;&gt;
&lt;thead&gt; 
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Name&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Type&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Element&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/thead&gt; 
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Heading&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;h1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Intro&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;p&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;You should create a template for this page type that displays both properties. It should meet the following conditions:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Both properties should be edited using a text area.&lt;/li&gt;
&lt;li&gt;If the Heading property contains line breaks those should be replaced with br tags when it&#39;s rendered, allowing editors to create headings that span multiple lines.&lt;/li&gt;
&lt;li&gt;If the Intro property happens to contain line breaks those should &lt;strong&gt;not&lt;/strong&gt; be replaced. That is, editors should not be able to force new lines in the Intro property.&lt;/li&gt;
&lt;li&gt;Both properties should be editable by clicking on them in on-page-edit mode.&lt;/li&gt;
&lt;li&gt;Both properties should offer a realistic preview at all times.&lt;/li&gt;
&lt;li&gt;The preview of the page should not rely on a full refresh of the page. That is, methods whos name contain&amp;nbsp;&lt;em&gt;FullRefresh&lt;/em&gt; are not allowed.&lt;/li&gt;
&lt;li&gt;You are not allowed to change the types of the properties and you are not allowed to move them to a block.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here&#39;s an example of how a page that meets these conditions should look in edit mode:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;thumbnail-centered&quot; src=&quot;/PageFiles/650/in_edit_mode.png&quot; alt=&quot;&quot; width=&quot;537&quot; height=&quot;150&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Sounds and looks pretty simple, right? As it turns out, while each requirement on its own is straight forward, combine them and it&#39;s not entirely obvious how to meet them all. Give it a try!&lt;/p&gt;
&lt;h2&gt;Solutions&lt;/h2&gt;
&lt;p&gt;Solutions can be found in separate articles:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/link/9d046eba9be640cd8ac81d227f9f5382.aspx?id=545&amp;amp;epslanguage=en&quot;&gt;Solution for Web Forms&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/link/d9fc0983be834c91bc0c5c7edc454bbc.aspx?id=544&amp;amp;epslanguage=en&quot;&gt;Solution for MVC&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</id><updated>2013-05-20T06:00:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Related content with EPiServer Find</title><link href="http://joelabrahamsson.com/related-content-with-episerver-find/" /><id>Wether it&#39;s done for editorial content, products or recipes, linking to related content can be a good way to enrich a site. For visitors, for business and for SEO. While manually selecting what content to link to often produces the best results automatic functionality for displaying related complement can be a good complement.
&lt;p&gt;EPiServer Find has a number of methods that can be used for finding related or similar content. Combine them and they can offer a powerful way to help visitors find interesting content and improve search engine rankings through internal links.&lt;/p&gt;
&lt;h2&gt;Find similar pages using MoreLike&lt;/h2&gt;
&lt;p&gt;Built into Find&#39;s .NET API is a method named &lt;span class=&quot;code-concept&quot;&gt;MoreLike&lt;/span&gt;. It requires a string as argument and adds a query to a search request that will match indexed objects with similar text.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;SearchClient.Instance.Search&amp;lt;PageData&amp;gt;()
    &lt;strong&gt;.MoreLike(&quot;banana&quot;)&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When using MoreLike the search results are ranked by how similar their texts are to the one we pass as argument to it. The similarity is essentially based on common words and there are &lt;a href=&quot;http://find.episerver.com/Documentation/dotnet-api-more-like-related-documents&quot;&gt;a number of adjustments&lt;/a&gt; that can be made to the algorithm to optimise it to suit the specific nature of the content on a specific site.&lt;/p&gt;
&lt;h2&gt;Add business logic using BoostMatching&lt;/h2&gt;
&lt;p&gt;On its own the result of the MoreLike method is highly dependent on the textual content on the site, producing varying results in terms of quality depending on the nature of the content on the site. It produces results based on similarity between texts but doesn&#39;t guarantee that there is any relation between the content other than shared usages of words in the text.&lt;/p&gt;
&lt;p&gt;Find&#39;s .NET API also features a method named &lt;span class=&quot;code-concept&quot;&gt;BoostMatching&lt;/span&gt; which can be used to apply boost factors using whatever criteria that can be described using a filter. In other words, pretty much anything. Using that we can upgrade a MoreLike query from producing &lt;em&gt;similar&lt;/em&gt; content to &lt;em&gt;related&lt;/em&gt; content.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;SearchClient.Instance.Search()
    .MoreLike(&quot;banana&quot;)
    &lt;strong&gt;.BoostMatching(x =&amp;gt; x.InCategory(42), 3)&lt;/strong&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What conditions we use for boosting is, naturally, dependent on the nature of the site and the type of content for which we want to find related content. If it&#39;s a blog post we may boost blog posts that share the same categories and tags. If it&#39;s a recipe site we may boost recipes that share the same ingredients. If it&#39;s a product we can boost based on categories, price and stock balance.&lt;/p&gt;
&lt;p&gt;In other words, BoostMatching allows us to apply custom business logic tailored for our specific site and needs of the business.&lt;/p&gt;
&lt;h2&gt;An example&lt;/h2&gt;
&lt;p&gt;On this site I have functionality to relate content using a number of mechanisms such as categories, tags and topics. If an article is grouped in a topic other articles in the same topic is listed.&lt;/p&gt;
&lt;p&gt;For articles that doesn&#39;t have such lists I still want to display a list of, as far as it&#39;s possible, related articles.&amp;nbsp;That&#39;s accomplished using the below method.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;//using System.Collections.Generic;
//using EPiServer.Find;
//using EPiServer.Find.Cms;
//using EPiServer.Find.Framework;

public virtual IEnumerable&amp;lt;EditorialPageBase&amp;gt; GetSimilarPages(EditorialPageBase page)
{
  //Create search request for pages of the type(s) that we&#39;re interested in
  //and apply a MoreLike query using the concatenated values of all searchable
  //properties on the current page.
  IQueriedSearch&amp;lt;EditorialPageBase&amp;gt; query = SearchClient.Instance
    .Search&amp;lt;EditorialPageBase&amp;gt;()
    .MoreLike(page.SearchText());

  //Apply major boost to articles in the same category.
  foreach (var category in page.Categories)
  {
    query = query.BoostMatching(x =&amp;gt; x.Categories.Match(category), 4);
  }

  //Apply a smaller but still significant boost to articles sharing tags with
  //the current page.
  foreach (var tagLink in page.TagReferences)
  {
    query = query.BoostMatching(x =&amp;gt; x.TagReferences.Match(tagLink.ToString()), 2);
  }

  return query
    //Utilize/apply editorial settings for how desirable a certain page
    //is in the results.
    .BoostMatching(x =&amp;gt; x.SearchPriority.Match(Priority.VeryLow), 0.1)
    .BoostMatching(x =&amp;gt; x.SearchPriority.Match(Priority.Low), 0.3)
    .BoostMatching(x =&amp;gt; x.SearchPriority.Match(Priority.High), 1.5)
    .BoostMatching(x =&amp;gt; x.SearchPriority.Match(Priority.VeryHigh), 2.5)
    //Exclude the current page (which is naturally the most similar page).
    .Filter(x =&amp;gt; !x.ContentLink.Match(page.ContentLink))
    //Exclude unpublished and filter based on access rights and language.    
    .FilterForVisitor()
    //Execute the query
    .Take(8)
    .GetContentResult(cacheForSeconds: 3600, cacheForEditorsAndAdmins: true);
}&lt;/code&gt;&lt;/pre&gt;
</id><updated>2013-05-06T09:40:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Building large scale EPiServer sites</title><link href="http://joelabrahamsson.com/building-large-scale-episerver-sites/" /><id>It has been proven by numerous sites that EPiServer CMS can handle huge amounts of content. Doing so does bring a few challenges though. Here&#39;s a few few patterns that I&#39;ve identified when it comes to building large scale EPiServer sites with great performance.
&lt;p&gt;Last week I received an e-mail with the subject ”Huge number of pages (&amp;gt;500 000) in EPiServer?” As you can imagine the e-mail contained questions related to whether EPiServer CMS can handle sites with A LOT of content.&lt;/p&gt;
&lt;p&gt;It has been proven on a number of occasions that it indeed can. For instance, several of the biggest newspapers in Sweden, with millions of pages, run EPiServer. There are also government sites with several hundreds of thousands of pages.&lt;/p&gt;
&lt;p&gt;That doesn’t mean that we’re not faced with challenges when building large EPiServer sites though.&lt;/p&gt;
&lt;p&gt;In my experience, what those challenges are differs depending on the type of site, or rather, depending on how the content is structured on the site. While an individual site may be a mix of the two, there are two categories of large scale sites in terms of how they structure their content.&lt;/p&gt;
&lt;h3&gt;Content that fit naturally in a deep hierarchy&lt;/h3&gt;
&lt;p&gt;This is common for government sites and the like. Such sites may publish a lot of content that is organized and exposed to visitors in a hierarchy based on topics, subtopic and so on.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;thumbnail-centered&quot; src=&quot;/PageFiles/643/Deep-hierarchy-london.png&quot; alt=&quot;&quot; width=&quot;630&quot; height=&quot;485&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Alternatively the content may fit naturally in a date-based hierarchy, such as an archive with publications.&lt;/p&gt;
&lt;ol&gt; &lt;/ol&gt;
&lt;h3&gt;Content that isn’t hierarchical or the hierarchy is shallow&lt;/h3&gt;
&lt;p&gt;This is very common on media sites such as newspapers. Those sites typically have a shallow hierarchy made up of sections. There may for instance be a first level section called &quot;Sport&quot; and a subsection to that called &quot;Football&quot;.&lt;/p&gt;
&lt;p&gt;An article about one of the Champions League semifinals 2013 is displayed in the context of Sport/Football but beyond that it has no natural place in a tree like structure. On a site with a lot of content this in turn means that an article in context of its place in the hierarchy may have thousands, or even millions, of siblings.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;thumbnail-centered&quot; src=&quot;/PageFiles/643/Shallow-hierarchy-mail-online.png&quot; alt=&quot;&quot; width=&quot;696&quot; height=&quot;665&quot; /&gt;&lt;/p&gt;
&lt;ol&gt; &lt;/ol&gt;
&lt;h2&gt;Finding content based on non-hierarchical criteria&lt;/h2&gt;
&lt;p&gt;Given that we’re dealing with a site that has a lot of content that fit nicely into a tree based structure EPiServer CMS works great out-of-the-box for editors. The CMS stores content in a tree, the content tree, and expose that to editors using UI components such as the Page tree and the Block gadget that also lets editors work with content in a tree.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;While there is&lt;/strong&gt; a lot of content, meaning that the content tree has a lot of branches and leafs editors can easily find the right place to publish new content. They can also find old content simply by navigating the content tree, or the site, the same way a public visitor would.&lt;/p&gt;
&lt;p&gt;In cases where the standard navigation doesn’t suffice, such as when an editor or visitors needs to find content that, in their view, isn’t placed where it should be on the site, basic free text search functionality typically can handle that.&lt;/p&gt;
&lt;p&gt;As for developers building navigation components is typically easy as all they have to do is utilize the page tree. EPiServer&#39;s methods for doing that, such as Get, GetChildren and GetAncestors are highly optimized and aggresively cached with clever dependencies for releasing their caches when needed and only then.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;However, no matter&lt;/strong&gt; how natural the content hierarchy is there are usually a number of requirements for components that lists content in a way that isn’t based on the hierarchy. Examples of such components could for instance be the most recently published pages of a certain type, all articles published be a certain author or department and all publications categorized with a certain keyword.&lt;/p&gt;
&lt;p&gt;For such requirements EPiServer CMS only has the method FindPagesWithCriteria to offer. Besides obvious usability issues for developers FPWC has some serious performance issues, especially on a site with a large volume of content.&lt;/p&gt;
&lt;p&gt;In other words, on a large scale EPiServer site with content fitting naturally into a deep hierarchy we’re faced with the challenge of finding content based on non-hierarchical criteria.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;There are two&lt;/strong&gt; common solutions to this problem. One is to somehow store the answer to such questions at a time where we know that the answer is changing. For instance, this may mean storing a list of the ten last published pages of a given type serialized into a property somewhere or in the Dynamic Data Store, updating each time a page is published. This requires quite a lot of development time and, worse, it requires us to know what questions will need answering beforehand. It’s also rather error prone.&lt;/p&gt;
&lt;p&gt;The second, and much better, common solution to this is to use a search engine. This has been done on a number of large EPiServer sites using different search engines. Today though the obvious solution is to use &lt;a href=&quot;/link/6f0db1b72ffa49968a45c16b1146b95a.aspx?id=43&amp;amp;epslanguage=en&quot;&gt;EPiServer Find&lt;/a&gt;, the search and content retrieval product that EPiServer offers. Find was in many ways built exactly to address this problem in a way that offers great usability for developers and short development time.&lt;/p&gt;
&lt;p class=&quot;conclusion&quot;&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Use a EPiServer Find to create navigations and listings of content that are not based on the contents place in the content tree.&lt;/p&gt;
&lt;h2&gt;Non-hierarchical content&lt;/h2&gt;
&lt;p&gt;When the content can’t naturally be fitted into a deep hierarchy additional challenges arise. First, EPiServer’s API and editorial interface is designed for sites organizing content in a tree. If the content can’t be organized into a deep hierarchy performance will suffer. Here’s how I put it in my reply to the e-mail:&lt;/p&gt;
&lt;blockquote&gt;“The content tree can handle millions of items BUT if those items aren&#39;t stored in a deep hierarchy there will be performance problems. That is, if you have a page with ten thousand children you have a problem. If you have a page with a hundred children and each of those have a hundred children you won&#39;t have a problem.”&lt;/blockquote&gt;
&lt;p&gt;While I knew this from experience, after sending that reply, I decided to conduct a few experiments to prove it.&lt;/p&gt;
&lt;p&gt;In the context of a scheduled job I wrote code that created ten thousand pages below the same parent. It also created a hundred pages below another common parent and then a hundred pages below each of those pages. Everything was done in batches of a hundred pages and the mean time for creating a page during each batch was logged.&lt;/p&gt;
&lt;p&gt;Let’s look at the results for creating 100x100 pages in a hierarchy first.&lt;/p&gt;
&lt;table class=&quot;table table-striped table-bordered table-condensed&quot; border=&quot;0&quot;&gt;
&lt;thead&gt; 
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Batch&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Avg. time per published page (ms)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/thead&gt; 
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1-100&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;201-300&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;501-600&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;901-1000&lt;/td&gt;
&lt;td&gt;24&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1901-2000&lt;/td&gt;
&lt;td&gt;24&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4901-5000&lt;/td&gt;
&lt;td&gt;33&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9901-10000&lt;span style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;There are of course some variances which would likely even themselves out with a larger sample (I ran the test only four times), but it&#39;s pretty clear that it takes almost exactly the same amount of time to create page number ten thousand as page number one when storing pages in a hierarchy where each page has ninetynine siblings.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Now, let’s compare that to creating 10000 pages below the same parent.&lt;/p&gt;
&lt;table class=&quot;table table-striped table-bordered table-condensed&quot; border=&quot;0&quot;&gt;
&lt;thead&gt; 
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Batch&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Avg. time per published page (ms)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/thead&gt; 
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1-100&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;201-300&lt;/td&gt;
&lt;td&gt;26&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;501-600&lt;/td&gt;
&lt;td&gt;34&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;901-1000&lt;/td&gt;
&lt;td&gt;50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1901-2000&lt;/td&gt;
&lt;td&gt;83&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4901-5000&lt;/td&gt;
&lt;td&gt;180&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9901-10000&lt;span&gt; &lt;/span&gt;&lt;/td&gt;
&lt;td&gt;414&lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;As we can see the time required to publish a page grows based on the number of existing pages below the page’s parent page. Plotted into a diagram we can see that this growth is linear.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;thumbnail-centered&quot; src=&quot;/PageFiles/643/time-growth.png&quot; alt=&quot;&quot; width=&quot;347&quot; height=&quot;208&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Beyond API performance issues, expanding the tree node for a page revealing it’s ten thousand pages in edit mode takes time. Below is what FireBug reported for me when I tried to expand a none with ten thousand children.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;thumbnail-centered&quot; src=&quot;/PageFiles/643/loading-10000-children.png&quot; alt=&quot;&quot; width=&quot;400&quot; height=&quot;216&quot; /&gt;&lt;/p&gt;
&lt;p&gt;After receiving the response from the server Firefox reported an unresponsive JavaScript on the page and it took several minutes before I actually got to see the pages in the page tree.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Of course, even if it the page tree wouldn&#39;t have any issues with displaying thousands of children for a node such a list would hardly be useful for editors.&lt;/p&gt;
&lt;p class=&quot;conclusion&quot;&gt;&lt;strong&gt;Conclusion:&lt;/strong&gt; EPiServer is built and optimized for sites that stores content in a hierarchy in which each node has hundreds and not thousands of child nodes.&lt;/p&gt;
&lt;p&gt;Clearly, EPiServer&#39;s page tree doesn&#39;t work well for large scale sites with huge volumes of non-hierarchical content. Not in terms of performance and not in terms of editor usability.&lt;/p&gt;
&lt;p&gt;Luckily there&#39;s a fairly easy solution that has proven to work very well. In fact, I&#39;ve seen it done so many times that I&#39;d call it a pattern. What is is? Faking it!&lt;/p&gt;
&lt;h3&gt;Structuring bulk content in arbitrary hierarchies&lt;/h3&gt;
&lt;p&gt;We know that EPiServer needs, or prefers, organizing pages in such a way that each node in its content tree doesn&#39;t have more than hundreds of immediate children. EPiServer does not however care about why a certain page belongs in a certain place in the tree. Therefor we can automatically place pages in a hierarchy based on some arbitrary criteria.&lt;/p&gt;
&lt;p&gt;For articles on a media site this is commonly done by placing them in a structure based on publish date.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;thumbnail-centered&quot; src=&quot;/PageFiles/643/page-tree-date-structure.png&quot; alt=&quot;&quot; width=&quot;394&quot; height=&quot;191&quot; /&gt;&lt;/p&gt;
&lt;p&gt;There are a number of ways to implement such functionality but it typically involves:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Defining a root node for a certain type of content.&lt;/li&gt;
&lt;li&gt;Hooking up to events from EPiServer&#39;s API listening to when content is created.&lt;/li&gt;
&lt;li&gt;When a page of a matching type is created ensure that there is a place for it in the date structure below the root, otherwise create it.&lt;/li&gt;
&lt;li&gt;Move the newly created content to its parent in the date structure.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Of course, when content resides in a structure whose only purpose is to work well with EPiServer performance wise we can&#39;t utilize the content hierarchy when building navigations. The solution to that typically involves four things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Defining one or&lt;/strong&gt; several properties on the content types that will be used for &quot;bulk content&quot;. These properties are typically of type PageReference, ContentReference or ContentArea. For instance, an article may have a property named Section of type PageReference which points to the Football section.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Utilizing the above&lt;/strong&gt; mentioned property/properties when rendering pages to determine in what context they should be shown. For instance, an article about a Champions League game may have a Section property pointing to a page named Football which in turn is a child of a page named Sport. Based on that the article&#39;s content is displayed framed by a header, navigation elements and right column from Football or Sport.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Using a search&lt;/strong&gt; engine to create listings. Essentially I&#39;m talking about the same problem as we looked at before here, finding content based on non-hierarchical criteria. The only difference is that we now need to apply the same solution in more places as the majority of the content of the site&#39;s content is organized in such a way in the content tree that it can&#39;t be used to build navigations and listings. &lt;br /&gt;&lt;strong&gt;With that said&lt;/strong&gt;, we can still utilize EPiServer&#39;s standard API methods for components such as the main navigation as those pages aren&#39;t the &quot;bulk content&quot; and therefor works well with the page tree. Again while we can use pretty much any search engine that offers good performance and scalability, EPiServer Find is the best option as it was born out of these specific needs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rewriting URLs.&lt;/strong&gt; By default URLs on an EPiServer site is built up using the page&#39;s name prefixed by the name of each of its ancestors in the page tree. When storing articles or other content in a structure that has nothing to do with how visitors sees the page on the site URLs won&#39;t seem very logical. For instance an URL like /2013/04/23/champions-league.. is hardly helpful and doesn&#39;t look very good. With older versions of EPiServer CMS we typically handled that using a custom URL rewriter. Nowadays with EPiServer 7 we do it using &lt;a href=&quot;/link/e9ec501e09a64e74bdad2df4f1102ae4.aspx?id=526&amp;amp;epslanguage=en&quot;&gt;custom routing&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p class=&quot;conclusion&quot;&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Automatically organize non-hierarchical content in arbitrary hierarchies based on creation date, first letter in their names or some other criteria. Use properties on the content to tie it to pages in the page tree which provide the context in which the content should be rendered. Use EPiServer Find to build listings.&lt;/p&gt;
&lt;p&gt;Using the above approach we solve the performance issues when dealing with non-hierarchical content of the type that is often found on media sites, blogs and the like. While that works great we have one more problem to solve - how editors create and find the content for which the page tree is more or less useless.&lt;/p&gt;
&lt;h3&gt;Custom components for editorial workflows&lt;/h3&gt;
&lt;p&gt;We could tell editors &quot;To create a new article click on the Articles node in the page tree. We have some code that will automatically move it a few levels down in a date based structure. Oh, and don&#39;t forget to set the Section property.&quot; However, odds are we wouldn&#39;t find much jobs afterwards and we&#39;d see buch of angry comments about EPiServer on Twitter.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Clearly, if we&#39;re&lt;/strong&gt; dealing with the type of site that the page tree doesn&#39;t work well with we can&#39;t just be content with solving performance issues. We&#39;ll also need to extend EPiServer&#39;s edit mode to provide good workflows for editors.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Exactly how such components should work and be implemented differs from site to site but it typically involves functionality to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create &quot;bulk content&quot; without having to use the page tree gadget.&lt;/li&gt;
&lt;li&gt;Either automatically populating &quot;infrastructure properties&quot; such as Section or making it very easy for editors to do so.&lt;/li&gt;
&lt;li&gt;List the most recent content. Especially on media sites it&#39;s a very common requirement to have a list that displays all articles that have either been published today, not yet been published or is scheduled to be published.&lt;/li&gt;
&lt;li&gt;Find content based on criteria such as author, publish date and section.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&#39;ve built such functionality both in EPiServer 6 and EPiServer 7 and based on those experiences I&#39;ve created the &lt;a href=&quot;/link/c307dee82d384e9cbfa436f08a8b949d.aspx?id=509&amp;amp;epslanguage=en&quot;&gt;PowerSlice&lt;/a&gt; project. PowerSlice is one way of addressing several of the above requirements and may solve all needs for some sites. For other sites it may be used for inspiration.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;thumbnail thumbnail-centered&quot; src=&quot;/PageFiles/643/creating-content-in-slice.png&quot; alt=&quot;&quot; width=&quot;377&quot; height=&quot;152&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Either way, it&#39;s&lt;/strong&gt; very much possible to build the components needed by editors. With EPiServer 7 it typically involves creating custom Dojo/Dijit widgets and utilizing EPiServer Find.&lt;/p&gt;
&lt;p class=&quot;conclusion&quot;&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Extend EPiServer&#39;s edit mode with custom components tailor made for the needs of the editors. PowerSlice may be an option and/or used for inspiration.&lt;/p&gt;
&lt;p&gt;Are you still with me? Perhaps it&#39;s about time we looked at an example.&lt;/p&gt;
&lt;h2&gt;An example - this site&lt;/h2&gt;
&lt;p&gt;This site doesn&#39;t exactly fit the &quot;large scale&quot; description. However, as it&#39;s primarily a blog it, along with certain parts of many other &quot;small&quot; sites, does have non-hierarchical content. Therefor I applied the above mentioned techniques to it, meaning that we can look at it as an example of how a large scale site, such as a media site, can be built.&lt;/p&gt;
&lt;h3&gt;Organizing pages&lt;/h3&gt;
&lt;p&gt;In terms of hiearchy there are two types of pages on the site. Articles and tags are automatically organized in two separate structures. Sections and standard pages are not.&lt;/p&gt;
&lt;p&gt;All articles resider under a node below the start page. Under that node they are grouped first by year and then by month.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;thumbnail-centered&quot; src=&quot;/PageFiles/643/example-page-tree.png&quot; alt=&quot;&quot; width=&quot;258&quot; height=&quot;516&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Articles have a property named MainCategory edited using a drop down from which it&#39;s possible to select one of the categories (sections) on the site.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;thumbnail-centered&quot; src=&quot;/PageFiles/643/example-category-property.png&quot; alt=&quot;&quot; width=&quot;228&quot; height=&quot;40&quot; /&gt;&lt;/p&gt;
&lt;p&gt;This property is used for breadcrumbs and context specific things when rendering an article.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;thumbnail-centered&quot; src=&quot;/PageFiles/643/Example-MainCategory-usage.png&quot; alt=&quot;&quot; width=&quot;448&quot; height=&quot;77&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Articles also have a content area property to which other categories can be added.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;thumbnail-centered&quot; src=&quot;/PageFiles/643/example-additional-categories-property.png&quot; alt=&quot;&quot; width=&quot;590&quot; height=&quot;92&quot; /&gt;&lt;/p&gt;
&lt;p&gt;MainCategory and any categories added to AdditionalCategories are combined by a code only property on articles named AllCategories.&lt;/p&gt;
&lt;p&gt;New articles can be created using a UI component that&#39;s created using PowerSlice.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;thumbnail-centered&quot; src=&quot;/PageFiles/643/Example-create-new-article.png&quot; alt=&quot;&quot; width=&quot;477&quot; height=&quot;273&quot; /&gt;&lt;/p&gt;
&lt;p&gt;When an article is created it&#39;s initial parent is the root node for articles. Using a modified version of my old open source project &lt;a href=&quot;https://github.com/joelabrahamsson/PageStructureBuilder&quot;&gt;PageStructureBuilder&lt;/a&gt; the article as automatically moved to a year/month structure.&lt;/p&gt;
&lt;h3&gt;Listings and routing&lt;/h3&gt;
&lt;p&gt;Categories/sections list articles &quot;belonging&quot; to them based ordered by publication date. This is done using a fairly simple search query using EPiServer Find that filters on article&#39;s AllCategories property.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;_searchClient.Search()
    .Filter(page =&amp;gt; page.Categories.Match(currentPage.ContentLink))
    .CurrentlyPublished()   
    .FilterOnReadAccess()
    .OrderByDescending(x =&amp;gt; x.StartPublish);&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As for URLs I use a custom partial router, which I&#39;ve &lt;a href=&quot;/link/e9ec501e09a64e74bdad2df4f1102ae4.aspx?id=526&amp;amp;epslanguage=en&quot;&gt;previously described in great detail&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Dealing with traffic&lt;/h2&gt;
&lt;p&gt;So far this article has been about how to build sites with large volumes of content on EPiServer CMS. There&#39;s of course another way to interpret &quot;large scale sites&quot; - sites with a lot of traffic.&lt;/p&gt;
&lt;p&gt;Again, it&#39;s already been proven by a number of existing EPiServer customers that EPiServer can handle huge volumes of traffic. With that said, it&#39;s of course also very much possible to build a site on EPiServer that crumbles once it&#39;s hit with more than a couple of concurrent requests.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A robust EPiServer&lt;/strong&gt; site that can handle a lot of traffic and let editors work efficiently at the same time requires a good implementation. And a good implementation requires skilled and experienced developers who know what they are doing.&lt;/p&gt;
&lt;p&gt;In general EPiServer CMS&#39;s API is highly optimized and the most significant methods for getting content based on the hierarchy are cached. As for EPiServer Find it&#39;s fast, highly scalable and also has mechanisms for caching that can be used when needed. So, as first step in hardening a site for production it&#39;s absolutely vital to use the API methods visely. Having done so the site will hold well on its own.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Sometimes though, &lt;/strong&gt;we&#39;re dealing with a site that has so much traffic that it&#39;s not just enough use caching to prevent database calls. The actual rendered HTML output needs to be cached as well. For that EPiServer offers a fairly basic &lt;a href=&quot;/link/cc5f6e31902d4913b22a2f7c573bbde7.aspx?id=184&amp;amp;epslanguage=en&quot;&gt;output cache&lt;/a&gt; that can be used.&lt;/p&gt;
&lt;p&gt;While that may be an option, for site with really, really, really much traffic we may need even more efficient output caching. In those cases we can either construct a custom output cache to use on the webservers or, which I prefer, use a web content accelerator/caching reverse proxy such as Varnish. We may also want to look in to using a CDN instead or as a compliment.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;One thing to&lt;/strong&gt; beware of though is that any form of output caching, with the exception of partial caching, will limit editors ability to use some of the functionality built into the CMS such as personalization. If that&#39;s a problem we can often work around that by loading parts of pages using JavaScript and not caching such requests. Of course that means more requests to the site though.&lt;/p&gt;
&lt;p&gt;In general, my philosophy is to build the site as robust and performant as possible without so that it can handle the traffic without any other form of caching. After that, if it&#39;s needed or economically motivated some sort of cache can be put in front of the site.&lt;/p&gt;
&lt;p&gt;This approach has two benefits. First of all we can choose to use output caching for the right reasons. Second, using output caching tends to hide performance problems in the application and while those may not be a problem at first they may be whenever the cache is released or if there&#39;s an issue with the output cache. Then it&#39;s very valuable if the web applciation can hold on its own.&lt;/p&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;ul class=&quot;check&quot;&gt;
&lt;li&gt;EPiServer CMS can handle sites with millions of pages.&lt;/li&gt;
&lt;li&gt;For large scale sites FindPagesWithCriteria doesn&#39;t work for non-hierarchical queries. Use EPiServer Find for that.&lt;/li&gt;
&lt;li&gt;EPiServer relies on content being split up into a hierarchy. If the content doesn&#39;t fit naturally into such a hierarchy, make one up and use a combination of properties, Find and edit mode extensions for creating new content and building listings.&lt;/li&gt;
&lt;/ul&gt;
</id><updated>2013-04-29T09:13:03.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>How EPiServer&#39;s HTML helper PropertyFor works</title><link href="http://joelabrahamsson.com/how-episervers-html-helper-propertyfor-works/" /><id>PropertyFor is the counterpart of the Property control when building websites using EPiServer 7 and ASP.NET MVC. However, it does not work the same way as the Property control and understanding how it works is key to rendering the markup that you want and need.
&lt;p&gt;When using Web Forms the standard/default/recommended way to render an EPiServer property is to use the EPiServer:Property control. When using ASP.NET MVC its counterpart is the HTML helper &lt;strong&gt;&lt;span class=&quot;code-concept&quot;&gt;PropertyFor&lt;/span&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;That is, PropertyFor is the counterpart the Property control in MVC in terms of being the recommended way to render a property. It is&amp;nbsp;however &lt;em&gt;not&lt;/em&gt; the equivalent of the Property control in terms of functionality.&lt;/p&gt;
&lt;h2&gt;Wrapping elements&lt;/h2&gt;
&lt;p&gt;As you may know, the Property control always wraps the property value in a HTML element. The element differs depending on the property type and can be customized using the CustomTag attribute on the control. This isn&#39;t the case with PropertyFor.&lt;/p&gt;
&lt;p&gt;To exemplify, let&#39;s look at the code below where we use the PropertyFor method to render a string property.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&amp;lt;div&amp;gt;
    @Html.PropertyFor(x =&amp;gt; x.Heading)
&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Given the Heading property has the value &quot;Banana&quot;, the above will output the following when the page is rendered in view mode.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&amp;lt;div&amp;gt;
    Banana
&amp;lt;/div&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When the page is rendered in edit mode the output will instead be:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&amp;lt;div&amp;gt;
    &amp;lt;div class=&quot;epi-editContainer&quot; data-epi-property-name=&quot;Heading&quot; data-epi-use-mvc=&quot;True&quot;&amp;gt;Banana&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, the property&#39;s value has been wrapped in a div with a CSS class and a couple of data-attributes.&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;conclusion&quot;&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;: PropertyFor &lt;em&gt;never&lt;/em&gt; wraps the property&#39;s value in an element when rendering it in view mode. &lt;em&gt;It always&lt;/em&gt; wraps the property&#39;s value in an element when rendering it in edit mode.&lt;/p&gt;
&lt;h3&gt;CustomTag and CssClass&lt;/h3&gt;
&lt;p&gt;As I&#39;ve previously written about, it&#39;s possible to &lt;a href=&quot;/link/7e15400e6eaf4ab7921d0a1becacb9b3.aspx?id=283&amp;amp;epslanguage=en&quot;&gt;pass settings such as CustomTag and CssClass to PropertyFor&lt;/a&gt;. With the Property control the CustomTag setting controls the type of element that the property is wrapped in and the CssClass setting adds one or more CSS classes to the wrapping element.&lt;/p&gt;
&lt;p&gt;Let&#39;s modify the previous example to see what PropertyFor does with them.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&amp;lt;div&amp;gt;
    @Html.PropertyFor(x =&amp;gt; x.Heading, new { CustomTag = &quot;h1&quot;, CssClass =&quot;muted&quot; })
&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In view mode this changes the output to:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&amp;lt;div&amp;gt;
    Banana
&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&#39;s right, it doesn&#39;t change the output at all.&lt;/p&gt;
&lt;p&gt;What about when rendered in edit mode?&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&amp;lt;div&amp;gt;
    &amp;lt;h1 class=&quot;epi-editContainer&quot; data-epi-property-name=&quot;Heading&quot; data-epi-use-mvc=&quot;True&quot; data-epi-property-rendersettings=&quot;{&amp;amp;quot;customTag&amp;amp;quot;:&amp;amp;quot;h1&amp;amp;quot;,&amp;amp;quot;cssClass&amp;amp;quot;:&amp;amp;quot;muted&amp;amp;quot;}&quot; class=&quot;heading&quot;&amp;gt;Banana&amp;lt;/h1&amp;gt;
&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Starting with CustomTag we can see that setting it to h1 changed the type of the wrapping element that PropertyFor added in edit mode.&lt;/p&gt;
&lt;p class=&quot;conclusion&quot;&gt;&lt;strong&gt;Conclusion:&lt;/strong&gt; CustomTag changes the type of element that wrapes the rendered property when rendered in edit mode.&lt;/p&gt;
&lt;p&gt;As for CssClass that added a class attribute with the specified value to the element. However, there already was another class attribute on the element and our custom CSS class wasn&#39;t added to that. It was added as a separate class attribute, meaning that the browser will ignore it. Here&#39;s how FireBug sees the rendered markup:&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;thumbnail&quot; src=&quot;/PageFiles/633/firebug-custom-class.png&quot; alt=&quot;&quot; width=&quot;625&quot; height=&quot;74&quot; /&gt;&lt;/p&gt;
&lt;p&gt;So, it appears that while CustomTag changes the type of wrapping element that PropertyFor renderes the property in in edit mode CssClass doesn&#39;t, in practice, have any effect on the class attribute on the wrapping element.&lt;/p&gt;
&lt;p&gt;However, there&#39;s another setting we can pass to PropertyFor, EditContainerClass. Let&#39;s see what happens if we use that instead of CssClass, like this:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&amp;lt;div&amp;gt;
    @Html.PropertyFor(x =&amp;gt; x.Heading, new { CustomTag = &quot;h1&quot;, EditContainerClass =&quot;muted&quot; })
&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That produces the following when rendered in edit mode:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&amp;lt;div&amp;gt;
    &amp;lt;h1 class=&quot;muted&quot; data-epi-property-name=&quot;Heading&quot; data-epi-use-mvc=&quot;True&quot; data-epi-property-rendersettings=&quot;{&amp;amp;quot;customTag&amp;amp;quot;:&amp;amp;quot;h1&amp;amp;quot;,&amp;amp;quot;editContainerClass&amp;amp;quot;:&amp;amp;quot;muted&amp;amp;quot;}&quot;&amp;gt;Banana&amp;lt;/h1&amp;gt;
&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Look at that. No second class attribute has been added and the first has changed from &quot;epi-editContainer&quot; to the value we specified in EditContainerClass.&lt;/p&gt;
&lt;p class=&quot;conclusion&quot;&gt;&lt;strong&gt;Conclusion:&lt;/strong&gt; CssClass does not change the CSS class for the wrapping element when rendered in edit mode. EditContainerClass does.&lt;/p&gt;
&lt;p&gt;Us specifying CustomTag, CssClass and, later, EditContainerClass also brought another change to the rendered markup in edit mode - a data-epi-property-rendersettings attribute was added to the wrapping element. The attributes value looks to be the serialized version of the anonymous object we used to pass the settings to PropertyFor with.&lt;/p&gt;
&lt;h2&gt;How PropertyFor renders property values&lt;/h2&gt;
&lt;p&gt;So far we&#39;ve looked at how and when PropertyFor wraps the output for a property. But, beyond rendering a wrapping element in edit mode, how does it actually render a property?&lt;/p&gt;
&lt;p&gt;In Web Forms the Property control uses the ClassFactory to resolve a control to which it delegates the actual rendering of the property. This way different controls are used for different types of properties. For instance, a string is rendered as is (wrapped in a p tag) while a LinkCollection is rendered as an ul-li list.&lt;/p&gt;
&lt;p&gt;The PropertyFor method works quite differently but in a way that achieves similar results - it delegates the actual rendering to ASP.NET MVC&#39;s &lt;strong&gt;&lt;span class=&quot;code-concept&quot;&gt;DisplayFor&lt;/span&gt;&lt;/strong&gt; method.&lt;/p&gt;
&lt;p class=&quot;conclusion&quot;&gt;&lt;strong&gt;Conclusion:&lt;/strong&gt; In view mode PropertyFor isn&#39;t much more than an alias for DisplayFor. In edit mode it adds a wrapping element to whatever is rendered by DisplayFor. The wrapping element contains attributes that the CMS uses to identify editable properties.&lt;/p&gt;
&lt;h3&gt;DisplayFor and display templates&lt;/h3&gt;
&lt;p&gt;The DisplayFor method uses a number of rules to determine what to render for a given object. These, in an abbreviated form based on the official &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ee407390(v=vs.98).aspx&quot;&gt;documentation&lt;/a&gt; on MSDN, are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If the property is typed as a primitive type (integer, string, and so on), the method renders a string that represents the property value.&lt;/li&gt;
&lt;li&gt;If the property type is Boolean, the method renders an HTML input element for a check box.&lt;/li&gt;
&lt;li&gt;If a property is annotated with a data type attribute, the attribute specifies the markup that is generated for the property. For example, if the property is marked with the EmailAddress attribute, the method generates markup that contains an HTML anchor that is configured with the mailto protocol.&lt;/li&gt;
&lt;li&gt;If the object contains multiple properties, for each property the method generates a string that consists of markup for the property name and markup for the property value.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;What the documentation&lt;/strong&gt; doesn&#39;t say clearly though is that the rendering is based on templates which can be overridden. That can be done by placing a partial view whose name matches the type of object that is to be displayed or whose name matches either a data type name or UI hint.&lt;/p&gt;
&lt;p&gt;EPiServer adds a number of such templates to our site using a virtual path provider. These are the ones that handle the acutal rendering of EPiServer specific types such as LinkCollection, ContentArea etc.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Should we want&lt;/strong&gt; to we can &lt;a href=&quot;/link/f2b4323122994d50aaefa2e9a3e53242.aspx?id=253&amp;amp;epslanguage=en&quot;&gt;customize the rendering&lt;/a&gt; of such types by creating our own display templates. We can also specify that a specific template should be used for a specific property, no matter its type, by adding a UI hint to it.&lt;/p&gt;
&lt;h2&gt;PropertyFor and content areas&lt;/h2&gt;
&lt;p&gt;So far we&#39;ve concluded that PropertyFor acts as a wrapper for DisplayFor and wraps the output from DisplayFor in an element, but only when invoked in edit mode context. There&#39;s seemingly an exception to that rule.&lt;/p&gt;
&lt;p&gt;Let&#39;s look at what happens when we render a property of type ContentArea. The code may look like this:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&amp;lt;div&amp;gt;
    @Html.PropertyFor(x =&amp;gt; x.Contents)
&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Given that the content area is empty this results in the following output in edit mode:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&amp;lt;div&amp;gt;
    &amp;lt;div class=&quot;epi-editContainer&quot; data-epi-property-name=&quot;Contents&quot; data-epi-use-mvc=&quot;True&quot;&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nothing surprising there. The call to PropertyFor results in a wrapping element, the div. Of course, since we&#39;re in edit mode that&#39;s expected.&lt;/p&gt;
&lt;p&gt;Now, let&#39;s look at the output in view mode:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&amp;lt;div&amp;gt;

&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nothing surprising there either. The wrapping element is gone. As we&#39;ve already concluded that it should be in view mode.&lt;/p&gt;
&lt;p&gt;Let&#39;s see what happens when we add something to the content area. In this case I&#39;ve added a page for which there is a very simple partial renderer which simply outputs &quot;Partial renderer output&quot;.&lt;/p&gt;
&lt;p&gt;Here&#39;s the output in edit mode:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&amp;lt;div&amp;gt;
    &amp;lt;div class=&quot;epi-editContainer&quot; data-epi-property-name=&quot;Contents&quot; data-epi-use-mvc=&quot;True&quot;&amp;gt;
        &amp;lt;div data-epi-block-id=&quot;4&quot; data-epi-content-name=&quot;Home&quot;&amp;gt;
            Partial renderer output
        &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Again, no surprises. The wrapping element is there. The single content in the area is also wrapped in a div which is used to communicate information about item in the area to the CMS.&lt;/p&gt;
&lt;p&gt;What about view mode then?&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&amp;lt;div&amp;gt;
    &amp;lt;div&amp;gt;
        &amp;lt;div&amp;gt;
            Partial renderer output
        &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&#39;s quite a few div tags! Compare them to the output we saw in edit mode and you find &amp;nbsp;that the wrapping element for the property (the second div) is there, even though we&#39;re in view mode.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;It appears as&lt;/strong&gt; though there&#39;s something treating content areas in a special way in PropertyFor, always outputting the wrapping element if the area isn&#39;t empty no matter in what context the area is being rendered.&lt;/p&gt;
&lt;p&gt;That&#39;s not the case though. Instead it&#39;s the default display template for content areas that works in a way that gives that effect.&lt;/p&gt;
&lt;p&gt;That display template delegates the rendering of the area to a method named &lt;strong&gt;&lt;span class=&quot;code-concept&quot;&gt;RenderContentArea&lt;/span&gt;&lt;/strong&gt; located in the class EPiServer.Web.Mvc.Html.ContentAreaExtensions.&amp;nbsp;That method checks if the context is view mode and if it is outputs the wrapping element.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why? Well, imagine&lt;/strong&gt; you want to render the content area as an ul-li list. In that case you&#39;d want to invoke PropertyFor with ChildrenCustomTagName set to &quot;li&quot; in order to make each item in the area wrapped with an li instead of a div.&lt;/p&gt;
&lt;p&gt;Then you&#39;d want to have the li tags wrapped in an ul. If you were to wrap the call to PropertyFor in an ul that would work great in view mode but you&#39;d end up with &amp;lt;ul&amp;gt;&amp;lt;div&amp;gt;&amp;lt;li&amp;gt; in edit mode as PropertyFor always wraps the output in a div, or some other tag specified using CustomTag.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;On the other hand,&lt;/strong&gt; if you didn&#39;t wrap the call to PropertyFor in an ul tag and set CustomTag to &quot;ul&quot; you&#39;d end up with an ul-li list in edit mode but a lone set of li tags in view mode. To prevent that, the default display template for content areas, by means of the RenderContentArea method, outputs the wrapping element in view mode.&lt;/p&gt;
&lt;p class=&quot;conclusion&quot;&gt;&lt;strong&gt;Conclusion:&lt;/strong&gt; The default display template for content areas is implemented in such a way that the wrapping element is always outputted no matter if the property is rendered in view mode or edit mode, but only if the content area isn&#39;t empty.&lt;/p&gt;
&lt;h2&gt;Rendering properties without PropertyFor&lt;/h2&gt;
&lt;p&gt;While PropertyFor is the primary intended way to render properties when building EPiServer templates using MVC there&#39;s nothing that says that we have to use it. We&#39;re free to render properties of content objects such as PageData or BlockData, or properties of view models, however we want.&lt;/p&gt;
&lt;p&gt;Of course, when doing so it&#39;s up to us to add the attributes the CMS needs to identify editable properties in preview/on-page-edit mode. To do that we can use the HTML helper extension EditAttributes. Using that method we feed it an expression which specifies a given property on the model in the view and it spits out whatever attributes the CMS needs on its wrapping element.&lt;/p&gt;
&lt;p&gt;Here&#39;s a simple example:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&amp;lt;h1 @Html.EditAttributes(x =&amp;gt; x.Heading)&amp;gt;@Model.Heading&amp;lt;/h1&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;One important thing to keep in mind though - when editing the page in on-page-edit mode the CMS will replace the value in the element that wraps the property value with the updated value. This means that if we&#39;re rendering something other than what the display template for the property does editors won&#39;t get a realistic preview.&lt;/p&gt;
&lt;p&gt;How that works and how to handle that is an article of its own :)&lt;/p&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;ul class=&quot;check&quot;&gt;
&lt;li&gt;PropertyFor acts as a wrapper for DisplayFor. Therefor, to understand how PropertyFor works we need to look at how DisplayFor works.&lt;/li&gt;
&lt;li&gt;Beyond wrapping DisplayFor, PropertyFor wraps the output in an element needed by the CMS when in edit mode.&lt;/li&gt;
&lt;li&gt;The wrapping element is by default a div but can be changed using CustomTag.&lt;/li&gt;
&lt;li&gt;A custom CSS class can be added to the wrapping element when in edit mode using EditContainerClass.&lt;/li&gt;
&lt;li&gt;When used with content areas the wrapping element will be outputted in view mode as well due to how the default display template for ContentArea works.&lt;/li&gt;
&lt;/ul&gt;
</id><updated>2013-04-20T14:04:32.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Add UIHint to an EPiServer property without affecting its editor</title><link href="http://joelabrahamsson.com/add-uihint-to-an-episerver-property-without-affecting-its-editor/" /><id>&lt;p&gt;We can use UI hints to make the PropertyFor and DisplayFor methods use a specific display template when rendering properties with ASP.NET MVC.&lt;/p&gt;
&lt;p&gt;For instance, when rendering a property like this...&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;[UIHint(&quot;Banana&quot;)]&lt;br /&gt;public virtual string Heading { get; set; }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;...using Html.PropertyFor() it will be &quot;sent&quot; to a display template named Banana, given such a template exists.&lt;/p&gt;
&lt;p&gt;There&#39;s just one problem. When adding a UI hint that no editor descriptor cares about we loose the original editing functionality for the property and it will be edited using the &quot;legacy&quot; editing functionality. That is, instead of a textbox for a string property editors will see a button saying &quot;Click the button to edit&quot;.&lt;/p&gt;
&lt;p&gt;To fix that, use an overload for the UIHint attribute and specify&amp;nbsp;&lt;strong&gt;&lt;span class=&quot;code-concept&quot;&gt;PresentationLayer.Website&lt;/span&gt;&lt;/strong&gt;, like this:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;[UIHint(&quot;Banana&quot;, PresentationLayer.Website)]&lt;br /&gt;public virtual string Heading { get; set; }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;One caveat, while this works great with PropertyFor it won&#39;t work with DisplayFor which won&#39;t recognize the UI hint any longer.&lt;/p&gt;
</id><updated>2013-04-18T15:49:30.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Specify z-index for a property&#39;s overlay in EPiServer&#39;s on page edit mode</title><link href="http://joelabrahamsson.com/specify-z-index-for-a-propertys-overlay-in-episervers-on-page-edit-mode/" /><id>&lt;p&gt;Sometimes two property values overlap when rendered in a template. It may for instance be a string property whose value should be rendered on top of an image which is also a property. Or it may be a link/URL property that should be rendered at the of a string property.&lt;/p&gt;
&lt;p&gt;By default both properties will have an overlay, the thin blue border that is positioned on top of the element in which the property value is rendered. However, only one of them will be clickable.&lt;/p&gt;
&lt;p&gt;To handle that we can specify the z-index for the overlay for the property that isn&#39;t clickable. To do so add a&amp;nbsp;&lt;strong&gt;&lt;span class=&quot;code-concept&quot;&gt;data-epi-overlay-z-index&lt;/span&gt;&lt;/strong&gt; attribute to the element that contains the property. For instance, when using ASP.NET MVC and Razor:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&amp;lt;h1 data-epi-overlay-z-index=&quot;123&quot; @Html.EditAttributes(x =&amp;gt; x.Heading)&amp;gt;
    @Model.Heading
&amp;lt;/h1&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
</id><updated>2013-04-18T15:31:47.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>EPiServer Find 101</title><link href="http://joelabrahamsson.com/episerver-find-101/" /><id>New to EPIServer Find and want a jump start? Here&#39;s what you need to know.
&lt;p&gt;If you&#39;re new to EPiServer Find and going to use it in a project, or just want to try it out, there&#39;s plenty of &lt;a href=&quot;http://find.episerver.com/Documentation&quot;&gt;documentation on Find&#39;s site&lt;/a&gt;. There&#39;s also training offered by EPiServer. Not to mention &lt;a href=&quot;http://world.episerver.com/Modules/Forum/Pages/Forum.aspx?id=58826&amp;amp;epslanguage=en&quot;&gt;the forum&lt;/a&gt; on EPiServer World.&lt;/p&gt;
&lt;p&gt;Sometimes you need a little quick start though. Here&#39;s the most essential things to know about Find&#39;s .NET API and CMS integration.&lt;/p&gt;
&lt;h2&gt;Setting up&lt;/h2&gt;
&lt;p&gt;You can grab yourself a free test index at &lt;a href=&quot;http://find.episerver.com&quot;&gt;find.episerver.com&lt;/a&gt;.&amp;nbsp;Once you have created your index you can copy and paste the necessary configuration into your app.config or web.config.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;thumbnail-centered&quot; src=&quot;/PageFiles/623/Find-configuration.png&quot; alt=&quot;&quot; width=&quot;714&quot; height=&quot;378&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Finally you need to download and reference Find&#39;s .NET API. That&#39;s easily done through NuGet given that you have EPiServer&#39;s NuGet feed added as a package source. There&#39;s three packages to choose from. For an EPiServer CMS site install&amp;nbsp;&lt;strong&gt;EPiServer Find CMS Integration&lt;/strong&gt;. For any other type of .NET application install&amp;nbsp;&lt;strong&gt;EPiServer Find Client API&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;Communicating with the REST API&lt;/h2&gt;
&lt;p&gt;You can use the .NET API from any .NET application. When doing so, all communication with Find&#39;s REST API goes through an instance of the &lt;strong&gt;&lt;span class=&quot;code-concept&quot;&gt;IClient&lt;/span&gt;&lt;/strong&gt; interface. To obtain such an instance when not using the CMS integration you can use the &lt;strong&gt;&lt;span class=&quot;code-concept&quot;&gt;Client.CreateFromConfig()&lt;/span&gt;&lt;/strong&gt; method to create it based on settings in app.config/web.config.&lt;/p&gt;
&lt;p&gt;If you&#39;re using the CMS integration or any other integration for other EPiServer products&amp;nbsp;&lt;em&gt;always&lt;/em&gt; use the singleton &lt;strong&gt;&lt;span class=&quot;code-concept&quot;&gt;SearchClient.Instance&lt;/span&gt;&lt;/strong&gt;. This is important. The singleton is preconfigured with conventions set up for CMS content.&lt;/p&gt;
&lt;blockquote&gt;&quot;If you&#39;re using the CMS integration&amp;nbsp;always&amp;nbsp;use the singleton SearchClient.Instance&quot;&lt;/blockquote&gt;
&lt;h2&gt;Finding things&lt;/h2&gt;
&lt;p&gt;Once you have a client search for indexed objects (CMS objects are automatically indexed upon save) using the &lt;strong&gt;&lt;span class=&quot;code-concept&quot;&gt;Search&amp;lt;T&amp;gt;()&lt;/span&gt;&lt;/strong&gt; method where T is the type of objects you want to search for. The method supports inheritance and searching for objects that implement an interface.&lt;/p&gt;
&lt;p&gt;The Search method returns an object which you can add queries and filters to. Use the &lt;strong&gt;&lt;span class=&quot;code-concept&quot;&gt;For&lt;/span&gt;&lt;/strong&gt; method for free text search. Use the &lt;strong&gt;&lt;span class=&quot;code-concept&quot;&gt;Filter&lt;/span&gt;&lt;/strong&gt; method to apply criterias.&lt;/p&gt;
&lt;p&gt;The Filter method is very similar to LINQ&#39;s Where method but has a slightly different syntax. You can filter on any property of a &quot;simple&quot; type, such as int, string, DateTime, double, GUID etc. Check out &lt;a href=&quot;http://find.episerver.com/Documentation/dotnet-api-filtering&quot;&gt;the documentation&lt;/a&gt; for more information or use Intellisense.&lt;/p&gt;
&lt;p&gt;You can use methods with familiar names from LINQ to apply sorting, projections and paging - &lt;strong&gt;&lt;span class=&quot;code-concept&quot;&gt;OrderBy&lt;/span&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;span class=&quot;code-concept&quot;&gt;Select&lt;/span&gt;&lt;/strong&gt;,&amp;nbsp;&lt;strong&gt;&lt;span class=&quot;code-concept&quot;&gt;Skip&lt;/span&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;span class=&quot;code-concept&quot;&gt;Take&lt;/span&gt;&lt;/strong&gt; etc.&lt;/p&gt;
&lt;p&gt;Once you&#39;re done building your search request execute it against the REST API and get the result using the &lt;strong&gt;&lt;span class=&quot;code-concept&quot;&gt;GetResult()&lt;/span&gt;&lt;/strong&gt; method. The returned object will be an object the implements IEnumerable&amp;lt;T&amp;gt; so you can start iterating over the results straight away.&lt;/p&gt;
&lt;p&gt;Note that if you&#39;re searching for CMS objects such as PageData and want to fetch the full objects you shouldn&#39;t use GetResult but instead use the &lt;strong&gt;&lt;span class=&quot;code-concept&quot;&gt;GetContentResult()&lt;/span&gt;&lt;/strong&gt; method. When using the integration for CMS 6, that&#39;s called GetPagesResult.&lt;/p&gt;
&lt;blockquote&gt;&quot;if you&#39;re searching for CMS objects such as PageData and want to fetch the full objects ... use the GetContentResult() method&quot;&lt;/blockquote&gt;
&lt;h3&gt;Unified Search&lt;/h3&gt;
&lt;p&gt;One of the things that makes Find powerful and easy to use at the same time is the fact that it let&#39;s us index our own .NET object and search for them in a strongly typed way. Sometimes though, such as building a search page, we want to search over many different types. Find makes that easy to using a concept called &lt;a href=&quot;http://find.episerver.com/Documentation/unified-search&quot;&gt;Unified Search&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In general - use the regular Search method for building listings, navigations and specialized search page with ease and use Unified Search when building free text search pages where users should search in *everything*.&lt;/p&gt;
&lt;h2&gt;Where to go from here&lt;/h2&gt;
&lt;p&gt;That&#39;s it. A few key concepts to get you started and a few important things to remember to avoid being faced by a YSOD.&lt;/p&gt;
&lt;p&gt;Once you&#39;ve familiarized yourself with Find&#39;s .NET API you can move on to &lt;a href=&quot;http://find.episerver.com/Documentation/dotnet-api-indexing&quot;&gt;indexing custom objects&lt;/a&gt; or why not check out some of the more specialized and interesting methods such as &lt;a href=&quot;http://find.episerver.com/Documentation/dotnet-api-more-like-related-documents&quot;&gt;MoreLike&lt;/a&gt; and &lt;a href=&quot;http://find.episerver.com/Documentation/dotnet-api-boosting-with-filters&quot;&gt;BoostMatching&lt;/a&gt;. Also, don&#39;t miss out of the many types of &lt;a href=&quot;http://find.episerver.com/Documentation/dotnet-api-facets&quot;&gt;facets&lt;/a&gt; which you can use to build many interesting things.&lt;/p&gt;
&lt;p&gt;Want to build a search page for an EPiServer site quickly? &lt;a href=&quot;/link/d90bae5d27f847289132b12e7b94750f.aspx?id=254&amp;amp;epslanguage=en&quot;&gt;Here&#39;s one&lt;/a&gt; complete with annotated source code for you.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Happy Finding!&lt;/strong&gt;&lt;/p&gt;
</id><updated>2013-04-16T22:36:20.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Pattern for EPiServer block preview MVC controller</title><link href="http://joelabrahamsson.com/pattern-for-episerver-block-preview-mvc-controller/" /><id>&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;using System.Web.Mvc;
using EPiServer.Core;
using EPiServer.Framework.DataAnnotations;
using EPiServer.Framework.Web;
using EPiServer.Web;

namespace MySite
{
    [TemplateDescriptor(
        Inherited = true,
        TemplateTypeCategory = TemplateTypeCategories.MvcController,
        Tags = new [] { RenderingTags.Preview },
        AvailableWithoutTag = false)]
    public class PreviewController : Controller, IRenderTemplate&amp;lt;BlockData&amp;gt;
    {
        public ActionResult Index(IContent currentContent)
        {
            //TODO: Create model suitable for the view and return ViewResult
            return View();
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Explained:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;using System.Web.Mvc;
using EPiServer.Core;
using EPiServer.Framework.DataAnnotations;
using EPiServer.Framework.Web;
using EPiServer.Web;

namespace MySite
{
    [TemplateDescriptor(
        //Support everything inheriting from BlockData.
        Inherited = true,
        //By default controllers implementing IRenderTemplate&amp;lt;T&amp;gt; where T is BlockData
        //are registered as partial renderers. As this will be a &quot;full page&quot; renderer
        //we need to change that.
        TemplateTypeCategory = TemplateTypeCategories.MvcController,
        //Should only be used for preview
        Tags = new [] { RenderingTags.Preview },
        AvailableWithoutTag = false)]
    public class PreviewController : Controller,
        //Register as template for BlockData. To only support a specific type
        //change the type parameter from BlockData to that type and optionally
        //set Inherited = false in the the TemplateDescriptor attribute above.
        IRenderTemplate&amp;lt;BlockData&amp;gt;
    {
        public ActionResult Index(
            //While we implement IRenderTemplate for BlockData model binding
            //can only deal with IContent, ie shared blocks in this case.
            IContent currentContent
            )
        {
            //TODO: Create model suitable for the view and return ViewResult
            return View();
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
</id><updated>2013-04-15T10:26:49.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Hiding EPiServer properties from editors</title><link href="http://joelabrahamsson.com/hiding-episerver-properties-from-editors/" /><id>&lt;p&gt;When managing a property in EPiServer&#39;s admin mode there is a setting named &quot;&lt;strong&gt;Display in Edit Mode&lt;/strong&gt;&quot;. To control this setting from code in EPiServer 7 use the&amp;nbsp;&lt;strong&gt;&lt;span class=&quot;code-concept&quot;&gt;ScaffoldColumn&lt;/span&gt;&lt;/strong&gt; attribute.&lt;/p&gt;
&lt;p&gt;When set to false it will hide the property from editors, meaning that while they may seem the rendered value in preview mode they won&#39;t see a blue box around it and they won&#39;t be able to click on the property to edit it. The property won&#39;t be visible in forms editing mode either.&lt;/p&gt;
&lt;p&gt;There is also the &lt;strong&gt;&lt;span class=&quot;code-concept&quot;&gt;Editable&lt;/span&gt;&lt;/strong&gt; attribute. When this is set to false the property will still be visible to editors in both preview mode, with a blue box around it, and in forms editing mode. The editor for it will however be disabled, meaning that while editors can inspect the property&#39;s value they can&#39;t modify it.&lt;/p&gt;
</id><updated>2013-04-14T16:10:08.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Custom routing for EPiServer content</title><link href="http://joelabrahamsson.com/custom-routing-for-episerver-content/" /><id>Two real-world examples of how to customize the routing for EPiServer pages to take control of the site&#39;s URLs and links.
&lt;p&gt;EPiServer 7 CMS uses the built in routing functionality in ASP.NET for URL handling. The default routing when using EPiServer 7 mimics the friendly URL functionality in older versions of the CMS in which the URL for a page is built up of it&#39;s URLSegment property prefixed by it&#39;s ancestors URL segments.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;thumbnail-centered&quot; src=&quot;/PageFiles/617/page-tree-routing.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;There are many nice aspects of the default behavior.&amp;nbsp; For instance, URL&#39;s for pages match their places in the page tree and in navigation elements making them seem logical and predictable. However, it also has the drawback of tying the URL for a page to it&#39;s location in the page tree making it risky to move content.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Also, in some&lt;/strong&gt; situations, such as when you have a site with a lot of content, it may not be appropriate to place content in a specific place in the content tree even though it belongs there.&lt;/p&gt;
&lt;p&gt;It may also be that a page is only used as a data bearer without a template and links to it should lead to some other page, optionally with some parameters in the URL.&lt;/p&gt;
&lt;p&gt;In such cases we need to extend or modify EPiServer&#39;s default routing. In this article I&#39;ll show two real-world examples of doing just that.&lt;/p&gt;
&lt;h2&gt;Custom routing using partial routing&lt;/h2&gt;
&lt;p&gt;The first example is drawn from how articles are routed on this site. The article you&#39;re currently reading is tied to the EPiServer CMS category (a page) on the site which is reflected in navigation elements.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;thumbnail-centered&quot; src=&quot;/PageFiles/617/navigation-elements.png&quot; alt=&quot;&quot; width=&quot;718&quot; height=&quot;315&quot; /&gt;&lt;/p&gt;
&lt;p&gt;It does not however reside under the CMS category&#39;s page. Instead it&#39;s placed in a hierarchical structure based on the date it was created.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;thumbnail-centered&quot; src=&quot;/PageFiles/617/place-in-page-tree.png&quot; alt=&quot;&quot; width=&quot;675&quot; height=&quot;341&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Why articles is stored this way is beyond the scope of this article but, as you can probably imagine, storing them this way brings a few problems.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Making the article&lt;/strong&gt; belong to the CMS category is straight forward. All that&#39;s needed is a property of type ContentReference or PageReference on the page type used for articles. That can then be used when building menus and breadcrumbs.&lt;/p&gt;
&lt;p&gt;Listing content based on categories is a bit trickier to achieve performance wise with the CMS&#39; API but in my case I have Find to help me with that.&lt;/p&gt;
&lt;p&gt;Finally, the URL for an article will be /&amp;lt;year&amp;gt;/&amp;lt;month&amp;gt;/&amp;lt;URLSegment&amp;gt;/. While that&#39;s not terrible it&#39;s not what I want. Instead I wanted the URL&#39;s for articles to be simply the host name followed by their URL segments.&lt;/p&gt;
&lt;h3&gt;Partial routing&lt;/h3&gt;
&lt;p&gt;EPiServer 7 features a concept called partial routing. In &lt;a href=&quot;/link/2f25082cc83c41c282edf9bf3ab743d1.aspx&quot;&gt;the developer guide&lt;/a&gt; it&#39;s described as&lt;/p&gt;
&lt;blockquote&gt;Partial routing makes it possible to extend routing beyond pages. You can use partial routing either to route to data outside EPiServer CMS or to route to other content types than pages.&lt;/blockquote&gt;
&lt;p&gt;We can however also use it to route ordinary pages, like articles in this case.&lt;/p&gt;
&lt;p&gt;To utilize partial routing we create a class implementing IPartialRouter&amp;lt;TContent, TRoutedData&amp;gt; found in the EPiServer.Web.Routing namespace. The first type parameter specifies the type of content we&#39;re interested in routing children for. The second the type of content, or other type of object that we&#39;ll be routing.&lt;/p&gt;
&lt;p&gt;Did I lose you there? Perhaps a fruity example can clarify things.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A class that implements&lt;/strong&gt; IPartialRouter&amp;lt;Banana, Apple&amp;gt; will be able to route outgoing URLs whenever the object to route is an apple. Whenever a part of the URL for an incoming request has been routed to a content object of type Banana and there are still parts of the URL left to route it will be handed the banana and information about the remaining URL and asked to return an apple.&lt;/p&gt;
&lt;p&gt;Crystal clear, right? Perhaps not. Let&#39;s look at how we can use it to route articles.&lt;/p&gt;
&lt;h3&gt;Implementing IPartialRouter&lt;/h3&gt;
&lt;p&gt;Given that we want articles to have relative URLs that are simply their URL segments the first type parameter when implementing IPartialRouter is the page type class that is used for the start page. The second type parameter is the page type used for articles.&lt;/p&gt;
&lt;p&gt;Let&#39;s create a class that implements IPartialRouter with those type parameters and have Visual Studio generate the required methods for us.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;using System.Web.Routing;&lt;br /&gt;using EPiServer.Web.Routing;&lt;br /&gt;using EPiServer.Web.Routing.Segments;&lt;br /&gt;using MySite.Models.Pages;&lt;br /&gt;&lt;br /&gt;namespace MySite.Routing&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; public class ArticleRouter : IPartialRouter&amp;lt;StartPage, ArticlePage&amp;gt;&lt;br /&gt;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public object RoutePartial(StartPage content, SegmentContext segmentContext)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new System.NotImplementedException();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public PartialRouteData GetPartialVirtualPath(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ArticlePage content, &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string language, &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; RouteValueDictionary routeValues,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; RequestContext requestContext)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new System.NotImplementedException();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, there are two methods that we&#39;ll need to implement. RoutePartial is for incoming requests while GetPartialVirtualPath is for outgoing.&lt;/p&gt;
&lt;p&gt;We&#39;ll start by implementing the RoutePartial method.&lt;/p&gt;
&lt;h3&gt;RoutePartial&lt;/h3&gt;
&lt;p&gt;The RoutePartial method will be invoked whenever a the first parts of the URL points to a page of the TContent type parameter and there are remaining parts of the URL left to route. In this example, as we&#39;re implementing the IPartialRouter interface with the start page&#39;s type as the TContent parameter that will pretty much always be the case.&lt;/p&gt;
&lt;p&gt;The method is invoked with two arguments. The first is the content of type TContent that the first parts of the URL route to, the start page in our case. The second is an object of type SegmentContext which contains information about the next segment in the URL to route.&lt;/p&gt;
&lt;p&gt;Using the two arguments it&#39;s our job to figure out what article, if any, the request should be routed to.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;public object RoutePartial(StartPage content, SegmentContext segmentContext)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; if (!content.ContentLink.CompareToIgnoreWorkID(ContentReference.StartPage))&lt;br /&gt;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return null;&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp; var nextSegment = segmentContext.GetNextValue(segmentContext.RemainingPath);&lt;br /&gt;&amp;nbsp; var urlSegment = nextSegment.Next;&lt;br /&gt;&amp;nbsp; if (string.IsNullOrEmpty(urlSegment))&lt;br /&gt;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return null;&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp; ArticlePage article = null;&lt;br /&gt;&lt;br /&gt;&amp;nbsp; //TODO: Figure out which article it is we&#39;re routing based on the urlSegment variable, if any, and populate the article variable with that.&lt;br /&gt;&lt;br /&gt;&amp;nbsp; if (article != null)&lt;br /&gt;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; segmentContext.RemainingPath = nextSegment.Remaining;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; segmentContext.RoutedContentLink = article.ContentLink;&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&amp;nbsp; &lt;br /&gt;&amp;nbsp; return article;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There&#39;s quite a few things going on in the above code.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;First of all it&lt;/strong&gt; verifies that the root content is indeed an object for which we want to route remaning parts of the URL. In other words, if we for some reason are dealing with a page of the StartPage type that is not the start page. Not likely when dealing with start pages perhaps, but stranger things have happened and this check may be vital in other scenarios.&lt;/p&gt;
&lt;p&gt;Next we proceed to retrieve the next part of the URL which we assign to the urlSegment variable. For an URL such as /hello-world/ the urlSegment variable&#39;s value will be &quot;hello-world&quot;. For an URL such as /hello/world/ the urlSegment variable&#39;s value will be &quot;hello&quot;.&lt;/p&gt;
&lt;p&gt;Given that there is indeed at least one more segment in the URL we proceed to locate an article whose URL segment matches that. As that&#39;s code specific to the site I&#39;ve omitted my implementation.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How one would do&lt;/strong&gt; this can vary greatly from site to site. On a small site we may simply retrieve all articles and use LINQ&#39;s Where method to find an article with a matching URLSegment property. On a larger site we may use EPiServer Find or we may make the page&#39;s ID a part of the URL when implementing outgoing routing which we&#39;ll get to shortly.&lt;/p&gt;
&lt;p&gt;However we choose to locate articles, or whatever it it we&#39;re routing, we need to make sure to do it in a good way performance wise. This code will be called &lt;em&gt;a lot&lt;/em&gt;!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Given that we&#39;ve&lt;/strong&gt; found an article that we wish to route to we remove the URL segment that we&#39;ve taken care of from the SegmentContext by assigning the remaning part of the URL to its RemainingPath property. That is, given an article with a URL such as /hello-world/ where we have extracted &quot;hello-world&quot; from the segment context we update it to set its remaining path to nothing.&lt;/p&gt;
&lt;p&gt;Also, given that we&#39;ve found an article, we modify the segment context so that it knows that we&#39;ve found content that we want to route to.&lt;/p&gt;
&lt;p&gt;Finally we return the article, or null, if we didn&#39;t find one. If we return null nothing in particular will happen. The routing will proceed as usual routing to a page of some other type or resulting in a 404.&lt;/p&gt;
&lt;h3&gt;GetPartialVirtualPath&lt;/h3&gt;
&lt;p&gt;The GetPartialVirtualPath method will be invoked when an article is being outgoing routed. That is, when we for instance create a link to an article with the PageLink HTML helper method.&lt;/p&gt;
&lt;p&gt;It&#39;s invoked with four arguments which we can use to determine the context in which the article is being routed. Based on those we need to return an object of type PartialRouteData.&lt;/p&gt;
&lt;p&gt;The PartialRouteData class has two properties - BasePathRoot and PartialVirtualPath. The generated relative URL will be a combination of the relative URL of the content referenced by BasePathRoot and whatever we set PartialVirtualPath to.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;public PartialRouteData GetPartialVirtualPath(&lt;br /&gt;&amp;nbsp; ArticlePage content, &lt;br /&gt;&amp;nbsp; string language, &lt;br /&gt;&amp;nbsp; RouteValueDictionary routeValues,&lt;br /&gt;&amp;nbsp; RequestContext requestContext)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; var contentLink = ContentRoute.GetValue(&quot;node&quot;, requestContext, routeValues) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; as ContentReference;&lt;br /&gt;&lt;br /&gt;&amp;nbsp; if (!content.ContentLink.CompareToIgnoreWorkID(contentLink))&lt;br /&gt;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return null;&lt;br /&gt;&amp;nbsp; }

  if (PageEditing.PageIsInEditMode)&lt;br /&gt;  {&lt;br /&gt;&amp;nbsp; &amp;nbsp; return null;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;&amp;nbsp; return new PartialRouteData&lt;br /&gt;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; BasePathRoot = ContentReference.StartPage,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; PartialVirtualPath = content.URLSegment&lt;br /&gt;&amp;nbsp; };&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;In the implementation&lt;/strong&gt; above we begin by extracting a reference to the content that is being routed using the ContentRoute.GetValue method. Typically this will be a reference to the same article that is being passed to the method as the &quot;content&quot; parameter. However, I&#39;ve found at least one situation when that wasn&#39;t the case.&lt;/p&gt;
&lt;p&gt;If the method is invoked in context of routing something else than the article passed in as the &quot;content&quot; variable we&#39;re not interested in modifying the routing so we simply return null.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Likewise, if the request is in context of EPiServer&#39;s edit mode we return null as we don&#39;t have any reason to modify the routing then. That is, we don&#39;t care what the URL is when the page is loaded into the CMS&#39;s IFrame and if we modify it things may not work as expected.&lt;/p&gt;
&lt;p&gt;If however we are dealing with an article that we want to modify the routing for we create a new PartialRouteData object, populate its properties and return it.&lt;/p&gt;
&lt;p&gt;Since in this example we want articles to simply have their own URL segments as URLs we set the BasePathRoot to a reference to the start page and the PartialVirtualPath to the article&#39;s URLSegment property.&lt;/p&gt;
&lt;h3&gt;Using the partial router&lt;/h3&gt;
&lt;p&gt;Our partial router class is done. In order for it to be used we need to add it to the site&#39;s route table during start-up though. That&#39;s easily done using an initialization module and the RegisterPartialRouter extension method that EPiServer provides (in the EPiServer.Web.Routing namespace).&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;using System.Web.Routing;&lt;br /&gt;using EPiServer.Framework;&lt;br /&gt;using EPiServer.Framework.Initialization;&lt;br /&gt;using EPiServer.Web.Routing;&lt;br /&gt;&lt;br /&gt;namespace MySite.Routing&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; [ModuleDependency(typeof(EPiServer.Web.InitializationModule))]&lt;br /&gt;&amp;nbsp; public class RouteInitialization : IInitializableModule&lt;br /&gt;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void Initialize(InitializationEngine context)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var articleRouter = new ArticleRouter();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; RouteTable.Routes.RegisterPartialRouter(articleRouter);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void Uninitialize(InitializationEngine context)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void Preload(string[] parameters)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Restoring tree-like URLs&lt;/h3&gt;
&lt;p&gt;In the above example we modify EPiServer&#39;s default routing to make pages of a specific type, articles, have URLs that are simply their URL segments. That&#39;s what I wanted for this site as it decouples article&#39;s URLs from both their place in the tree and their categories.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;thumbnail-centered&quot; src=&quot;/PageFiles/617/startpage_as_url_root.png&quot; alt=&quot;&quot; width=&quot;718&quot; height=&quot;319&quot; /&gt;&lt;/p&gt;
&lt;p&gt;However, we&#39;re not limited to that specific use case. For instance we may instead want articles in the example scenario we&#39;ve looked at here to have a URL based on their categories instead. As if they were actually placed under their categories in the page tree.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;thumbnail-centered&quot; src=&quot;/PageFiles/617/category_as_url_root.png&quot; alt=&quot;&quot; width=&quot;718&quot; height=&quot;319&quot; /&gt;&lt;/p&gt;
&lt;p&gt;To accomplish that we would need to make a few modifications to our partial router class.&lt;/p&gt;
&lt;p&gt;Since the &quot;URL homes&quot;, the base path, for articles won&#39;t be the start page but instead a categories the first step is to modify the TContent type parameter when implementing IPartialRouter. Instead of the start page&#39;s type we set it to the type under which articles will reside URL-wise. In the case of this site that would be the class CategoryPage.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;public class ArticleRouter : IPartialRouter&amp;lt;&lt;strong&gt;CategoryPage&lt;/strong&gt;, ArticlePage&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Changing the type parameter of the implemented interface we need to change the type of the RoutePartial method&#39;s first parameter or the compiler will complain.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;public object RoutePartial(&lt;strong&gt;CategoryPage&lt;/strong&gt; content, SegmentContext segmentContext)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now the compiler is happy but we&#39;ll need to make some changes to the code as well. Let&#39;s start with the GetPartialVirtualPath method as that&#39;s easiest.&lt;/p&gt;
&lt;p&gt;All we need to do there is change what we set the BasePathRoot property on the object we return to. Instead of setting it to a reference to the start page we set it to a reference to some other page that will provide the first part of the article&#39;s URL. For our example scenario that would be the property that points to the article&#39;s main category.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;return new PartialRouteData&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; BasePathRoot = &lt;strong&gt;content.MainCategory&lt;/strong&gt;,&lt;br /&gt;&amp;nbsp; PartialVirtualPath = content.URLSegment&lt;br /&gt;};&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The RoutePartial method will need to undergo larger changes.&lt;/p&gt;
&lt;p&gt;We can skip the initial check that the root content which is passed in in as the &quot;content&quot; variable is indeed the root page we care about as we now have multiple possible roots.&lt;/p&gt;
&lt;p&gt;Instead we&#39;ll need to verify that the root, the category, should be used as the routing parent for the article that we&#39;re routing.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;ArticlePage article = null;&lt;br /&gt;&lt;br /&gt;//TODO: Figure out which article it is we&#39;re routing based on the urlSegment variable, if any, and populate the article variable with that.&lt;br /&gt;&lt;br /&gt;if (article == null &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; || &lt;strong&gt;content.ContentLink.CompareToIgnoreWorkID(article.MainCategory)&lt;/strong&gt;)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; return null;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;segmentContext.RemainingPath = nextSegment.Remaining;&lt;br /&gt;segmentContext.RoutedContentLink = article.ContentLink;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;return article;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Custom routing using a custom segment&lt;/h2&gt;
&lt;p&gt;We&#39;ve now seen an example of how we can use the partial routing concept in EPiServer 7 to implement custom routing. In the next example we&#39;ll look at another way of customizing routing - by using a custom implementation of the ISegment interface.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;On this site I use&lt;/strong&gt; pages to define tags. That is, each tag is a page somewhere in the page tree and articles have a content area to which I can add one or more tag pages. This allows me to change the name of a tag without having to update all pages tagged with it. It also gives me the possibility to add unique content to a tag beyond its name.&lt;/p&gt;
&lt;p&gt;When I tag a page with one or more existing tags I simply drag them to the content area. When I render a list of tags I simply output a link to each tag using the PageLink HTML helper.&lt;/p&gt;
&lt;p&gt;As I have a separate template for tag pages this works great. However, when the site first went live I didn&#39;t have that template. Instead I wanted a tag-link to point to a search for the tag using the site&#39;s search page.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;thumbnail-centered&quot; src=&quot;/PageFiles/617/tag_search_url.png&quot; alt=&quot;&quot; width=&quot;718&quot; height=&quot;367&quot; /&gt;&lt;/p&gt;
&lt;p&gt;One way to solve that would of course have been to find all places where links to tags were rendered and modify the code there to link to the search page. That wouldn&#39;t have been a very flexible solution though. By instead modifying the outgoing URLs for tag pages by modifying routing for them I didn&#39;t have to touch any other code.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;At first glance it&lt;/strong&gt; may seem like we could use partial routing for this scenario as well but a case like this, where we want to route to a specific page with one or more query string parameters isn&#39;t really what partial routing is for.&lt;/p&gt;
&lt;p&gt;Instead we can handle cases like this by creating a custom implementation of the ISegment interface and register a&amp;nbsp; route that uses the segment.&lt;/p&gt;
&lt;h3&gt;Creating a segment&lt;/h3&gt;
&lt;p&gt;In order to create a custom segment we create a class that implements ISegment (in the EPiServer.Web.Routing.Segments namespace). Alternatively we can let our class inherit SegmentBase which I&#39;ll do in this example.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;using System;&lt;br /&gt;using System.Web.Routing;&lt;br /&gt;using EPiServer.Web.Routing.Segments;&lt;br /&gt;&lt;br /&gt;namespace MySite.Routing&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; public class TagSearchSegment : SegmentBase&lt;br /&gt;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public TagSearchSegment(string name) : base(name)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public override bool RouteDataMatch(SegmentContext context)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new NotImplementedException();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public override string GetVirtualPathSegment(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; RequestContext requestContext, &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; RouteValueDictionary values)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new NotImplementedException();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see from the code above, where I&#39;ve had Visual Studio autogenerate required methods for me, SegmentBase has two abstract methods that we must implement - RouteDataMatch and GetVirtualPathSegment.&lt;/p&gt;
&lt;p&gt;RouteDataMatch is invoked during in-bound routing. We get passed information about the current context and can use that to determine if we want to modify the routing. If we do we modify the context in some way and return true. However, as we only care about out-bound routing in this example we can simply implement it to return false.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;public override bool RouteDataMatch(SegmentContext context)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; return false;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;GetVirtualPathSegment&lt;/h3&gt;
&lt;p&gt;The GetVirtualPathSegment method is invoked during outgoing routing and in order to modify the URL we&#39;ll need to return a string with the URL, or part of the URL, that we want to route to. We&#39;ll also need to remove values that we feel we&#39;ve taken care of from the RouteValueDictionary that is passed to the method.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;public override string GetVirtualPathSegment(&lt;br /&gt;&amp;nbsp; RequestContext requestContext, &lt;br /&gt;&amp;nbsp; RouteValueDictionary values)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; if (GetContextMode(requestContext.HttpContext, requestContext.RouteData) &lt;br /&gt;      != ContextMode.Default)&lt;br /&gt;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return null;&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp; var contentLink = ContentRoute.GetValue(&quot;node&quot;, requestContext, values) &lt;br /&gt;                      as ContentReference;&lt;br /&gt;&lt;br /&gt;&amp;nbsp; if (ContentReference.IsNullOrEmpty(contentLink))&lt;br /&gt;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return null;&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp; var contentLoader = ServiceLocator.Current.GetInstance&amp;lt;IContentLoader&amp;gt;();&lt;br /&gt;&amp;nbsp; var tagToRoute = contentLoader.Get&amp;lt;IContent&amp;gt;(contentLink) as TagPage;&lt;br /&gt;&amp;nbsp; if (tagToRoute == null)&lt;br /&gt;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return null;&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp; string tagSearchUrl = null;&lt;br /&gt;&lt;br /&gt;&amp;nbsp; //TODO: Figure out the url we want to route to, if any, and set the tagSearchUrl variable to that&lt;br /&gt;&lt;br /&gt;&amp;nbsp; if (tagSearchUrl == null)&lt;br /&gt;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return null;&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp; values.Remove(&quot;node&quot;);&lt;br /&gt;&amp;nbsp; values.Remove(&quot;controller&quot;);&lt;br /&gt;&amp;nbsp; values.Remove(&quot;action&quot;);&lt;br /&gt;&amp;nbsp; values.Remove(&quot;routedData&quot;);&lt;br /&gt;&lt;br /&gt;&amp;nbsp; return tagSearchUrl;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&#39;s quite a mouthful! Let&#39;s go through it step by step.&lt;/p&gt;
&lt;p&gt;First we check that we&#39;re not in edit mode using a helper method. This is necessary as we will otherwise get a 404,&amp;nbsp; or worse, when viewing tag pages in edit mode as our code will route to the search page while EPiServer will add the tag&#39;s ID to the URL, meaning that we&#39;ll end up viewing invoking the search page&#39;s template with the tag page as the current page.&lt;/p&gt;
&lt;p&gt;The GetContextMode method looks like this:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;private static ContextMode GetContextMode(&lt;br /&gt;&amp;nbsp; HttpContextBase httpContext, &lt;br /&gt;&amp;nbsp; RouteData routeData)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; var contextModeKey = &quot;contextmode&quot;;&lt;br /&gt;&amp;nbsp; if (routeData.DataTokens.ContainsKey(contextModeKey))&lt;br /&gt;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return (ContextMode)routeData.DataTokens[contextModeKey];&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&amp;nbsp; if ((httpContext == null) || (httpContext.Request == null))&lt;br /&gt;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return ContextMode.Default;&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&amp;nbsp; if (!PageEditing.GetPageIsInEditMode(httpContext))&lt;br /&gt;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return ContextMode.Default;&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&amp;nbsp; return ContextMode.Edit;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next we proceed to extract a reference to the content that is being  routed. If we can&#39;t find such a reference we&#39;re probably routing a file  or something else that we don&#39;t care about so we return null.&lt;/p&gt;
&lt;p&gt;Given that we have a content reference we proceed to fetch the content that we&#39;re routing. If it isn&#39;t a tag we don&#39;t care about it so we return null.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;If however the&lt;/strong&gt; content that we&#39;re routing is a tag we build up the URL we want to route to. I&#39;ve omitted that code as it may be specific to each site and use case.&lt;/p&gt;
&lt;p&gt;Given that we have a URL that we want to route to we return it, but before doing so we remove route values that we don&#39;t want anyone else who cares about routing to see as we&#39;ve already taken care of them.&lt;/p&gt;
&lt;h3&gt;Using the segment&lt;/h3&gt;
&lt;p&gt;With the custom segment done we need to register a route that uses it for it to matter. As this should be done during start-up of the site we add an initialization module.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;using System.Collections.Generic;&lt;br /&gt;using System.Web.Routing;&lt;br /&gt;using EPiServer.Framework;&lt;br /&gt;using EPiServer.Framework.Initialization;&lt;br /&gt;using EPiServer.Web.Routing;&lt;br /&gt;using EPiServer.Web.Routing.Segments;&lt;br /&gt;&lt;br /&gt;namespace MySite.Routing&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; [ModuleDependency(typeof(EPiServer.Web.InitializationModule))]&lt;br /&gt;&amp;nbsp; public class RouteInitialization : IInitializableModule&lt;br /&gt;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void Initialize(InitializationEngine context)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var segment = new TagSearchSegment(&quot;tag&quot;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var routingParameters = new MapContentRouteParameters()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SegmentMappings = new Dictionary&amp;lt;string, ISegment&amp;gt;()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; };&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; routingParameters.SegmentMappings.Add(&quot;tag&quot;, segment);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; RouteTable.Routes.MapContentRoute(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; name: &quot;tags&quot;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; url: &quot;{language}/{tag}&quot;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; defaults: new { action = &quot;index&quot; },&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; parameters: routingParameters);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void Uninitialize(InitializationEngine context)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void Preload(string[] parameters)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Using the code in the Initialize method above we register a route for &quot;{language}/{tag}&quot;. We map the {tag} part to our custom segment meaning that it will be replaced with whatever we return from the segment&#39;s GetVirtualPathSegment method.&lt;/p&gt;
&lt;h2&gt;Basic routing&lt;/h2&gt;
&lt;p&gt;We&#39;ve just seen two fairly advanced examples of how the routing for content can be customized when using EPiServer 7. In both cases we&#39;re more or less in complete control and can execute custom logic on a per-request basis.&lt;/p&gt;
&lt;p&gt;That&#39;s nice, but there may be cases where we want to do something simpler. Were we don&#39;t need all that power and flexibility. For instance, let&#39;s say we for some reason wanted to support outputting only the first n characters of the name of a page given that the request is for a page followed by /name/&amp;lt;n&amp;gt;/.&lt;/p&gt;
&lt;p&gt;Not the most realistic scenario perhaps, but it does make for a simple example. Anyhow, To handle such a case we wouldn&#39;t have to create a partial router or a custom segment. All we need to do is register a route using the MapContentRoute method during start-up.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;RouteTable.Routes.MapContentRoute(&lt;br /&gt;&amp;nbsp; &quot;myRoute&quot;, &quot;{language}/{node}/{action}/{charcount}&quot;, &lt;br /&gt;&amp;nbsp; new {action = &quot;name&quot;});&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, given that we&#39;re using MVC, we can add an action to controllers for pages named Name which will be used for matching requests.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;public ActionResult Name(CategoryPage currentPage, int charCount)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; if (currentPage.PageName.Length &amp;lt; charCount)&lt;br /&gt;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; charCount = currentPage.PageName.Length;&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&amp;nbsp; return new ContentResult()&lt;br /&gt;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Content = currentPage.PageName.Substring(0, charCount)&lt;br /&gt;&amp;nbsp; };&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img class=&quot;thumbnail-centered&quot; src=&quot;/PageFiles/617/name_routing.png&quot; alt=&quot;&quot; width=&quot;511&quot; height=&quot;207&quot; /&gt;&lt;/p&gt;
&lt;p&gt;For another example of this type of custom routing check the &lt;a href=&quot;/link/93f6e76b807943689b9aedef019fc067.aspx&quot;&gt;routing section&lt;/a&gt; in EPiServer&#39;s developers guide.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;We&#39;ve seen a couple of examples of how we can take charge of the routing for specific types of content. With this in our toolbox we can free the URLs for pages from the content tree, change where pages links to as well as other interesting stuff.&lt;/p&gt;
&lt;p&gt;A couple of words of warning is in place though.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;First of all, when&lt;/strong&gt; modifying both the outbound and inbound routing as in the first example, the one with articles, we&#39;re bypassing EPiServer&#39;s functionality for ensuring that no two pages can have the same URL. That is, in the example with the articles we&#39;ll need to ensure that no two articles have the same URL segment.&lt;/p&gt;
&lt;p&gt;Second, do think about that the methods for routing, such as the ones we&#39;ve looked at in this article may be invoked a lot, so be sure to test the performance with realistic data before deploying to production.&lt;/p&gt;
&lt;p&gt;With that said, I must say that it&#39;s nice that we can control the routing in just about any way we&#39;d like. That brings many interesting possibilities.&lt;/p&gt;
&lt;p&gt;Happy routing!&lt;/p&gt;
</id><updated>2013-04-09T06:30:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Slice your EPiServer content with PowerSlice!</title><link href="http://joelabrahamsson.com/slice-your-episerver-content-with-powerslice/" /><id>Lately I&#39;ve been working on a little module for EPiServer CMS for listing and creating contents in other ways than using the page tree. I call it PowerSlice and it&#39;s now available for download.
&lt;p&gt;&lt;em&gt;Want to get slicing right away or prefer a short introduction video? Check out &lt;a href=&quot;/link/c307dee82d384e9cbfa436f08a8b949d.aspx?id=509&amp;amp;epslanguage=en&quot;&gt;PowerSlice&#39;s site&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Content manangement using EPiServer CMS is largely based on a hierarchical structure - the content tree. Pages is organized in the page tree and blocks in folders.&lt;/p&gt;
&lt;p&gt;This hierarchy is great in many ways. By using the hierarchy as data source for navigation and listing components when developing templates editors are free to organize the site&#39;s content in a flexible way while not having to call on developers to modify functionality for navigation components and the like.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;However, not all&lt;/strong&gt; content fits naturally into a hierarchical structure. On a medium sized corporate websites most of the content is naturally fitted into a hierarchical structure - but then there&#39;s the news room and the corporate blog.&lt;/p&gt;
&lt;p&gt;Such content may share a natural first level parent but other than that there may not be anything specific that groups the content into a hierarchy. At least not naturally.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;On other types of&lt;/strong&gt; sites, such as media sites and blogs, almost none of the content can be fitted into a deep hierarchical structure. Instead sections, categories and keywords/tags is used to create the site&#39;s taxonomy and navigation.&lt;/p&gt;
&lt;h2&gt;Freeing content from the content tree using Find&lt;/h2&gt;
&lt;p&gt;EPiServer CMS doesn&#39;t handle such content very well out of the box. Luckily EPiServer Find provides the perfect compliment. Using Find we as developers can easily list all content in a specific category no matter of where it&#39;s located in the content tree. Or all content tagged with a given combination of tags.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;By using Find we&lt;/strong&gt; can easily build templates without a dependency on the page tree. However, in order to easily work with content that isn&#39;t easily grouped using a tree structure editors need some help. Find can come to the rescue here as well, but we as developers will need to extend EPiServer&#39;s user interface.&lt;/p&gt;
&lt;h3&gt;Freeing editors from the content tree using PowerSlice&lt;/h3&gt;
&lt;p&gt;I&#39;ve worked quite a lot with media sites using EPiServer. I&#39;ve also built this site, which features articles classified by categories and tags rather than a hierarchy, on EPiServer.&lt;/p&gt;
&lt;p&gt;Therefor, to make it easier to handle non-hierarchical content and illustrate how media sites, news room functionality or blogs can be built using EPiServer CMS and Find I&#39;ve created an extension module that makes it easy to list content matching a defined set of criteria. Each such listing is called a &quot;slice&quot;. Why? It&#39;s a slice of the site&#39;s content tree.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A slice may be&lt;/strong&gt; all pages or blocks of a given type. Or it may be all content created by the user. Or all content who&#39;s status is &quot;ready to publish&quot;. Or...&lt;/p&gt;
&lt;p&gt;All content in a slice is listed using &quot;infinite&quot; scrolling. Editors can filter it using free text search and sort it, by default either by name or by publish date.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;thumbnail-centered&quot; src=&quot;/PageFiles/591/slices-from-alloy.png&quot; alt=&quot;&quot; width=&quot;271&quot; height=&quot;230&quot; /&gt;&lt;/p&gt;
&lt;p&gt;When creating a slice the developer can also add one or several ways to create new content, typically within the slice. For instance if a slice lists all content of a number of page types used for articles the editor can use it to select one of those page types, enter a name and hit the Create button and a new page will be created at a predefined location in the page tree.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;thumbnail-centered&quot; src=&quot;/PageFiles/591/creating-content-in-slice.png&quot; alt=&quot;&quot; width=&quot;379&quot; height=&quot;153&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Besides enabling new and improved workflows for editors (and developers) PowerSlice can also be used for exposing custom content types. That is, instances of custom types implementing IContent which won&#39;t be displayed in the page tree or blocks gadget.&lt;/p&gt;
&lt;h2&gt;Download and documentation&lt;/h2&gt;
&lt;p&gt;The source code for PowerSlice, which is a number of C# classes, JavaScript files and HTML-templates used by the JavaScript components is &lt;a title=&quot;PowerSlice source code on GitHub&quot; href=&quot;https://github.com/joelabrahamsson/PowerSlice&quot;&gt;located on GitHub&lt;/a&gt;. The module is also packaged as a NuGet package available on &lt;a title=&quot;EPiServer&#39;s NuGet feed&quot; href=&quot;http://nuget.episerver.com&quot;&gt;EPiServer&#39;s NuGet feed&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Creating a slice is easy. In it&#39;s simplest form all we need to do is create a class with a single string property returning the slice&#39;s name. Meanwhile, should we want to we can customize the slice to apply filtering, specify the default sort option, add additional sort options, add ways to create content etc.&lt;/p&gt;
&lt;p&gt;Documentation as well as a video introducing what PowerSlice is can be found &lt;a title=&quot;PowerSlice documentation and video&quot; href=&quot;/link/c307dee82d384e9cbfa436f08a8b949d.aspx?id=509&amp;amp;epslanguage=en&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Happy slicing!&lt;/strong&gt;&lt;/p&gt;
</id><updated>2013-03-27T05:00:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Localization in widgets used as EPiServer gadgets or property editors</title><link href="http://joelabrahamsson.com/localization-in-widgets-used-as-episerver-gadgets-or-property-editors/" /><id>&lt;p&gt;Given a language resource file like this:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&amp;gt;&lt;br /&gt;&amp;lt;languages&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;language name=&quot;English&quot; id=&quot;en&quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;mystuff&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;substuff&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;key&amp;gt;Value&amp;lt;/key&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/substuff&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/mystuff&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;/language&amp;gt;&lt;br /&gt;&amp;lt;/languages&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The node &quot;mystuff&quot; can be accessed in a JavaScript UI-component such as a gadget or custom editor using require and the i18n module, like this:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;define([&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &quot;epi/i18n!epi/cms/nls/mystuff&quot;&lt;br /&gt;], function (&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; resources&lt;br /&gt;) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return declare(&quot;&quot;, [], {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; resources: resources,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; });&lt;br /&gt;});&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The resources variable will be an object like this:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; substuff: {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; key: &quot;value&quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To instead retrieve only the &quot;substuff&quot; element the required module can be modified to epi/i18n!epi/cms/nls/mystuff.substuff.&lt;/p&gt;
&lt;p&gt;To output a localized resource like &quot;key&quot; above in a template the following can be used:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;${resources.substuff.key}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
</id><updated>2013-03-24T20:45:03.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Specifying drag-n-drop support in custom EPiServer editor descriptor</title><link href="http://joelabrahamsson.com/specifying-drag-n-drop-support-in-custom-episerver-editor-descriptor/" /><id>&lt;p&gt;Editor descriptors can be used to change how a property, or properties of a given type, is edited. One such example is described in my article about &lt;a href=&quot;/link/0ce0d801c6594c9c9384409475d388bd.aspx?id=281&amp;amp;epslanguage=en&quot;&gt;how to let editors populate content reference properties using dropdowns&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;When using an editor that doesn&#39;t support drag-n-drop the drag-n-drop functionality can be restored by specifying a drop target type in the editor descriptor. Example:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;public override void ModifyMetadata(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ExtendedMetadata metadata, &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IEnumerable&amp;lt;System.Attribute&amp;gt; attributes)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; base.ModifyMetadata(metadata, attributes);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; metadata.AdditionalValues[&quot;DropTargetType&quot;] = new[] { &quot;epi.cms.pagereference&quot; };&lt;br /&gt;} &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Similarly for files the drop target type can be set to &quot;fileurl&quot;:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;metadata.AdditionalValues[&quot;DropTargetType&quot;] = new [] { &quot;fileurl&quot; };&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To restrict the type of content that can be dropped to pages the editor descriptors EditorConfiguration property can be used:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;EditorConfiguration[&quot;typeIdentifiers&quot;] = &quot;epi.cms.page&quot;;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If the editor descriptor is for a block type used as a property what property in the block to map the dropped item to can be specified using:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;metadata.AdditionalValues[&quot;DropTargetChildProperty&quot;] = &quot;LinkedPage&quot;;&lt;/code&gt;&lt;/pre&gt;
</id><updated>2013-03-18T21:45:07.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>List of EPiServer content interfaces and properties</title><link href="http://joelabrahamsson.com/list-of-episerver-content-interfaces-and-properties/" /><id>&lt;table class=&quot;table&quot; border=&quot;0&quot;&gt;
&lt;thead&gt; 
&lt;tr&gt;
&lt;th&gt;&amp;nbsp;Interface&lt;/th&gt; &lt;th&gt;Member&lt;br /&gt;&lt;/th&gt; &lt;th&gt;Type &lt;br /&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt; 
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;IContentData&lt;/td&gt;
&lt;td&gt;Property &lt;br /&gt;&lt;/td&gt;
&lt;td&gt;PropertyDataCollection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IInitializableContent&lt;/td&gt;
&lt;td&gt;SetDefaultValues(ContentType)&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IModifiedTrackable&lt;/td&gt;
&lt;td&gt;ResetModified()&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IModifiedTrackable&lt;/td&gt;
&lt;td&gt;IsModified&lt;/td&gt;
&lt;td&gt;bool &lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IReadOnly &lt;br /&gt;&lt;/td&gt;
&lt;td&gt;CreateWritableClone() &lt;br /&gt;&lt;/td&gt;
&lt;td&gt;object&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IReadOnly&lt;/td&gt;
&lt;td&gt;MakeReadOnly()&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IReadOnly&lt;/td&gt;
&lt;td&gt;IsReadOnly&lt;/td&gt;
&lt;td&gt;bool &lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IReadOnly&amp;lt;T&amp;gt; &lt;br /&gt;&lt;/td&gt;
&lt;td&gt;CreateWritableClone&amp;lt;T&amp;gt; &lt;br /&gt;&lt;/td&gt;
&lt;td&gt;T &lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IContentSecurable&lt;/td&gt;
&lt;td&gt;GetContentSecurityDescriptor() &lt;br /&gt;&lt;/td&gt;
&lt;td&gt;IContentSecurityDescriptor&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ISecurable&lt;/td&gt;
&lt;td&gt;GetSecurityDescriptor() &lt;br /&gt;&lt;/td&gt;
&lt;td&gt;ISecurityDescriptor &lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IContent &lt;br /&gt;&lt;/td&gt;
&lt;td&gt;ContentGuid&lt;/td&gt;
&lt;td&gt;Guid &lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IContent&lt;/td&gt;
&lt;td&gt;ContentLink&lt;/td&gt;
&lt;td&gt;ContentReference &lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IContent &lt;br /&gt;&lt;/td&gt;
&lt;td&gt;ContentTypeID&lt;/td&gt;
&lt;td&gt;int &lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IContent&lt;/td&gt;
&lt;td&gt;IsDeleted&lt;/td&gt;
&lt;td&gt;bool &lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IContent&lt;/td&gt;
&lt;td&gt;Name&lt;/td&gt;
&lt;td&gt;string &lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IContent&lt;/td&gt;
&lt;td&gt;ParentLink&lt;/td&gt;
&lt;td&gt;ContentReference &lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ILocalizable&lt;/td&gt;
&lt;td&gt;ExistingLanguages&lt;/td&gt;
&lt;td&gt;IEnumerable&amp;lt;CultureInfo&amp;gt; &lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ILocalizable&lt;/td&gt;
&lt;td&gt;Language&lt;/td&gt;
&lt;td&gt;CultureInfo &lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ILocalizable&lt;/td&gt;
&lt;td&gt;MasterLanguage &lt;br /&gt;&lt;/td&gt;
&lt;td&gt;CultureInfo &lt;br /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IVersionable&lt;/td&gt;
&lt;td&gt;IsPendingPublish&lt;/td&gt;
&lt;td&gt;bool&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IVersionable&lt;/td&gt;
&lt;td&gt;StartPublish&lt;/td&gt;
&lt;td&gt;DateTime?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IVersionable&lt;/td&gt;
&lt;td&gt;Status&lt;/td&gt;
&lt;td&gt;VersionStatus&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IVersionable&lt;/td&gt;
&lt;td&gt;StopPublish&lt;/td&gt;
&lt;td&gt;DateTime?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IResourceable&lt;/td&gt;
&lt;td&gt;ContentFolderID&lt;/td&gt;
&lt;td&gt;long&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IChangeTrackable&lt;/td&gt;
&lt;td&gt;Changed&lt;/td&gt;
&lt;td&gt;DateTime&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IChangeTrackable&lt;/td&gt;
&lt;td&gt;ChangedBy&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IChangeTrackable&lt;/td&gt;
&lt;td&gt;Created&lt;/td&gt;
&lt;td&gt;DateTime&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IChangeTrackable&lt;/td&gt;
&lt;td&gt;CreatedBy&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IChangeTrackable&lt;/td&gt;
&lt;td&gt;Deleted&lt;/td&gt;
&lt;td&gt;DateTime?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IChangeTrackable&lt;/td&gt;
&lt;td&gt;DeletedBy&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IChangeTrackable&lt;/td&gt;
&lt;td&gt;Saved&lt;/td&gt;
&lt;td&gt;DateTime&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IChangeTrackable&lt;/td&gt;
&lt;td&gt;SetChangedOnPublish&lt;/td&gt;
&lt;td&gt;bool&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IRoutable&lt;/td&gt;
&lt;td&gt;RouteSegment&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ICategorizable&lt;/td&gt;
&lt;td&gt;Category&lt;/td&gt;
&lt;td&gt;CategoryList&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IExportable&lt;/td&gt;
&lt;td&gt;ShouldBeImplicitlyExported&lt;/td&gt;
&lt;td&gt;bool&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
</id><updated>2013-03-18T21:05:11.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>EPiServer and MVC – What is the view model?</title><link href="http://joelabrahamsson.com/episerver-and-mvc-what-is-the-view-model/" /><id>Perhaps the most discussed and debated question of all when it comes to EPiServer and ASP.NET MVC development is “What is the view model?” Here&#39;s my thoughts on the subject and the reasoning behind the path chosen in the Alloy templates.
&lt;p&gt;In &lt;a href=&quot;/link/4e3e6d68067b4c288327d2716ee0af70.aspx&quot;&gt;my article&lt;/a&gt; about the MVC templates for EPiServer 7 I wrote&lt;/p&gt;
&lt;blockquote&gt;&quot;&lt;span&gt;Perhaps the most discussed question of all when it comes to EPiServer and MVC development is &#39;What is the model?&#39; This is a multifaceted question, which could easily make this article very long. Hence, I will leave the background discussion for a later article or blog post&quot;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p&gt;In this article I&#39;ll follow up on that with both the background reasoning for what types of models are passed to views from controllers in the MVC templates, as well as general thoughs about (view) models when working with EPiServer CMS and ASP.NET MVC.&lt;/p&gt;
&lt;h2&gt;To use view models or not to use view models&lt;/h2&gt;
&lt;p&gt;Should we use a separate view model or simply pass PageData/BlockData to the view? In general ASP.NET MVC development it’s a well established best practice, at least in larger projects, to use separate view models. There are four commonly used arguments for this approach:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;By creating a model to the needs of the view we can keep the view simple and free from complex logic.&lt;/li&gt;
&lt;li&gt;By creating a view model we can create unit tests for the logic that takes domain models or other data as arguments and returns the data needed by the view.&lt;/li&gt;
&lt;li&gt;By using separate view models we can change the domain models without having to change the view models and vice versa.&lt;/li&gt;
&lt;li&gt;Model binding in ASP.NET MVC is vulnerable to mass assignment attacks and using a separate view model can prevent that.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;All of the above arguments are of course valid but also context specific.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;For instance, a page&lt;/strong&gt; type is often already designed with the needs of the view in mind. We’re after all using a content management system in which the domain objects represent content intended to be displayed using templates.&lt;/p&gt;
&lt;p&gt;That is, in many, but not all, scenarios a view, no matter if it’s MVC or Web Forms, simply renders properties from a PageData or BlockData object. In such cases there’s also no logic to test meaning that the second argument doesn’t make much sense in this context.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Using view models&lt;/strong&gt; to be able to change domain models without having to update views, or vice versa, is an attractive idea from an architectural standpoint. It does come at a steep price however, as it requires a lot of code for mapping CMS content objects to view models.&lt;/p&gt;
&lt;p&gt;While that can be handled by mapping frameworks such as AutoMapper we’d still be forced to write more code whenever we want to add a new property to a content type that should be displayed in the view, as we’d then have to update the page or block type as well as the view model.&lt;/p&gt;
&lt;p&gt;Also, designing for future changes which &lt;em&gt;may&lt;/em&gt; happen is a case of Big Design Up Front. Often the code that hasn’t been written yet is most easy to change.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Finally, while mass&lt;/strong&gt; assignment is a very real threat when using ASP.NET MVC the model binding of CMS content is handled by EPiServer and EPiServer sites rarely have code in which non-trusted users are allowed to create or modify pages or blocks.&lt;/p&gt;
&lt;p&gt;For these reasons the MVC template does allow them selves to use pages and blocks as view models when doing so offers the path of least resistance.&lt;/p&gt;
&lt;p&gt;There is however another aspect of the underlying “What is the model” question – how to handle data needed by the overall layout rather than the specific view.&lt;/p&gt;
&lt;h2&gt;Framework components&lt;/h2&gt;
&lt;p&gt;Let’s review one of the pages from the Alloy site below.&lt;/p&gt;
&lt;p&gt;It’s pretty obvious that the headline, text and form is unique for this page and therefor something that the rendering view should handle. But what about the header and footer?&lt;/p&gt;
&lt;p&gt;There’s clearly quite a lot of data being displayed there but hardly any of it is related to the specific page. As for the breadcrumb and sub navigation those are both tied to the current pages location in the page tree but we can probably all agree that we wouldn’t like each page type specific controller or view to have to care about them.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;thumbnail-centered&quot; src=&quot;/PageFiles/551/Alloy_model_cropped.png&quot; alt=&quot;&quot; width=&quot;700&quot; height=&quot;720&quot; /&gt;&lt;/p&gt;
&lt;p&gt;While handling such “framework” components is straightforward using master pages and user controls in Web Forms there’s no clear-cut solution when using ASP.NET MVC. There are however a number of possible solutions which each can be grouped into one of two general patterns:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Use a base class for view models with properties needed by the sites framework. Such properties can then be rendered in layout files, optionally using partial views. &amp;nbsp;&lt;/li&gt;
&lt;li&gt;Use child actions in layouts to render framework components such as navigations. Each child action, invoked by the Action or RenderAction HTML helpers, can then figure out the current page by looking at the request context.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Coming from Web&lt;/strong&gt; Forms development where user controls is frequently used the second approach is attractive.&amp;nbsp;By using child actions we can compose each page by using a number of stand alone components without any dependencies between them.&lt;/p&gt;
&lt;p&gt;However, each child action will spawn a full MVC cycle, which is costly performance wise.&amp;nbsp;Each such action would also have to figure out the current page context, which is rather tedious and possibly error prone.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The first approach&lt;/strong&gt; requires that all actions responsible for pages populate common properties of the view model.&amp;nbsp;While that can be handled by using a base class for controllers with such actions we would end up with, possibly complex, inheritance hierarchies not only for view models but also for controllers.&lt;/p&gt;
&lt;h2&gt;View models in the MVC templates&lt;/h2&gt;
&lt;p&gt;Based on the reasoning about the necessity, or lack of such, for separate view models and the need for almost the exact same context in layouts and navigation components used in most views the solution in the MVC templates is to pass the current page object to the view along side data needed by framework components. This is done using a base class, or rather an interface to utilize generic variance.&lt;/p&gt;
&lt;h3&gt;IPageViewModel&lt;/h3&gt;
&lt;p&gt;&lt;img class=&quot;thumbnail pull-right&quot; src=&quot;/PageFiles/551/IPageViewModel.png&quot; alt=&quot;&quot; width=&quot;178&quot; height=&quot;112&quot; /&gt;All non-partial views and layouts in the MVC templates uses a model of type IPageViewModel&amp;lt;T&amp;gt;. The type parameter T has to be a descendent of PageData.&lt;/p&gt;
&lt;p&gt;The interface defines a CurrentPage property of type T as well a couple of properties intended to provide context to layouts and framework components such as navigation elements.&lt;/p&gt;
&lt;p&gt;The idea behind this solution is that all views, and especially their layout files, can rely on some common characteristics of the view model.&lt;/p&gt;
&lt;h3&gt;Populating context properties&lt;/h3&gt;
&lt;p&gt;To free controllers from having to populate these common properties of the view model an action filter named PageViewContextActionFilter is registered globally at start up. This filter inspects the view model which is about to be passed to the view and, given that it’s of type IPageViewModel, sets the common properties required by the sites framework.&lt;/p&gt;
&lt;p&gt;By using this approach each action for a page can use it’s own specific view model as long as it implements IPageViewModel without having to care about populating common properties.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;At the same time&lt;/strong&gt; the logic for populating such common properties have been moved out from the sites controllers into a specific class responsible for framework components, which can be modified and tested without having to deal with controllers.&lt;/p&gt;
&lt;p&gt;Should a specific controller or action want to influence the common properties of the view model it can do so by populating them on the view model as the filter then won’t modify them.&amp;nbsp;Alternatively a controller can implement an interface named IModifyLayout that tells the filter to pass the Layout property of the view model to the controller after having populated it with default values.&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;thumbnail-centered&quot; src=&quot;/PageFiles/551/alloy_view_model_handling.png&quot; alt=&quot;&quot; width=&quot;573&quot; height=&quot;707&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Using an action&lt;/strong&gt; filter instead of populating all properties of the view model in controllers makes the code less obvious and harder to follow. Clearly a bad thing. However, considering the alternative we&#39;d either have to duplicate a lot of code or rely on inhertitance which would have almost the same negative effects while also tying controllers to a possibly complex inheritance hiearchy.&lt;/p&gt;
&lt;p&gt;By taking the action filter route each controller can go on it&#39;s merry way focusing only on the specifics needed for the page type it handles.&lt;/p&gt;
&lt;h3&gt;Models for partial views&lt;/h3&gt;
&lt;p&gt;Partial views doesn&#39;t follow the pattern described above. Instead they either use a completely custom view model or the current content object is passed directly to the view.&lt;/p&gt;
&lt;p&gt;The reason for not using a similar approach as for non-partial views is that the partial views don&#39;t have layouts and typically don&#39;t need to know about a broader context.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;While the approach used in the MVC templates isn’t the most obvious and takes a while to wrap one’s head around it makes it easy to create new controller, models and views. As such I find it allows rapid development while maintaining decent separation of concerns.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;When working with&lt;/strong&gt; a view one has access to both view specific properties as well as a broader context. While this may seem like it&#39;s violating &quot;best practices&quot; I think it&#39;s good to keep in mind that best practices is dependent on context. And in the case of many EPiServer sites the context is that a page type very much is a view model in it self.&lt;/p&gt;
&lt;p&gt;I&#39;ve also used the same approach as in the MVC templates in a few other projects since and found it working well. Software design and development is always about &lt;em&gt;context&lt;/em&gt; though.&amp;nbsp;I can imagine sites where completely view-specific view models may makes sense. Similarly I can imagine sites where simply passing the current PageData object to the view would be an attractive solution.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Therefor I personally&lt;/strong&gt; think that we can use the view model approach used in the MVC templates in most projects as a start. As with many other things we should however always look at the specific context of the project and think about how we can deliver most customer value and flexibility for evolving customer needs.&lt;/p&gt;
</id><updated>2013-03-17T01:22:14.0000000Z</updated><summary type="html">Blog post</summary></entry></feed>