Search code examples
asp.net-mvc-4asp.net-web-apinservicebusowin

NServiceBus, Web API and OWIN


I'm just trying to add NServiceBus in a web API hosted in OWIN. My goal would be to be able to make a simple Bus.Send() inside a controller. I found plenty of blog posts, StackOverflow answers, etc. but still no luck in accomplishing this simple task.

I'm working on a project based on these 2 posts (I did not start it but I suspect my ex collegue to have taken it from somewhere on the web) :

Injecting NServiceBus into ASP.NET MVC 3 and the Web API adaptation : Injecting NServiceBus into ASP.NET WebApi

I have a resolver adapter :

public class NServiceBusResolverAdapter : IDependencyResolver
{
    private IBuilder builder;

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

    public object GetService(Type serviceType)
    {

        if (typeof(IHttpController).IsAssignableFrom(serviceType))
        {
            return builder.Build(serviceType);
        }

        return null;


    }

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

        return null;
    }

    public IDependencyScope BeginScope()
    {
        return this;
    }

    public void Dispose()
    {

    }
}

And also a controller activator :

public class NServiceBusControllerActivator : IHttpControllerActivator
{
    public IHttpController Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
    {
        Console.WriteLine("NServiceBusControllerActivator Create");
        return DependencyResolver.Current.GetService(controllerType) as IHttpController;
    }

}

All wrapped in an extension method so that it can be use to configure NServiceBus :

public static class NServiceBusConfigureExtension
{
    public static Configure ForWebApi(this Configure configure)
    {
        // Register our http controller activator with NSB
        configure.Configurer.RegisterSingleton(typeof(IHttpControllerActivator), new NServiceBusControllerActivator());

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

        // Register each http controller class with the NServiceBus container
        foreach (Type type in controllers)
        {
            configure.Configurer.ConfigureComponent(type, DependencyLifecycle.InstancePerCall);
        }

        // Set the WebApi dependency resolver to use our resolver
        System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver =
        new NServiceBusResolverAdapter(configure.Builder);

        return configure;
    }

}

So basically, in the Startup class, NServiceBus gets configured via the extension ForWebApi() :

public class Startup
{
    // This code configures Web API. The Startup class is specified as a type
    // parameter in the WebApp.Start method.
    public void Configuration(IAppBuilder appBuilder)
    {
        // Configure Web API for self-host. 
        HttpConfiguration config = new HttpConfiguration();
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

        // Inject NServicebus with Autofac

        Configure.Serialization.Xml();
        Configure.Transactions.Disable();

        Configure.With()
             .AutofacBuilder()
             .ForWebApi()
             .DefineEndpointName("MyServerWebApi")
             .UseTransport<Msmq>()
             .PurgeOnStartup(false)
             .UnicastBus()
             .ImpersonateSender(false)
             .CreateBus()
             .Start();


        appBuilder.UseWebApi(config);
    }
} 

Then, based on what is written in the blog posts from David Boike and Karl Nilsson (see previous links), I shouldn't have anything else to do in the controller but to add a IBus property that should be automaticaly injected...

public class ValuesController : ApiController 
{

    // Add the Bus property to be injected
    public IBus Bus { get; set; }

    // GET api/values 
    public IEnumerable<string> Get()
    {
        return new string[] { String.Format("Welcome to ASP.NET MVC! Bus is '{0}'.", Bus.GetType().FullName) };
    }
}

That's the "theory" because in practice, the Bus property always returns Null. So is there anyone out there that could help me with this simple task ? Maybe I got it all wrong and there's a better way with Autofac or another DI container ? Feel free to provide any input that should prove helpful. But if you have a sample project on GitHub it would be even nicer !

NOTE : The versions I use are :

  • Owin : 2.0.2.0
  • System.Web.Mvc : 4.0.0.0

Solution

  • I decided to go with a simple constructor injection with Autofac. So I ditched the whole activator and adapter. Added a ioc container registration module where I init and configure everything. Based on that sample

    For now it seems to work fine.