Reputation: 3645
I'm currently working on a project whereby I will be developing views that will be pre-compiled and will be part of an external MVC 3.0 web solution I do not have any control over.
Part of my requirements is that I will need to access an underlying database in order to get some data. I would like to use Ninject (I've been informed that's what the external solution uses) to inject the database instance into my controllers as necessary.
I understand that you add the bindings in such a place as the Global.asax however I do not have access to this as that is part of the external solution out of my control.
Is there anyway I can create this dependency injection in my project that contains the pre-compiled views etc and ensure it is resolved when the external project loads our controller?
If this is too vague let me know and I'll try and offer more information.
EDIT: Initially upon taken on Darin's suggestion I got the exception below:
System.InvalidOperationException crossed a native/managed boundary
Message=Sequence contains no elements
Source=System.Core
StackTrace:
at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source)
at Ninject.Web.Mvc.NinjectMvcHttpApplicationPlugin.Start() in c:\Projects\Ninject\ninject.web.mvc\mvc3\src\Ninject.Web.Mvc\NinjectMvcHttpApplicationPlugin.cs:line 53
at Ninject.Web.Common.Bootstrapper.<Initialize>b__0(INinjectHttpApplicationPlugin c) in c:\Projects\Ninject\Ninject.Web.Common\src\Ninject.Web.Common\Bootstrapper.cs:line 52
at Ninject.Infrastructure.Language.ExtensionsForIEnumerableOfT.Map[T](IEnumerable`1 series, Action`1 action) in c:\Projects\Ninject\ninject\src\Ninject\Infrastructure\Language\ExtensionsForIEnumerableOfT.cs:line 32
at Ninject.Web.Common.Bootstrapper.Initialize(Func`1 createKernelCallback) in c:\Projects\Ninject\Ninject.Web.Common\src\Ninject.Web.Common\Bootstrapper.cs:line 52
at MyApp.App_Start.NinjectWebCommon.Start() in C:\App\NinjectWebCommon.cs:line 28
InnerException:
However upon thinking about it, the bootstrapper should already be initialised in our external MVC application (assuming they are using this method I guess). So I don't need to do all the initialisation all I need to do is register my dependencies with the current Kernal.
Something like:
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
/// <summary>
/// Starts the application
/// </summary>
public static void Start()
{
RegisterServices(bootstrapper.Kernel);
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IDataContext>().To<ApiDataContext>();
}
}
When doing this I now get the items injected. However I'm not 100% this is the correct solution but it seems to work?
Upvotes: 1
Views: 1487
Reputation: 1039298
I understand that you add the bindings in such a place as the Global.asax
Not necessarily. Have you recently installed the Ninject.MVC3
NuGet in a new MVC application? If you haven't I invite you to do so now. Simply create a new ASP.NET MVC 3 project using the Internet Application template in Visual Studio and install this NuGet. Ready?
After doing that you will notice that the NuGet package created in App_Start
folder to your project. It didn't touch at any Global.asax
. Now let's inspect the contents of the NinjectWebCommon.cs
file added to this folder:
[assembly: WebActivator.PreApplicationStartMethod(typeof(MvcApplication1.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(MvcApplication1.App_Start.NinjectWebCommon), "Stop")]
namespace MvcApplication1.App_Start
{
using System;
using System.Web;
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using Ninject;
using Ninject.Web.Common;
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
/// <summary>
/// Starts the application
/// </summary>
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
/// <summary>
/// Stops the application.
/// </summary>
public static void Stop()
{
bootstrapper.ShutDown();
}
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
return kernel;
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
}
}
}
Notice the WebActivator's PreApplicationStartMethod
and ApplicationShutdownMethodAttribute
assembly attributes that allow you to plug code that executes when an ASP.NET application respectively starts and shuts down.
Alright, now simply put this code in your library and configure your kernel in the RegisterServices
method.
Upvotes: 3