Injecting NServiceBus into ASP.NET MVC 3

In the past, integrating NServiceBus into a web application typically meant adding the fluent configuration block to the Global.asax file and then keeping a static reference to the IBus property, because ASP.NET has not been very friendly to dependency injection.

In ASP.NET MVC 3, Microsoft has changed that by adding some nice abstractions around dependency resolution.  With a little effort, this allows us to inject NServiceBus (and its dependency injection container) into the dependency resolution pipeline.

In this example, I will show how to add NServiceBus to an MVC 3 web application so that common NServiceBus types (IBus chief among them) are injected into your controller classes.

Note: Karl Nilsson has written a post extending this one, showing how to inject NServiceBus into an ASP.NET MVC4 Web API solution, which requires just a few minor adjustments.

IDependencyResolver

ASP.NET MVC uses the IDependencyResolver interface to resolve types into implementation classes.  The first thing we will need to do is write a very quick adapter that will refer all requests to an underlying NServiceBus IBuilder instance.

public class NServiceBusResolverAdapter : IDependencyResolver
{
	private IBuilder builder;

	public NServiceBusResolverAdapter(IBuilder builder)
	{
		this.builder = builder;
	}

	public object GetService(Type serviceType)
	{
		return builder.Build(serviceType);
	}

	public IEnumerable<object> GetServices(Type serviceType)
	{
		return builder.BuildAll(serviceType);
	}
}

Under the hood, IBuilder is another abstraction for the dependency injection container used by NServiceBus. This is currently Spring, but in a future version will be changed to Autofac, although as an NServiceBus developer you can change the container to just about anything you want. This is one of the strengths of NServiceBus.

If NServiceBus doesn’t have a registration for a given type, it will return null. This is good, because MVC will assume (correctly) that if you don’t provide an implementation for a type that it should do whatever it would have done by default. This means we don’t have to cover every type under the sun, only the ones we really care about.

Keep in mind that creating the class doesn’t really do anything yet – we will have to register it later. But first, we need another puzzle piece.

IControllerActivator

What we’re really after is injecting properties into our controllers, and for that, we need the assistance of a controller activator.

	public class NServiceBusControllerActivator : IControllerActivator
	{
		public IController Create(RequestContext requestContext, Type controllerType)
		{
			return DependencyResolver.Current
				 .GetService(controllerType) as IController;
		}
	}

MVC uses a controller activator to retrieve a specific controller class. With our controller activator in the pipeline, we can use NServiceBus’s container to instantiate that controller, giving us the chance to inject our properties. Again, this just creates the class. We still need to register it with the system in the next step.

Configuration Class

This static class provides an extension to the NServiceBus fluent configuration that will allow us to register our dependency resolver and controller activator.

	public static class ConfigureMvc3
	{
		public static Configure ForMVC(this Configure configure)
		{
			// Register our controller activator with NSB
			configure.Configurer.RegisterSingleton(typeof(IControllerActivator),
				new NServiceBusControllerActivator());

			// Find every controller class so that we can register it
			var controllers = Configure.TypesToScan
				.Where(t => typeof(IController).IsAssignableFrom(t));

			// Register each controller class with the NServiceBus container
			foreach (Type type in controllers)
				configure.Configurer.ConfigureComponent(type, ComponentCallModelEnum.Singlecall);

			// Set the MVC dependency resolver to use our resolver
			DependencyResolver.SetResolver(new NServiceBusResolverAdapter(configure.Builder));

			// Required by the fluent configuration semantics
			return configure;
		}
	}

NServiceBus Startup

With this all created, now we can start up NServiceBus in the Application_Start() method of the MvcApplication class.

protected void Application_Start()
{
	// These lines are stock from the MVC Application project template
	AreaRegistration.RegisterAllAreas();
	RegisterGlobalFilters(GlobalFilters.Filters);
	RegisterRoutes(RouteTable.Routes);

	// Here is our NServiceBus fluent configuration
	Configure.WithWeb()
		.DefaultBuilder()
		.ForMVC()	// <------ here is the line that registers everything
		.Log4Net()
		.XmlSerializer()
		.MsmqTransport()
			.IsTransactional(false)
			.PurgeOnStartup(false)
		.UnicastBus()
			.ImpersonateSender(false)
		.CreateBus()
		.Start();

	// We don't have to store the IBus that results from .Start() because it will
	// be injected into all of our controllers for us.
}

Now if you edit your HomeController (assuming you’re using the MVC 3 sample application):

public class HomeController : Controller
{
	// Add the Bus property to be injected
	public IBus Bus { get; set; }

	public ActionResult Index()
	{
		// Let's see what gets injected
		ViewBag.Message = String.Format("Welcome to ASP.NET MVC! Bus is '{0}'.",
			Bus.GetType().FullName);
		return View();
	}

	public ActionResult About()
	{
		return View();
	}
}

This is what you should see:

MVC with NServiceBus

Conclusion

This example shows how to gain NServiceBus property injection for all of our controller classes. We could easily add this to other types, if needed, by finding how those types are activated and inserting NServiceBus into their creation in the same way.

Related Posts:

  • Indu Alagarsamy


    David, this is awesome….
    I have a basic question one that involves using the bus from the web. I have a page where the user fills in all of the order details and clicks Create Order. I can then do a Bus.Send message.
    I can pass feedback immediate feedback, saying “Your order request has been received…”
    If they go to the status page, and if the command handler for create order hadn’t persisted stuff in the db or if the db persistence resulted in the error queue, how can I prevent bad user experience, i.e. missing order request when the user goes to the status screen?
    Thanks for your input,
    Regards,
    Indu

  • Indu Alagarsamy


    David, this is awesome….
    I have a basic question one that involves using the bus from the web. I have a page where the user fills in all of the order details and clicks Create Order. I can then do a Bus.Send message.
    I can pass feedback immediate feedback, saying “Your order request has been received…”
    If they go to the status page, and if the command handler for create order hadn’t persisted stuff in the db or if the db persistence resulted in the error queue, how can I prevent bad user experience, i.e. missing order request when the user goes to the status screen?
    Thanks for your input,
    Regards,
    Indu

  • http://www.make-awesome.com David Boike


    Indu, it looks like Werner has already done a pretty good job of responding to your question in the NServiceBus discussion group:

    http://tech.groups.yahoo.com/group/nservicebus/message/11180

    I would agree with him. You don’t need to

  • Jason Aminto


    Good stuff…Do you have an example of how to configure NServiceBus when unit testing your controller? I can’t seem to get the configuration resolved between Test.Initialize and the config you’ve mentioned in the article.

    Thanks!

  • Pingback: Injecting NServiceBus into ASP.NET WebApi « Thoughts, opinions and mistaeks

  • http://www.facebook.com/kumar.iyer.359778 Kumar Iyer


    Wouldn’t this be much simpler by using a DI framework like Windsor castle?

  • http://www.make-awesome.com David Boike


    NServiceBus contains a pluggable DI framework. By default it uses Autofac, but you can change it to use Castle Windsor if you want. So essentially, by integrating NServiceBus, you are using a DI framework.

    The trick is getting it to play nice with MVC’s built-in dependency resolver so that you get the injection support on your controllers. That’s what this post is all about.

  • ahbeng


    Hi David,
    Purchased your “Learning NServiceBus” book and in chapter 4, the way NServiceBus was set up in the source code was the static class, singleton way, as opposed to what you blogged about here.
    Not sure if that was so because it would make it easier for your readers to follow, or if there’s an advantage using one way over the other.
    Could you elaborate please?

  • http://www.make-awesome.com David Boike


    These days so much goes into the Global.asax I like to try to prevent it from becoming a dumping ground. Therefore I like to do all my application startup stuff in separate classes with a one-liner in the Global.asax to call it if necessary. Helps with separation of concerns and makes it easier to refactor or pull relevant pieces of code into new projects.