If you are planning to use S#arp Lite with ASP.NET Web API then this guide provides just what you need. This is not a Wiki on what S#arp Lite is and how to use it in an ASP.NET project. If you are looking for that information please go here.
For those that have not used S#arp Lite you can use a tool that will greatly help you jump start your first S#arp Lite project. The tool is called Templify and you can get it from here. Be sure you read the “README.txt” that comes along with the project so you are properly guided in creating your first S#arp Lite project.
S#arp Lite works with MVC 4 out of the box but if you want to use it with Web API then you would need to get the code from this repo and add some configuration to your project. Now it’s nice that you can use S#arp Lite with Web API but it is much better that your S#arp Lite project can support both MVC and Web API. In order to do so, you need to add three new classes to your {YourProjectName}.Init project. The first two classes involves setting up the structure map resolver, there is already a great project on this and so we will be borrowing codes from it. Your code should look like the following:
public class StructureMapDependencyScope : IDependencyScope
{
public StructureMapDependencyScope(IContainer container)
{
_container = container;
}
public object GetService(Type serviceType) {
if (serviceType.IsAbstract || serviceType.IsInterface) {
return _container.TryGetInstance(serviceType);
}
else {
return _container.GetInstance(serviceType);
}
}
public IEnumerable<object> GetServices(Type serviceType) {
return _container.GetAllInstances(serviceType).Cast<object>();
}
public void Dispose()
{
_container.Dispose();
}
protected readonly IContainer _container;
}
public class StructureMapResolver : StructureMapDependencyScope, IDependencyResolver, IHttpControllerActivator
{
private readonly IContainer container;
public StructureMapResolver(IContainer container)
: base(container)
{
if (container == null)
throw new ArgumentNullException("container");
this.container = container;
this.container.Inject(typeof(IHttpControllerActivator), this);
}
public IDependencyScope BeginScope()
{
return new StructureMapDependencyScope(container.GetNestedContainer());
}
public IHttpController Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
{
return container.GetNestedContainer().GetInstance(controllerType) as IHttpController;
}
}
At this point you should already have a reference to System.Net.Http and System.Web.Http.
The next class you need to create is for the initialization of the dependency resolver that was just created. I named the new class after DependencyResolverInitializer that already exists in the S#arp Lite template project, named it WebApiDependencyResolverInitializer. You can of course give your class what ever name you prefer. The Initialize method of WebApiDependencyResolverInitializer is almost identical to DependencyResolverInitializer.Initialize method with the exception of, as you may have guessed it, how the StructureMap dependency resolver was registered (see line 24).
using System;
using System.Web.Http;
using NHibernate;
using SharpLite.Domain.DataInterfaces;
using SharpLite.NHibernateProvider;
using StructureMap;
using NHibernateProvider;
public class WebApiDependencyResolverInitializer
{
public static void Initialize(HttpConfiguration config)
{
_container = new Container(x =>
{
x.For<ISessionFactory>()
.Singleton()
.Use(() => NHibernateInitializer.Initialize().BuildSessionFactory());
x.For<IEntityDuplicateChecker>().Use<EntityDuplicateChecker>();
x.For(typeof(IRepository<>)).Use(typeof(Repository<>));
x.For(typeof(IRepositoryWithTypedId<,>)).Use(typeof(RepositoryWithTypedId<,>));
});
config.DependencyResolver = new StructureMapResolver(_container);
}
public static void AddDependency(Type pluginType, Type concreteType)
{
_container.Configure(x => x.For(pluginType).Use(concreteType));
}
private static Container _container;
}
Then we just need to call the Initialize method from Application_Start in Global.asax file. The Application_Start method should look like:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
DependencyResolverInitializer.Initialize();
WebApiDependencyResolverInitializer.Initialize(GlobalConfiguration.Configuration);
GlobalConfiguration.Configuration.MessageHandlers.Add(new BasicAuthenticationMessageHandler());
}
There is one more thing we need to do and that is to configure a new httpmodule in web.config. If you have used Templify in creating your S#arpLite project then you should already have the following:
<system.web>
.
.
.
<httpModules>
<add name="SessionPerRequestModule" type="SharpLite.NHibernateProvider.Web.SessionPerRequestModule, SharpLite.NHibernateProvider" />
</httpModules>
</system.web>
<system.webServer>
.
.
.
<modules runAllManagedModulesForAllRequests="true">
<add name="SessionPerRequestModule" type="SharpLite.NHibernateProvider.Web.SessionPerRequestModule, SharpLite.NHibernateProvider" />
</modules>
</system.webServer>
What you need to do is add the Web API verison of SessionPerRequestModule like so:
<system.web>
<httpModules>
<span style="color: #ff0000;"><add name="WebApiSessionPerRequestModule" type="SharpLite.NHibernateProvider.WebApi.SessionPerRequestModule, SharpLite.NHibernateProvider" /></span>
<add name="SessionPerRequestModule" type="SharpLite.NHibernateProvider.Web.SessionPerRequestModule, SharpLite.NHibernateProvider" />
</httpModules>
</system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<span style="color: #ff0000;"><strong><add name="WebApiSessionPerRequestModule" type="SharpLite.NHibernateProvider.WebApi.SessionPerRequestModule, SharpLite.NHibernateProvider" /></strong></span>
<add name="SessionPerRequestModule" type="SharpLite.NHibernateProvider.Web.SessionPerRequestModule, SharpLite.NHibernateProvider" />
</modules>
</system.webServer>
That’s it! Now your application can inject repositories to both MVC and API controllers.