<?xml version="1.0" encoding="utf-8"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><language>en</language><title>Blog posts by Tom Pipe</title> <link>https://world.optimizely.com/blogs/Tom-Pipe/</link><description></description><ttl>60</ttl><generator>Optimizely World</generator><item> <title>Utilising MEF to self-register HTTP modules</title>            <link>http://blog.tompipe.co.uk/post.aspx?id=4577d217-4738-4c66-804f-14ca2a15d034</link>            <description>&lt;!-- .csharpcode,.csharpcode pre { font-size:small; color:#000; font-family:consolas, &quot;Courier New&quot; , courier, monospace; background-color:#fff; }  .csharpcode pre { margin:0; }  .csharpcode .rem { color:green; }  .csharpcode .kwrd { color:#00f; }  .csharpcode .str { color:#006080; }  .csharpcode .op { color:#0000c0; }  .csharpcode .preproc { color:#c63; }  .csharpcode .asp { background-color:#ff0; }  .csharpcode .html { color:maroon; }  .csharpcode .attr { color:red; }  .csharpcode .alt { background-color:#f4f4f4; width:100%; margin:0; }  .csharpcode .lnum { color:#606060; }  --&gt;
&lt;p&gt;After &lt;a href=&quot;http://haacked.com/archive/2010/05/16/three-hidden-extensibility-gems-in-asp-net-4.aspx&quot; target=&quot;_blank&quot;&gt;reading&lt;/a&gt; about .NET 4’s new &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/system.web.preapplicationstartmethodattribute.aspx&quot; target=&quot;_blank&quot;&gt;PreApplicationStart&lt;/a&gt; method being used to register build providers without touching the web.config. I thought about other instances where editing the web.config was mundane. The first thing that came to mind was registering HTTP modules.&lt;/p&gt;
&lt;p&gt;HTTP Modules are a fantastic way to intercept HTTP requests, and “inject” code at each stage of the request lifecycle, and they are invaluable for sectioning code into pluggable components for reuse in another application. The only thing that’s bugged me is the need to register each module by adding an entry in the &amp;lt;httpModules&amp;gt; section within the web.config.&lt;/p&gt;
&lt;p&gt;Clearly great minds think alike. David Ebbo, an architect on the ASP.NET team &lt;a href=&quot;http://blog.davidebbo.com/2011/02/register-your-http-modules-at-runtime.html&quot; target=&quot;_blank&quot;&gt;announced&lt;/a&gt; a RegisterModule() API had been added in MVC3 allowing HttpModules to be registered without touching config, by using code like below:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;    [assembly: System.Web.PreApplicationStartMethod(&lt;span class=&quot;kwrd&quot;&gt;typeof&lt;/span&gt;(Initializer), &lt;span class=&quot;str&quot;&gt;&quot;Initialize&quot;&lt;/span&gt;)]
    &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;class&lt;/span&gt; Initializer
    {
        &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;void&lt;/span&gt; Initialize()
        {
            DynamicModuleUtility.RegisterModule(&lt;span class=&quot;kwrd&quot;&gt;typeof&lt;/span&gt;(ModuleA));
            DynamicModuleUtility.RegisterModule(&lt;span class=&quot;kwrd&quot;&gt;typeof&lt;/span&gt;(ModuleB));
            DynamicModuleUtility.RegisterModule(&lt;span class=&quot;kwrd&quot;&gt;typeof&lt;/span&gt;(ModuleC));
        }
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Yes it has it’s advantages, but this feels more like a step sideways than a step forward. Each module still has to be explicitly defined, so it’s almost exactly the same steps as adding a HttpModule via the web.config, albeit a slightly different syntax.&lt;/p&gt;
&lt;p&gt;This got me wondering if there was an easy way to discover modules and automatically register them using the RegisterModule method, and that seemed like a perfect scenario for MEF.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;Managed Extensibility Framework (MEF)&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, &quot;Courier New&quot;, courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } --&gt;&lt;/p&gt;
&lt;p&gt;MEF is a component of .NET 4.0 for creating lightweight, extensible applications. Extensions (known as parts, or exports) can be dynamically discovered (imported) from a configurable location (known as a Catalog) and used at run-time with no configuration required.&lt;/p&gt;
&lt;p&gt;MEF uses an &lt;em&gt;attributed programming model &lt;/em&gt;where “imports” and “exports” are declared by decorating classes or members with the Import and Export attributes.&lt;/p&gt;
&lt;p&gt;An Import is matched with one or more Exports, providing they have the same “contract”. The contract consists of a string, called the contract name, and the type of the exported or imported object, called the contract type. Only if both the contract name and contract type match is an export considered to be a match.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Attributes&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Usually classes are marked with the &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/system.componentmodel.composition.exportattribute.aspx&quot; target=&quot;_blank&quot;&gt;ExportAttribute&lt;/a&gt; but I wanted something that’s more distinct and self-explanatory. Therefore I created a new attribute, derived from the standard ExportAttribute. The code for the attribute is as follows:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;    [MetadataAttribute]
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = &lt;span class=&quot;kwrd&quot;&gt;false&lt;/span&gt;)]
    &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;class&lt;/span&gt; AutoRegisterHttpModuleAttribute : ExportAttribute, IMefMetaData
    {
        &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; AutoRegisterHttpModuleAttribute() : &lt;span class=&quot;kwrd&quot;&gt;base&lt;/span&gt;(&lt;span class=&quot;kwrd&quot;&gt;typeof&lt;/span&gt;(IHttpModule))
        {
            Enabled = &lt;span class=&quot;kwrd&quot;&gt;true&lt;/span&gt;;
        }

        &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;bool&lt;/span&gt; Enabled
        {
            get; set;
        }

        &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;string&lt;/span&gt; Name
        {
            get; set;
        }
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nothing unusual here, except the &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/system.componentmodel.composition.metadataattributeattribute(v=VS.100).aspx&quot; target=&quot;_blank&quot;&gt;MetadataAttribute&lt;/a&gt;. This informs MEF that there is additional metadata to be exposed. There isn’t necessarily a requirement for any metadata, but I’ve taken the opportunity to add some basic properties to assist us (I’ll describe this later).&lt;/p&gt;
&lt;p&gt;The metadata is abstracted to an interface named IMefMetaData , known as a metadata view. A metadata view must have only properties, and those properties must only have get accessors.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;    &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;interface&lt;/span&gt; IMefMetaData
    {
        &lt;span class=&quot;kwrd&quot;&gt;bool&lt;/span&gt; Enabled
        {
            get;
        }

        &lt;span class=&quot;kwrd&quot;&gt;string&lt;/span&gt; Name
        {
            get;
        }
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, &quot;Courier New&quot;, courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } --&gt;&lt;/p&gt;
&lt;p&gt;Back to the attribute, note the Type parameter passed into the base constructor, this just defines the Type of our contract stating it must be of type IHttpModule.&lt;/p&gt;
&lt;p&gt;Now we have an attribute with which to decorate our HttpModules, we need to instruct MEF to discover and import any classes marked with this attribute and compose them into a Catalog.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Discovery and Import&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;As mentioned above, a MEF contract is just a string (when importing by type, it’s just the &lt;em&gt;name&lt;/em&gt; of that type). There are two ways you can define an Import in MEF, &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/system.componentmodel.composition.importattribute.aspx&quot; target=&quot;_blank&quot;&gt;Import&lt;/a&gt; and &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/system.componentmodel.composition.importmanyattribute.aspx&quot; target=&quot;_blank&quot;&gt;ImportMany&lt;/a&gt; with cardinality being the difference.&lt;/p&gt;
&lt;p&gt;The Import attribute refers only to single imports. (zero-to-one and exactly-one cardinalities). Marking a property with this attribute specifies there is a &lt;em&gt;single&lt;/em&gt; instance of the stated contract, and there is a &lt;em&gt;single&lt;/em&gt; source to match.&lt;/p&gt;
&lt;p&gt;Using ImportMany attribute declares zero-to-many cardinality, and states that instead of a &lt;em&gt;single&lt;/em&gt; export, there can be many exports which match the contract. Using it on an IEnumerable, as shown below, MEF will fill the IEnumerable with all parts it can find that export that type, in this case IHttpModule.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;        [ImportMany]
        &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; IEnumerable&amp;lt;IHttpModule&amp;gt; Modules { get; set; }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, &quot;Courier New&quot;, courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } --&gt;&lt;/p&gt;
&lt;p&gt;Usually this is sufficient, but because we want to use some metadata, we need to alter the property signature in order to expose it. MEF provides an &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/dd986615.aspx&quot; target=&quot;_blank&quot;&gt;overload&lt;/a&gt; of &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/dd642331.aspx&quot; target=&quot;_blank&quot;&gt;Lazy&amp;lt;T&amp;gt;&lt;/a&gt; to allow access to the metadata without instantiating the underlying export. The corresponding property signature looks like this:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;        [ImportMany(&lt;span class=&quot;kwrd&quot;&gt;typeof&lt;/span&gt;(IHttpModule))]
        &lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; IEnumerable&amp;lt;Lazy&amp;lt;IHttpModule, IMefMetaData&amp;gt;&amp;gt; Modules
        {
            get; set;
        }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, &quot;Courier New&quot;, courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } --&gt;&lt;/p&gt;
&lt;p&gt;The property alone won’t do a thing, we need to instruct MEF to discover parts and populate this property. Firstly we tell MEF we want to discover attributed parts within the application’s bin directory by using the &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/system.componentmodel.composition.hosting.directorycatalog.aspx&quot; target=&quot;_blank&quot;&gt;DirectoryCatalog&lt;/a&gt;class. Next we create a &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/system.componentmodel.composition.hosting.compositioncontainer.aspx&quot; target=&quot;_blank&quot;&gt;CompositionContainer&lt;/a&gt; to hold the parts for composition and finally we tell MEF to Compose the Import parts within this class:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;        var catalog = &lt;span class=&quot;kwrd&quot;&gt;new&lt;/span&gt; DirectoryCatalog(HttpRuntime.BinDirectory);
        var container = &lt;span class=&quot;kwrd&quot;&gt;new&lt;/span&gt; CompositionContainer(catalog);
        container.ComposeParts(this);&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This populates the Modules property with all classes decorated with the attribute we defined earlier, so we should now have an IEnumerable list of HttpModules that need to be auto-registered, so we now just need to call the RegisterModule method for each module:&lt;/p&gt;
&lt;p&gt;&lt;!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, &quot;Courier New&quot;, courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } --&gt;&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;        &lt;span class=&quot;kwrd&quot;&gt;foreach&lt;/span&gt; (var httpModule &lt;span class=&quot;kwrd&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;this&lt;/span&gt;.Modules.Where(m =&amp;gt; m.Metadata.Enabled))
        {
            var msg = httpModule.Metadata.Name ?? httpModule.GetType().FullName;

            log.InfoFormat(&lt;span class=&quot;str&quot;&gt;&quot;Adding SelfRegistering HttpModule {0}&quot;&lt;/span&gt;, msg);
            DynamicModuleUtility.RegisterModule(httpModule.Value.GetType());
        }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, &quot;Courier New&quot;, courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } --&gt;&lt;/p&gt;
&lt;p&gt;So by utilising the metadata added earlier, we can add some rudimentary notifications using log4net, showing which modules are being registered (helpful for debugging) and we also have a facility to easily disable modules in code to also assist in debugging etc.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;So now instead of registering a HttpModule via the web.config, we simply decorate it with the AutoRegisterHttpModuleAttribute. It will get automatically registered and will intercept any requests as normal.    &lt;br /&gt; &lt;br /&gt;In my opinion this “shortcut” is an absolute godsend for distributing self-contained projects and sharing code between solutions with minimal configuration - HttpModules can now really be the “plug-ins” I think they were intended to be.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Gotchas&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I foresee only one issue whereby it could take other developers a while to find and debug any issues if they are being caused by a self-registered HttpModule. However once we become accustomed to using this method of registering modules, it should be easy enough to find modules using the “Find usages” feature within Visual Studio. A minor issue compared to the benefits this offers.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Future ideas and &lt;strong&gt;Code download&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I will shortly be uploading the full VS solution (probably to EPiCode), but first I want to add a few useful additions in there that utilise this technique, and I’ll write some more blog posts explaining those awesome plugins.   &lt;br /&gt; &lt;br /&gt;Watch this space. &lt;img class=&quot;wlEmoticon wlEmoticon-smile&quot; style=&quot;border-style: none;&quot; src=&quot;http://blog.tompipe.co.uk/image.axd?picture=wlEmoticon-smile_2.png&quot; alt=&quot;Smile&quot; /&gt;&lt;/p&gt;</description>            <guid>http://blog.tompipe.co.uk/post.aspx?id=4577d217-4738-4c66-804f-14ca2a15d034</guid>            <pubDate>Mon, 16 Jan 2012 23:08:00 GMT</pubDate>           <category>Blog post</category></item><item> <title>CMS Tab Captions</title>            <link>http://blog.tompipe.co.uk/post.aspx?id=a8c0194d-aaed-4bc2-9bfc-ddec22634e6e</link>            <description>&lt;p&gt;By default EPiServer CMS creates some &amp;ldquo;standard&amp;rdquo; tabs. Here&amp;rsquo;s a screenshot of the DB showing the default captions etc:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://blog.tompipe.co.uk/image.axd?picture=clip_image001.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;clip_image001&quot; src=&quot;http://blog.tompipe.co.uk/image.axd?picture=clip_image001_thumb.png&quot; border=&quot;0&quot; alt=&quot;clip_image001&quot; width=&quot;482&quot; height=&quot;114&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;However, the GroupCaption is NOT the caption which is displayed in the CMS, that is taken from the language XML file. Here&amp;rsquo;s a snippet from the LanguageEN.xml file showing the English translations:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://blog.tompipe.co.uk/image.axd?picture=image.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;image&quot; src=&quot;http://blog.tompipe.co.uk/image.axd?picture=image_thumb.png&quot; border=&quot;0&quot; alt=&quot;image&quot; width=&quot;349&quot; height=&quot;425&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Whilst most of the tabs translations are identical, the Information tab will display &amp;ldquo;Content&amp;ldquo; as it&amp;rsquo;s caption, not &amp;ldquo;Information&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Take care not to create a tab with a caption of &amp;ldquo;Content&amp;rdquo; or &amp;ldquo;Information&amp;rdquo;, or you could create a confusing situation where two identically names tabs appear in the CMS. e.g:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://blog.tompipe.co.uk/image.axd?picture=clip_image002.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;clip_image002&quot; src=&quot;http://blog.tompipe.co.uk/image.axd?picture=clip_image002_thumb.png&quot; border=&quot;0&quot; alt=&quot;clip_image002&quot; width=&quot;380&quot; height=&quot;275&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Which can result in this:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://blog.tompipe.co.uk/image.axd?picture=image_1.png&quot;&gt;&lt;img style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px&quot; title=&quot;image&quot; src=&quot;http://blog.tompipe.co.uk/image.axd?picture=image_thumb_1.png&quot; border=&quot;0&quot; alt=&quot;image&quot; width=&quot;355&quot; height=&quot;153&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This can confuse some non savvy editors. Try not to make things difficult for them &lt;img class=&quot;wlEmoticon wlEmoticon-smile&quot; style=&quot;border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none&quot; src=&quot;http://blog.tompipe.co.uk/image.axd?picture=wlEmoticon-smile_1.png&quot; alt=&quot;Smile&quot; /&gt;&lt;/p&gt;</description>            <guid>http://blog.tompipe.co.uk/post.aspx?id=a8c0194d-aaed-4bc2-9bfc-ddec22634e6e</guid>            <pubDate>Wed, 23 Nov 2011 16:44:00 GMT</pubDate>           <category>Blog post</category></item><item> <title>EPiServer Community and image thumbnailing woes</title>            <link>http://blog.tompipe.co.uk/post.aspx?id=ebd985cc-cc55-479d-a5ac-75c8499c2bef</link>            <description>&lt;p&gt;&lt;strong&gt;The task&amp;hellip;      &lt;br /&gt;&lt;/strong&gt;The EPiServer community product has an integrated ImageGallery Module which handles persisting and retrieval of Images within the system. The module also offers a handy image thumbnailing feature via a number of overloaded methods within the &lt;a href=&quot;http://sdk.episerver.com/community/4/html/T_EPiServer_Community_ImageGallery_ImageGalleryHandler.htm&quot; target=&quot;_blank&quot;&gt;ImageGalleryHandler&lt;/a&gt; class.&lt;/p&gt;
&lt;p&gt;The thumbnailing is controlled by some settings within the web.config file, as shown below:    &lt;br /&gt;&lt;/p&gt;
&lt;div id=&quot;scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:475c1aa7-24ba-4a74-8591-5ec4755aa17d&quot; class=&quot;wlWriterEditableSmartContent&quot; style=&quot;padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px&quot;&gt;
&lt;pre style=&quot;background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;;font-family:Courier New;font-size:8.25&quot; class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;imageGallery 
    &lt;/span&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt;imageAbsoluteFilePath&lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;=&quot;C:\Site\webRoot\ImageGallery\Originals&quot;&lt;/span&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt; 
    thumbnailVirtualFilePath&lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;=&quot;~/ImageGallery/Thumbnails&quot;&lt;/span&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt; 
    imgExtension&lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;=&quot;.jpg&quot;&lt;/span&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt; 
    imgMaxWidth&lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;=&quot;640&quot;&lt;/span&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt; 
    imgMaxHeight&lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;=&quot;640&quot;&lt;/span&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt; 
    saveOriginal&lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;=&quot;true&quot;&lt;/span&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt; 
    maxUserImageQuota&lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;=&quot;0&quot;&lt;/span&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt; 
    imgQuality&lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;=&quot;100&quot;&lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;
&lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;imageGallery&lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;!-- Code inserted with Steve Dunn&#39;s Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;
&lt;p&gt;These settings appear to allow the location of the images to be changed, which is all well and good in theory, but in practice it restricts the location of the thumbnails to always reside beneath the site root.&lt;/p&gt;
&lt;p&gt;Due to our release process (a full release package, and new, dated IIS root folder for each release) the images &lt;strong&gt;HAD&lt;/strong&gt; to reside outside the site root.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The answer&amp;hellip;      &lt;br /&gt;&lt;/strong&gt;Easy right? This is a perfect opportunity to use a &lt;a href=&quot;http://world.episerver.com/Documentation/Items/Tech-Notes/EPiServer-CMS-6/EPiServer-CMS-60/Virtual-Path-Providers/&quot; target=&quot;_blank&quot;&gt;Virtual Path Provider&lt;/a&gt;, isn&#39;t this exactly what they were designed for? EPiServer offer easy registration of various provider types within the episerver.config file and a boat load of custom providers within the &lt;a href=&quot;http://sdk.episerver.com/library/cms5/html/N_EPiServer_Web_Hosting.htm&quot; target=&quot;_blank&quot;&gt;EPiServer.Web.Hosting&lt;/a&gt; namespace. Hell, they even use them to relocate the UI and Util directories from within the program files directory.&lt;/p&gt;
&lt;p&gt;So, registering the following provider within episerver.config should solve the issue right?&lt;/p&gt;
&lt;div id=&quot;scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:cbf6bfb6-f98b-4d68-ac59-b7ef2850dcb2&quot; class=&quot;wlWriterEditableSmartContent&quot; style=&quot;padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px&quot;&gt;
&lt;pre style=&quot;background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;&quot; class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;add &lt;/span&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt;virtualPath&lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;=&quot;~/ImageGallery/&quot;&lt;/span&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt; 
     physicalPath&lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;=&quot;C:\Site\ImageGallery&quot;&lt;/span&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt;
     name&lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;=&quot;Galleries&quot;&lt;/span&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt;
     type&lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;=&quot;EPiServer.Web.Hosting.VirtualPathNativeProvider,EPiServer&quot;&lt;/span&gt;&lt;span style=&quot;color: #FF0000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;!-- Code inserted with Steve Dunn&#39;s Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;Unfortunately not.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The issue&amp;hellip;      &lt;br /&gt;&lt;/strong&gt;The thumbnail is actually created within the ImageGalleryFactory by an aptly named CreateThumbnail method.&lt;/p&gt;
&lt;p&gt;Within the method body is the following if/else statement:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;kwrd&quot;&gt;if&lt;/span&gt; (HostingEnvironment.IsHosted)
{
    absoluteImageGalleryPath = HostingEnvironment.MapPath(ImageGalleryModule.GetVirtualThumbnailPath(image.ImageGalleryId));
}
&lt;span class=&quot;kwrd&quot;&gt;else&lt;/span&gt;
{
    absoluteImageGalleryPath = ImageGalleryModule.GetAbsoluteImageGalleryPath(image.ImageGalleryId);
}&lt;/code&gt;&lt;/pre&gt;
&lt;!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, &quot;Courier New&quot;, courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } --&gt;
&lt;p&gt;GetVirtualThumbnailPath concatenates the ImageGalleryID onto the thumbnailVirtualPath specified in the web.config and in this example returns something like &quot;~/ImageGallery/Thumbnails/8/8&quot;&lt;/p&gt;
&lt;p&gt;HostingEnvironment.MapPath therefore returns the physical path of the folder, as if it resided under the site root &quot;C:\Site\webRoot\ImageGallery\Thumbnails&quot;.&lt;/p&gt;
&lt;p&gt;The VPP we configured earlier is not taken into consideration, and thumbnails will always be created under the site root regardless.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The solution&amp;hellip;.      &lt;br /&gt;&lt;/strong&gt;My original intention was to simply define a custom factory derived from ImageGalleryFactory and override the CreateThumbnail method. Unfortunately someone at EPiServer decided we shouldn&#39;t be allowed to customise the ImageFactory, and marked the class as internal, so that idea could progress no further.&lt;/p&gt;
&lt;p&gt;To workaround this, I ended up creating a custom ImageGalleryHandler, derived from the standard ImageGalleryHandler. Defined a new static Instance property (getting and setting the underlying ImageGallery.Instance, cast to the custom type) which gets instantiated within the static constructor, and therefore overwrites the base.Instance.&lt;/p&gt;
&lt;p&gt;Because it&#39;s a derived version of the ImageGalleryHandler, the instance can be passed around as a standard ImageGalleryHandler, and will appear to be so to other libraries and classes, which can use it as &quot;normal&quot;. Polymorphism at its most useful!&lt;/p&gt;
&lt;p&gt;I then created an override to the GetThumbnail method and within it, called the base.GetThumbnail overload, then if the createThumbnail parameter is true. I raise the OnThumbnailCreated event passing in the created thumbnail.&lt;/p&gt;
&lt;p&gt;I subscribed to the OnThumbnailCreated event within the Application_Start in Global.asax, and within the event handler I use HostingEnvironment.VirtualPathProvider.GetDirectory method instead of Server.MapPath. This returns a NativeDirectory object which has a LocalPath property containing the physical path to the intended thumbnail folder as defined in the episerver.config.&lt;/p&gt;
&lt;p&gt;I now have a reference to the new thumbnail object (and therefore the folder beneath the site root), and i also have a reference to the intended physical location. So after some brief sanity checks I can copy (or move) the new thumbnail to the destination folder.&lt;/p&gt;
&lt;p&gt;OBJECTIVE COMPLETE&amp;nbsp;&lt;img title=&quot;Laughing&quot; src=&quot;http://blog.tompipe.co.uk/editors/tiny_mce3/plugins/emotions/img/smiley-laughing.gif&quot; border=&quot;0&quot; alt=&quot;Laughing&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Conclusion&amp;hellip;      &lt;br /&gt;&lt;/strong&gt;Whilst probably not the most elegant of solutions, it definitely achieves the goal. I consider this to be a &#39;filthy hack&#39; to workaround the limitations imposed by EPiServer&#39;s internal classes. If anyone has an suggestions, alternative methods, or improvements &amp;ndash; feel free to discuss them below.&lt;/p&gt;
&lt;p&gt;Within the source I&#39;ve taken the idea further by subscribing to the ImageRemoved event exposed by the standard ImageGalleryHandler so I can &quot;tidy up&quot; the thumbnails when the original image is removed.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Source      &lt;br /&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;div id=&quot;scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:ad08ead9-3cf9-4e5c-8367-75d33b26520b&quot; class=&quot;wlWriterEditableSmartContent&quot; style=&quot;padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px&quot;&gt;
&lt;pre style=&quot;background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;&quot; class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;namespace&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; Custom.Community.Handlers
{
    &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; System;
    &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; System.Drawing;
    &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; System.IO;
    &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; System.Linq;
    &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; System.Web.Hosting;

    &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; EPiServer.Common;
    &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; EPiServer.Common.Exceptions;
    &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; EPiServer.Community.ImageGallery;
    &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; EPiServer.Web.Hosting;

    &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;using&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; Image &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; EPiServer.Community.ImageGallery.Image;

    &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; CustomImageGalleryHandler : ImageGalleryHandler
    {
        &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; CustomImageGalleryHandler()
        {
            Instance &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; CustomImageGalleryHandler();
        }

        &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;protected&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; CustomImageGalleryHandler()
        {
        }

        &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;event&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; EPiServerCommonEventHandler ImageThumbnailCreated;

        &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; CustomImageGalleryHandler Instance
        {
            &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;
            {
                &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; (CustomImageGalleryHandler)ImageGalleryHandler.Instance;
            }
            &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;
            {
                ImageGalleryHandler.Instance &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; value;
            }
        }

        &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; Instance_ImageRemoved(&lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; sender, EPiServerCommonEventArgs e)
        {
            var image &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; (Image)e.Object;
            &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; path &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; GetThumbnailVPP(image.ImageGallery).LocalPath;

            &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;try&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;
            {
                &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; (Directory.Exists(path))
                {
                    &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;foreach&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; str2 &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; Directory.GetFiles(path, image.ID &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;_*&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;).Where(File.Exists))
                    {
                        File.Delete(str2);
                    }
                }
            }
            &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;catch&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; (Exception exception3)
            {
                &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;throw&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; FrameworkException(&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;Could not delete thumbnails&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;, exception3);
            }
        }

        &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; ThumbnailCreated(&lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; sender, EPiServerCommonEventArgs e)
        {
            var thumb &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; (Thumbnail)e.Object;
            var vpp &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; GetThumbnailVPP(thumb.Parent.ImageGallery);

            &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Directory.Exists(vpp.LocalPath))
            {
                &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;try&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;
                {
                    Directory.CreateDirectory(vpp.LocalPath);
                }
                &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;catch&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; (Exception exception2)
                {
                    &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;throw&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; FrameworkException(&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;Failed to create directory: \&quot;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; vpp.LocalPath &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;\&quot;.&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;, exception2);
                }
            }

            var imagePath &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; HostingEnvironment.MapPath(&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;~&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; thumb.Url);
            &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.IsNullOrEmpty(imagePath)) &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;;

            var source &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; FileInfo(imagePath);
            var filename &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; Path.GetFileName(source.FullName);

            &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; (source.Exists &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.IsNullOrEmpty(filename))
            {
                var dest &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; FileInfo(Path.Combine(vpp.LocalPath, filename));
                &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;dest.Exists &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; source.LastWriteTime &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; dest.LastWriteTime)
                {
                    source.CopyTo(dest.FullName, &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;);
                }
            }
        }

        &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;override&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; Thumbnail GetThumbnail(Image image, &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; width, &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; height, ThumbnailFormat thumbnailFormat, &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;bool&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; createThumbnail, Watermark thumbnailTag, Color thumbBgColor)
        {
            var thumbnail &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;base&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.GetThumbnail(image, width, height, thumbnailFormat, createThumbnail, thumbnailTag, thumbBgColor);

            &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; (createThumbnail)
            {
                &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.OnThumbnailCreated(thumbnail);
            }

            &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; thumbnail;
        }

        &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;protected&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;virtual&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; OnThumbnailCreated(Thumbnail thumb)
        {
            &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.ImageThumbnailCreated &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;null&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;)
            {
                &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.ImageThumbnailCreated(ImageGalleryModule.Instance.UniqueName, &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; EPiServerCommonEventArgs(thumb.ID.ToString(), &lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;created_thumbnail&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;, thumb));
            }
        }

        &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;private&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;static&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; NativeDirectory GetThumbnailVPP(ImageGallery gallery)
        {
            &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;try&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;
            {
                var virtualPath &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; ImageGalleryModule.GetVirtualThumbnailPath(gallery.ID);
                var vpp &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; HostingEnvironment.VirtualPathProvider.GetDirectory(virtualPath) &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;as&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; NativeDirectory;

                &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; (vpp &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;null&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;)
                {
                    &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; vpp;
                }

                &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;throw&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; ArgumentNullException(&lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;null&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.Format(&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;No provider configured for the {0} virtual path&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;, virtualPath));
            }
            &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;catch&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; (Exception exception2)
            {
                &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;throw&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #0000FF;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; FrameworkException(&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;Could not get path to upload directory&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;, exception2);
            }
        }
    }
}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;!-- Code inserted with Steve Dunn&#39;s Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;</description>            <guid>http://blog.tompipe.co.uk/post.aspx?id=ebd985cc-cc55-479d-a5ac-75c8499c2bef</guid>            <pubDate>Fri, 23 Sep 2011 21:40:00 GMT</pubDate>           <category>Blog post</category></item></channel>
</rss>