<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><atom:link rel="hub" href="http://tumblr.superfeedr.com/" xmlns:atom="http://www.w3.org/2005/Atom"/><description>Back- and front-end web developer at Q42. Usually works with C# and Javascript but occasionally wanders off…

Follow me at @lukasvan3l</description><title>Lukasvan3L</title><generator>Tumblr (3.0; @developer3l)</generator><link>http://developer.3l.nl/</link><item><title>Class not enhanced correctly - Siena</title><description>&lt;p&gt;When calling my EnhancedModel.findById(Object) function, I get this error:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UnsupportedOperationException&lt;/strong&gt;&lt;span&gt; occured&amp;#160;: Class not enhanced correctly&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Turns out this is because inside the EnhancedModel I created an overload of the findById function with two parameters: findById(String, String).&lt;/p&gt;
&lt;p&gt;This is also the case with getByKey(Object) function; if you create an overload with other parameters; class not enhanced correctly.&lt;/p&gt;</description><link>http://developer.3l.nl/post/23533993737</link><guid>http://developer.3l.nl/post/23533993737</guid><pubDate>Tue, 22 May 2012 09:13:20 +0200</pubDate><category>PlayFramework</category><dc:creator>lukasvan3l</dc:creator></item><item><title>PlayFramework &amp; GAE localization editor</title><description>&lt;p&gt;Play Framework includes the messages-file way of handling the translation of values. Unfortunately, this won&amp;#8217;t do for the site I&amp;#8217;m creating: it has 7 different languages and editors need to be able to translate on-the-fly.&lt;/p&gt;
&lt;p&gt;So I thought I&amp;#8217;d share the solution that&amp;#8217;s now implemented: translations via the BigTable datastore.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Datastore&lt;br/&gt;&lt;/strong&gt;First of all, there&amp;#8217;s a model:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;@Entity&lt;br/&gt;public class Translation extends EnhancedModel {&lt;span class="Apple-tab-span"&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;  @Id(Generator.AUTO_INCREMENT)&lt;br/&gt;  public Long id;&lt;span class="Apple-tab-span"&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;  public String locale;&lt;br/&gt;  public String name;&lt;br/&gt;  public String translation;&lt;/p&gt;
&lt;p&gt;  @Index(&amp;#8220;qidx&amp;#8221;)&lt;br/&gt;  public List&amp;lt;String&amp;gt; q;&lt;/p&gt;
&lt;p&gt;  @PreSave&lt;br/&gt;  @PreInsert&lt;br/&gt;  @PreUpdate&lt;br/&gt;  public void updateSearchFields()&lt;br/&gt;  {&lt;br/&gt;    if (this.translation&amp;#160;!= null &amp;amp;&amp;amp; this.translation.isEmpty())&lt;br/&gt;      this.translation = null;&lt;br/&gt;    this.q = Utils.splitSearchWords(String.format(&amp;#8220;%s %s&amp;#8221;, name, translation));&lt;br/&gt;  }&lt;br/&gt;}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I&amp;#8217;m using Siena 2.0.7, that&amp;#8217;s where the annotations are coming from. The &amp;#8220;q&amp;#8221; field gets indexed and the editors can search on that field when they&amp;#8217;re looking for a translation. OnSave of a record this field also gets updated.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;PlayPlugin&lt;/strong&gt;&lt;br/&gt;Next up is the code that actually translates the &amp;amp;{&amp;#8216;translatable message&amp;#8217;} that the views are asking for. This is going to be a PlayPlugin overriding the getMessage function:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;public class MessagesDbPlugin extends PlayPlugin {&lt;br/&gt;  @Override&lt;br/&gt;  public String getMessage(String locale, Object key, Object&amp;#8230; args) {   &lt;br/&gt;    return String.format(getTranslation(locale, key.toString()), args);&lt;br/&gt;  }&lt;br/&gt;} &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now we&amp;#8217;re set up to get the actual translations from the database. Of course we need to also cache them using the gae memcached client, as it&amp;#8217;s much faster then the actual datastore.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;private static String getTranslation(String locale, String key)&lt;br/&gt;{&lt;br/&gt;  if (Utils.isNullOrEmpty(key))&lt;br/&gt;    return &amp;#8220;&amp;#8221;;&lt;/p&gt;
&lt;p&gt;  // look up in cache&lt;br/&gt;  String value = Cache.get(Translation.generateCacheKey(locale, key), String.class);&lt;br/&gt;  if (!Utils.isNullOrEmpty(value))&lt;br/&gt;    return value;&lt;/p&gt;
&lt;p&gt;  // look up in database&lt;br/&gt;  Translation t = Translation.all().filter(&amp;#8220;locale&amp;#8221;, locale).filter(&amp;#8220;name&amp;#8221;, key).get();&lt;br/&gt;  if (t&amp;#160;!= null)&lt;br/&gt;  {&lt;br/&gt;    cache(t);&lt;br/&gt;    return Utils.isNullOrEmpty(t.translation)&amp;#160;? t.name&amp;#160;: t.translation;&lt;br/&gt;  }&lt;/p&gt;
&lt;p&gt;  // validate the locale: is it possible?&lt;br/&gt;  if (!Play.langs.contains(locale))&lt;br/&gt;  {&lt;br/&gt;    Logger.error(&amp;#8220;Invalid language: %s&amp;#8221;, locale);&lt;br/&gt;    return &amp;#8220;&amp;#8221;;&lt;br/&gt;  }&lt;/p&gt;
&lt;p&gt;  // not found: insert into the database and the cache for each language&lt;br/&gt;  for (String lang&amp;#160;: Play.langs)&lt;br/&gt;  {&lt;br/&gt;    Translation newT = new Translation();&lt;br/&gt;    newT.locale = lang;&lt;br/&gt;    newT.name = key;&lt;br/&gt;    newT.translation = null;&lt;br/&gt;    newT.save();&lt;br/&gt;    cache(newT);&lt;br/&gt;  }&lt;/p&gt;
&lt;div&gt;  // now return the key, as the value is empty&lt;/div&gt;
&lt;p&gt;  return key;&lt;br/&gt;}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That&amp;#8217;s it, you&amp;#8217;re set! Each time a translation is requested that doesn&amp;#8217;t yet exist in the database, it gets inserted. So if you accidentally skip one and don&amp;#8217;t enter it in the database, is pops up in the cms anyway.&lt;/p&gt;
&lt;div&gt;&lt;strong&gt;CMS&lt;/strong&gt;&lt;/div&gt;
&lt;div&gt;I&amp;#8217;m not going to display all the javascript, html and css involved in making the translations editable, but it&amp;#8217;s fairly easy. Getting the translations you searched for is plain and simple:&lt;/div&gt;
&lt;div&gt;
&lt;blockquote&gt;Translation.all().filter(&amp;#8220;locale&amp;#8221;, locale).filter(&amp;#8220;q&amp;#8221;, q.toLowerCase().trim()).fetch();&lt;/blockquote&gt;
&lt;/div&gt;
&lt;div&gt;And don&amp;#8217;t forget to invalidate the cache entry after you saved a new translation!&lt;/div&gt;
&lt;div&gt;That&amp;#8217;s it! I might make a Play Module out of it some day, if enough people ask me to :)&lt;/div&gt;</description><link>http://developer.3l.nl/post/22375390424</link><guid>http://developer.3l.nl/post/22375390424</guid><pubDate>Fri, 04 May 2012 11:30:17 +0200</pubDate><category>translations</category><category>playframework</category><category>gae</category><dc:creator>lukasvan3l</dc:creator></item><item><title>Set play framework id for gae:deploy</title><description>&lt;p&gt;We&amp;#8217;re working on setting up our playframework / google appengine project with a full &lt;a href="http://en.wikipedia.org/wiki/Development,_testing,_acceptance_and_production"&gt;DTAP roadmap&lt;/a&gt;. The way we did that at Q42 is first to &lt;a href="http://q42.nl/continuous-deployment-to-appengine"&gt;integrate our project in Teamcity&lt;/a&gt;; teamcity now even does automatic deploys to google appengine!&lt;/p&gt;
&lt;p&gt;One problem I encountered was that I wanted to set a specific Framework ID when executing the gae:deploy command. Turns out, you can just append the id just as you would on a run command. So:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;play gae:deploy - -%gae-dev&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;play gae:deploy - -%gae-prod&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now you can have different values in your application.conf for different appengine environments, for instance&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;%gae-dev.application.baseUrl=http://project-dev.appspot.com/&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;%gae-prod.application.baseUrl=http://project.appspot.com/&lt;/p&gt;
&lt;/blockquote&gt;</description><link>http://developer.3l.nl/post/22247933748</link><guid>http://developer.3l.nl/post/22247933748</guid><pubDate>Wed, 02 May 2012 11:06:00 +0200</pubDate><category>gae</category><category>playframework</category><dc:creator>lukasvan3l</dc:creator></item><item><title>Museumify - facial recognition</title><description>&lt;a href="http://www.museumify.com/"&gt;Museumify - facial recognition&lt;/a&gt;: &lt;p&gt;For the &lt;a href="http://www.mwhackathon.com/"&gt;Museums and the Web 2012 Hackathon&lt;/a&gt; that I participated in, I created &lt;a href="http://museumify.com"&gt;Museumify&lt;/a&gt;. You input a picture of yourself, and your face will be inserted on top of the face of a piece of art. Here’s obama:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://25.media.tumblr.com/tumblr_m2fstwwO551rs8cnwo1_250.png"/&gt;&lt;/p&gt;
&lt;p&gt;The technique behind it is fairly simple: it uses &lt;a href="http://face.com"&gt;face.com&lt;/a&gt; where you input the URL to an image and it returns JSON containing the location of the eyes, nose, mouse, etc. Here’s a sample:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre&gt;{"width":140, "height":140, "tags":[{"recognizable":false, &lt;br/&gt;"width":77.86, "height":77.86, "center":{"x":48.93,"y":53.93}, &lt;br/&gt;"eye_left":{"x":29.65,"y":37.36}, "eye_right":{"x":67.52,"y":38.95}, &lt;br/&gt;"mouth_left":{"x":30.09,"y":73.59}, "mouth_center":{"x":46.26,"y":78.64}, "mouth_right":{"x":65.45,"y":75.99}, &lt;br/&gt;"nose":{"x":44.89,"y":61.78}, "ear_left":null, "ear_right":null, &lt;br/&gt;"chin":null, "yaw":4.43, "roll":3.56, "pitch":-5.05, &lt;br/&gt;"attributes":{"face":{"value":"true","confidence":96}, "gender":{"value":"male","confidence":37}, &lt;br/&gt;"glasses":{"value":"true","confidence":96}, "smiling":{"value":"true","confidence":95}}}]}&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;With the eye, mouth and nose information, you can find out what direction the face is looking at, if it’s en profile etc. The museumify site only crops the picture and overlays it, but a lot more is possible this way. Think of overlaying your picture on an art object that’s looking the same direction.&lt;/p&gt;
&lt;p&gt;Maybe in the future I’ll pick up the project again to include this. But for now, it was a nice experiment and will just be sitting there :)&lt;/p&gt;</description><link>http://developer.3l.nl/post/21309485412</link><guid>http://developer.3l.nl/post/21309485412</guid><pubDate>Wed, 18 Apr 2012 05:49:00 +0200</pubDate><category>hackathon</category><category>facial recognition</category><dc:creator>lukasvan3l</dc:creator></item><item><title>PlayFramework + GAE OnApplicationStart code</title><description>&lt;p&gt;Google App Engine works in mysterious ways! The default @OnApplicationStart doJob of play framework apparantly doesn&amp;#8217;t work. But there&amp;#8217;s a workaround if you want to have code executed when your application is booted. For instance, to inject bootstrap data in your database.&lt;/p&gt;
&lt;p&gt;The solution I found makes use of the Plugins functionality of play. A plugin can execute code on application start, exactly what we need!&lt;/p&gt;
&lt;p&gt;So here&amp;#8217;s my code to create a one-class-plugin:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;package plugins;&lt;/p&gt;
&lt;p&gt;import play.*;&lt;br/&gt;import play.Play.Mode;&lt;br/&gt;import play.test.Fixtures;&lt;/p&gt;
&lt;p&gt;public class Bootstrap extends PlayPlugin {&lt;/p&gt;
&lt;p&gt;  @Override&lt;br/&gt;  public void onApplicationStart()&lt;br/&gt;  {&lt;br/&gt;    if (Play.mode == Mode.DEV)&lt;br/&gt;    {&lt;br/&gt;      Logger.info(&amp;#8220;Loading data&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;.&amp;#8221;);&lt;br/&gt;      Fixtures.deleteAllModels();&lt;br/&gt;      Fixtures.loadModels(&amp;#8220;data.yml&amp;#8221;);&lt;br/&gt;    }&lt;br/&gt;    Logger.info(&amp;#8220;App loaded!&amp;#8221;);&lt;br/&gt;  }&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And then one little extra: put a &amp;#8220;play.plugins&amp;#8221; file in your /app directory with the following contents:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;4242:plugins.Bootstrap&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This registers the plugin with a priority of 4242 with Play. SpringPlugin, for instance, has a priority of 1000.&lt;/p&gt;
&lt;p&gt;That&amp;#8217;s it! No ugly url&amp;#8217;s to call after a deploy, this code gets executed automagically.&lt;/p&gt;</description><link>http://developer.3l.nl/post/20521474324</link><guid>http://developer.3l.nl/post/20521474324</guid><pubDate>Thu, 05 Apr 2012 13:27:17 +0200</pubDate><category>gae</category><category>playframework</category><category>plugin</category><dc:creator>lukasvan3l</dc:creator></item><item><title>Addthis bug!</title><description>&lt;p&gt;Addthis updated its code somewhere in the past days. At two specific places in their code they set &amp;#8220;d = document&amp;#8221;. Because there&amp;#8217;s no &amp;#8220;var&amp;#8221; in front of this, window.d gets set to document. This code conflicts with a library we use (spiffy) that also binds to window.d.&lt;/p&gt;
&lt;p&gt;The symptoms are  javascript breaking, and when you open the console you get js errors on every mouse move.&lt;/p&gt;</description><link>http://developer.3l.nl/post/18941878869</link><guid>http://developer.3l.nl/post/18941878869</guid><pubDate>Thu, 08 Mar 2012 09:38:54 +0100</pubDate><category>spiffy</category><dc:creator>lukasvan3l</dc:creator></item><item><title>ISingletonDependency is tenant specific!</title><description>&lt;p&gt;I don&amp;#8217;t know if it&amp;#8217;s positive or negative, but certainly worth knowing if you&amp;#8217;re working with the OrchardCMS Multitenancy module:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A different instance of the ISingletonDependency is created for each tenant.&lt;/strong&gt;&lt;/p&gt;</description><link>http://developer.3l.nl/post/17605301719</link><guid>http://developer.3l.nl/post/17605301719</guid><pubDate>Tue, 14 Feb 2012 14:12:42 +0100</pubDate><category>orchard</category><category>Multitenancy</category><dc:creator>lukasvan3l</dc:creator></item><item><title>AirPlay crashes my router dir-635</title><description>&lt;p&gt;During my honeymoon in America, june last year, I bought an iPad 2 and an AppleTV 2. In theory, that would enable me to wirelessly stream music and video to my television, using AirPlay.&lt;/p&gt;
&lt;p&gt;Unfortunately, every time I tried it, I heard 5 seconds of audio and then my router gave up. It seemed to be rebooting, both my wired pc and wireless laptop didn&amp;#8217;t receive a signal from the router.&lt;/p&gt;
&lt;p&gt;During my last attempt before I was going to buy a new router (and an expensive one this time!) I updated the firmware of my d-link dir-635 from 1.09W to 1.13b. And low-and-behold: it works! I&amp;#8217;ve been listening my spotify playlist via iPad for the past hour or so, unobstructed.&lt;/p&gt;
&lt;p&gt;In the &lt;a href="https://docs.google.com/open?id=0B4y6nR4siEp7MDdlMzgxMGEtYTI1ZS00OGE2LWFjMTItNDNlMjExN2MzNDVh" target="_blank"&gt;release notes&lt;/a&gt; I can&amp;#8217;t find the change that fixed it. If you find out, please let me know! For now, I&amp;#8217;m happy :)&lt;/p&gt;</description><link>http://developer.3l.nl/post/17500320084</link><guid>http://developer.3l.nl/post/17500320084</guid><pubDate>Sun, 12 Feb 2012 19:50:01 +0100</pubDate><category>hardware</category><category>router</category><category>ipad</category><category>airplay</category><dc:creator>lukasvan3l</dc:creator></item><item><title>log4net 1.2.11 dependency hell</title><description>&lt;p&gt;Whowh, that&amp;#8217;s a nice error:&lt;/p&gt;
&lt;pre&gt;Looks like you forgot to register the http module Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule
To fix this add
&amp;lt;add name="PerRequestLifestyle" type="Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule, Castle.Windsor" /&amp;gt;
to the &amp;lt;httpModules&amp;gt; section on your web.config.
Windsor also detected you're running IIS in Integrated Pipeline mode. This means that you also need to add the module to the &amp;lt;modules&amp;gt; section under &amp;lt;system.webServer&amp;gt;.
Alternatively make sure you have Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35 assembly in your GAC (it is installed by ASP.NET MVC3 or WebMatrix) and Windsor will be able to register the module automatically without having to add anything to the config file.
&lt;/pre&gt;
&lt;p&gt;That doesn&amp;#8217;t make sense&amp;#8230; After some fumbling around I got the next error message:&lt;/p&gt;
&lt;pre&gt;An error occurred creating the configuration section handler for common/logging: Unable to create type 'Common.Logging.Log4Net.Log4NetLoggerFactoryAdapter, Common.Logging.Log4Net'&lt;/pre&gt;
&lt;p&gt;And after that another error in log4net configuration. Eventually colleague Mark helped me figure out the following was the underlying problem:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;log4net version 1.2.11 has a different publicKeyToken then 1.2.10&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;So when I upgraded my nuget files, log4net 1.2.11 got downloaded and referenced. But castle.windsor was looking for 1.2.10, and didn&amp;#8217;t see the similarity with 1.2.11. And so it epically failed :( For some reason it did work on my machine, but not on the live server, which didn&amp;#8217;t help.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What can we learn from this?&lt;br/&gt;&lt;/strong&gt;It took me 2 hours to figure out what was wrong. And all that because I let castle.windsor do the dependency injection via public properties. This just ended up with CollectionObjectService being null:&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;public&lt;/span&gt; CollectionObjectService CollectionObjectService { &lt;span&gt;get&lt;/span&gt;; &lt;span&gt;set&lt;/span&gt;; }
&lt;span&gt;public&lt;/span&gt; SynchronizerService()
{
}&lt;/pre&gt;
&lt;p&gt;When I re-wrote it so the services use constructors to get their dependencies injected, the error that actually told me what was wrong turned up:&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;public&lt;/span&gt; CollectionObjectService CollectionObjectService { &lt;span&gt;get&lt;/span&gt;; &lt;span&gt;private&lt;/span&gt; &lt;span&gt;set&lt;/span&gt;; }
&lt;span&gt;public&lt;/span&gt; SynchronizerService(CollectionObjectService coService)
{
  &lt;span&gt;this&lt;/span&gt;.CollectionObjectService = coService;
}&lt;/pre&gt;</description><link>http://developer.3l.nl/post/16463925249</link><guid>http://developer.3l.nl/post/16463925249</guid><pubDate>Wed, 25 Jan 2012 15:16:06 +0100</pubDate><category>.net</category><category>iis</category><category>ioc</category><category>windsor</category><category>log4net</category><category>dependency hell</category><dc:creator>lukasvan3l</dc:creator></item><item><title>Google mail vs Google apps</title><description>&lt;p&gt;My current e-mail setup is as follows:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Mail sent to my 3l.nl mailaccount is received in a pop3 mailbox&lt;/li&gt;
&lt;li&gt;My gmail account is set up to download the mail from the pop3 mailbox periodically&lt;/li&gt;
&lt;li&gt;My father and mother both have 3l.nl mailaddresses, and receive the pop3 mails directly in outlook&lt;/li&gt;
&lt;li&gt;My brother and sister both have 3l.nl mailaddresses, but they&amp;#8217;re just aliasses and their mail is directly sent to their gmail or hotmail (yup, some people still use it&amp;#8230;) address.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;A change of heart&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m thinking of a new setup using Google Apps. This enables my parents to open their mail directly in a webmail environment (they travel a lot) and on their phone. And everywhere the mail is synchronized (which it is not at the moment).&lt;/p&gt;
&lt;p&gt;Also it eliminates the need of an additional gmail address for myself, as it&amp;#8217;s unneccessary and my mail arrives delayed, because the pop3 server is pinged periodically (5 minutes, but still).&lt;/p&gt;
&lt;p&gt;And last but not least, we&amp;#8217;ll be using our awesome 3l.nl e-mail adresses to log in, how cool is that?!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The downside&lt;br/&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;All the mail, contacts, calendar and documents I currently have resides in my gmail account. I would like to keep that and move it to the new 3l.nl google apps account.&lt;/li&gt;
&lt;li&gt;My gmail account has analytics access, picasa albums uploaded, etc. All that will have to be setup again using my new 3l.nl google apps account&lt;/li&gt;
&lt;li&gt;The aliasses that I set up for my brother and sister won&amp;#8217;t work anymore. I&amp;#8217;ll have to create emailadresses for them, and install filters that forward all incoming mail to their own gmail / hotmail address. And that process includes creating and validating forward addresses, etc&amp;#8230;&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Do you see any solutions to one of my problems? I could also just use e-mail forwarding rules for my parents, and create private gmail accounts for them. But I think this is definitely worth a shot!&lt;/p&gt;
&lt;ul&gt;&lt;/ul&gt;</description><link>http://developer.3l.nl/post/16252030473</link><guid>http://developer.3l.nl/post/16252030473</guid><pubDate>Sat, 21 Jan 2012 23:55:09 +0100</pubDate><category>mail</category><category>google</category><category>gmail</category><category>google apps</category><dc:creator>lukasvan3l</dc:creator></item><item><title>Orchard import &amp; export 1-n relations</title><description>&lt;p&gt;While developing in Orchard with a team, recipes are very useful. Everyone has their own database (so we don&amp;#8217;t break each others environment), and sometimes you want to share your content with a colleague. Or your database got corrupted and you need to re-install. Not to mention backupping. That&amp;#8217;s when &lt;a href="http://docs.orchardproject.net/Documentation/Making-a-Web-Site-Recipe" target="_blank"&gt;Recipes&lt;/a&gt; come in.&lt;/p&gt;
&lt;p&gt;For each of my orchard projects I created extensive recipes with custom Commands and importable ContentParts. I want to share a little code snippet for importing and exporting complicated ContentParts. It&amp;#8217;s not as easy as it seems because it works with Linq.XElement properties.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;First, the exporting&lt;br/&gt;&lt;/strong&gt;Inside the ContentPartDriver, here&amp;#8217;s my code for the override function Exporting(ContentPart part, ExportContentContext context), which exports a richtext string into an attribute and related Offer elements into child-elements:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre&gt;&lt;span&gt;// first, get the ContentPart element&lt;/span&gt;
&lt;span&gt;var&lt;/span&gt; parent = context.Element(part.PartDefinition.Name);

&lt;span&gt;// a simple one: a string&lt;/span&gt;
&lt;span&gt;if&lt;/span&gt; (!&lt;span&gt;string&lt;/span&gt;.IsNullOrEmpty(part.RichTextBlock1))
  parent.SetAttributeValue(&lt;span&gt;"RichTextBlock1"&lt;/span&gt;, part.RichTextBlock1);

&lt;span&gt;// a 1-n relationship&lt;/span&gt;
&lt;span&gt;// create the container element&lt;/span&gt;
parent.SetElementValue(&lt;span&gt;"offers"&lt;/span&gt;, &lt;span&gt;""&lt;/span&gt;);
&lt;span&gt;var&lt;/span&gt; offers = parent.Element(&lt;span&gt;"offers"&lt;/span&gt;);
&lt;span&gt;foreach&lt;/span&gt; (&lt;span&gt;var&lt;/span&gt; offer &lt;span&gt;in&lt;/span&gt; part.Offers)
{
  &lt;span&gt;// every node must have a unique name, else SetElementValue won't work&lt;/span&gt;
  &lt;span&gt;var&lt;/span&gt; elid = &lt;span&gt;"offer"&lt;/span&gt; + offer.Id;
  &lt;span&gt;// again, first create the container element&lt;/span&gt;
  offers.SetElementValue(elid, &lt;span&gt;""&lt;/span&gt;);
  &lt;span&gt;var&lt;/span&gt; el = offers.Element(elid);
  &lt;span&gt;// then import the values (without Id, it will be autogenerated)&lt;/span&gt;
  &lt;span&gt;//el.SetAttributeValue("Id", offer.Id);&lt;/span&gt;
  el.SetAttributeValue(&lt;span&gt;"Image"&lt;/span&gt;, offer.Image);
  el.SetAttributeValue(&lt;span&gt;"Price"&lt;/span&gt;, offer.Price);
  el.SetAttributeValue(&lt;span&gt;"Url"&lt;/span&gt;, offer.Url);&lt;br/&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Expand the recipe&lt;/strong&gt;&lt;br/&gt;So now, when I execute the export function (don&amp;#8217;t forget to check the Data checkbox!), I get the entire contentitem with my custom contentpart embedded into it. The export.xml file that&amp;#8217;s generated can be used as recipe, or parts of it can be used.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;And then, the importing&lt;/strong&gt;&lt;br/&gt;So now I override the Importing(ContentPart part, ImportContentContext context) function as follows:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre&gt;&lt;div&gt;&lt;pre&gt;&lt;span&gt;&lt;span&gt;// this gets injected into the constructor by Autofac&lt;br/&gt;private readonly IRepository&amp;lt;OfferRecord&amp;gt; _offerRepository;&lt;/span&gt;&lt;span&gt;&lt;br/&gt;&lt;br/&gt;// first import the simple richtext field&lt;br/&gt;var&lt;/span&gt;&lt;/span&gt;&lt;span&gt; RichTextBlock1 = context.Attribute(part.PartDefinition.Name, &lt;/span&gt;&lt;span&gt;"RichTextBlock1"&lt;/span&gt;&lt;span&gt;);
&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (RichTextBlock1 != &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;) part.RichTextBlock1 = RichTextBlock1;
&lt;br/&gt;// then get the "offers" element
&lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt; offers = context.Data.Element(part.PartDefinition.Name).Element(&lt;/span&gt;&lt;span&gt;"offers"&lt;/span&gt;&lt;span&gt;);
&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (offers != &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;)
{
  &lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt; offerList = &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; List&amp;lt;OfferRecord&amp;gt;();&lt;br/&gt;  // and import each of the offer elements. I'm not checking on nodenames because they're unique!
  &lt;/span&gt;&lt;span&gt;foreach&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt; offer &lt;/span&gt;&lt;span&gt;in&lt;/span&gt;&lt;span&gt; offers.Elements())
  { 
    &lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt; n = &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; OfferRecord();
    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (offer.Attribute(&lt;/span&gt;&lt;span&gt;"Image"&lt;/span&gt;&lt;span&gt;) != &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;)
      n.Image = offer.Attribute(&lt;/span&gt;&lt;span&gt;"Image"&lt;/span&gt;&lt;span&gt;).Value;
    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (offer.Attribute(&lt;/span&gt;&lt;span&gt;"Price"&lt;/span&gt;&lt;span&gt;) != &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;)
      n.Price = offer.Attribute(&lt;/span&gt;&lt;span&gt;"Price"&lt;/span&gt;&lt;span&gt;).Value;
    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; (offer.Attribute(&lt;/span&gt;&lt;span&gt;"Url"&lt;/span&gt;&lt;span&gt;) != &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;)
      n.Url = offer.Attribute(&lt;/span&gt;&lt;span&gt;"Url"&lt;/span&gt;&lt;span&gt;).Value;&lt;br/&gt;&lt;br/&gt;    // the new offer should first be saved to database, then attached to the ContentPart
    _offerRepository.Create(n);
    offerList.Add(n);
  }
  part.Offers = offerList;
}&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;That&amp;#8217;s it! Importing and exporting works like a charme, and my colleague&amp;#8217;s have the same pages as I have when they re-install orchard with my recipe!&lt;/p&gt;</description><link>http://developer.3l.nl/post/16165483880</link><guid>http://developer.3l.nl/post/16165483880</guid><pubDate>Fri, 20 Jan 2012 10:52:01 +0100</pubDate><category>orchard</category><category>import</category><category>export</category><category>xml</category><category>recipe</category><dc:creator>lukasvan3l</dc:creator></item><item><title>404 and 500 pages in .NET</title><description>&lt;p&gt;The web.config settings for 404 and 500 error pages are a nuisance! I&amp;#8217;ve got the following configuration that gets me as close to my goals as I can get:&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;customErrors&lt;/span&gt; &lt;span&gt;mode&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt;On&lt;/span&gt;&lt;span&gt;"&lt;/span&gt; &lt;span&gt;defaultRedirect&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt;~/500.html&lt;/span&gt;&lt;span&gt;"&lt;/span&gt; &lt;span&gt;redirectMode&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt;ResponseRewrite&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;
  &lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;error&lt;/span&gt; &lt;span&gt;statusCode&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt;404&lt;/span&gt;&lt;span&gt;"&lt;/span&gt; &lt;span&gt;redirect&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt;~/page-not-found&lt;/span&gt;&lt;span&gt;"&lt;/span&gt; &lt;span&gt;/&amp;gt;&lt;/span&gt;
  &lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;error&lt;/span&gt; &lt;span&gt;statusCode&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt;500&lt;/span&gt;&lt;span&gt;"&lt;/span&gt; &lt;span&gt;redirect&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt;~/500.html&lt;/span&gt;&lt;span&gt;"&lt;/span&gt; &lt;span&gt;/&amp;gt;&lt;/span&gt;
&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;customErrors&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;
&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;httpErrors&lt;/span&gt; &lt;span&gt;errorMode&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt;Custom&lt;/span&gt;&lt;span&gt;"&lt;/span&gt; &lt;span&gt;existingResponse&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt;Replace&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;
  &lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;clear&lt;/span&gt; &lt;span&gt;/&amp;gt;&lt;/span&gt;
  &lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;error&lt;/span&gt; &lt;span&gt;statusCode&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt;404&lt;/span&gt;&lt;span&gt;"&lt;/span&gt; &lt;span&gt;subStatusCode&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt;-1&lt;/span&gt;&lt;span&gt;"&lt;/span&gt; &lt;span&gt;path&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt;/page-not-found&lt;/span&gt;&lt;span&gt;"&lt;/span&gt; &lt;span&gt;responseMode&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt;ExecuteURL&lt;/span&gt;&lt;span&gt;"&lt;/span&gt; &lt;span&gt;/&amp;gt;&lt;/span&gt;
  &lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;error&lt;/span&gt; &lt;span&gt;statusCode&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt;500&lt;/span&gt;&lt;span&gt;"&lt;/span&gt; &lt;span&gt;path&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt;~/500.html&lt;/span&gt;&lt;span&gt;"&lt;/span&gt; &lt;span&gt;responseMode&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;"&lt;/span&gt;&lt;span&gt;File&lt;/span&gt;&lt;span&gt;"&lt;/span&gt; &lt;span&gt;/&amp;gt;&lt;/span&gt;
&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;httpErrors&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;This achieves the following goals:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;The URL doesn&amp;#8217;t change (you don&amp;#8217;t get redirected to 500.html)&lt;/li&gt;
&lt;li&gt;404 page is editable via the CMS&lt;/li&gt;
&lt;li&gt;The 404 page is relative to the domain name, therefore in the right language (domain.nl/page-not-found gives Dutch content, domain.fr/page-not-found French)&lt;/li&gt;
&lt;li&gt;The 500 page can never give a 500 error itself: it&amp;#8217;s a static html file&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;But unfortunately there&amp;#8217;s more neccessary features missing:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;The 404 and 500 pages now return a statuscode 200&lt;/li&gt;
&lt;li&gt;The 500 page is static, so the contents isn&amp;#8217;t translatable&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;The second problem can be fixed by loading the translated values via Ajax. If the ajax request also fails, the fallback language is English. Otherwise you get the right language.&lt;/p&gt;
&lt;p&gt;But how to fix the statuscode so that it returns the one I expect is a mystery for me.&lt;/p&gt;
&lt;ul&gt;&lt;/ul&gt;</description><link>http://developer.3l.nl/post/15298535116</link><guid>http://developer.3l.nl/post/15298535116</guid><pubDate>Wed, 04 Jan 2012 17:32:32 +0100</pubDate><dc:creator>lukasvan3l</dc:creator></item><item><title>Orchard Multitenancy module</title><description>&lt;p&gt;I ran into a few issues working with the Multitenancy Module in Orchard CMS:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Setting up a development environment using IIS&lt;br/&gt;&lt;/strong&gt;First of all there&amp;#8217;s just one site running on my server, but it needs to be reached by multiple domains. For instance, http://localhost should go to my default site, and http://tenant should go to the tenant site. To get this working in IIS, edit the Hosts file (c:\Windows\System32\drivers\etc\hosts) and add:&lt;/p&gt;
&lt;pre&gt;127.0.0.1		localhost&lt;br/&gt;127.0.0.1		tenant&lt;/pre&gt;
&lt;p&gt;When you surf to http://tenant, this file tells your machine to go to 127.0.0.1 instead of look the domain up on the internet.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Deleting tenants&lt;br/&gt;&lt;/strong&gt;When you create a tenant, a new folder gets created in the AppData/Sites directory. Next to the existing Default site.&lt;/p&gt;
&lt;p&gt;The tenants are retrieved by the function ShellSettingsManager.LoadSettings(). This function checks the AppData/Sites folder for folders containing a Settings.txt file. So if you&amp;#8217;re running into problems with your tenant, it&amp;#8217;s easy to remove it again by removing the directory.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Custom named Routes&lt;br/&gt;&lt;/strong&gt;When it was working, I immediately got this error message:&lt;/p&gt;
&lt;pre&gt;A route named 'LocationDetails' is already in the route collection. Route names must be unique.&lt;br/&gt;Parameter name: name&lt;/pre&gt;
&lt;p&gt;And more disturbingly, the error message was also shown on my default site! First thing to do is remove the tenant directory from AppData/Sites, so the default site builds again. Then find out wtf is happening!&lt;/p&gt;
&lt;p&gt;Apparantly there&amp;#8217;s one MVC RouteTable in memory. So when a module registers a route, it also gets registered for each tenant that has the module enabled. The problem here is that I was adding named routes to the RouteTable. By simple removing the &amp;#8220;Name = &amp;#8220;LocationDetails&amp;#8221;&amp;#8220;, both sites were working again, both enabling my LocationDetailsModule.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Wrap-up&lt;br/&gt;&lt;/strong&gt;I&amp;#8217;m going to use the multitenancy module to host 7 different languages of the same site, each on its own domain name. With this module I can have 1 codebase and configure each site to behave slightly different. If I run into any other problems, you&amp;#8217;ll be the first to hear :)&lt;/p&gt;</description><link>http://developer.3l.nl/post/15021859836</link><guid>http://developer.3l.nl/post/15021859836</guid><pubDate>Fri, 30 Dec 2011 11:44:21 +0100</pubDate><category>orchard</category><category>multitenancy</category><dc:creator>lukasvan3l</dc:creator></item><item><title>My f1rst Orchard site</title><description>&lt;p&gt;&lt;img src="http://media.tumblr.com/tumblr_lwnx8hZYb71qev0qn.jpg"/&gt;&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve been working on a project based on the Orchard CMS for a travel agency. We chose Orchard because of the modularity; four different travel sites will be based on this same architecture. Different themes, different modules, but one codebase.&lt;/p&gt;
&lt;p&gt;Last week the first site went live: check it out at &lt;a href="http://www.charmequality.nl" target="_blank"&gt;&lt;a href="http://www.charmequality.nl"&gt;http://www.charmequality.nl&lt;/a&gt;&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;We faced some interesting problems and came up with creative solutions. A few key learnings:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;The modularity is indeed amazing: on a live site en- or disable a feature and the site can get changed in many different ways&lt;/li&gt;
&lt;li&gt;The learning curve for developing Orchard is quite steep, not easy to step in. The cms is using some complicated techniques that take some time to fully understand. But once you get to know them, you&amp;#8217;ll also have improved your c# knowledge!&lt;/li&gt;
&lt;li&gt;Orchard&amp;#8217;s performance is far from optimal. Outputcaching is needed to make it work and we still have CPU spikes when visitor counters rise. When you need live data on your outputcached page, consider using Ajax requests to load the uncachable data and scatter it on the page&lt;/li&gt;
&lt;li&gt;The gallery has loads of good stuff! Some modules don&amp;#8217;t work perfectly out-of-the-box, but can usually be fixed without much hassle. Don&amp;#8217;t give up too easily! Fixing the issue also helps you better understand the inner workings of Orchard.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;All in all I&amp;#8217;m glad to have had this experience. And it&amp;#8217;s not over yet, there&amp;#8217;s a 1.1 version in the making and after that we&amp;#8217;re starting on the second travel agency site.&lt;/p&gt;</description><link>http://developer.3l.nl/post/14672054448</link><guid>http://developer.3l.nl/post/14672054448</guid><pubDate>Fri, 23 Dec 2011 16:39:23 +0100</pubDate><category>deploy</category><category>orchard</category><dc:creator>lukasvan3l</dc:creator></item><item><title>Don't trust Modules!</title><description>&lt;p&gt;One of the powers of Orchard is a gallery filled with useful modules. Just install them and you&amp;#8217;re good to go. But if you want to build a high-performance website with Orchard CMS, you&amp;#8217;re gonna have to do more than that. The modules are really generic and that could cost you in performance. Also, they&amp;#8217;re contributed by the community, and not everyone has the performance focus you might need.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Output Caching module&lt;/strong&gt;&lt;br/&gt;The &lt;a href="http://gallery.orchardproject.net/List/Modules/Orchard.Module.Contrib.Cache" target="_blank"&gt;output caching module&lt;/a&gt; for instance, does a terrific job at outputcaching. If I had built it myself it wouldn&amp;#8217;t be as flexible with a cms module where editors can change the cachetime per route and even invalide specific cache entries. But for my application it can be modified to greatly increase the response times of a cached page.&lt;br/&gt;For each page that is outputcached, the OutputCacheFilter computes a CacheKey that&amp;#8217;s unique for this specific url and serversettings by joining the url, tenant, culture and themeid.&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;private&lt;/span&gt; &lt;span&gt;string&lt;/span&gt; ComputeCacheKey(&lt;span&gt;ActionExecutingContext&lt;/span&gt; filterContext)&lt;br/&gt;{&lt;br/&gt;  &lt;span&gt;var&lt;/span&gt; keyBuilder = &lt;span&gt;new&lt;/span&gt; &lt;span&gt;StringBuilder&lt;/span&gt;();&lt;br/&gt;  keyBuilder.Append(&lt;span&gt;"tenant="&lt;/span&gt;).Append(_shellSettings.Name).Append(&lt;span&gt;";"&lt;/span&gt;);&lt;br/&gt;  keyBuilder.Append(&lt;span&gt;"url="&lt;/span&gt;).Append(filterContext.HttpContext.Request.RawUrl.ToLowerInvariant()).Append(&lt;span&gt;";"&lt;/span&gt;);&lt;br/&gt;  &lt;span&gt;foreach&lt;/span&gt; (&lt;span&gt;var&lt;/span&gt; pair &lt;span&gt;in&lt;/span&gt; filterContext.ActionParameters)&lt;br/&gt;    keyBuilder.AppendFormat(&lt;span&gt;"{0}={1};"&lt;/span&gt;, pair.Key, pair.Value);&lt;br/&gt;  keyBuilder.Append(&lt;span&gt;"culture="&lt;/span&gt;).Append(_workContext.CurrentCulture).Append(&lt;span&gt;";"&lt;/span&gt;);&lt;br/&gt;  keyBuilder.Append(&lt;span&gt;"theme="&lt;/span&gt;).Append(_themeManager.GetRequestTheme(filterContext.RequestContext).Id).Append(&lt;span&gt;";"&lt;/span&gt;);&lt;br/&gt;  &lt;span&gt;return&lt;/span&gt; keyBuilder.ToString();&lt;br/&gt;}&lt;br/&gt;&lt;/pre&gt;
&lt;p&gt;In my application each tenant has its own culture. So I don&amp;#8217;t need both of them in my cachekey. When I take out the line that includes the CurrentCulture, the page response time drops from 45ms to 5ms!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SecureSocketsLayer module&lt;/strong&gt;&lt;br/&gt;The &lt;a href="http://gallery.orchardproject.net/List/Modules/Orchard.Module.Contrib.SecuredSocketsLayer" target="_blank"&gt;SecureSocketsLayer&lt;/a&gt; also gets executed for each page request (even the outputcached ones!). In it&amp;#8217;s filter is the following code:&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;var&lt;/span&gt; settings = _services.WorkContext.CurrentSite.As&amp;lt;SslSettingsPart&amp;gt;();&lt;br/&gt;&lt;/pre&gt;

&lt;p&gt;This does multiple database queries and costs about 40ms. On an outputcached page that&amp;#8217;s a lot of unneccesary overhead!. In my specific application I only needed to do one area over SSL. So I put the setting (EnableSSL) in the AppSettings, and created my own filter with a tiny piece of code.&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;var&lt;/span&gt; wishedPort = 80;&lt;br/&gt;&lt;span&gt;if&lt;/span&gt; (UseSsl)&lt;br/&gt;{&lt;br/&gt;  &lt;span&gt;var&lt;/span&gt; area = filterContext.Controller.ControllerContext.RouteData.Values[&lt;span&gt;"area"&lt;/span&gt;];&lt;br/&gt;  &lt;span&gt;if&lt;/span&gt; (area != &lt;span&gt;null&lt;/span&gt; &amp;amp;&amp;amp; area.ToString() == &lt;span&gt;"Viaselect.Checkout"&lt;/span&gt;)&lt;br/&gt;    wishedPort = 443;&lt;br/&gt;}&lt;br/&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br/&gt;When you install a module, take a good look at the code! The developer might have made choices differently than you would have made them. And sometimes it&amp;#8217;s a really quick fix to tune a module and benefit from it&amp;#8217;s extra&amp;#8217;s!&lt;/p&gt;</description><link>http://developer.3l.nl/post/13588961151</link><guid>http://developer.3l.nl/post/13588961151</guid><pubDate>Thu, 01 Dec 2011 14:54:25 +0100</pubDate><category>orchard</category><category>performance</category><category>modules</category><dc:creator>lukasvan3l</dc:creator></item><item><title>Speeding up Orchard: Packaging and Minification</title><description>&lt;p&gt;Orchard is really flexible and modular. This has a big drawback while performance tuning: it&amp;#8217;s really hard to package the static resources. Each module has its own javascript and css files, and one module doesn&amp;#8217;t know about the files of the other. Time to hack performance into it!&lt;/p&gt;
&lt;p&gt;The solution I implemented was a plain batch file. It gets fed a list of css and js files and minifies them to one output file. It does take a few steps to include a new js or css file, but it performs a lot better!&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s the bat file, using the Microsoft Ajax Minifier and DotLess:&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;for&lt;/span&gt; /R %%i &lt;span&gt;in&lt;/span&gt; (*.less) &lt;span&gt;do&lt;/span&gt; (&lt;br/&gt;  tools\dotless.compiler.exe &lt;span&gt;"%%i"&lt;/span&gt; &lt;span&gt;"%%i.css"&lt;/span&gt;&lt;br/&gt;)&lt;br/&gt;&lt;br/&gt;tools\AjaxMin-4.37.exe -js -clobber -xml &lt;span&gt;"minify.xml"&lt;/span&gt; -&lt;span&gt;out&lt;/span&gt; &lt;span&gt;"Orchard.Web\min"&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;So first of all I take each *.less file and run it through the dotless compiler. The output is a *.less.css file next to each original, which I&amp;#8217;ve included in the minify.xml file that AjaxMin parses. Here&amp;#8217;s a portion of it:&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;root&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span&gt;  &amp;lt;&lt;/span&gt;&lt;span&gt;output&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;path&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;"&lt;span&gt;js.js&lt;/span&gt;"&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;path&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;"c:\inetpub&lt;span&gt;/Modules/Viaselect/Scripts/plugins/jquery.ba-hashchange.min.js&lt;/span&gt;"&lt;span&gt; /&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;path&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;"c:\inetpub&lt;span&gt;/Modules/Viaselect/Scripts/menu.js&lt;/span&gt;"&lt;span&gt; /&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;span&gt;  &amp;lt;/&lt;/span&gt;&lt;span&gt;output&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span&gt;  &amp;lt;&lt;/span&gt;&lt;span&gt;output&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;path&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;"&lt;span&gt;css.css&lt;/span&gt;"&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;path&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;"c:\inetpub&lt;span&gt;/Themes/CharmeQuality/styles/base.less.css&lt;/span&gt;"&lt;span&gt; /&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;input&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;path&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;"c:\inetpub&lt;span&gt;/modules/viaselect/styles/datepicker.less.css&lt;/span&gt;"&lt;span&gt; /&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span&gt;  &amp;lt;/&lt;/span&gt;&lt;span&gt;output&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;root&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;Unfortunately I didn&amp;#8217;t get it to work with relative paths, so I had to make them absolute. We&amp;#8217;ll cross that bridge when we get there :)&lt;/p&gt;
&lt;p&gt;So now I have a js.js and a css.css that I include in the layout.cshtml:&lt;/p&gt;
&lt;pre&gt;  Script.Require(&lt;span&gt;"jQuery"&lt;/span&gt;).AtHead();&lt;br/&gt;  Script.Include(&lt;span&gt;"~/min/js.debug.js"&lt;/span&gt;, &lt;span&gt;"~/min/js.js"&lt;/span&gt;);&lt;br/&gt;  Style.Include(&lt;span&gt;"~/min/css.debug.css"&lt;/span&gt;, &lt;span&gt;"~/min/css.css"&lt;/span&gt;);&lt;br/&gt;&lt;/pre&gt;
&lt;p&gt;And of course when you&amp;#8217;re in debug mode, you want firebug to give you the right codelines! Here&amp;#8217;s how to tackle that one; the debug files contain the following:&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;@import&lt;/span&gt; url("/Themes/CharmeQuality/styles/base.less");&lt;br/&gt;&lt;span&gt;@import&lt;/span&gt; url("/modules/viaselect/styles/datepicker.less");&lt;br/&gt;&lt;/pre&gt;
&lt;pre&gt;document.write(&lt;span&gt;"&amp;lt;script src='/Modules/Viaselect/Scripts/plugins/jquery.ba-hashchange.min.js'&amp;gt;&amp;lt;\/script&amp;gt;"&lt;/span&gt;);&lt;br/&gt;document.write(&lt;span&gt;"&amp;lt;script src='/Modules/Viaselect/Scripts/menu.js'&amp;gt;&amp;lt;\/script&amp;gt;"&lt;/span&gt;);&lt;br/&gt;&lt;/pre&gt;
&lt;p&gt;It&amp;#8217;s not the best solution, but for now it speeds up the site considerably! I wouldn&amp;#8217;t know how to create a module that takes care of this. The ResourceManager is way too complicated to just include the package if the file you&amp;#8217;re requesting is inside the xml file. If any of you have good ideas, let me know! I&amp;#8217;d love to facilitate this module :)&lt;/p&gt;</description><link>http://developer.3l.nl/post/13502077908</link><guid>http://developer.3l.nl/post/13502077908</guid><pubDate>Tue, 29 Nov 2011 16:50:00 +0100</pubDate><category>orchard</category><category>performance</category><category>minification</category><category>packaging</category><category>statics</category><dc:creator>lukasvan3l</dc:creator></item><item><title>Combining Classic ASP and .NET MVC3</title><description>&lt;p&gt;There&amp;#8217;s this old-old-old website that I want to give a little upgrade. It&amp;#8217;s written in classic ASP (remember &amp;#8220;on error resume next&amp;#8221;?) and has a nice content management system. I&amp;#8217;m not planning on re-writing the whole thing, but just to make some tweaks.&lt;/p&gt;
&lt;p&gt;First thing I wanted to do was upgrade to .net 4 and .net mvc3. I&amp;#8217;ve allways hosted my sites at &lt;a href="http://www.vevida.nl" target="_blank"&gt;Vevida&lt;/a&gt;, and they&amp;#8217;ve never let me down. This time they moved my website to a different server (took about 20 minutes) and then helped me configure the whole thing. All I have is FTP access and the CMS was in a protected folder so your browser asked a username/password to enter it. In .net 4 this isn&amp;#8217;t possible anymore (apparantly) so I created my own authorization using FormsAuthentication:&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;system.web&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span&gt;  &amp;lt;&lt;/span&gt;&lt;span&gt;authentication&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;mode&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;"&lt;span&gt;Forms&lt;/span&gt;"&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;forms&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;loginUrl&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;"&lt;span&gt;Login.aspx&lt;/span&gt;"&lt;span&gt; &lt;/span&gt;&lt;span&gt;defaultUrl&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;"&lt;span&gt;Members&lt;/span&gt;"&lt;span&gt; /&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span&gt;  &amp;lt;/&lt;/span&gt;&lt;span&gt;authentication&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span&gt;  &amp;lt;&lt;/span&gt;&lt;span&gt;authorization&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;allow&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;users&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;"&lt;span&gt;?&lt;/span&gt;"&lt;span&gt; /&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span&gt;  &amp;lt;/&lt;/span&gt;&lt;span&gt;authorization&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;system.web&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;location&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;path&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;"&lt;span&gt;cms&lt;/span&gt;"&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span&gt;  &amp;lt;&lt;/span&gt;&lt;span&gt;system.web&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;authorization&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span&gt;      &amp;lt;&lt;/span&gt;&lt;span&gt;deny&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;users&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;"&lt;span&gt;?&lt;/span&gt;"&lt;span&gt; /&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span&gt;      &amp;lt;&lt;/span&gt;&lt;span&gt;allow&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;users&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;"&lt;span&gt;*&lt;/span&gt;"&lt;span&gt; /&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;authorization&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span&gt;  &amp;lt;/&lt;/span&gt;&lt;span&gt;system.web&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;location&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;And then the login logic using a normal .aspx file:&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;var&lt;/span&gt; username = Request.Form[&lt;span&gt;"username"&lt;/span&gt;];&lt;br/&gt;&lt;span&gt;var&lt;/span&gt; password = Request.Form[&lt;span&gt;"password"&lt;/span&gt;];&lt;br/&gt;&lt;br/&gt;&lt;span&gt;if&lt;/span&gt; (username == &lt;span&gt;"specific"&lt;/span&gt; &amp;amp;&amp;amp; password == &lt;span&gt;"credentials"&lt;/span&gt;)&lt;br/&gt;{&lt;br/&gt;  &lt;span&gt;FormsAuthentication&lt;/span&gt;.RedirectFromLoginPage(username, &lt;span&gt;true&lt;/span&gt;);&lt;br/&gt;}&lt;br/&gt;&lt;/pre&gt;

&lt;p&gt;That&amp;#8217;s easy! Everything&amp;#8217;s up-and-running again, and now I can start using .asp and .aspx and .cshtml files next to eachother :)&lt;/p&gt;</description><link>http://developer.3l.nl/post/13293978207</link><guid>http://developer.3l.nl/post/13293978207</guid><pubDate>Fri, 25 Nov 2011 10:51:14 +0100</pubDate><category>mvc</category><category>.net</category><category>classic asp</category><dc:creator>lukasvan3l</dc:creator></item><item><title>Profiling orchard with Eqatec Profiler</title><description>&lt;p&gt;I can&amp;#8217;t seem to get Red-Gate Ants Performance Profiler to attach to the right website. If I let it attach to IIS directly, it restarts IIS in .net2.0 mode instead of .net4.0. When I let it create its own webserver, I do get .net4.0, but am welcomed with the message &amp;#8220;&lt;em&gt;Operation could destabilize the runtime&lt;/em&gt;&amp;#8221; in the WarmupHttpModule constructor. Not very comforting.&lt;/p&gt;
&lt;p&gt;Luckily a colleague showed me &lt;a href="http://eqatec.com/Profiler/Home.aspx" target="_blank"&gt;Eqatec Profiler&lt;/a&gt;. It works really ingenious: it re-compiles selected DLL&amp;#8217;s, injecting profiling logic into them. This should work nicely with Orchard CMS.&lt;/p&gt;
&lt;p&gt;So I want Eqatec to handle the Orchard Core, and installed modules. First problem occurs: the modules are dynamically compiled. As Eqatec can only handle DLL files that are in the same folder, I made references from Orchard.Web to the modules I wanted to investigate. This is my config for Eqatec:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Eqatec Orchard configuration" height="526" src="http://www.3l.nl/meuk/dev/eqatec1.png" width="351"/&gt;&lt;/p&gt;
&lt;p&gt;All I have to do now is click &amp;#8220;Build&amp;#8221;, the selected dll&amp;#8217;s are re-compiled and when I surf to my website (http://localhost) I see logs coming in in the &amp;#8220;Run&amp;#8221; tab. I don&amp;#8217;t want to profile the start-up costs of Orchard, so I&amp;#8217;ll refresh my browser a couple of times, then hit &amp;#8220;reset counters&amp;#8221;, refresh twice, and click &amp;#8220;take snapshot&amp;#8221;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Eqatec Orchard profiling output" height="321" src="http://www.3l.nl/meuk/dev/eqatec2.png" width="546"/&gt;&lt;/p&gt;
&lt;p&gt;Perfect! This overview tells us the BuildDisplay was called 4 times, resulting in a total time of nearly 600ms that it took. And The repository did 126 database GetById() calls. And a whopping 316.100 time IsCurrent() on an IVolatileToken&lt;/p&gt;
&lt;p&gt;So we&amp;#8217;ve got some pointers on where to look for performance fixes ;)&lt;/p&gt;
&lt;p&gt;&lt;em&gt;ps. Eqatec has a &lt;a href="http://info.eqatec.com/acton/fs/blocks/showLandingPage/a/1551/p/p-0016/t/page/fm/0" target="_blank"&gt;time limited campaign&lt;/a&gt; where you can get a Corporate license worth $999 for free!&lt;/em&gt;&lt;/p&gt;</description><link>http://developer.3l.nl/post/13209357555</link><guid>http://developer.3l.nl/post/13209357555</guid><pubDate>Wed, 23 Nov 2011 18:20:49 +0100</pubDate><category>performance</category><category>profiling</category><category>orchard</category><category>eqatec</category><dc:creator>lukasvan3l</dc:creator></item><item><title>External data in Orchard</title><description>&lt;p&gt;I have a webservice that gives me information to display on a detail page. This needs to be output in an orchard page with its masterpage and widgets surrounding it.&lt;/p&gt;
&lt;p&gt;Colleagues of mine are trying the approach where they import the webservice data into Orchard, and let Orchard figure out the routing and displaying of the content. They have a fixed set of detail pages, none ever disappear and sometimes pages get added. (They are running into performance issues because they need an initial import of about 500.000 items)&lt;/p&gt;
&lt;p&gt;My case is a little bit different: the data changes constantly and there can&amp;#8217;t be a delay. The data has to come directly from the webservices, I can&amp;#8217;t even cache it for a few minutes. So I fiddled around a bit and came up with this solution. In orchard I create a LocationDetails contenttype that&amp;#8217;s not creatable and automatically gets the LocationDetailsPart:&lt;/p&gt;
&lt;pre&gt;&lt;pre&gt;ContentDefinitionManager.AlterPartDefinition(&lt;span&gt;typeof&lt;/span&gt;(&lt;span&gt;LocationDetailsPart&lt;/span&gt;).Name, part =&amp;gt; part&lt;br/&gt;  .Attachable(&lt;span&gt;false&lt;/span&gt;)&lt;br/&gt;);&lt;br/&gt;ContentDefinitionManager.AlterTypeDefinition(&lt;span&gt;"LocationDetails"&lt;/span&gt;, cfg =&amp;gt; cfg&lt;br/&gt;  .WithPart(&lt;span&gt;typeof&lt;/span&gt;(&lt;span&gt;LocationDetailsPart&lt;/span&gt;).Name)&lt;br/&gt;  .Creatable(&lt;span&gt;false&lt;/span&gt;)&lt;br/&gt;);&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;I then implemented a custom Controller that matches a url. If the appropriate content is found on the webservice, a temporary LocationDetails contentitem gets created (but doesn&amp;#8217;t get inserted into the database!) and gets passed the details from the webservice.&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;var details = getStuffFromWebservice();&lt;br/&gt;if (details == null) return new HttpNotFoundResult();&lt;br/&gt;&lt;br/&gt;var&lt;/span&gt; contentItem = _contentManager.New("&lt;span&gt;LocationDetails"&lt;/span&gt;);&lt;br/&gt;contentItem.As&amp;lt;&lt;span&gt;LocationDetailsPart&lt;/span&gt;&amp;gt;().Details = details;&lt;br/&gt;&lt;br/&gt;&lt;span&gt;return&lt;/span&gt; &lt;span&gt;new&lt;/span&gt; &lt;span&gt;ShapeResult&lt;/span&gt;(&lt;span&gt;this&lt;/span&gt;, _contentManager.BuildDisplay(contentItem));&lt;/pre&gt;
&lt;p&gt;After that it&amp;#8217;s just using the default display logica of Orchard!&lt;/p&gt;</description><link>http://developer.3l.nl/post/13199164939</link><guid>http://developer.3l.nl/post/13199164939</guid><pubDate>Wed, 23 Nov 2011 10:29:14 +0100</pubDate><category>orchard</category><category>webservices</category><dc:creator>lukasvan3l</dc:creator></item><item><title>Multiple features in one orchard module</title><description>&lt;p&gt;When you&amp;#8217;re creating multiple features in an Orchard module, it&amp;#8217;s important to specify of each class for which feature it&amp;#8217;s needed. The Q42.DbTranslations module for instance, contains two features: Q42.DbTranslations and Q42.AdminCultureSelector.&lt;/p&gt;
&lt;p&gt;First attempt I only decorated the Handler to be specific to this feature:&lt;/p&gt;
&lt;pre&gt;[OrchardFeature(&lt;span&gt;"Q42.AdminCultureSelector"&lt;/span&gt;)]&lt;br/&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;AdminCultureSettingsPartHandler&lt;/span&gt;&lt;span&gt; : &lt;/span&gt;&lt;span&gt;ContentHandler&lt;br/&gt;&lt;/span&gt;&lt;span&gt;{&lt;br/&gt;&lt;/span&gt;&lt;span&gt;  &lt;/span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; AdminCultureSettingsPartHandler(&lt;/span&gt;&lt;span&gt;IRepository&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;AdminCultureSettingsPartRecord&lt;/span&gt;&lt;span&gt;&amp;gt; repository)&lt;br/&gt;&lt;/span&gt;&lt;span&gt;  {&lt;br/&gt;&lt;/span&gt;&lt;span&gt;    Filters.Add(&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ActivatingFilter&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;AdminCultureSettingsPart&lt;/span&gt;&lt;span&gt;&amp;gt;(&lt;/span&gt;&lt;span&gt;"Site"&lt;/span&gt;&lt;span&gt;));&lt;br/&gt;&lt;/span&gt;&lt;span&gt;    Filters.Add(&lt;/span&gt;&lt;span&gt;StorageFilter&lt;/span&gt;&lt;span&gt;.For(repository));&lt;br/&gt;&lt;/span&gt;&lt;span&gt;  }&lt;br/&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;I expected the AdminCultureSettingsPart not to be attached to Site, and therefore the whole feature would be disabled. But alas, it didn&amp;#8217;t work. So I decorated the Part, the PartRecord and the Driver with OrchardFeature, and that fixed the problems.&lt;/p&gt;
&lt;p&gt;But then you&amp;#8217;re not there yet. Because when you have multiple features in a module, everything that isn&amp;#8217;t specifically decorated with an OrchardFeature, is automatically allways enabled. So everything specific for DbTranslations also needed to be decorated.&lt;/p&gt;
&lt;p&gt;Actually, every class except Migrations needs to be decorated, when you have multiple features in one module. In the end I decided to split the two and create separate modules for them :)&lt;/p&gt;</description><link>http://developer.3l.nl/post/13160899431</link><guid>http://developer.3l.nl/post/13160899431</guid><pubDate>Tue, 22 Nov 2011 17:37:00 +0100</pubDate><category>features</category><category>modules</category><category>orchard</category><dc:creator>lukasvan3l</dc:creator></item></channel></rss>

