Configuring Nancy to use views in a separate assembly

I’m in the process of setting up a Nancy application that will run in ASP.NET on IIS and on Ubuntu (using Mono). As a result I put the main Nancy application into an assembly all of its own and created two host assemblies, one for each environment.

I found pretty quickly that it was a real pain to get the FileSystemViewLocationProvider to work properly in this scenario without a lot of futzing about… and I don’t like it when you have to manually mess around with thing just to get an application deployed properly, or even just running in the debugger.

My solution was to use the ResourceViewLocationProvider instead and just have the views added as resources to the assembly.

I also created a custom bootstrapper for my application so that it would know to pick up the resources instead of the files.

using Nancy;
using Nancy.Bootstrapper;
using Nancy.TinyIoc;
using Nancy.ViewEngines;
using Nancy.ViewEngines.Razor;

namespace HelloWorld.Web
{
  public class HelloWorldBootstrapper : DefaultNancyBootstrapper
  {
    protected override void ConfigureApplicationContainer(TinyIoCContainer container)
    {
      base.ConfigureApplicationContainer(container);

      // Configure the resource view location provider
      var assembly = GetType().Assembly;
      ResourceViewLocationProvider
          .RootNamespaces
          .Add(assembly, "HelloWorld.Web.Views");
    }
    protected override void ApplicationStartup(TinyIoCContainer container, IPipelines pipelines)
    {
      StaticConfiguration.CaseSensitive = true;
      StaticConfiguration.DisableErrorTraces = false;
      StaticConfiguration.EnableRequestTracing = true;
      base.ApplicationStartup(container, pipelines);
    }
    protected override NancyInternalConfiguration InternalConfiguration
    {
      get
      {
        var result = NancyInternalConfiguration
          .WithOverrides(nic => nic.ViewLocationProvider = typeof (ResourceViewLocationProvider));
        return result;
      }
    }

    protected override System.Collections.Generic.IEnumerable ViewEngines
    {
      get 
      { 
        yield return typeof (RazorViewEngine);
      }
    }
  }
}

I also found that adding the Razor view engine via NuGet also adds a post build action to the project file which doesn’t work in Ubuntu. I had to strip that out to allow the build to work, however, since my bootstrapper explicitly references to the RazorViewEngine the file is copied by the build engine to the output directory anyway.

2 Comments

  1. Thank you for sharing the info! Works perfect for me.

Leave a Comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s