Referencing custom assemblies in Orchard module

Tags: orchard, module, assembly, tip

This is one of the common problems you can run into at module development time.

In the most usual (and preferred) dev setup you work in VS 2010 on a single Orchard.sln solution containing full Orchard source and add your custom modules as an additional  projects. This setup works perfectly fine unless you try to use additional assemblies not listed in /lib folder (under the full Orchard source code root, as downloaded from Codeplex).

If you try to add a custom assembly reference to your module project it’s inevitable that sooner or later you’ll run into:

"The type or namespace name 'yyy' does not exist in the namespace 'xxx' (are you missing an assembly reference?)"

exception when debugging from Visual Studio. The reason is fairly simple. As Orchard is a sophisticated platform, it’s still an ASP.NET MVC application though and needs all of the assemblies used placed in the Orchard.Web /bin folder (apart from those coming from GAC)! [EDIT] Orchard has also a second directory for holding custom assemblies - /AppData/Dependencies - and this is the place where all of non-core dlls land. Renaud Paquay from the Orchard Team wrote about the reasons behind that below.

When you install a module from NuGet package, the necessary assemblies contained in this package get copied to the Orchard.Web application’s /AppData/Dependencies folder and everything is fine. But when you debug the whole app from VS, the modules are already there and no installation (and file copying) happens…

The workaround to this problem is to add all assemblies referenced by your module(s) to the Orchard.Web project too.

[EDIT] There is also a different workaround. You can store all your necessary assemblies in a single folder, and point Orchard to look into that folder at runtime (when the dynamic compilation happens). To achieve that just add the path to that folder to Web.config file in Orchard.Web project. The path should be placed in /runtime/assemblyBinding/probing privatePath property, separated with semi-colon from others.

As I stated above, this is only necessary at development time. When you deploy your module as NuGet package (via package create command) and install it – everything is perfectly fine. Your custom assemblies get packaged together with the module source and Orchard copies them to the appropriate locations.

And btw, I’d like to give you a tip at the end of this articleUĊ›miech

When using custom assemblies in your modules, check if they exist in /lib folder under the Orchard listing root. If so, make use of them – those assemblies won’t get packaged within your module NuGet package, so you’ll end up with a much lighter file. Remember though that for this to happen you MUST use exactly the same version of assemblies as in /lib folder.

Hope you find it helpful!

4 Comments

  • Renaud Paquay said

    Hi Piotr,

    This is Renaud from the Orchard Team. What you mention is this post is correct and works, but i just want to mention that Orchard has a dynamic compilation system (see http://orchardproject.net/docs/Orchard-module-loader-and-dynamic-compilation.ashx) that tries to make things easier for installing modules.

    Basically, one of the things Orchard does is have an additional "bin" folder for storing assemblies: AppData/Dependencies. Orchard handles copying assemblies automatically to that folder when a module constains a custom reference assembly. An example of such a module is the "Orchard.Lucene" module, which contains Lucene.NET assembly. If you install that module through the gallery, you will see that "Lucene.NET.dll" is copied to "AppData\Dependencies".

    The reason this works is because there is a section in the web.config file of Orchard.Web that tells ASP.NET (the CLR really) to look for additional assemblies in that directory. The main reason we did this is to avoid an AppDomain restart when a module is installed, as well as making sure the "Bin" folder is not poluted with assemblies which could cause issues when compiling Views (by default, all assemblies in "bin" are added as references when compiling views).

  • pszmyd said

    Hi Renaud,

    Great thanks for a verbose comment on the topic as it brings a lot of clarification to how it all works! And thanks also for pointing out that it's not really the /bin folder where everything gets copied but /AppData/Dependencies.

    I tried to be concise and deliver the easy solution (which obviously polutes the default /bin folder) for two reasons:

    1. It allows to keep track of the assemblies referenced from inside VS without manual copying
    2. At dev time the AppDomain restarts are not an issue

    Of course it could be done "the Orchard way:)" as you suggest, so the /bin folder wouldn't be involved. One would place all assemblies needed in his development work in completely separate folder, and include the path to it inside Orchard.Web Web.config's element.

  • Renaud Paquay said

    Hi Piotr, it's Renaud again :-)

    This dynamic compilation thing is quite complicated, so let me add a point of clarification: If you follow the Orchard convention when building a module, there is no need to modify the default "web.config" in Orchard.web.

    Let's take the case of the Lucene module. After the module is compiled in VS, you will have this file layout:

    Orchard.Web\Lucene\bin\Lucene.dll <= the orchard module Orchard.Web\Lucene\bin\Lucene.NET.dll <= the Lucene library

    When Orchard.Web is launched, the Orchard framework will detect that the "Lucene" module depends on "Lucene.NET" and will copy both assemblies to "App_Data\Dependencies", so you end up with this:

    Orchard.Web\AppData\Dependencies\Lucene.dll <= the orchard module Orchard.Web\AppData\Dependencies\Lucene.NET.dll <= the Lucene library

    Since "App_Data\Dependencies" is already a probing folder in web.config of Orchard.web, there is no need to update this file.

    So, basically, we tried to make sure that module development work "out of the box" in Visual Studio without having to add assembly references to Orchard.Web or modify web.config (as long as you follow the conventions).

    As you mention though, this is optional, and copying assemblies manually to "~/bin" will work too (the Orchard framework automatically detects that situation).

    HTH, Renaud

  • pszmyd said

    @Renaud: Great thanks for describing how does it all work. It'll surely help many of us. Keep up the awesome work with Orchard!:)