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 :
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.