Using Ninject.MVC For Better ASP.NET MVC Integration
After the ASP.NET MVC infrastructure is ready, next logical step it to setup IoC container for application. Ninject setup is easy task, usually you solve that by implementation of your own ControllerFactory and put it to ControllerBuilder. As soon it is good enough approach it does not solve some important MVC implications, like injection of prosperities into filters. To make our lives a little easier Ninject team released Ninject.Web.MVC extension library that solves a lot of similar problems.
Getting binaries
Just follow the github to download latest version of Ninject.Web.MVC and place it to web site /Bin
directory. No changes to web.config
or something.
Tweaking global.asax
Now, let’s change global.asax
according to Ninject.Web.MVC guidelines. I’ll just show how my current global.aspx
looks like:
<%@ Application Language='C#' Inherits="Ninject.Web.Mvc.NinjectHttpApplication" %>
<%@ Import Namespace="Ninject" %>
<script RunAt="server">
public void Application_Start()
{
}
protected override void OnApplicationStarted()
{
AreaRegistration.RegisterAllAreas();
}
protected override IKernel CreateKernel()
{
var kernel = new StandardKernel();
Sba.Web.Infrastructure.RegisterServices.For(kernel);
return kernel;
}
public void Application_End()
{
}
public void Application_Error(object sender, EventArgs args)
{
}
</script>
So, we basically inherit from NinjectHttpApplication
class and override CreateKernel()
method. You can see that inside the method I do call to RegisterServices
- it is nothing more as static class, with For
method that actually do the registration. Here is example:
using Ninject;
using Ninject.Web.Mvc;
using Sba.Common.Repositories;
using Sba.Sales.Models;
using Sba.Sales.Repositories;
using Sba.Sales.Repositories.ViewHandlerRepositories;
namespace Sba.Web.Infrastructure
{
public class RegisterServices
{
public static void For(IKernel kernel)
{
kernel.Bind<ISessionLoader>().To<LazySessionLoader>();
kernel.Bind<ILazyLoadChecker>().To<NHibernateLazyLoadChecker>();
kernel.Bind<IDraftInvoicesRepository>().To<DraftInvoicesRepository>();
kernel.Bind<IDraftInvoiceLinesRepository>().To<DraftInvoiceLinesRepository>();
kernel.Bind<IPaymentTermsRepository>().To<PaymentTermsRepository>();
kernel.Bind<IUnitsRepository>().To<UnitsRepository>();
kernel.Bind<ICustomersRepository>().To<CustomersRepository>();
}
}
}
Injection the properties into filters
The main advantage of NinjectHttpApplication
class usage, that now it handles the injection in different MVC entities by itself. For instance if you need inject to filter:
using System.Web.Mvc;
using Ninject;
using Economic2.Core;
using Sba.Common.Repositories;
namespace Sba.Common.Infrastructure.Filters
{
public class SbaAuthorizeAttribute : AuthorizeAttribute
{
[Inject]
public ISessionLoader SessionLoader { get; set; }
public override void OnAuthorization(AuthorizationContext filterContext)
{
// some authorization logic here..
}
}
}
After the ASP.NET MVC infrastructure is ready, next logical step it to setup IoC container for application. Ninject setup is easy task, usually you solve that by implementation of your own ControllerFactory and put it to ControllerBuilder. As soon it is good enough approach it does not solve some important MVC implications, like injection of prosperities into filters. To make our lives a little easier Ninject team released Ninject.Web.MVC extension library that solves a lot of similar problems.
Getting binaries
Just follow the github to download latest version of Ninject.Web.MVC and place it to web site /Bin
directory. No changes to web.config
or something.
Tweaking global.asax
Now, let’s change global.asax
according to Ninject.Web.MVC guidelines. I’ll just show how my current global.aspx
looks like:
<%@ Application Language='C#' Inherits="Ninject.Web.Mvc.NinjectHttpApplication" %> <%@ Import Namespace="Ninject" %> <script RunAt="server"> public void Application_Start() { } protected override void OnApplicationStarted() { AreaRegistration.RegisterAllAreas(); } protected override IKernel CreateKernel() { var kernel = new StandardKernel(); Sba.Web.Infrastructure.RegisterServices.For(kernel); return kernel; } public void Application_End() { } public void Application_Error(object sender, EventArgs args) { } </script>
So, we basically inherit from NinjectHttpApplication
class and override CreateKernel()
method. You can see that inside the method I do call to RegisterServices
- it is nothing more as static class, with For
method that actually do the registration. Here is example:
using Ninject; using Ninject.Web.Mvc; using Sba.Common.Repositories; using Sba.Sales.Models; using Sba.Sales.Repositories; using Sba.Sales.Repositories.ViewHandlerRepositories; namespace Sba.Web.Infrastructure { public class RegisterServices { public static void For(IKernel kernel) { kernel.Bind<ISessionLoader>().To<LazySessionLoader>(); kernel.Bind<ILazyLoadChecker>().To<NHibernateLazyLoadChecker>(); kernel.Bind<IDraftInvoicesRepository>().To<DraftInvoicesRepository>(); kernel.Bind<IDraftInvoiceLinesRepository>().To<DraftInvoiceLinesRepository>(); kernel.Bind<IPaymentTermsRepository>().To<PaymentTermsRepository>(); kernel.Bind<IUnitsRepository>().To<UnitsRepository>(); kernel.Bind<ICustomersRepository>().To<CustomersRepository>(); } } }
Injection the properties into filters
The main advantage of NinjectHttpApplication
class usage, that now it handles the injection in different MVC entities by itself. For instance if you need inject to filter:
using System.Web.Mvc; using Ninject; using Economic2.Core; using Sba.Common.Repositories; namespace Sba.Common.Infrastructure.Filters { public class SbaAuthorizeAttribute : AuthorizeAttribute { [Inject] public ISessionLoader SessionLoader { get; set; } public override void OnAuthorization(AuthorizationContext filterContext) { // some authorization logic here.. } } }