.NET Get Noticed 2017

Integrating Nancy with Autofac and ASP.NET Core IoC

For couple last days, I worked on gifty to catch up a little bit. My primal task was to introduce JWT authentication to my microservices hosted by Nancy. That’s the topic for next post but today, I’ll describe the proper steps to fully integrate Nancy with Autofac and ASP.NET Core since it’s not that obvious (at least wasn’t for me) and took me way to much time to finally do it. So, I hope that this one will help you one way or another.

 

Installing packages

At the beginning, I’d like to mention one thing since probably some of you don’t know it. By default, Nancy is integrated with dependency injection container called TinyIoC. So, if you’re not familiar with Autofac, there’s no need to do all this configuration I’m going to describe in the below paragraphs. You can easily start and play with it for a while and then decide whether it suits you or not. I wanted to use another container simply because I know Autofac, I don’t know TinyIoC and I heard that for more complex solutions it’s just not enough library. Ok, let’s move forward.

One thing, that I really like about Nancy is the fact that it has dedicated packages for different IoC container integrations. Therefore, the first step is to install the following one:

 


<PackageReference Include="Nancy.Bootstrappers.Autofac" Version="2.0.0-clinteastwood"/>

 

Having all dependencies restored (using „dotnet restore” command) we can finally implement some code.

 

Implementing Nancy custom bootstrapper

The first thing is custom bootstrapper for Nancy. The basic implementation looks as follows:

 


internal sealed class AuthBootstraper : AutofacNancyBootstrapper
{        
        protected override void ConfigureApplicationContainer(ILifetimeScope container)
        {
            base.ConfigureApplicationContainer(container);
        }
}

 

Before discussing the code there should be a short explanation of what is actually a bootstrapper. I really like the definition given on the GitHub by Nancy team:

In essence, the bootstrapper is a friendly syntax, or Domain Specific Language (DSL), on top of an Inversion of Control Container that helps out with the component discovery and composition of the framework at runtime.

So, in a nutshell, this class is responsible for the whole application config when it starts up but not only. Bootstrapper also manages IoC container and provides „hooks” to some events that might happen during our app is running like on request error, before request etc. We’ll discuss them more in the post dedicated to mentioned JWT authentication. Today, we’ll stick to configuration only. All right, as you see above our custom bootstrapper derives from AutofacNancyBootstrapper class which provides many virtual methods for different tasks but one that should interest us is called ConfigureApplicationContainer which takes Autofac’s ILifitimeScope as a parameter. This is the place when we can register our dependencies inside the application. That’s cool but hang on. If you’re familiar with Autofac you know that registration is done by ContainerBuilder. ILiftimeScope provides methods for resolving existing dependencies so, what should we do? It turns out that Nancy package we’ve just installed provides extension method for ILifetimeScope called Update. The signature looks as follows:

 

public static class ComponentContextExtensions
{
    public static T Update<T>(this T context, Action<ContainerBuilder> builderAction) where T : IComponentContext;
}

 

Simple is that! We can create an action which takes ContainerBuilder and returns void and then pass is to the Update method. Sweet, here’s some example if it’s still not clear:

 

            container.Update(builder => 
            {                
                builder.RegisterType<SomeImplmentation>().As<SomeInterface>();
            });

 

Now, this is the end of the entire configuration. You can now inject some dependencies inside Nancy modules. Hurray! Well, not completely…

 

Integrating with ASP.NET Core IoC container

Ok, for some purposes the above solution is enough. I mean, you can register whatever you want and then use it. But in my project, I wanted also to have an ability to resolve dependencies registered by ASP.NET Core IoC container. The first example that comes up to my mind is registering settings which I described in one of my previous posts. How can we deal with that? Well, we should somehow take all of the dependencies from the one container and rewrite them into another. But the problem is that default ASP.NET Core container and Autofac are not compatible. They use different classes/interfaces for the entire process. Fortunately, there’s a package made by Autofac team which is going to help us a lot:

 


<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.0.0"/>

 

This one provides extension method on ContainerBuilder called Populate which takes IServiceCollection as a parameter and do exactly what we need – register them inside the Autofac. Let’s modify our bootstrapper a little bit:

 

    internal sealed class AuthBootstraper : AutofacNancyBootstrapper
    {
        private readonly IServiceCollection _services;

        public AuthBootstraper(IServiceCollection services)
        {
            _services = services;
        }

        protected override void ConfigureApplicationContainer(ILifetimeScope container)
        {
            base.ConfigureApplicationContainer(container);

            container.Update(builder => 
            {                                
                builder.Populate(_services);
            });
        }
    }

 

All right, the last problem to overcome is delivering need services to the bootstrapper. The default adding Nancy to the OWIN pipeline looks as follows:

 


app.UseOwin().UseNancy();

 

Fortunately, there’s an overload which can help us to manually instantiate bootstrapper and sign it to the NancyOptions. Without any further explanation, I’ll show you the code:

 

    public class Startup
    {
        public Startup(IHostingEnvironment env)
        {
            var builder = new ConfigurationBuilder()
                .SetBasePath(env.ContentRootPath)
                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
                .AddEnvironmentVariables();
            Configuration = builder.Build();
        }
        public IConfigurationRoot Configuration { get; }
        public IServiceCollection Services { get; private set; }

        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<AuthSettings>(Configuration.GetSection("AuthSettings"));

            Services = services;
        }

        public void Configure(IApplicationBuilder app)
        {
            app.UseOwin().UseNancy(x => x.Bootstrapper = new AuthBootstraper(Services));
        }
    }

 

Now, our microservices are kicked off by Nancy but also has all we needed to move forward 馃槈 If you want to see more of the gifty code, I encourage you to visit its GitHub which finally contains something more than just auto generated code 馃榾 New post about JWT will come up probably in next two days, so stay tuned and come here from time to time 馃槈

Don’t miss new posts!

If you enjoy reading my blog, follow me on Twitter or leave a like on Facebook. It costs nothing and will let you be up to date with new posts 馃檪