Blog posts by Thomas Krantz
2013-04-17T12:18:04.0000000Z
/blogs/Thomas-Krantz-/
Optimizely World
Hide pages in the page tree in EPiServer 7
http://tedgustaf.com//link/13d760d0ca0048efa67c621c53d4ae50.aspx?id=321&epslanguage=en
2013-04-17T12:18:04.0000000Z
<p class="intro">Sometimes it could be useful to manipulate how certain pages are displayed in the page tree in EPiServer 7. Because the page tree is loaded from a REST based store, all you really need to do is provide a custom implementation of the ContentQuery responsible for...</p><p>Sometimes it could be useful to manipulate how certain pages are displayed in the page tree in EPiServer 7. Because the page tree is loaded from a REST based store, all you really need to do is provide a custom implementation of the ContentQuery responsible for loading the children.</p>
<p>The REST stores in EPiServer are discovered at application startup. The <strong>ContentStructureStore</strong> which is used for loading content into the page tree (no shit?), will be provided with a number of ContentQuery classes at initialization. One of them is <strong>EPiServer.Cms.Shell.UI.Rest.ContentQuery.GetChildrenQuery</strong>.</p>
<h3>Provide your custom query</h3>
<p>First add a reference to <strong>EPiServer.Cms.Shell.UI assembly</strong>. Yes, you will now have a dependency to an EPiServer module, so think about that for a moment.</p>
<p>Then add your own <strong>GetChildrenQuery</strong> class. You get alot of goodies through the <strong>ContentQueryParameters</strong> object passed to <strong>GetContent</strong>, such as <strong>CurrentPrincipal</strong>, <strong>CurrentLanguage</strong> etc.</p>
<p>So, short example. I’ll hide all content that have a name containing “Alloy”.</p>
<div id="codeSnippetWrapper" style="overflow: auto; cursor: text; font-size: 8pt; height: 229px; font-family: 'Courier New', courier, monospace; direction: ltr; text-align: left; margin: 20px 0px 10px; line-height: 12pt; max-height: 200px; width: 97.5%; background-color: #f4f4f4; border: silver 1px solid; padding: 4px;">
<div id="codeSnippet" style="overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; color: black; direction: ltr; text-align: left; line-height: 12pt; width: 100%; background-color: #f4f4f4; border-style: none; padding: 0px;">
<pre style="overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; color: black; direction: ltr; text-align: left; margin: 0em; line-height: 12pt; width: 100%; background-color: white; border-style: none; padding: 0px;"><span style="color: #0000ff;">using</span> System;</pre>
<!--CRLF-->
<pre style="overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; color: black; direction: ltr; text-align: left; margin: 0em; line-height: 12pt; width: 100%; background-color: #f4f4f4; border-style: none; padding: 0px;"><span style="color: #0000ff;">using</span> System.Collections.Generic;</pre>
<!--CRLF-->
<pre style="overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; color: black; direction: ltr; text-align: left; margin: 0em; line-height: 12pt; width: 100%; background-color: white; border-style: none; padding: 0px;"><span style="color: #0000ff;">using</span> System.Diagnostics;</pre>
<!--CRLF-->
<pre style="overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; color: black; direction: ltr; text-align: left; margin: 0em; line-height: 12pt; width: 100%; background-color: #f4f4f4; border-style: none; padding: 0px;"><span style="color: #0000ff;">using</span> System.Linq;</pre>
<!--CRLF-->
<pre style="overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; color: black; direction: ltr; text-align: left; margin: 0em; line-height: 12pt; width: 100%; background-color: white; border-style: none; padding: 0px;"><span style="color: #0000ff;">using</span> System.Web;</pre>
<!--CRLF-->
<pre style="overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; color: black; direction: ltr; text-align: left; margin: 0em; line-height: 12pt; width: 100%; background-color: #f4f4f4; border-style: none; padding: 0px;"><span style="color: #0000ff;">using</span> EPiServer.Cms.Shell.UI.Rest.ContentQuery;</pre>
<!--CRLF-->
<pre style="overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; color: black; direction: ltr; text-align: left; margin: 0em; line-height: 12pt; width: 100%; background-color: white; border-style: none; padding: 0px;"><span style="color: #0000ff;">using</span> EPiServer.Core;</pre>
<!--CRLF-->
<pre style="overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; color: black; direction: ltr; text-align: left; margin: 0em; line-height: 12pt; width: 100%; background-color: #f4f4f4; border-style: none; padding: 0px;"><span style="color: #0000ff;">using</span> EPiServer.ServiceLocation;</pre>
<!--CRLF-->
<pre style="overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; color: black; direction: ltr; text-align: left; margin: 0em; line-height: 12pt; width: 100%; background-color: white; border-style: none; padding: 0px;"> </pre>
<!--CRLF-->
<pre style="overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; color: black; direction: ltr; text-align: left; margin: 0em; line-height: 12pt; width: 100%; background-color: #f4f4f4; border-style: none; padding: 0px;"><span style="color: #0000ff;">namespace</span> EPiServer.Templates.Alloy.Business</pre>
<!--CRLF-->
<pre style="overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; color: black; direction: ltr; text-align: left; margin: 0em; line-height: 12pt; width: 100%; background-color: white; border-style: none; padding: 0px;">{</pre>
<!--CRLF-->
<pre style="overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; color: black; direction: ltr; text-align: left; margin: 0em; line-height: 12pt; width: 100%; background-color: #f4f4f4; border-style: none; padding: 0px;"> [ServiceConfiguration(<span style="color: #0000ff;">typeof</span>(IContentQuery))]</pre>
<!--CRLF-->
<pre style="overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; color: black; direction: ltr; text-align: left; margin: 0em; line-height: 12pt; width: 100%; background-color: white; border-style: none; padding: 0px;"> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span> MyGetChildrenQuery : GetChildrenQuery</pre>
<!--CRLF-->
<pre style="overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; color: black; direction: ltr; text-align: left; margin: 0em; line-height: 12pt; width: 100%; background-color: #f4f4f4; border-style: none; padding: 0px;"> {</pre>
<!--CRLF-->
<pre style="overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; color: black; direction: ltr; text-align: left; margin: 0em; line-height: 12pt; width: 100%; background-color: white; border-style: none; padding: 0px;"> <span style="color: #0000ff;">public</span> MyGetChildrenQuery(IContentQueryHelper queryHelper, IContentRepository contentRepository, LanguageSelectorFactory languageSelectorFactory) : <span style="color: #0000ff;">base</span>(queryHelper, contentRepository, languageSelectorFactory)</pre>
<!--CRLF-->
<pre style="overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; color: black; direction: ltr; text-align: left; margin: 0em; line-height: 12pt; width: 100%; background-color: #f4f4f4; border-style: none; padding: 0px;"> {</pre>
<!--CRLF-->
<pre style="overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; color: black; direction: ltr; text-align: left; margin: 0em; line-height: 12pt; width: 100%; background-color: white; border-style: none; padding: 0px;"> }</pre>
<!--CRLF-->
<pre style="overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; color: black; direction: ltr; text-align: left; margin: 0em; line-height: 12pt; width: 100%; background-color: #f4f4f4; border-style: none; padding: 0px;"> </pre>
<!--CRLF-->
<pre style="overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; color: black; direction: ltr; text-align: left; margin: 0em; line-height: 12pt; width: 100%; background-color: white; border-style: none; padding: 0px;"> <span style="color: #0000ff;">protected</span> <span style="color: #0000ff;">override</span> IEnumerable<IContent> GetContent(ContentQueryParameters parameters)</pre>
<!--CRLF-->
<pre style="overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; color: black; direction: ltr; text-align: left; margin: 0em; line-height: 12pt; width: 100%; background-color: #f4f4f4; border-style: none; padding: 0px;"> {</pre>
<!--CRLF-->
<pre style="overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; color: black; direction: ltr; text-align: left; margin: 0em; line-height: 12pt; width: 100%; background-color: white; border-style: none; padding: 0px;"> <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">base</span>.GetContent(parameters).Where(x => !x.Name.Contains(<span style="color: #006080;">"Alloy"</span>));</pre>
<!--CRLF-->
<pre style="overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; color: black; direction: ltr; text-align: left; margin: 0em; line-height: 12pt; width: 100%; background-color: #f4f4f4; border-style: none; padding: 0px;"> }</pre>
<!--CRLF-->
<pre style="overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; color: black; direction: ltr; text-align: left; margin: 0em; line-height: 12pt; width: 100%; background-color: white; border-style: none; padding: 0px;"> }</pre>
<!--CRLF-->
<pre style="overflow: visible; font-size: 8pt; font-family: 'Courier New', courier, monospace; color: black; direction: ltr; text-align: left; margin: 0em; line-height: 12pt; width: 100%; background-color: #f4f4f4; border-style: none; padding: 0px;">}</pre>
<!--CRLF--></div>
</div>
Localization of block type names in EPiServer 7
http://tedgustaf.com//link/26e86947ceb9409690800a070c5e30c1.aspx?id=307&epslanguage=sv
2012-11-23T12:30:32.0000000Z
<p class="intro">EPiServer 7 adds the concept of blocks, which differs in alot of ways from Composer blocks. One is how you provide localized names for the editor.</p><p>In EPiServer 7 we not only have <strong>pages</strong>, we also have <strong>blocks</strong>. Just as you translate <strong>page types</strong> by putting the translations in <em>/language/pagetypes/pagetype, </em>you need to organize <strong>block types</strong> in a similar <em>/language/blocktypes/blocktype</em> structure. Otherwise EPiServer 7 will not be able to load them.</p>
<p><img style="display: inline; border-width: 0px;" title="localization of block types names in EPiServer 7" src="http://tedgustaf.com/Global/Blog/2012/11/23/image_e3aca83f-a466-4b62-b513-be26d380015c.png" border="0" alt="localization of block types names in EPiServer 7" width="500" height="250" /></p>
Conventions for EPiServer 7 MVC Views
http://tedgustaf.com//link/7ccd105ed172413a94d3a9a3b852b6c8.aspx?id=304&epslanguage=sv
2012-11-14T15:24:44.0000000Z
<p class="intro">ASP.NET MVC is largely built on conventions for controllers, models, and views. However, I prefer tweaking these conventions a bit for EPiServer 7 sites to separate block views from page views.</p><p>Building a web site on EPiServer 7 using ASP.NET MVC, you will probably end up with a fairly long list of blocks and pages as the site grows. EPiServer 7 follows the MVC convention of searching <strong>~/Views/</strong> for all views, which means blocks and pages will both be located in that folder.</p>
<p>I want to separate block views from page views, using the folders <strong>~/Views/Blocks/</strong> and <strong>~/Views/Pages/</strong>. To customize the MVC search convention to handle these additional paths, you need to add a class deriving from RazorViewEngine, like so:</p>
<p><img style="border: 0px currentColor; display: inline;" title="Customizing ASP.NET MVC conventions to use a different folder structure" src="http://tedgustaf.com/Global/Blog/2012/11/14/image_b10be5f6-5a1c-4720-86a1-88cb2b3663f9.png" alt="Customizing ASP.NET MVC conventions to use a different folder structure" width="642" height="235" /></p>
<p>Then you need to register the engine, which you can do in the <strong>Application_Start </strong>method in your <strong>Global.asax</strong> file:</p>
<p><img style="display: inline; border: 0px;" title="image" src="http://tedgustaf.com/Global/Blog/2012/11/14/image_581f56b4-6f85-4423-8ea1-6303da1011b4.png" border="0" alt="image" width="400" height="67" /></p>
<p>That’s it!</p>
Using a bit of System.Runtime.Caching with EPiServer
/blogs/Thomas-Krantz-/Dates/2012/4/Using-a-bit-of-SystemRuntimeCaching-with-EPiServer/
2012-04-06T00:36:06.0000000Z
<p>I have been poking around in System.Runtime.Caching that was introduced with .NET 4, and more specifically the MemoryCache.</p> <p>The MemoryCache is virtually the same as the good old ASP.NET Cache, except it’s not dependent on System.Web which means you can use it without an HttpContext.</p> <p>ChangeMonitors monitors changes in the state of data which a cache item depends on, and I’ve written a simple custom ChangeMonitor called PageChangeMonitor to monitor published EPiServer pages.</p> <div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.74%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; height: 210px; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> PageChangeMonitor : ChangeMonitor</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">private</span> PageReference _pageLink;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">public</span> PageChangeMonitor(PageReference pageLink)</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">if</span>(PageReference.IsNullOrEmpty(pageLink))</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span> ArgumentNullException(<span style="color: #006080">"pageLink"</span>);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> } </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">bool</span> init = <span style="color: #0000ff">false</span>;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">try</span></pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> _pageLink = pageLink;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> DataFactory.Instance.PublishedPage += PublishedPage;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> init = <span style="color: #0000ff">true</span>;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">finally</span></pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">base</span>.InitializationComplete();</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">if</span>(!init)</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">base</span>.Dispose();</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">void</span> PublishedPage(<span style="color: #0000ff">object</span> sender, PageEventArgs e)</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">if</span>(e.PageLink.ID == _pageLink.ID)</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> OnChanged(e.PageLink);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">protected</span> <span style="color: #0000ff">override</span> <span style="color: #0000ff">void</span> Dispose(<span style="color: #0000ff">bool</span> disposing)</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> DataFactory.Instance.PublishedPage -= PublishedPage;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">public</span> <span style="color: #0000ff">override</span> <span style="color: #0000ff">string</span> UniqueId</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> get { <span style="color: #0000ff">return</span> Guid.NewGuid().ToString(); }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> }</pre>
<!--CRLF--></div>
</div>
<p>The PageChangeMonitor can be used to expire the cache item when a certain page is published. An example:</p>
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 98.83%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; height: 210px; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #0000ff">public</span> <span style="color: #0000ff">string</span> GetSomeDataForPage(PageData page)</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> var cacheKey = <span style="color: #0000ff">string</span>.Format(<span style="color: #006080">"some-data-{0}"</span>, page.PageLink.ID);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> var cache = MemoryCache.Default;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> var someData = (<span style="color: #0000ff">string</span>) cache.Get(cacheKey);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">if</span>(someData != <span style="color: #0000ff">null</span>)</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> <span style="color: #008000">// data was cached</span></pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">return</span> someData;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> <span style="color: #008000">// data was not in cache. Either it has never been cached,</span></pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> <span style="color: #008000">// or the PageChangeMonitor expired the cache when the page </span></pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> <span style="color: #008000">// was published.</span></pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> someData = DoSomeHeavyLiftingAndReturnData(page);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> var policy = <span style="color: #0000ff">new</span> CacheItemPolicy();</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> <span style="color: #008000">// create the PageChangeMonitor that should monitor the page</span></pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> var monitor = <span style="color: #0000ff">new</span> PageChangeMonitor(page.PageLink);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> policy.ChangeMonitors.Add(monitor);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> cache.Add(cacheKey, someData, policy);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">return</span> someData;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> }</pre>
<!--CRLF--></div>
</div>
<p>Enjoy! And remember – <strong>cache is king</strong>.</p>
Visual Studio 2010 Add-In for sorting language XML files
/blogs/Thomas-Krantz-/Dates/2011/5/Visual-Studio-2010-Add-In-for-sorting-language-XML-files/
2011-05-25T00:33:14.0000000Z
<h2>Background</h2> <p>As EPiServer sites grow, their language files usually grows rapidly as well. It’s not uncommon to have several hundred lines of language keys split into different files. </p> <p>Maintaining such a site and making sure all language keys are translated in all languages can be a pain. I think there are a few Admin plugins for addressing these problems as well.</p> <p>In our team we have a common practise to always have one language file per language, and to have them alphabetically sorted. That way, you can easily navigate through them, and by just comparing the line numbers you see if there are differences. No Admin plugins needed.</p> <p>Problem is, to continuously sorting your keys in alphabetical order, can also be a pain :)</p> <h2>Solution</h2> <p>I put together a simple VS 2010 add-in, which installs to the right-click menu in Visual Studio.</p> <p><a href="/link/0e20daa227964d3583c377e2fecc4f98.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="editor_before" border="0" alt="editor_before" src="/link/ca8342361b384ebd847f7727f5e2ecb6.png" width="498" height="335" /></a> </p> <p>Once clicked, the XML will sort on element name, like so:</p> <p><a href="/link/2bb9cb34e1594a73b5251f9f28d504ab.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="editor_after" border="0" alt="editor_after" src="/link/41d39098b3114521b3dcb3f532945c0b.png" width="497" height="306" /></a> </p> <h2>Installation</h2> <p>The attached zip contains two files.</p> <p><a href="/link/712050d911db4e62b0a8d50d3085052c.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="files" border="0" alt="files" src="/link/834cbb2e57f04ba1bb658ed285626736.png" width="605" height="266" /></a> </p> <p>Put them in your /Documents/Visual Studio 2010/Addins folder</p> <p>Visual Studio will pick up the addin:</p> <p><a href="/link/27d7e0e3bfb4438fb38b9640770dcf3e.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="manager" border="0" alt="manager" src="/link/4c14cf7a8aae49aeb6ce9616aa0fc9f2.png" width="531" height="344" /></a> </p> <h2>Feedback</h2> <p>Take it for a spin! Of course this add-in should work on any XML, even if it would be kind of pointless to sort your Web.config :)</p> <p>Feel free to email me or twitter at <a href="http://twitter.com/thomas_krantz">@thomas_krantz</a></p> <p>I’ll put the source code online somewhere if somebody is interested.</p> Here’s the file: <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:F60BB8FA-6F02-4999-8F5E-9DD4E92C4DA7:26073a52-ee40-4567-9472-eafed78e22a3" class="wlWriterEditableSmartContent"><div><a href="/link/41e39e49d555429db4521475ed0bc672.zip" target="_self">SortXML.zip</a></div></div>
Custom property for selecting Visitor Groups
/blogs/Thomas-Krantz-/Dates/2011/4/Custom-property-for-selecting-Visitor-Groups/
2011-04-20T12:41:55.0000000Z
<p>This custom property will render a checkbox list of all visitor groups, allowing multiple selections. </p> <p><a href="/link/9ad0fabdcc1149b393f91e1bc49b4fa4.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="/link/e15644699b534d92bb553abca5b39d48.png" width="372" height="32" /></a> </p> <p>Add a reference to EPiServer.ApplicationModules.</p> <div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"> <div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"> <pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #0000ff">using</span> EPiServer.Personalization.VisitorGroups;</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"><span style="color: #0000ff">namespace</span> MySite.Website.Plugins.SpecializedProperties.VisitorGroups</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">{</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> [PageDefinitionTypePlugIn(DisplayName = <span style="color: #006080">"Visitor Group selection"</span>)]</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> PropertyVisitorGroups : PropertyMultipleValue</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">public</span> <span style="color: #0000ff">override</span> IPropertyControl CreatePropertyControl()</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">return</span> <span style="color: #0000ff">new</span> PropertyVisitorGroupsControl();</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> PropertyVisitorGroupsControl : PropertySelectMultipleControlBase</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> <span style="color: #0000ff">protected</span> <span style="color: #0000ff">override</span> <span style="color: #0000ff">void</span> SetupEditControls()</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> var repository = <span style="color: #0000ff">new</span> VisitorGroupStore(DynamicDataStoreFactory.Instance);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> var list = repository.List()</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> .OrderBy(v => v.Name)</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> .Select(v => <span style="color: #0000ff">new</span> ListItem(v.Name, v.Id.ToString())</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> {</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> Selected = ((PropertyMultipleValue) PropertyData).IsValueActive(v.Id.ToString())</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> })</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> .ToArray();</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> </pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> EditControl.Items.AddRange(list);</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"> }</pre>
<!--CRLF-->
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px">}</pre>
<!--CRLF--></div>
</div>
Automating Selenium tests
/blogs/Thomas-Krantz-/Dates/2011/1/Automating-Selenium-tests/
2011-01-27T10:27:02.0000000Z
<p>This post explains how to setup automated Selenium tests on an EPiServer website. </p> <p>Beyond the scope of this post:</p> <ul> <li>Installation and configuration of the build server itself. I’m using Team Foundation Server but I’m sure any build server will work. </li> <li>How Selenium works in any great detail. I will only provide a few examples how to login to EPiServer and verify content. </li> </ul> <h2>What is Selenium and why should you care?</h2> <p>Selenium is a set of tools for testing web applications by recording all clicks, keystrokes and what-not, and replaying them and verify that certain elements contain certain values. </p> <p>Key components include:</p> <ul> <li>Selenium IDE <ul> <li>A plugin for Firefox allowing you to record, edit and play back tests. It can export the test you have recorded to a C# class. </li> <li>You don’t have to use this, you can code your tests from scratch as well. </li> </ul> </li> <li>Selenium Remote Control (RC) <ul> <li>A java server which starts up browsers and run commands you pass along from your tests. </li> <li>Listens to a TCP port and receives commands from the Client Drivers. </li> <li>I��m running this on the build server. </li> </ul> </li> <li>Selenium Client Drivers <ul> <li>These are language specific drivers used for wrapping calls to Selenium RC. </li> </ul> </li> </ul> <p>This is <em>awesome</em> because it will allow you to remote control a browser from within a C# class, used in a Visual Studio Test project which your Build Server will run in your Continuous Integration environment. <strong>How cool is that?</strong> This will ensure that not only does your code compile, but you can automate the whole process of clicking around the site after the build to verify that everything still seem to work. </p> <h2>Requirements</h2> <p>- Java SE 6 JRE on the server running Selenium RC</p> <p>- Firefox on the same server running RC</p> <p>- Selenium RC (<a href="http://seleniumhq.org/download/">http://seleniumhq.org/download/</a>)</p> <p>- Selenium IDE (<a href="http://seleniumhq.org/download/">http://seleniumhq.org/download/</a>)</p> <p>- Some build server, obviously.</p> <h2>1. Install Selenium RC on the Build Server</h2> <p>Download and unzip selenium-remote-control-1.0.3.zip.</p> <p>It contains the client drivers you need in your Visual Studio project, and the Remote Control server you will run on your build server.</p> <p>Put selenium-server.jar somewhere. Fire up a cmd.exe and run “java –jar selenium-server.jar”. With default settings the server will listen to TCP 4444 on all networks. You probably want to wrap this into a Windows Service.</p> <h2>2. Install Firefox on the server</h2> <p>Go get Firefox (<a href="http://www.getfirefox.com">http://www.getfirefox.com</a>) and make sure the path to Firefox.exe is included in the environment variable PATH, or the RC will not find it.</p> <h2>3. Install Selenium IDE</h2> <p>Install the plugin in Firefox on your workstation.</p> <h2>4. Create a new test case and start recording traffic</h2> <p>Fire up Selenium IDE and go to your favorite site. Hit the red record button in the top right corner to start recording. In the example screenshot I have recorded the steps involving login to EPiServer, a few clicks on the site, and I have added a few assertions about the pages.</p> <p><a href="/link/ff1f397bb4f94f89b472afb7043fa5bb.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="/link/e5f428344c1e46939ece9fa14cc8493e.png" width="527" height="437" /></a> </p> <p>The IDE will add a right-click menu to ease the adding of assertions. Just right-click some element and it will give you the option to assert that a certain text is displayed “anywhere” on the page (verifyTextPresent) or a text has to be in a certain xpath(assertText).</p> <p><a href="/link/120b372b42234b20a51b4483dc9b20e5.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="/link/62bba3e0bc1747b4b9adc93788d36f29.png" width="360" height="343" /></a> </p> <p>A very good idea is to add tests for the Edit and Admin modes to catch errors with custom properties modified, plugins crashing etc.</p> <h2>5. Export the test to a C# class</h2> <p>Export the test case to a C# class and you will have a TestFixture class ready to use in a Visual Studio Test project. You will need to add references to the NUnit and Selenium dll:s that came with the RC zip.</p> <p><a href="/link/03567471e9ca4f46b7f5640457e76918.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="/link/4fdf4f377bb041dfa081b31cf675894e.png" width="244" height="162" /></a> </p> <p>This is key:</p> <p><a href="/link/f152e72e3b284109a6eb871d9031e744.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="/link/57af3afc52bc414f8b851af54783beec.png" width="535" height="95" /></a> </p> <p>This will tell Selenium to send your commands to the RC server running at 192.168.0.123 on port 4444.</p> <p>Make sure you add a sufficient timeout using the <strong>setTimeout()</strong> method which is used for all Open calls. Default is 30 seconds which probably isn’t enough since we’re hitting a brand new compiled EPiServer site.</p> <p><a href="/link/c4fc1b384903438283bcaa2024aeda86.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="/link/5a901240af5d4eca8bb0be3adcaf0a3a.png" width="542" height="201" /></a> </p> <p>If you are running the TFS Build Server you probably want to replace the NUnit attributes with VS attributes, or make some magic to the Build Definition in order to make the build server run your tests.</p> <h2>6. Run the unit test</h2> <p>In Visual Studio, use the Run Unit Tests command to verify that the test passes. Watch the RC command window on the build server as it starts up Firefox and step-by-step runs your test.</p> <h2>7. Pretty much done!</h2> <p>If you have a build server automatically executing test dll:s, this should work without problems. Just make sure the RC server is running.</p> <p>I had some issues with timeouts because the site was too slow to start. Another totally unrelated problem was that the TFS Build Server refused to build my EPiServer 6 .NET 4 project, claiming that it was missing a “resgen.exe” executable included in Windows SDK. Some googling hinted me to install Visual Studio on the build server. <strong>No way, Jose! Absolutely not, never. </strong>Turns out the Windows SDK 7.0A included in VS 2010 hasn’t been released for download separately, so I simply copied the whole SDK folder and registry keys to the build server. Worked like a charm!</p> <p>I have some ideas for integrating screenshots of failing tests into the build reports, but that’s a subject for another blog post!</p>
CMO 2.0 and .NET 4 installation problems and solutions
/blogs/Thomas-Krantz-/Dates/2011/1/CMO-20-and-NET-4-installation-problems-and-solutions/
2011-01-13T11:54:55.0000000Z
<p>When I installed CMO 2.0 on a CMS 6 site running .NET 4, I had some issues with the installer. Same problems on both my dev and production environment.</p> <p>After the module installation in Deployment Center, <strong>the site does not start</strong>. Btw, why can’t I have the option to only install the necessary CMO services and application files? It’s a scary feeling to let an installer do what it wants to my production config files.</p> <h2></h2> <h2>Web.config modifications</h2> <p>1. The installer pokes around in Web.config modifying some configSections, namely it adds some sections to system.web.extensions/scripting/webServices sectionGroup.</p> <p><a href="/link/c16e19d2ef38476784d1291fb3b26e70.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="/link/83edceac774042b6bfe9068605bfbb5d.png" width="437" height="114" /></a> </p> <p>I’m not sure why but once these lines were removed I’m getting the next error.</p> <p><strong>2.</strong> The installer alters the targetFramework and set it to 3.5. I changed this back to 4.0</p> <h4></h4> <p><strong>3.</strong> CMO adds some httphandlers that refers to a 3.5 assembly. </p> <p>I needed to change this handler in order to get Live Monitor and the Thumbnail service working:</p> <p><font size="1" face="Courier New"><add name="svc-Integrated" path="*.svc" verb="*"  <br />type="System.ServiceModel.Activation.HttpHandler,  <br />System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"  <br />resourceType="Unspecified" preCondition="integratedMode"/></font></p> <p>Which is located here:</p> <p><a href="/link/6b484fe8ba7b48949f00257c5984976a.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="/link/00b4ffe3caf44201a2dc69c2b2ede4fc.png" width="576" height="139" /></a> </p> <p>Change it to:</p> <p><font size="1" face="Courier New"><add name="svc-Integrated" path="*.svc" verb="*" type="System.ServiceModel.Activation.HttpHandler,  <br />System.ServiceModel.Activation, Version=4.0.0.0, Culture=neutral,  <br />PublicKeyToken=31bf3856ad364e35" resourceType="Unspecified"  <br />preCondition="integratedMode" /></font></p> <h2>KPI Settings throws an Exception</h2> <p><strong>4.</strong> This is probably not a 4.0 issue but something caused by some cultureInfo thing. I don’t know. </p> <p>In CMO/Campaigns/Settings you can click “KPI Settings” to configure KPI.</p> <p><font size="1">I</font><a href="/link/00dffb134c0744a8807c758f768333b4.png"><font size="1"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="/link/3f0654e262ad4987a30010f6075b2abd.png" width="342" height="127" /></font></a><font size="1"> </font></p> <p>This caused this one…</p> <p><a href="/link/1f081bd542e84f649eb4f01b52513563.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="/link/d7c19c9a7c3641909e2518ea7640bb56.png" width="514" height="93" /></a> </p> <p>While I probably should have waited for a proper patch, I needed to get this running. So… <strong>at my own risk</strong>, I patched  <font size="1" face="Courier New">C:\Program Files (x86)\EPiServer\CMS\6.0.530.\Install\Modules\CMO2.0.0.0\CMO\Units\Kpi\KpiSettingsEditor.ascx</font></p> <p><a href="/link/a25c3a787f7f474aa4115b2893046002.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="/link/7e37f644895d4c888ffadaa61cdd871a.png" width="557" height="59" /></a> </p> <p>I changed ValueToCompare to “0,01” with a comma instead. </p> <h2>App_Browsers</h2> <p><strong>5. </strong>The browser or gateway element with ID “Safari1Plus” cannot be found.</p> <p><a href="/link/03722c6aa78446fdae39849656f229dd.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="/link/86434baf8df24580927a3326b11fabb5.png" width="430" height="212" /></a> </p> <p>I removed Safari.browser and Chrome.browser from the App_Browsers folder.</p> <p><strong>Done!</strong></p>
Flickr Virtual Path Provider
/blogs/Thomas-Krantz-/Dates/2010/8/Flickr-Virtual-Path-Provider/
2010-08-19T00:15:58.0000000Z
<p>I just put together a VPP for using Flickr photosets and photos in the EPiServer filemanager. The photos are cached locally. Uploading (among other things) is not yet supported.</p> <p>This little experiment of mine should be considered an.. uhm, well, an experiment. Use at your own risk.</p> <h2>Installation</h2> <p>Installation is easy, just add the VPP to your virtualPath section. You need to insert your own API key and User Id in the URL.</p> <p><a href="/link/f63b90ffbaff4b6e84788df41ccf42be.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="/link/e4f1672669c740328716724b4a964f67.png" width="614" height="48" /></a></p> <p>The VPP will display photosets as directories. </p> <p><a href="/link/2ec069251ed64fb3b39859a1d2033703.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="/link/becfb9ba0c7a4d42888b3f0760942efd.png" width="586" height="279" /></a></p> <p> </p> <p>Binaries and full source code is located at <a href="http://flickrvpp.codeplex.com/">http://flickrvpp.codeplex.com/</a></p>
Insert EPiServer page properties into CSS-files with EPiCssModifier
/blogs/Thomas-Krantz-/Dates/2010/8/Insert-EPiServer-page-properties-into-CSS-files-with-EPiCssModifier/
2010-08-12T16:39:40.0000000Z
<p>Have you ever wanted to replace hard wired image urls in your css files with images selected from EPiServer? That is, without using inline css in your templates.</p> <p>Usually, your css may look something like:</p> <p><a href="/link/e46f93a3b58a4ab99b5b9784770c09c6.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="/link/d65098ab412e4e8da3e67ff5dcfaea0e.png" width="328" height="131" /></a> </p> <p>You want to let the editors pick the image for the logo, right?</p> <p>If you’re using PageTypeBuilder – which you should – then it’s only a matter of adding a property attribute to your page type class. Like so:</p> <p><a href="/link/6bc6e007be1a477cbfa58915e056715e.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="/link/04efa3f6b6f34442ab570afdcb643d5a.png" width="524" height="56" /></a> </p> <p>The CssFragment attribute in the property declaration means that you want to replace /ui/gfx/logo.png in all css-files with whatever value LogoImage contains.</p> <p>What happens when you render the page is that the css links are modified slightly. This is your original css link:</p> <p><a href="/link/72a8ea36bae2411fb4031d043a92dcc4.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="/link/dcf4d5c12a6b4076847102e9c4f34292.png" width="511" height="36" /></a> </p> <p>Instead, it will render:</p> <p><a href="/link/2700414595284b78bb95598bcd6cba24.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="/link/2be4c904fc66453da0e2a195064a07ef.png" width="513" height="35" /></a> </p> <p>Note the appended query string to the css link.</p> <p>Then a http handler will catch the request to the css-file and do a simple search and replace based on the query string parameters. The result will be a css that looks like this:</p> <p><a href="/link/9c2ad24594734c42be16d387f23fb4b8.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="/link/46852d86dbfe43d8bb20291088f6f40f.png" width="307" height="118" /></a> </p> <h2>Prerequisites:</h2> <p>1. EPiServer CMS 6</p> <p>2. PageTypeBuilder</p> <h2>To use:</h2> <p>1. Unzip, compile and drop the EPiCssModifier.dll in your /bin</p> <p>2. Add this to the Web.config:</p> <p><a href="/link/3db3b8c65ded468cad45f7ef6569cc17.png"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="/link/90de0ed7bb434484955d0ff61cd7b7cf.png" width="493" height="89" /></a></p> <p>3. Voila! You’ve got yourself an inline-css free road to happiness.</p> <p>Download source and binaries for <a href="http://www.tkz.se/EPiCssModifier.zip">EPiCssModifier</a></p>
Filter and sort pages in as few lines as possible
/blogs/Thomas-Krantz-/Dates/2009/9/Filter-and-sort-pages-in-as-few-lines-as-possible/
2009-09-08T13:46:39.0000000Z
<p>An example of a couple of useful lambda expressions. At least I think so. These lines are used on a typical A-Z index page, and use a HTTP parameter (line 2) to filter the pages. On line 3 it uses a gorgious lambda to sort by page name.</p> <p>Can it be done shorter or more beautiful, I wonder? :)</p> <div class="csharpcode"> </div> <div class="csharpcode"> <pre class="language-csharp"><code><span class="lnum"> 1: </span>List<PageData> pages = <span class="kwrd">new</span> List<PageData>(GetChildren(CurrentPage.PageLink));</code></pre>
<pre class="language-csharp"><code><span class="lnum"> 2: </span>pages.RemoveAll(page => !page.PageName.ToUpper().StartsWith(Request[<span class="str">"c"</span>].ToUpper()));</code></pre>
<pre class="language-csharp"><code><span class="lnum"> 3: </span>pages.Sort((p1, p2) => p1.PageName.CompareTo(p2.PageName));</code></pre>
<pre class="language-csharp"><code><span class="lnum"> 4: </span> </code></pre>
<pre class="language-csharp"><code><span class="lnum"> 5: </span><span class="rem">// plDictionary is a PageList. Contains all pages with a page name starting with </span></code></pre>
<pre class="language-csharp"><code><span class="lnum"> 6: </span><span class="rem">// the string Request["c"].</span></code></pre>
<pre class="language-csharp"><code><span class="lnum"> 7: </span>plDictionary.DataSource = pages;</code></pre>
<pre class="language-csharp"><code><span class="lnum"> 8: </span>plDictionary.DataBind();</code></pre>
</div>
<style type="text/css"><![CDATA[
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", 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; }]]></style>
EPiCodeSmells
/blogs/Thomas-Krantz-/Dates/2009/9/EPiCodeSmells/
2009-09-07T19:07:28.0000000Z
<p>My thoughts on some code smells I’ve come across. These three are the ones that tend to turn my stomach the most.</p> <p>Here goes..</p> <h2>Class properties for easy access to MainBody, MainIntro etc.</h2> <p>I often see a bunch of these duplicated in all templates, often disguised in a “#region Properties”, an obvious hint that I am in for a treat..</p> <pre class="language-csharp"><code> <span class="kwrd">public</span> <span class="kwrd">string</span> MainBody
{
get
{
<span class="kwrd">if</span>(IsValue(<span class="str">"MainBody"</span>))
<span class="kwrd">return</span> (<span class="kwrd">string</span>) CurrentPage[<span class="str">"MainBody"</span>];
<span class="kwrd">return</span> String.Empty;
}
}</code></pre>
<style type="text/css"><![CDATA[
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", 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; }]]></style>
<style type="text/css"><![CDATA[
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", 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; }]]></style>I have even seen code snippets in Visual Studio being used to generate these. This indicates the lack of sensible base classes. And if you want strongly typed Episerver properties, there are <a href="http://pagetypebuilder.codeplex.com/" target="_blank">better ways</a>.
<h2></h2>
<h2>Hardcoded ids in Web.config</h2>
<p>When poking around a new project, one of the first things I generally do, is open up Web.config. I scroll down to the appSettings-element, and if I find 10+ custom keys, I can smell the lack of Admin tabs and/or Settings page.</p>
<p>Usually goes something like:</p>
<pre class="language-csharp"><code> <add key=<span class="str">"ContactFormPage"</span> <span class="kwrd">value</span>=<span class="str">"12312"</span> />
<add key=<span class="str">"ContactFormPageEN"</span> <span class="kwrd">value</span>=<span class="str">"54312"</span> />
<add key=<span class="str">"ProductModulePageTypeId"</span> <span class="kwrd">value</span>=<span class="str">"93"</span> />
<add key=<span class="str">"ModuleContactPageTypeId"</span> <span class="kwrd">value</span>=<span class="str">"38,39"</span> />
<add key=<span class="str">"ModulePageTypeId"</span> <span class="kwrd">value</span>=<span class="str">"3"</span> />
<add key=<span class="str">"MyCoolPageTypeId"</span> <span class="kwrd">value</span>=<span class="str">"42"</span> />
<add key=<span class="str">"CalendarEventPageType"</span> <span class="kwrd">value</span>=<span class="str">"11"</span> />
<add key=<span class="str">"DivisionStartPageTypeId"</span> <span class="kwrd">value</span>=<span class="str">"46"</span> />
<add key=<span class="str">"404PageId"</span> <span class="kwrd">value</span>=<span class="str">"78781"</span> />
<add key=<span class="str">"FileNotFoundPageId"</span> <span class="kwrd">value</span>=<span class="str">"12333"</span>/>
<add key=<span class="str">"GenericErrorPageId"</span> <span class="kwrd">value</span>=<span class="str">"543"</span>/></code></pre>
<p>Episerver comes with a “Pagetype” property type. Use it.</p>
<h2></h2>
<style type="text/css"><![CDATA[
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", 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; }]]></style>
<h2>The Utils-class</h2>
<p>Everyone got them. At least some version of it, duplicated from one project to another, tweaked and refactored along the way. It usually contains the all familiar StripHtml(), Ellipse(), PreviewText(), MyGetPropertyWithFallbackValue(). </p>
<p>Not really a smell perhaps, but I sort it into the <a href="http://en.wikipedia.org/wiki/Don%27t_repeat_yourself" target="_blank">DRY</a> category.</p>
<p>Thoughts anyone? I am sure you have experienced your fair share of smells, perhaps worse than mine…?</p>