<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Geekrocket Blog]]></title><description><![CDATA[Posts about Sitecore and software development]]></description><link>https://blog.geekrocket.com/</link><image><url>https://blog.geekrocket.com/favicon.png</url><title>Geekrocket Blog</title><link>https://blog.geekrocket.com/</link></image><generator>Ghost 5.88</generator><lastBuildDate>Mon, 13 Apr 2026 11:21:09 GMT</lastBuildDate><atom:link href="https://blog.geekrocket.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Bucket Folder Path Resolution Allows Inheritance]]></title><description><![CDATA[<p>SXA allows you to configure bucket folder path rules on your multisite Settings item, for example <strong>/sitecore/Content/(tenant)/(site)/Settings </strong>in the &quot;Rules for Resolving the Bucket Folder Path&quot; field.</p><figure class="kg-card kg-image-card"><img src="https://blog.geekrocket.com/content/images/2021/12/Create-rule.png" class="kg-image" alt loading="lazy" width="1004" height="763" srcset="https://blog.geekrocket.com/content/images/size/w600/2021/12/Create-rule.png 600w, https://blog.geekrocket.com/content/images/size/w1000/2021/12/Create-rule.png 1000w, https://blog.geekrocket.com/content/images/2021/12/Create-rule.png 1004w" sizes="(min-width: 720px) 720px"></figure><p>We had a list of rules - one for each of the bucket folders that we&apos;</p>]]></description><link>https://blog.geekrocket.com/bucket-folder-path-resolution-allows-inheritance/</link><guid isPermaLink="false">69a5e07d8c61d516e008ce80</guid><category><![CDATA[Sitecore]]></category><dc:creator><![CDATA[Matt Taylor]]></dc:creator><pubDate>Sun, 05 Dec 2021 23:05:00 GMT</pubDate><content:encoded><![CDATA[<p>SXA allows you to configure bucket folder path rules on your multisite Settings item, for example <strong>/sitecore/Content/(tenant)/(site)/Settings </strong>in the &quot;Rules for Resolving the Bucket Folder Path&quot; field.</p><figure class="kg-card kg-image-card"><img src="https://blog.geekrocket.com/content/images/2021/12/Create-rule.png" class="kg-image" alt loading="lazy" width="1004" height="763" srcset="https://blog.geekrocket.com/content/images/size/w600/2021/12/Create-rule.png 600w, https://blog.geekrocket.com/content/images/size/w1000/2021/12/Create-rule.png 1000w, https://blog.geekrocket.com/content/images/2021/12/Create-rule.png 1004w" sizes="(min-width: 720px) 720px"></figure><p>We had a list of rules - one for each of the bucket folders that we&apos;re using to store data being imported via Data Exchange Framework pipeline batches. This grew slowly but steadily over time, with our process being:</p><ul><li>Create a new data template and folder template to represent the data, configuring the standard values as required.</li><li>Create an instance of the folder to hold the data</li><li>Build the pipeline to import/update the data</li><li>Add a rule to this Settings item to configure the bucketing for the folder template</li></ul><p>This was based on the initial assumption that we might have different bucketing requirements, plus looking at the default &quot;<strong>where the item bucket is based on the &lt;template&gt; template</strong>&quot; rule suggested that it was looking for an exact match on the selected template.</p><p>Looking at the implementation of that rule, the Sitecore item definition is located in the <strong>/sitecore/system/Settings/Rules/Definitions/Elements/Bucketing</strong>, and is named <strong>Bucket Item Template.</strong></p><p>The underlying type is <strong>Sitecore.Buckets.Rules.Bucketing.Conditions.WhenBucketTemplateIs </strong>(in <strong>Sitecore.Buckets</strong>)<strong> </strong>and looking at the actual implementation of that we found that it checks not just the folder template itself, but also checks against the list of base templates.</p><p>This meant we could simplify by creating a new &quot;Bucketing Base Folder&quot; template, inherit that on to all of our type-specific folder templates, and simplify the bucket folder rule down to just &quot;where the item bucket is based on the &lt;Bucketing Base Fodler&gt; template&quot; to have the rule applied consistently.</p>]]></content:encoded></item><item><title><![CDATA[Show Pipeline Batch Status]]></title><description><![CDATA[<p>We were running a series of data importing jobs and wanted to show the count of items in the pipeline status dialog:</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://blog.geekrocket.com/content/images/2021/12/Status-1.png" class="kg-image" alt loading="lazy" width="1051" height="580" srcset="https://blog.geekrocket.com/content/images/size/w600/2021/12/Status-1.png 600w, https://blog.geekrocket.com/content/images/size/w1000/2021/12/Status-1.png 1000w, https://blog.geekrocket.com/content/images/2021/12/Status-1.png 1051w"></figure><p>The Show Pipeline Batch Status command is available when a Pipeline Batch item (under <strong>/sitecore/System/Data Exchange/(provider)/Pipeline Batches/</strong>) is selected and is currently running.</p><p>Our</p>]]></description><link>https://blog.geekrocket.com/show-pipeline-batch-status/</link><guid isPermaLink="false">69a5e07d8c61d516e008ce7f</guid><category><![CDATA[Sitecore]]></category><category><![CDATA[Data Exchange Framework]]></category><dc:creator><![CDATA[Matt Taylor]]></dc:creator><pubDate>Fri, 03 Dec 2021 20:56:37 GMT</pubDate><content:encoded><![CDATA[<p>We were running a series of data importing jobs and wanted to show the count of items in the pipeline status dialog:</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://blog.geekrocket.com/content/images/2021/12/Status-1.png" class="kg-image" alt loading="lazy" width="1051" height="580" srcset="https://blog.geekrocket.com/content/images/size/w600/2021/12/Status-1.png 600w, https://blog.geekrocket.com/content/images/size/w1000/2021/12/Status-1.png 1000w, https://blog.geekrocket.com/content/images/2021/12/Status-1.png 1051w"></figure><p>The Show Pipeline Batch Status command is available when a Pipeline Batch item (under <strong>/sitecore/System/Data Exchange/(provider)/Pipeline Batches/</strong>) is selected and is currently running.</p><p>Our pipelines use IterableDataSettings objects to pass lists of items that need to be created or updated, and this is the count we would like to display - but it doesn&apos;t automatically just count the number of items in these objects and use it as the &quot;Entities submitted&quot; count.</p><p>With the &quot;Show Pipeline Batch Status&quot; button in the Content Editor as my starting point, I tracked back from there:</p><ul><li>Inspecting the button shows that the onclick event fires <code>javascript:return scForm.invoke(&apos;dataExchange:showPipelineBatchStatusCommand()&apos;, event)</code></li><li>This method name is a good place to start, so opening up dotPeek and searching for &quot;PipelineBatchStatusCommand&quot; leads to <code>Sitecore.DataExchange.Local.Commands.ShowPipelineBatchStatusCommand</code>. After validating the state of the pipeline batch, this method calls <code>GetRunningPipelineBatchContext(...)</code> on the pipeline batch runner to retrieve a <code>PipelineBatchSummary</code> object.</li><li>A <code>PipelineBatchSummary</code> has an <code>int EntitySubmitedCount</code> (sp) property, so now we know where the count is stored!</li><li>Doing a &quot;find usages&quot; on the property itself reveals an example usage in <code>Sitecore.DataExchange.Providers.XConnect.Processors.PipelineSteps.BaseSubmitXConnectBatchStepProcessor.OnBatchProcessed(...)</code>. It makes sense that this kind of foundational method could be used to update this property consistently for any of the XConnect batches that are running.</li><li>The <code>OnBatchProcessed(...)</code> method ultimately calls the equivalent of: <code>pipelineContext?.PipelineBatchContext?.CurrentPipelineBatch?.GetPipelineBatchSummary()</code> to access the <code>PipelineBatchSummary</code> object, and then does a simple <code>+=</code> to increment that int property.</li></ul><p>For reference - <code>GetPipelineBatchSummary()</code> used by the previous step is an extension method found in <code>Sitecore.DataExchange.Extensions</code>. It calls <code>pipelineBatch.GetPlugin&lt;PipelineBatchSummary&gt;()</code> - so this object is tracked in the pipeline batch itself using the standard DEF plugin system.</p><p>Updating our import job to increment this property allowed us to show the total number of items we had processed.</p>]]></content:encoded></item><item><title><![CDATA[Blank lines in files generated by T4 templates]]></title><description><![CDATA[Why does my T4 text template (.tt) generate a code file full of empty lines?]]></description><link>https://blog.geekrocket.com/blank-lines-in-files-generated-by-t4-templates/</link><guid isPermaLink="false">69a5e07d8c61d516e008ce7c</guid><category><![CDATA[.NET]]></category><dc:creator><![CDATA[Matt Taylor]]></dc:creator><pubDate>Wed, 04 Apr 2018 06:37:00 GMT</pubDate><content:encoded><![CDATA[<p>After checking out an old solution and running a T4 template (.tt file) that used to work perfectly, I found that the output included a whole heap of additional line breaks.</p><pre><code>// The template looks like this:
&lt;#@ template debug=&quot;false&quot; hostspecific=&quot;true&quot; language=&quot;C#&quot; #&gt;
&lt;#@ output extension=&quot;.cs&quot; #&gt;
&lt;#@ assembly name=&quot;System.Core&quot; #&gt;
&lt;#
  // Code to do things
#&gt;
public class Foo() {
....
}

</code></pre><p>The output looked like this:</p><pre><code>// The output looks like this: 



 
public class Foo() {
....
}
</code></pre><p>There were also additional blank lines within the body of the generated class - with a blank line being present wherever a T4 tag was closed and a new line started (i.e. <code>#&gt;</code>). After a bit of digging and experimentation I found that the file was checked out with <code>LF</code> line endings instead of <code>CRLF</code> line endings.</p><p>It seems that a line ending of <code>\r\n</code> after a closing tag is completely omitted, but if the line ending is just <code>\n</code> it won&apos;t be omitted and will actually be rendered out to the generated document.</p><p><em>The fix?</em></p><p>A find/replace to change changing each <code>\n</code> to a <code>\r\n</code> and then re-running the T4 template generated the correct output:</p><pre><code>// The fixed output without any extra empty lines:
public class Foo() {
....
}
</code></pre>]]></content:encoded></item><item><title><![CDATA[Refactoring out SheerResponse calls in Sitecore 8+]]></title><description><![CDATA[<p>Sheer UI was deprecated in Sitecore 8 and has been replaced by the SPEAK framework.</p><p>Calls to the <code>SheerResponse</code> class should be remapped to the <code>ClientResponse</code> class, for example:</p><p><code>Sitecore.Web.UI.Sheer.SheerResponse.Alert(&quot;Invalid user.&quot;);</code></p><p>becomes</p><p><code>Context.ClientPage.ClientResponse.Alert(&quot;Invalid user.&quot;);</code></p>]]></description><link>https://blog.geekrocket.com/refactoring-out-sheerresponse-calls-in-sitecore-8/</link><guid isPermaLink="false">69a5e07d8c61d516e008ce7b</guid><category><![CDATA[Sitecore]]></category><dc:creator><![CDATA[Matt Taylor]]></dc:creator><pubDate>Fri, 29 Dec 2017 05:37:00 GMT</pubDate><content:encoded><![CDATA[<p>Sheer UI was deprecated in Sitecore 8 and has been replaced by the SPEAK framework.</p><p>Calls to the <code>SheerResponse</code> class should be remapped to the <code>ClientResponse</code> class, for example:</p><p><code>Sitecore.Web.UI.Sheer.SheerResponse.Alert(&quot;Invalid user.&quot;);</code></p><p>becomes</p><p><code>Context.ClientPage.ClientResponse.Alert(&quot;Invalid user.&quot;);</code></p>]]></content:encoded></item><item><title><![CDATA[Making legacy Unity code a bit more testable]]></title><description><![CDATA[<p>A current project I&apos;m working on uses <a href="https://msdn.microsoft.com/en-us/library/ff647202.aspx">Unity</a> to do dependency injection which has created a little bit of a challenge. Much of this code was architected and built several years ago, and generally follows a repository/DAO pattern where:</p><p><strong>A static <code>InjectionContainer</code> class holds a reference to</strong></p>]]></description><link>https://blog.geekrocket.com/making-legacy-unity-code-a-bit-more-testable/</link><guid isPermaLink="false">69a5e07d8c61d516e008ce7e</guid><category><![CDATA[.NET]]></category><dc:creator><![CDATA[Matt Taylor]]></dc:creator><pubDate>Wed, 13 Apr 2016 06:39:00 GMT</pubDate><content:encoded><![CDATA[<p>A current project I&apos;m working on uses <a href="https://msdn.microsoft.com/en-us/library/ff647202.aspx">Unity</a> to do dependency injection which has created a little bit of a challenge. Much of this code was architected and built several years ago, and generally follows a repository/DAO pattern where:</p><p><strong>A static <code>InjectionContainer</code> class holds a reference to our UnityContainer.</strong> This container maps all the interfaces to the implementation instances, and is configured at <code>Application_Start</code> as defined in <code>Global.asax.cs</code> (as this is a .NET web application).</p><pre><code>void Application_Start(object sender, EventArgs e)
{
    // Code that runs on application startup
    var container = new UnityContainer();
    container.RegisterInstance&lt;IMessagingDao&gt;(new MessagingDao());
    InjectionContainer.Container = container;
}
</code></pre><p><strong>To actually &quot;do&quot; something, a page/control will create an instance of a repository class.</strong> The repository can then resolve and invoke methods on any relevant DAO object(s) as required, as well as internally encapsulating all business logic. Each instance of the repository lives only as long as the calling method requires, and it is disposed of when it falls out of scope. The intent here is to keep all the business logic at the repository layer, separate from the data access layer. A repository class might look similar to:</p><pre><code>public class MessagingRepository
{
    // Many methods, similar to:
    public void SendMessage(Message message)
    {
        // (Additional repo-level logic omitted from here)
        var dao = InjectionContainer.Container.Resolve&lt;IMessagingDao&gt;();
        dao.SendMessage(message);
    }
}
</code></pre><p>Yes, there are lots of newer/better patterns, but this is what we&apos;ve got and it works. Without a good business case for why we should rip it out, refactor/rewrite and regression test everything - it&apos;s going to stick around for a little while.</p><p>The challenge here was to make this more testable. The complications were:</p><ol><li><strong>To minimise changes to the existing code.</strong> The purpose is to make the code testable, and possibly a little bit cleaner along the way.</li><li><strong>To work around the anti-pattern of having a static IoC class.</strong> The static <code>InjectionContainer</code> class also causes complications running tests concurrently in the same app domain when you want to have different mappings configured. I&apos;m a big fan of <a href="http://www.ncrunch.net">NCrunch</a> so I wanted whatever solution I used to play nicely with it&apos;s test runner.</li></ol><p>Unfortunately we can&apos;t just jump to constructor injection as the change was too big and would necessitate us re-testing everything at a point in time where we weren&apos;t able to do this. But we can take a few steps in that direction...</p><p>Each repository contains several methods, many of which will ultimately be resolving the DAO. So why not replace all the calls to resolve the interface with a method to give us a single interception point?</p><pre><code>public class MessagingRepository
{
    private IMessagingDao _messagingDao;
    private IMessagingDao ResolveMessagingDao()
    {
        if (_messagingDao == null)
            _messagingDao = InjectionContainer.Container.Resolve&lt;IMessagingDao&gt;();
        return _messagingDao;
    }

    public void SendMessage(Message message)
    {
        var dao = ResolveMessagingDao();
        dao.SendMessage(message);
    }
}
</code></pre><p>I used the more verbose name &quot;ResolveMessagingDao&quot; as some of the repositories rely upon multiple DAOs, so it was easier to be clearly consistent everywhere rather than having some methods named &quot;ResolveDao&quot; if only a single DAO was used in that repository.</p><p>This new <code>ResolveMessagingDao()</code> method will now resolve and cache the reference to the DAO object for the lifetime of the repository, which is fine given that our usage pattern is to create an instance of the repository when required, use the repository, then discard it when it falls out of scope. This gives us the point to add constructor injection, by replacing the implicit default constructor with two explicit constructors:</p><pre><code>public MessagingRepository()
{
    // Explicit parameterless constructor to replace the implicit
    // default constructor which we used to rely on.
}

public MessagingRepository(IMessagingDao messagingDao)
{
    if (messagingDao == null)
        throw new ArgumentNullException(&quot;messagingDao&quot;);

    _messagingDao = messagingDao;
}
</code></pre><p>These constructors give us two options:</p><ol><li>Implicit support for the old behaviour, where creating an instance of the repository using the parameterless constructor will cause the DAOs to be resolved via Unity. Additionally, the reference to this DAO instance is then cached within the repository for each subsequent use (although admittedly the &quot;cost&quot; of resolving it is insignificant).</li><li>Explicit support via the new constructor, which allows us to supply the instances of the DAO we want the repository to use. Additionally by preventing null values from being provided to that constructor, I&apos;m making sure that I can&apos;t pass in null unexpectedly and then have it (silently) fall back to using Unity for resolution.</li></ol><p>Another option would have been to resolve the DAOs in the parameterless constructor, but this didn&apos;t feel like the correct solution as there are often repository methods that don&apos;t even need to access anything at the DAO layer at all.</p><p>Ultimately this solution worked and made all the repository-layer code testable by allowing it to be run against explicitly-created mock DAO objects with minimal side effects on the main project itself.</p>]]></content:encoded></item><item><title><![CDATA[ViewState is not always your enemy]]></title><description><![CDATA[<p>I had to support a legacy Web Forms application and while in the process of cleaning up several existing UserControls I had to explain to another developer exactly why using the ViewState to store custom properties wasn&apos;t worse than the current solution - which was, on every page</p>]]></description><link>https://blog.geekrocket.com/viewstate-is-not-always-your-enemy/</link><guid isPermaLink="false">69a5e07d8c61d516e008ce7d</guid><category><![CDATA[.NET]]></category><dc:creator><![CDATA[Matt Taylor]]></dc:creator><pubDate>Fri, 08 Apr 2016 06:38:00 GMT</pubDate><content:encoded><![CDATA[<p>I had to support a legacy Web Forms application and while in the process of cleaning up several existing UserControls I had to explain to another developer exactly why using the ViewState to store custom properties wasn&apos;t worse than the current solution - which was, on every page load, setting a large number of properties that weren&apos;t persisted beyond that page view.</p><p>For example, we had a property on the UserControl that wouldn&apos;t persist the value between postbacks:</p><pre><code>public string EmptyMessage { get; set; }
</code></pre><p>This value was being set in the parent&apos;s <code>Page_Load</code> event on every page load. To change this so that it would persist the value, I could replace the property declaration with:</p><pre><code>public string EmptyMessage
{
    get { return (string)ViewState[&quot;EmptyMessage&quot;]; }
    set { ViewState[&quot;EmptyMessage&quot;] = value; }
}
</code></pre><p>In explaining this change, I had to summarise why this wasn&apos;t a terrible idea. I&apos;ll admit that I had spent a long time thinking that the ViewState was a monstrous blob of encoded text that did nothing but bulk up my web pages unnecessarily, and for a long time wrote code so that every page essentially had <code>EnableViewState=&quot;false&quot;</code>. ViewState isn&apos;t the right answer for absolutely everything, but it is definitely useful in some circumstances.</p><p>My key points were:</p><ul><li><strong>If it makes sense to persist a value, then persist it.</strong> If saving a property lets you save time or effort, then just persist it. This can help make your code more declarative, so your parent control &quot;tells&quot; this control how to behave once and this control can &quot;remember&quot; to behave a certain way, display a certain message, etc.</li><li><strong>Work out if the ViewState is the right place to persist this information.</strong> This is a much bigger question, but the ViewState generally isn&apos;t the right place to store large blobs of data. Small strings and other simple values, sure.</li><li><strong>Setting a ViewState-backed property at design time won&apos;t make your ViewState huge, because these values aren&apos;t actually be stored in the ViewState.</strong> If you declare an initial value, for example <code>&lt;project:MyControl runat=&quot;server&quot; EmptyMessage=&quot;There&apos;s nothing here!&quot; /&gt;</code> - this default value won&apos;t be saved in to the ViewState because it&apos;s being set before <code>TrackViewState()</code> is called. The value will actually just be re-applied to your object on each subsequent page load, and then be overwritten later in the page lifecycle if you&apos;ve actually changed it.</li><li><strong>Don&apos;t try to save things to the ViewState in Init.</strong> Similar to the point above, changes you make at this point in the page lifecycle aren&apos;t tracked yet, so you&apos;d have to re-apply them on each page request.</li></ul><p>I remember that when I started to understand how the <a href="https://msdn.microsoft.com/en-us/library/ms972976.aspx">ViewState behaves over the page life cycle</a> it was an &quot;a-ha!&quot; moment where the ViewState became something that made sense, rather than being a strange black box that just &quot;somehow&quot; sometimes remembered things.</p>]]></content:encoded></item><item><title><![CDATA[Fast session timeouts and Sitecore robot detection]]></title><description><![CDATA[<p>Unfortunately I&apos;ve seen this issue in two different projects over the last few years. Sitecore uses a visitor identification sublayout to determine whether a site visitor is a bot or an actual human visitor. If you are a bot, your session times out much faster (1 minute, by</p>]]></description><link>https://blog.geekrocket.com/fast-session-timeouts-and-sitecore-robot-detection/</link><guid isPermaLink="false">69a5e07d8c61d516e008ce7a</guid><category><![CDATA[Sitecore]]></category><dc:creator><![CDATA[Matt Taylor]]></dc:creator><pubDate>Thu, 03 Mar 2016 05:35:00 GMT</pubDate><content:encoded><![CDATA[<p>Unfortunately I&apos;ve seen this issue in two different projects over the last few years. Sitecore uses a visitor identification sublayout to determine whether a site visitor is a bot or an actual human visitor. If you are a bot, your session times out much faster (1 minute, by default) than the session timeout value you would have otherwise configured.</p><p>The first time I saw this, it was an intermittent issue as the visitor identification sublayout was only missing on certain pages. Whether the user had a normal session duration or the shorter (a.k.a. &quot;Why have I been logged out?!&quot;) duration depended on their path through the site.</p><p>The visitor identification sublayout should be included on <em>every</em> page. The easiest way to do this is to include it in your masterpages/layouts:</p><pre><code>// Webforms
&lt;sc:VisitorIdentification runat=&quot;server&quot; /&gt;

// MVC
@Html.Sitecore().VisitorIdentification()
</code></pre><p>This renders out a stylesheet tag - if your browser actually requests this file, you&apos;re probably a person and it marks your session as &apos;not a robot&apos;. If you don&apos;t load this empty stylesheet, you&apos;re probably a robot and you&apos;ll have the much faster logout. The exact session timeout is configured as:</p><pre><code>&lt;setting name=&quot;Analytics.Robots.SessionTimeout&quot; value=&quot;1&quot; /&gt;
</code></pre><p>Rather than adding the VisitorIdentification sublayout to every page, there is also the thermonuclear option of disabling the robot detection entirely by setting this value to <em>false</em>:</p><pre><code>&lt;setting name=&quot;Analytics.AutoDetectBots&quot; value=&quot;false&quot; /&gt;
</code></pre><p>More information is available in the Sitecore documentation on how to <a href="https://doc.sitecore.net/sitecore_experience_platform/xdb_configuration/configure_the_robot_detection_component">configure the robot detection component</a>.</p>]]></content:encoded></item><item><title><![CDATA[Clearing a custom delivery server cache on publish]]></title><description><![CDATA[<p>We have a non-Sitecore custom cache (which follows identical rules on both delivery servers and the authoring server) responsible for building up a hierarchy that is derived from a combination of Sitecore items and data in a custom database. The only trigger that can invalidate this cache is if the</p>]]></description><link>https://blog.geekrocket.com/clearing-a-custom-delivery-server-cache-on-publish/</link><guid isPermaLink="false">69a5e07d8c61d516e008ce79</guid><category><![CDATA[Sitecore]]></category><dc:creator><![CDATA[Matt Taylor]]></dc:creator><pubDate>Thu, 25 Feb 2016 05:33:00 GMT</pubDate><content:encoded><![CDATA[<p>We have a non-Sitecore custom cache (which follows identical rules on both delivery servers and the authoring server) responsible for building up a hierarchy that is derived from a combination of Sitecore items and data in a custom database. The only trigger that can invalidate this cache is if the Sitecore items are modified and republished. So how do we pick up when this happens?</p><p>Our previous implementation hooked in to the Publish pipeline, and was basically a PublishProcessor that used a little bit of logic to determine if the item being published should trigger clearing the internal cache. The method itself looked something like this:</p><pre><code>namespace Project.Pipelines.Publish
{
    public class ClearListCache : PublishProcessor
    {
        public override void Process(PublishContext context)
        {
            // Clear our cache
        }
    }
}
</code></pre><p>This was then hooked up to the publish pipeline in <code>Sitecore.config</code>.</p><p>Our new implementation is an event handler that listens for the <code>publish:end:remote</code> (on delivery servers) or <code>publish:end</code> event (on the authoring server):</p><pre><code>namespace Project.Pipelines.Publish
{
    public class PublishEndClearCacheHandler
    {
        public void ClearCache(object sender, EventArgs args)
        {
            // Clear our cache
        }
    }
}
</code></pre><p>With the following in <code>Sitecore.config</code> (on the delivery server):</p><pre><code>&lt;event name=&quot;publish:end:remote&quot;&gt;
    &lt;handler
        type=&quot;Project.Pipelines.Publish.PublishEndClearCacheHandler, Project&quot;
        method=&quot;ClearCache&quot; /&gt;
&lt;/event&gt;
</code></pre><p>The handler <code>type</code> is a string containing the <a href="https://msdn.microsoft.com/en-us/library/system.type.assemblyqualifiedname(v=vs.110).aspx">assembly-qualified name</a> of the event handler class - that is, the type name including the namespace, followed by a comma, followed by the assembly display name. The <code>method</code> string contains the name of the method on that type to invoke.</p><p>The handler for this particular event can also accept a <code>PublishEndRemoteEventArgs</code> instead of an <code>EventArgs</code> argument - however we didn&apos;t need it in this case.</p>]]></content:encoded></item><item><title><![CDATA[Sitecore 8 DateFields are now UTC]]></title><description><![CDATA[<p>After upgrading from Sitecore 7 to Sitecore 8 we started to notice that some of the dates shown across our site (in the format &quot;22 Feb 2016&quot;) were showing a date one day earlier than expected.</p><p>This date is pulled from a <code>DateField</code> on the item in Sitecore,</p>]]></description><link>https://blog.geekrocket.com/sitecore-8-datefields-are-now-utc/</link><guid isPermaLink="false">69a5e07d8c61d516e008ce77</guid><category><![CDATA[Sitecore]]></category><dc:creator><![CDATA[Matt Taylor]]></dc:creator><pubDate>Wed, 24 Feb 2016 05:28:00 GMT</pubDate><content:encoded><![CDATA[<p>After upgrading from Sitecore 7 to Sitecore 8 we started to notice that some of the dates shown across our site (in the format &quot;22 Feb 2016&quot;) were showing a date one day earlier than expected.</p><p>This date is pulled from a <code>DateField</code> on the item in Sitecore, and stepping through in the debugger it became apparent that the dates were off by exactly 11 hours. Eleven hours is the difference between our current timezone and UTC... suspicious! After a little bit of <a href="https://briancaos.wordpress.com/2015/04/16/sitecore-8-servertimezone-my-dates-are-all-wrong/">reading</a> and checking the documentation I confirmed that this is indeed the case.</p><p>We were previously using an extension method named <code>GetDateTime</code> which we used to return a <code>DateTime?</code> value from a <code>DateField</code> on an <code>Item</code>, so it was simply a matter of tweaking it slightly to take advantage of the <code>DateUtil.ToServerTime</code> method Sitecore already provides:</p><pre><code>public static DateTime? GetLocalDateTime(this Item item, string fieldName)
{
    var field = item.Fields[fieldName];
    if(field != null)
    {
        var field = (DateField)item.Fields[fieldName];
        var value = field.DateTime;
        if(value.Year &gt; 0001)
            return DateUtil.ToServerTime(value);
    }
    return null;
}
</code></pre><p>I think my favourite thing about this issue was that our testing team initially missed this - because most of the testing was done in the afternoon! If an article was created after 11am, even subtracting 11 hours meant that it would still show the &quot;correct&quot; day. Only pages created before 11am would show the date for the previous day.</p>]]></content:encoded></item><item><title><![CDATA[Testing non-public methods from another project]]></title><description><![CDATA[<p>I had a few methods in a project that implemented some business logic that I wanted to be able to test from another project, but that weren&apos;t public. So how can I test them? Well...</p><p><em>A testable method should be relatively self-contained.</em> It should take a set of</p>]]></description><link>https://blog.geekrocket.com/testing-non-public-methods-from-another-project/</link><guid isPermaLink="false">69a5e07d8c61d516e008ce78</guid><category><![CDATA[.NET]]></category><dc:creator><![CDATA[Matt Taylor]]></dc:creator><pubDate>Tue, 23 Feb 2016 03:56:00 GMT</pubDate><content:encoded><![CDATA[<p>I had a few methods in a project that implemented some business logic that I wanted to be able to test from another project, but that weren&apos;t public. So how can I test them? Well...</p><p><em>A testable method should be relatively self-contained.</em> It should take a set of inputs and return any outputs without requiring or mutating any additional &quot;global&quot; state, so that you&apos;re testing just the behaviour of that method.</p><p><em>You need to be able to call the method.</em> This is easy if the method is <code>static</code>, or if it&apos;s on a public class that&apos;s easy to instantiate (i.e. no huge amount of build-up or tear-down should be required).</p><p><em>The method you&apos;re testing needs to be visible to your test project.</em> What <a href="https://msdn.microsoft.com/en-us/library/ms173121.aspx">access modifier</a> would let me make these already-static methods visible only within the main project and my test project?</p><ul><li>These methods weren&apos;t <code>public</code>, and had no reason to be. They shouldn&apos;t be called from anything outside that project (except tests!)</li><li>A <code>private</code> method is inaccessible.</li><li>A <code>protected</code> method on a public class would give me the ability to create a derived test class that would inherit from the base class, and would thus have access to the method... but that&apos;s too clunky.</li><li><code>protected internal</code> - also not quite right, similar to &apos;protected&apos; in this instance.</li><li><code>internal</code> which would allow them to be &quot;accessed by any code in the same assembly, but not from another assembly&quot;.</li></ul><p>Luckily <code>internal</code> (<code>Friend</code> in Visual Basic) works with the <strong>InternalsVisibleTo</strong> attribute to allow you to specify a set of other assemblies which are allowed to access <code>internal</code> methods. This was as simple as adding a declaration to my <em>main project</em> - which I put in to AssemblyInfo.cs:</p><pre><code>[assembly:InternalsVisibleTo(&quot;My.Test.Project&quot;)]
</code></pre><p>Now, My.Test.Project can call the internal methods declared in my main project without requiring me to make these methods visible to the entire world.</p><p>This gets a little bit trickier if you&apos;re using signed assemblies as you have to include the public key - but this is documented on the InternalsVisibleTo attribute <a href="https://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.internalsvisibletoattribute(v=vs.110).aspx#Anchor_7">MSDN page</a>.</p>]]></content:encoded></item></channel></rss>