Send mail to the author(s) E-mail

View Richard Soeteman's profile on LinkedIn

RSS 2.0 | Atom 1.0 | CDF




The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

Sign In


# Tuesday, 25 September 2012
Tuesday, 25 September 2012 09:36:02 (GMT Daylight Time, UTC+01:00) ( Package | Umbraco )

This Blog is not active anymore, further posts will be available on my company website. Read new posts here

A couple of months ago, Umbraco V4.8 was released and when I was testing CMSImport against this version I got a weird exception.


What happened?

I’m using the HTMLAgilityPack to extract images and files from the bodytext property so we can import them into Umbraco. In previous versions, Umbraco shipped with the 1.3.0 version. The version of the HTMLAgilityPack that is shipped in 4.8+ is version Since the dll is signed it’s throwing an error in case of a version conflict. I’ve seen a post on the forum where Lee Kelleher describes a similar issue. In the case of UComponents it’s the Lucene DLL but it’s the same problem as I was facing. To fix this issue as described in the forum thread requires an entry in the web.config file and putting the Legacy DLL into a separate folder. It’s all fine to use upgrade instructions for a client project but when you develop a package you don’t want your customers manual upgrade web.config files for a specific version. You also don’t want to have a big if statement in your installer that creates entries based on a version number and you also don’t want to drop support for older versions of Umbraco because of this minor conflict.

The solution

After searching a bit, I found this interesting article that describes the AppDomain.AssemblyResolve Event. This event gets triggered when an Assembly is required that can’t be found and allows you to return the correct assembly. In our case the DLL Version of HTMLAgilityPack. In the example below you see that I derive my class from ApplicationBase (I know there is a new class in 4.8, but I’m still supporting 4.7 also ;-)) so this class will be picked up automatically . When the  required assembly (Args.Name on line 13) is the HTMLAgilityPack Version 1.3.0 I load that assembly from the /bin/legacy/ location and all is working again :) 

Update 2-10-2012 Modified source code. It doesn’t use HTTPContext anymore since that might not be available

   1:      public class UpdateThirdPartyDllBindings : ApplicationBase
   2:      {
   3:          public UpdateThirdPartyDllBindings()
   4:          {
   5:              AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
   6:          }
   8:          /// <summary>
   9:          /// Assembly could not be resolved let's see if we can load it dynamically
  10:          /// </summary>
  11:          Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
  12:          {
  13:              if (args.Name == "HtmlAgilityPack, Version=, Culture=neutral, PublicKeyToken=bd319b19eaf3b43a")
  14:              {
  15:                  try
  16:                  {
  17:                      //Get the bin folder. Don't use HTTPContext since that can be null
  18:                      string binFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin\\legacy");
  19:                      string legacyFile = Path.Combine(binFolder, "HtmlAgilityPack.dll");
  20:                      return Assembly.LoadFile(legacyFile);
  22:                  }
  23:                  catch (Exception ex)
  24:                  {
  25:                      Log.Add(LogTypes.Error, -1, string.Format("SEOChecker error loading HTMLAgilityPack version {0}:{1} ", args.Name, ex));
  26:                  }
  27:              }
  28:              return null;
  29:          }
  30:      }

All I need to do now is make sure the Legacy DLL is shipped in the package. When you are using an older version of Umbraco this Legacy DLL will exists in your bin folder but will be ignored and for version 4.8 + the AssemblyResolve implementation will make sure the legacy DLL is loaded.

Hope this helps you solve version conflicts of dll’s in your own packages