Lukasvan3L

A pragmatic programmer

1 note &

AirPlay crashes my router dir-635

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.

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’t receive a signal from the router.

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’ve been listening my spotify playlist via iPad for the past hour or so, unobstructed.

In the release notes I can’t find the change that fixed it. If you find out, please let me know! For now, I’m happy :)

0 notes &

log4net 1.2.11 dependency hell

Whowh, that’s a nice error:

Looks like you forgot to register the http module Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule
To fix this add
<add name="PerRequestLifestyle" type="Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule, Castle.Windsor" />
to the <httpModules> 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 <modules> section under <system.webServer>.
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.

That doesn’t make sense… After some fumbling around I got the next error message:

An error occurred creating the configuration section handler for common/logging: Unable to create type 'Common.Logging.Log4Net.Log4NetLoggerFactoryAdapter, Common.Logging.Log4Net'

And after that another error in log4net configuration. Eventually colleague Mark helped me figure out the following was the underlying problem:

log4net version 1.2.11 has a different publicKeyToken then 1.2.10

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’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’t help.

What can we learn from this?
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:

public CollectionObjectService CollectionObjectService { get; set; }
public SynchronizerService()
{
}

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:

public CollectionObjectService CollectionObjectService { get; private set; }
public SynchronizerService(CollectionObjectService coService)
{
  this.CollectionObjectService = coService;
}

6 notes &

Google mail vs Google apps

My current e-mail setup is as follows:

  • Mail sent to my 3l.nl mailaccount is received in a pop3 mailbox
  • My gmail account is set up to download the mail from the pop3 mailbox periodically
  • My father and mother both have 3l.nl mailaddresses, and receive the pop3 mails directly in outlook
  • My brother and sister both have 3l.nl mailaddresses, but they’re just aliasses and their mail is directly sent to their gmail or hotmail (yup, some people still use it…) address.

A change of heart

I’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).

Also it eliminates the need of an additional gmail address for myself, as it’s unneccessary and my mail arrives delayed, because the pop3 server is pinged periodically (5 minutes, but still).

And last but not least, we’ll be using our awesome 3l.nl e-mail adresses to log in, how cool is that?!

The downside

  • 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.
  • 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
  • The aliasses that I set up for my brother and sister won’t work anymore. I’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…

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!

    31 notes &

    Orchard import & export 1-n relations

    While developing in Orchard with a team, recipes are very useful. Everyone has their own database (so we don’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’s when Recipes come in.

    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’s not as easy as it seems because it works with Linq.XElement properties.

    First, the exporting
    Inside the ContentPartDriver, here’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:

    // first, get the ContentPart element
    var parent = context.Element(part.PartDefinition.Name);
    
    // a simple one: a string
    if (!string.IsNullOrEmpty(part.RichTextBlock1))
      parent.SetAttributeValue("RichTextBlock1", part.RichTextBlock1);
    
    // a 1-n relationship
    // create the container element
    parent.SetElementValue("offers", "");
    var offers = parent.Element("offers");
    foreach (var offer in part.Offers)
    {
      // every node must have a unique name, else SetElementValue won't work
      var elid = "offer" + offer.Id;
      // again, first create the container element
      offers.SetElementValue(elid, "");
      var el = offers.Element(elid);
      // then import the values (without Id, it will be autogenerated)
      //el.SetAttributeValue("Id", offer.Id);
      el.SetAttributeValue("Image", offer.Image);
      el.SetAttributeValue("Price", offer.Price);
      el.SetAttributeValue("Url", offer.Url);
    }

    Expand the recipe
    So now, when I execute the export function (don’t forget to check the Data checkbox!), I get the entire contentitem with my custom contentpart embedded into it. The export.xml file that’s generated can be used as recipe, or parts of it can be used.

    And then, the importing
    So now I override the Importing(ContentPart part, ImportContentContext context) function as follows:

    // this gets injected into the constructor by Autofac
    private readonly IRepository<OfferRecord> _offerRepository;


    // first import the simple richtext field
    var
    RichTextBlock1 = context.Attribute(part.PartDefinition.Name, "RichTextBlock1"); if (RichTextBlock1 != null) part.RichTextBlock1 = RichTextBlock1;
    // then get the "offers" element
    var offers = context.Data.Element(part.PartDefinition.Name).Element("offers"); if (offers != null) { var offerList = new List<OfferRecord>();
    // and import each of the offer elements. I'm not checking on nodenames because they're unique!
    foreach (var offer in offers.Elements()) { var n = new OfferRecord(); if (offer.Attribute("Image") != null) n.Image = offer.Attribute("Image").Value; if (offer.Attribute("Price") != null) n.Price = offer.Attribute("Price").Value; if (offer.Attribute("Url") != null) n.Url = offer.Attribute("Url").Value;

    // the new offer should first be saved to database, then attached to the ContentPart _offerRepository.Create(n); offerList.Add(n); } part.Offers = offerList; }

    That’s it! Importing and exporting works like a charme, and my colleague’s have the same pages as I have when they re-install orchard with my recipe!

    0 notes &

    404 and 500 pages in .NET

    The web.config settings for 404 and 500 error pages are a nuisance! I’ve got the following configuration that gets me as close to my goals as I can get:

    <customErrors mode="On" defaultRedirect="~/500.html" redirectMode="ResponseRewrite">
      <error statusCode="404" redirect="~/page-not-found" />
      <error statusCode="500" redirect="~/500.html" />
    </customErrors>
    <httpErrors errorMode="Custom" existingResponse="Replace">
      <clear />
      <error statusCode="404" subStatusCode="-1" path="/page-not-found" responseMode="ExecuteURL" />
      <error statusCode="500" path="~/500.html" responseMode="File" />
    </httpErrors>

    This achieves the following goals:

    • The URL doesn’t change (you don’t get redirected to 500.html)
    • 404 page is editable via the CMS
    • 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)
    • The 500 page can never give a 500 error itself: it’s a static html file

    But unfortunately there’s more neccessary features missing:

    • The 404 and 500 pages now return a statuscode 200
    • The 500 page is static, so the contents isn’t translatable

    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.

    But how to fix the statuscode so that it returns the one I expect is a mystery for me.

      3 notes &

      Orchard Multitenancy module

      I ran into a few issues working with the Multitenancy Module in Orchard CMS:

      Setting up a development environment using IIS
      First of all there’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:

      127.0.0.1		localhost
      127.0.0.1 tenant

      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.

      Deleting tenants
      When you create a tenant, a new folder gets created in the AppData/Sites directory. Next to the existing Default site.

      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’re running into problems with your tenant, it’s easy to remove it again by removing the directory.

      Custom named Routes
      When it was working, I immediately got this error message:

      A route named 'LocationDetails' is already in the route collection. Route names must be unique.
      Parameter name: name

      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!

      Apparantly there’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 “Name = “LocationDetails”“, both sites were working again, both enabling my LocationDetailsModule.

      Wrap-up
      I’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’ll be the first to hear :)

      16 notes &

      My f1rst Orchard site

      I’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.

      Last week the first site went live: check it out at http://www.charmequality.nl!

      We faced some interesting problems and came up with creative solutions. A few key learnings:

      • The modularity is indeed amazing: on a live site en- or disable a feature and the site can get changed in many different ways
      • 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’ll also have improved your c# knowledge!
      • Orchard’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
      • The gallery has loads of good stuff! Some modules don’t work perfectly out-of-the-box, but can usually be fixed without much hassle. Don’t give up too easily! Fixing the issue also helps you better understand the inner workings of Orchard.

      All in all I’m glad to have had this experience. And it’s not over yet, there’s a 1.1 version in the making and after that we’re starting on the second travel agency site.

      3 notes &

      Don’t trust Modules!

      One of the powers of Orchard is a gallery filled with useful modules. Just install them and you’re good to go. But if you want to build a high-performance website with Orchard CMS, you’re gonna have to do more than that. The modules are really generic and that could cost you in performance. Also, they’re contributed by the community, and not everyone has the performance focus you might need.

      Output Caching module
      The output caching module for instance, does a terrific job at outputcaching. If I had built it myself it wouldn’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.
      For each page that is outputcached, the OutputCacheFilter computes a CacheKey that’s unique for this specific url and serversettings by joining the url, tenant, culture and themeid.

      private string ComputeCacheKey(ActionExecutingContext filterContext)
      {
        var keyBuilder = new StringBuilder();
        keyBuilder.Append("tenant=").Append(_shellSettings.Name).Append(";");
        keyBuilder.Append("url=").Append(filterContext.HttpContext.Request.RawUrl.ToLowerInvariant()).Append(";");
        foreach (var pair in filterContext.ActionParameters)
          keyBuilder.AppendFormat("{0}={1};", pair.Key, pair.Value);
        keyBuilder.Append("culture=").Append(_workContext.CurrentCulture).Append(";");
        keyBuilder.Append("theme=").Append(_themeManager.GetRequestTheme(filterContext.RequestContext).Id).Append(";");
        return keyBuilder.ToString();
      }

      In my application each tenant has its own culture. So I don’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!

      SecureSocketsLayer module
      The SecureSocketsLayer also gets executed for each page request (even the outputcached ones!). In it’s filter is the following code:

      var settings = _services.WorkContext.CurrentSite.As<SslSettingsPart>();

      This does multiple database queries and costs about 40ms. On an outputcached page that’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.

      var wishedPort = 80;
      if (UseSsl)
      {
        var area = filterContext.Controller.ControllerContext.RouteData.Values["area"];
        if (area != null && area.ToString() == "Viaselect.Checkout")
          wishedPort = 443;
      }

      Conclusion
      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’s a really quick fix to tune a module and benefit from it’s extra’s!

      2 notes &

      Speeding up Orchard: Packaging and Minification

      Orchard is really flexible and modular. This has a big drawback while performance tuning: it’s really hard to package the static resources. Each module has its own javascript and css files, and one module doesn’t know about the files of the other. Time to hack performance into it!

      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!

      Here’s the bat file, using the Microsoft Ajax Minifier and DotLess:

      for /R %%i in (*.less) do (
        tools\dotless.compiler.exe "%%i" "%%i.css"
      )

      tools\AjaxMin-4.37.exe -js -clobber -xml "minify.xml" -out "Orchard.Web\min"

      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’ve included in the minify.xml file that AjaxMin parses. Here’s a portion of it:

      <root>
        <output path="js.js">
          <input path="c:\inetpub/Modules/Viaselect/Scripts/plugins/jquery.ba-hashchange.min.js" />
          <input path="c:\inetpub/Modules/Viaselect/Scripts/menu.js" />
        </output>
        <output path="css.css">
          <input path="c:\inetpub/Themes/CharmeQuality/styles/base.less.css" />
          <input path="c:\inetpub/modules/viaselect/styles/datepicker.less.css" />
        </output>
      </root>

      Unfortunately I didn’t get it to work with relative paths, so I had to make them absolute. We’ll cross that bridge when we get there :)

      So now I have a js.js and a css.css that I include in the layout.cshtml:

        Script.Require("jQuery").AtHead();
        Script.Include("~/min/js.debug.js""~/min/js.js");
        Style.Include("~/min/css.debug.css""~/min/css.css");

      And of course when you’re in debug mode, you want firebug to give you the right codelines! Here’s how to tackle that one; the debug files contain the following:

      @import url("/Themes/CharmeQuality/styles/base.less");
      @import url("/modules/viaselect/styles/datepicker.less");
      document.write("<script src='/Modules/Viaselect/Scripts/plugins/jquery.ba-hashchange.min.js'><\/script>");
      document.write("<script src='/Modules/Viaselect/Scripts/menu.js'><\/script>");

      It’s not the best solution, but for now it speeds up the site considerably! I wouldn’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’re requesting is inside the xml file. If any of you have good ideas, let me know! I’d love to facilitate this module :)