<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">Blog posts by Hjalmar Moa</title><link href="http://world.optimizely.com" /><updated>2011-01-12T17:03:13.0000000Z</updated><id>https://world.optimizely.com/blogs/Hjalmar-Moa/</id> <generator uri="http://world.optimizely.com" version="2.0">Optimizely World</generator> <entry><title>Using properties on pages not in EPiServer</title><link href="https://world.optimizely.com/blogs/Hjalmar-Moa/Dates/2011/1/Using-properties-on-pages-not-in-EPiServer/" /><id>&lt;p&gt;Sometimes I’ve had some use for a page on a site which isn’t a EPiServer page. Some pages should just be used once or a page that the editor shouldn’t touch. I found a use for it when I had to create a password recovery page. I couldn’t see a benefit in having it cluttering the page tree.&lt;/p&gt;  &lt;p&gt;The problem comes when we want to use the master page from our site which uses properties or page listings. The problem is that the properties don’t know which page you are on, since you aren’t on an episerver page. The solution is to inherit from a base page like the following, or just to implement in on the page itself.&lt;/p&gt;  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;class&lt;/span&gt; EPiServerContextPageBase : Page, ICurrentPage, IPageSource
    {
        &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; EPiServerContextPageBase()
        {
            CurrentPage = DataFactory.Instance.GetPage(PageReference.StartPage);
        }

        &lt;span class=&quot;kwrd&quot;&gt;private&lt;/span&gt; PageData currentPage;
        &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; EPiServer.Core.PageData CurrentPage
        {
            get
            {
                &lt;span class=&quot;kwrd&quot;&gt;return&lt;/span&gt; currentPage;
            }
            set
            {
                currentPage = &lt;span class=&quot;kwrd&quot;&gt;value&lt;/span&gt;;
            }
        }

        &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; PageDataCollection GetChildren(PageReference pageLink)
        {
            &lt;span class=&quot;kwrd&quot;&gt;return&lt;/span&gt; DataFactory.Instance.GetChildren(pageLink);
        }

        &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; PageData GetPage(PageReference pageLink)
        {
            &lt;span class=&quot;kwrd&quot;&gt;return&lt;/span&gt; DataFactory.Instance.GetPage(pageLink);
        }
    }&lt;/code&gt;&lt;/pre&gt;

&lt;style type=&quot;text/css&quot;&gt;&lt;![CDATA[
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, &quot;Courier New&quot;, courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }]]&gt;&lt;/style&gt;

&lt;p&gt;These interfaces creates a context for properties and lists to work. &lt;/p&gt;

&lt;p&gt;I hope you found it useful. :)&lt;/p&gt;</id><updated>2011-01-12T17:03:13.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Some thoughts on using the Repository design pattern</title><link href="https://world.optimizely.com/blogs/Hjalmar-Moa/Dates/2010/1/Some-thoughts-on-using-the-Repository-design-pattern/" /><id>&lt;p&gt;There is plenty of talk about MVC vs. Web Forms going on. One thing that MVC pushes for is small controller classes and a rich domain model. A rich domain model is equally useful in Web Forms but somehow seldom implemented. &lt;/p&gt;  &lt;p&gt;Using a tiered design, logic is to be placed in the business layer and the presentation should be in the user interface. A lot of times business logic is nested with presentation logic in a big non-reusable pile.&lt;/p&gt;  &lt;p&gt;One way to move some logic into the business layer is to create a “Repository” class for some types of data. &lt;/p&gt;  &lt;p&gt;As an example, a CalendarEventRepository could be created that get the events which are displayed in the calendar on a website. &lt;/p&gt;  &lt;p&gt;The following example shows you how to fetch pages from a set location. The page types are specified with &lt;a href=&quot;http://pagetypebuilder.codeplex.com/&quot;&gt;Page Type Builder&lt;/a&gt; so we can filter them by type in an easy way.&lt;/p&gt;  &lt;div class=&quot;csharpcode&quot;&gt;   &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;   1:  &lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;class&lt;/span&gt; CalendarEventRepository : RepositoryBase&amp;lt;CalendarItemPageType&amp;gt;&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;   2:  &lt;/span&gt;    {&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;   3:  &lt;/span&gt;        &lt;span class=&quot;rem&quot;&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;   4:  &lt;/span&gt;        &lt;span class=&quot;rem&quot;&gt;/// Get the calendar events from the specified year&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;   5:  &lt;/span&gt;        &lt;span class=&quot;rem&quot;&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;   6:  &lt;/span&gt;        &lt;span class=&quot;rem&quot;&gt;/// &amp;lt;param name=&amp;quot;language&amp;quot;&amp;gt;language branch&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;   7:  &lt;/span&gt;        &lt;span class=&quot;rem&quot;&gt;/// &amp;lt;returns&amp;gt;all events&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;   8:  &lt;/span&gt;        &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;static&lt;/span&gt; ICalendarEvent[] GetCalendarEvents(&lt;span class=&quot;kwrd&quot;&gt;string&lt;/span&gt; language)&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;   9:  &lt;/span&gt;        {&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;  10:  &lt;/span&gt;            CalendarItemPageType[] items = GetPagesFrom(SettingsPageType.Instance.CalendarPage, language);&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;  11:  &lt;/span&gt;            &lt;span class=&quot;kwrd&quot;&gt;if&lt;/span&gt; (items == &lt;span class=&quot;kwrd&quot;&gt;null&lt;/span&gt;)&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;  12:  &lt;/span&gt;            {&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;  13:  &lt;/span&gt;                log4net.LogManager.GetLogger(&lt;span class=&quot;str&quot;&gt;&amp;quot;CalendarEventRepository&amp;quot;&lt;/span&gt;)&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;  14:  &lt;/span&gt;                    .Debug(&lt;span class=&quot;str&quot;&gt;&amp;quot;Settings.CalendarPageLink is not set&amp;quot;&lt;/span&gt;);&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;  15:  &lt;/span&gt;&amp;#160;&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;  16:  &lt;/span&gt;                &lt;span class=&quot;kwrd&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;new&lt;/span&gt; ICalendarEvent[0];&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;  17:  &lt;/span&gt;            }&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;  18:  &lt;/span&gt;            &lt;span class=&quot;kwrd&quot;&gt;if&lt;/span&gt; (items.Length == 0)&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;  19:  &lt;/span&gt;            {&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;  20:  &lt;/span&gt;                log4net.LogManager.GetLogger(&lt;span class=&quot;str&quot;&gt;&amp;quot;CalendarEventRepository&amp;quot;&lt;/span&gt;)&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;  21:  &lt;/span&gt;                    .Debug(&lt;span class=&quot;str&quot;&gt;&amp;quot;No pages of type &#39;CalendarItemPageType&#39; below page &amp;quot;&lt;/span&gt; + SettingsPageType.Instance.CalendarPage.ID);&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;  22:  &lt;/span&gt;&amp;#160;&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;  23:  &lt;/span&gt;                &lt;span class=&quot;kwrd&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;new&lt;/span&gt; ICalendarEvent[0];&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;  24:  &lt;/span&gt;            }&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;  25:  &lt;/span&gt;&amp;#160;&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;  26:  &lt;/span&gt;            items = items&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;  27:  &lt;/span&gt;                .OrderBy(page =&amp;gt; page.PageDate)&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;  28:  &lt;/span&gt;                .ToArray();&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;  29:  &lt;/span&gt;&amp;#160;&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;  30:  &lt;/span&gt;            &lt;span class=&quot;kwrd&quot;&gt;return&lt;/span&gt; items;&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;  31:  &lt;/span&gt;        }&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The base class has a function that get the pages of choice&lt;/p&gt;

&lt;div class=&quot;csharpcode&quot;&gt;
  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;   1:  &lt;/span&gt;    &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;class&lt;/span&gt; RepositoryBase&amp;lt;T&amp;gt; &lt;span class=&quot;kwrd&quot;&gt;where&lt;/span&gt; T: TypedPageData&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;   2:  &lt;/span&gt;    {&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;   3:  &lt;/span&gt;        &lt;span class=&quot;kwrd&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;static&lt;/span&gt; T[] GetPagesFrom(PageReference pageLink, &lt;span class=&quot;kwrd&quot;&gt;string&lt;/span&gt; language)&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;   4:  &lt;/span&gt;        {&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;   5:  &lt;/span&gt;            &lt;span class=&quot;kwrd&quot;&gt;if&lt;/span&gt; (PageReference.IsNullOrEmpty(pageLink)) &lt;span class=&quot;kwrd&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;null&lt;/span&gt;;&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;   6:  &lt;/span&gt;            PageDataCollection children = DataFactory.Instance.GetChildren(pageLink, &lt;span class=&quot;kwrd&quot;&gt;new&lt;/span&gt; LanguageSelector(language));&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;   7:  &lt;/span&gt;            EPiServer.Filters.FilterForVisitor.Filter(children);&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;   8:  &lt;/span&gt;&amp;#160;&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;   9:  &lt;/span&gt;            T[] items = children&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;  10:  &lt;/span&gt;                .Where(page =&amp;gt; page &lt;span class=&quot;kwrd&quot;&gt;is&lt;/span&gt; T)&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;  11:  &lt;/span&gt;                .Select(page =&amp;gt; page &lt;span class=&quot;kwrd&quot;&gt;as&lt;/span&gt; T)&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;  12:  &lt;/span&gt;                .ToArray();&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;  13:  &lt;/span&gt;&amp;#160;&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;  14:  &lt;/span&gt;            &lt;span class=&quot;kwrd&quot;&gt;return&lt;/span&gt; items;&lt;/code&gt;&lt;/pre&gt;

  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;  15:  &lt;/span&gt;        }&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Our page type implements an interface so we can return a loosely coupled reference:&lt;/p&gt;

&lt;div class=&quot;csharpcode&quot;&gt;
  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;lnum&quot;&gt;   1:  &lt;/span&gt;    &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;class&lt;/span&gt; CalendarItemPageType : DatePageType, ICalendarEvent&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;csharpcode&quot;&gt;&amp;#160;&lt;/div&gt;
&lt;style type=&quot;text/css&quot;&gt;&lt;![CDATA[
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, &quot;Courier New&quot;, courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }]]&gt;&lt;/style&gt;&lt;style type=&quot;text/css&quot;&gt;&lt;![CDATA[
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, &quot;Courier New&quot;, courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }]]&gt;&lt;/style&gt;

&lt;h2&gt;The advantages&lt;/h2&gt;

&lt;p&gt;“Separation of concerns” has been a big topic lately. The page shouldn’t have to know how the calendar is implemented, it should trust the repository to send the data it needs. The repository should just serve the data and not be bothered who uses it.&lt;/p&gt;

&lt;p&gt;The repository returns an interface for the same reason. The class using the repository doesn’t need to know that the repository is really just returning a page.&lt;/p&gt;

&lt;p&gt;Having returned an interface gives us the freedom to change the implementation of the repository without changing anything else on the site. The events could equally well be classes hosted in the Dynamic Data Store, or returned from a RSS feed.&lt;/p&gt;


&lt;h2&gt;Is it worth the bother?&lt;/h2&gt;

&lt;p&gt;I have heard some times that it is overkill to create an entirely new class just to get some child pages. &lt;/p&gt;

&lt;p&gt;This might seem a good enough reason to start with, but code tends to grow overtime. Soon the excuse is that it is too many places to change instead. &lt;/p&gt;

&lt;p&gt;The second excuse is that it is too hard to understand code that uses interfaces. I don’t have a good comment on this….&lt;/p&gt;

&lt;p&gt;What’s your opinion?&lt;/p&gt;</id><updated>2010-01-27T19:42:37.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Adding glossary functionality in XHtml-property content</title><link href="https://world.optimizely.com/blogs/Hjalmar-Moa/Dates/2009/9/Adding-glossary-functionality-in-XHtml-property-content/" /><id>&lt;p&gt;A customer wanted to be able to have explanation for the words in the site dictionary. The chosen solution for making this popup was to mark the text with a span around it.&lt;/p&gt;  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;span&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;=&amp;quot;description&amp;quot;&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;Word&lt;span class=&quot;kwrd&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;html&quot;&gt;span&lt;/span&gt;&lt;span class=&quot;kwrd&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The replacement of this should only be displayed in view-mode. To make this I extended the xhtml-control to return a new control&lt;/p&gt;

&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;[PageDefinitionTypePlugIn]
&lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;class&lt;/span&gt; DictionaryXHTMLString : PropertyXhtmlString
{
    &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;override&lt;/span&gt; IPropertyControl CreatePropertyControl()
    {
        &lt;span class=&quot;kwrd&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;new&lt;/span&gt; DictionaryXHTMLStringControl();
    }
}&lt;/code&gt;&lt;/pre&gt;

&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;class&lt;/span&gt; DictionaryXHTMLStringControl : PropertyLongStringControl
{
    &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;void&lt;/span&gt; CreateDefaultControls()
    {
        &lt;span class=&quot;kwrd&quot;&gt;base&lt;/span&gt;.CreateDefaultControls();
        &lt;span class=&quot;kwrd&quot;&gt;foreach&lt;/span&gt; (Control ctrl &lt;span class=&quot;kwrd&quot;&gt;in&lt;/span&gt; Controls[0].Controls)
        {
            Literal lit = ctrl &lt;span class=&quot;kwrd&quot;&gt;as&lt;/span&gt; Literal;
            &lt;span class=&quot;kwrd&quot;&gt;if&lt;/span&gt; (lit != &lt;span class=&quot;kwrd&quot;&gt;null&lt;/span&gt;)
            {
                lit.Text = GlossaryFilter.GetDictionaryMarkup(lit.Text);
            }
        }
    }
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The PropertyLongStringControl populates the control tree with a panel and a list of Literals. If dynamic content is included it comes as a different class so we don’t have to worry about it.&lt;/p&gt;

&lt;p&gt;The magic is performed by the glossary filter which adds the span tags by parsing the content with a small regex.&lt;/p&gt;

&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;string&lt;/span&gt; GetDictionaryMarkup(&lt;span class=&quot;kwrd&quot;&gt;string&lt;/span&gt; markup)
{
    &lt;span class=&quot;kwrd&quot;&gt;try&lt;/span&gt;
    {
        GlossaryWordCollection gc = GlossaryWord.GetAllGlossaryWords(&lt;span class=&quot;kwrd&quot;&gt;false&lt;/span&gt;);

        &lt;span class=&quot;kwrd&quot;&gt;foreach&lt;/span&gt; (GlossaryWord word &lt;span class=&quot;kwrd&quot;&gt;in&lt;/span&gt; gc)
        {
            &lt;span class=&quot;kwrd&quot;&gt;if&lt;/span&gt; (!&lt;span class=&quot;kwrd&quot;&gt;string&lt;/span&gt;.IsNullOrEmpty(word.ToolTip))
            {
                Regex ex = &lt;span class=&quot;kwrd&quot;&gt;new&lt;/span&gt; Regex(&lt;span class=&quot;kwrd&quot;&gt;string&lt;/span&gt;.Format(&lt;span class=&quot;str&quot;&gt;@&amp;quot;(&amp;gt;[^&amp;lt;]*?)(?&amp;lt;data&amp;gt;\b{0}\b)&amp;quot;&lt;/span&gt;, word.Word), RegexOptions.IgnoreCase);
                &lt;span class=&quot;kwrd&quot;&gt;string&lt;/span&gt; replaceString = &lt;span class=&quot;kwrd&quot;&gt;string&lt;/span&gt;.Format(&lt;span class=&quot;str&quot;&gt;&amp;quot;$1&amp;lt;span class=\&amp;quot;tooltip\&amp;quot; rel=\&amp;quot;{0}\&amp;quot;&amp;gt;$2&amp;lt;/span&amp;gt;&amp;quot;&lt;/span&gt;,word.Description);
                &lt;span class=&quot;kwrd&quot;&gt;string&lt;/span&gt; newmarkup = ex.Replace(markup, replaceString);
                markup = newmarkup;
            }
        }
        &lt;span class=&quot;kwrd&quot;&gt;return&lt;/span&gt; markup;
    }
    &lt;span class=&quot;kwrd&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;rem&quot;&gt;//if whatever happens, return the original string.&lt;/span&gt;
    {
        &lt;span class=&quot;kwrd&quot;&gt;return&lt;/span&gt; markup;
    }
}&lt;/code&gt;&lt;/pre&gt;


&lt;style type=&quot;text/css&quot;&gt;&lt;![CDATA[
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, &quot;Courier New&quot;, courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }]]&gt;&lt;/style&gt;

&lt;p&gt;This replaces the first occurrence of a word in the text after any tag. If all occurrences should be matched the regex could be changed or perhaps loop it for a while….&lt;/p&gt;

&lt;p&gt;The attribute rel in the tag was chosen as to not have a tooltip when hovering the tag. The popup is then created with javascript, but that’s just a matter of choosing how to display it.&lt;/p&gt;
&lt;style type=&quot;text/css&quot;&gt;&lt;![CDATA[
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, &quot;Courier New&quot;, courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }]]&gt;&lt;/style&gt;</id><updated>2009-09-03T17:39:26.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Odd behavoiur in the Longstring property</title><link href="https://world.optimizely.com/blogs/Hjalmar-Moa/Dates/2009/9/Odd-behavoiur-in-the-Longstring-property/" /><id>&lt;p&gt;An oddity I just found is that the LongString property renders differently with the &amp;lt;episerver:property tag when the user is logged in or not. The evidence that made me react was some embedded &amp;amp;nbsp; in the text. these were encoded and thus invisible when the user was logged in.&lt;/p&gt;  &lt;p&gt;I havn’t looked into the reasons for this but the solution for situations where it&#180;s just a string to print is to use the xhtml-property with disabled editor controls.&lt;/p&gt;  &lt;p&gt;This problem was tricky to notice because it&#180;s common to require login for staging servers.&lt;/p&gt;</id><updated>2009-09-02T13:47:59.0000000Z</updated><summary type="html">Blog post</summary></entry></feed>