I'm building an MVC4 app using EF5 and ninject. Something broke when I upgraded from MVC3 to 4. So I created a brand new solution, got all my nuget packages, added all my references, then copied in my code.
Project builds, thats fabulous.
My problem is the (Ninjection) sp? doesn't seem to be wiring up correctly. I get the "No Parameterless constructor defined for this object" as a runtime error when I try to load the page. However, if I simply add an empty public parameterless constructor, the page renders and all is right with the world.
My App_Start Code runs fine, NinjectWebCommon.cs (included at the bottom of the question) I've stepped through the code, but other that copying and pasting, and following tutorials online. I don't understand IoC well enough to know what to do next.
namespace search.Controllers
{
public class HomeController : Controller
{
ICamaService _service = null;
[Inject]
public HomeController(ICamaService service)
{
_service = service;
}
************** ADDING THIS FIXES THE RUNTIME ERROR *********
public HomeController(){
;
}
***********
//TODO: ADD ACTIONS
public ViewResult Index()
{
return View();
}
}
}
Here is my composition root:
[assembly: WebActivator.PreApplicationStartMethod(typeof(search4.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(search4.App_Start.NinjectWebCommon), "Stop")]
namespace search4.App_Start
{
using System;
using System.Web;
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using Ninject;
using Ninject.Web.Common;
using search.Services;
using search.Data;
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
public static void Stop()
{
bootstrapper.ShutDown();
}
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;
}
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<ICamaContext>().To<CamaContext>().InRequestScope();
kernel.Bind<ICamaService>().To<CamaService>().InRequestScope();
}
}
}
![Screen Capture of Exception][1]
http://shareimage.ro/viewer.php?file=svs5kwamqy0pxbyntig4.gif
I am not a Ninject user, but from my experiences with other IOC frameworks in MVC, you would need to replace the DefaultControllerFactory with an implementation that injects objects instead of requiring a default constructor.
Looks like your bindings arn't being registered propertly.
Im not sure exactly what's wrong, but I create a NinjectApplicationModule that works for me:
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
kernel.Load(new NinjectApplicationModules());
}
public class NinjectApplicationModules : NinjectModule
{
/// <summary>
/// Loads the Binding module into the kernel. Used to map Abstract Classes to Concrete classes at runtime.
/// </summary>
public override void Load()
{
// Bindings...
Bind<ICamaContext>().To<CamaContext>().InRequestScope();
Bind<ICamaService>().To<CamaService>().InRequestScope();
}
}
Check you data model class.
Public Class A ()
{
public A() {
}
public string Name{get; set;}
}
But you need to remove this default Class A Constructor.
Public Class A ()
{
public string Name{get; set;}
}
I was already facing No Parameter less constructor defined for this object
Related
I am developing an ASP.NET MVC application. In my application, I need to provide REST API. So I added Web Api 2 to my existing MVC application. Before I added Web API 2, I was using ninject for dependency injection. I installed it via Nuget Package.
The whole website is already developed and working. But the problem started when I added Web Api 2 to my project. Ninject for MVC cannot be used with Web Api. So I installed Ninject for Web Api 2. So my NinjectWebCommon class has been changed after I installed it.
This is my NinjectWebCommon file in App_Start folder
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(AyarDirectory.Web.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethodAttribute(typeof(AyarDirectory.Web.App_Start.NinjectWebCommon), "Stop")]
namespace AyarDirectory.Web.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();
try
{
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
return kernel;
}
catch
{
kernel.Dispose();
throw;
}
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
System.Web.Mvc.DependencyResolver.SetResolver(new AyarDirectory.Web.Infrastructure.NinjectDependencyResolver(kernel));
}
}
}
I changed only that place after I installed ninject for web api 2.Then I run my application. Website is working fine. Website is still working. But Web Api is not working.
This is my resolver class
namespace AyarDirectory.Web.Infrastructure
{
public class NinjectDependencyResolver : IDependencyResolver
{
private IKernel kernel;
public NinjectDependencyResolver(IKernel kernelParam)
{
kernel = kernelParam;
AddBindings();
}
public object GetService(Type serviceType)
{
return kernel.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return kernel.GetAll(serviceType);
}
private void AddBindings()
{
kernel.Bind<ICategoryRepo>().To<CategoryRepo>();
}
}
}
I do dependency injection in Api Controller like this:
public class RegionsController : ApiController
{
private IRegionRepo regionRepo;
private RegionsController(IRegionRepo regionParam)
{
this.regionRepo = regionParam;
}
. . . }
When I access one of the action of api controller, it is giving me the following error.
{"Message":"An error has occurred.","ExceptionMessage":"An error occurred when trying to create a controller of type 'RegionsController'. Make sure that the controller has a parameterless public constructor.","ExceptionType":"System.InvalidOperationException","StackTrace":" at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)\r\n at System.Web.Http.Controllers.HttpControllerDescriptor.CreateController(HttpRequestMessage request)\r\n at System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken)\r\n at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__0.MoveNext()","InnerException":{"Message":"An error has occurred.","ExceptionMessage":"Type 'AyarDirectory.Web.Controllers.Api.RegionsController' does not have a default constructor","ExceptionType":"System.ArgumentException","StackTrace":" at System.Linq.Expressions.Expression.New(Type type)\r\n at System.Web.Http.Internal.TypeActivator.Create[TBase](Type instanceType)\r\n at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request, Type controllerType, Func`1& activator)\r\n at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)"}}
So, what is missing or wrong with my code? How can I use Ninject for Web Api 2? I am using MVC 5.
Just do 2 more steps below:
From Nugget package manager:
install-package Ninject.Web.WebApi
Now Edit NinjectWebCommon.cs File and add the following line at the end of the CreateKernel() method and before returning kernel properties:
GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
return kernel;
I'm using MVC4 and Unity 2.1. My services require a service key based on credentials retrieved from session state.
I register my service(s) like so:
container.RegisterType<IInventoryService, InventoryService>();
The constructor for InventoryService is equally simple:
public InventoryService(ServiceKey serviceKey) { ... }
In my website when I've needed a service I use a service locator that automatically composes the service key using credentials from session.
public static T Resolve<T>(ServiceKey serviceKey = null)
{
if (serviceKey == null)
{
serviceKey = SessionManager.ServiceKey;
}
var parameterOverride = new ParameterOverride(SERVICEKEY_PARAMETERNAME, serviceKey);
return Resolve<T>(null, parameterOverride);
}
This has worked well. The problem is that I'm now converting my site to MVC and attempting to inject services into controllers using a simple dependency resolver that uses my exiting service locator (dependency factory):
public class CustomDependencyResolver : IDependencyResolver
{
public object GetService(Type serviceType)
{
return MvcDependencyFactory.Resolve(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return MvcDependencyFactory.ResolveAll(serviceType);
}
}
My controller looks like:
public InventoryController(IInventoryService inventoryService) { ... }
The problem is that MVC still complains about not finding a parameterless constructor when trying to instantiate the inventory controller. I think this is because I haven't registered a service key in Unity. But if I try doing so, I find that MVC is trying to resolve the controllers, and subsequently the services, before session has even been constructed.
Am I not thinking about this correctly? Each step feels pretty reasonable -- using session credentials in a service, using a service in a controller, using a resolver to help build the controller -- but I've been beating my head against the wall getting this to work.
You can use the InjectionFactory in Unity (Microsoft.Practices.Unity.InjectionFactory) to specify a function to handle the resolution of your dependency. This function will only be executed when the dependency is resolved. In the below example, "c" is your Unity container passed as a argument so that you can do additional resolves within your function.
replace:
container.RegisterType<IInventoryService, InventoryService>();
with:
container.RegisterType<IInventoryService>(new InjectionFactory(c =>
new InventoryService(SessionManager.ServiceKey)));
Using the Unity.Mvc4 package seemed to fix the problem, though it's not clear to me why. But rather than use yet another package and hide away my questions, I decided to add a parameterless constructor that manually resolves itself as necessary:
public InventoryController() : this (MvcDependencyFactory.Resolve<IInventoryService>(SessionManger.ServiceKey) { }
It still allows for unit testing of the controllers (via injection) while being transparent about where the resolution is happening when the parameterless constructor is called.
Below is a custom IDependencyResolver, which was fairly straight forward once I started to dig into how it worked and differed from IoC container resolution. You need the try/catches to capture MVC's attempted resolution of IControllerActivator (source: http://www.devtrends.co.uk/blog/do-not-implement-icontrolleractivator-in-asp.net-mvc-3). If IControllerActivator cannot be resolved, your custom IDependencyResolver will be queried for your controller instead (which will use your IoC container of choice).
I added the below class to my basic MVC4's App_Start folder:
using System;
using System.Collections.Generic;
using System.Web.Mvc;
using Microsoft.Practices.Unity;
using Sample.Web.Controllers;
namespace Sample.Web.App_Start
{
public static class UnityConfig
{
public static void ConfigureContainer()
{
IUnityContainer container = BuildUnityContainer();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
private static IUnityContainer BuildUnityContainer()
{
var container = new UnityContainer();
container.RegisterType<IHomeService>(new InjectionFactory( c =>
new HomeService("this string is a dependency.")));
container.RegisterType<IController, HomeController>("Home");
return container;
}
}
public class UnityDependencyResolver : IDependencyResolver
{
private readonly IUnityContainer _container;
public UnityDependencyResolver(IUnityContainer container)
{
_container = container;
}
public object GetService(Type serviceType)
{
try
{
return _container.Resolve(serviceType);
}
catch (ResolutionFailedException)
{
return null;
}
}
public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return _container.ResolveAll(serviceType);
}
catch (ResolutionFailedException)
{
return new List<object>();
}
}
}
}
Here is my simple controller:
using System.Web.Mvc;
namespace Sample.Web.Controllers
{
public class HomeController : Controller
{
private readonly IHomeService _service;
public HomeController(IHomeService service)
{
_service = service;
}
public ActionResult Index()
{
ViewBag.SomeData = _service.GetSomeData();
return View();
}
}
public interface IHomeService
{
string GetSomeData();
}
public class HomeService : IHomeService
{
private readonly string _data;
public HomeService(string data)
{
_data = data;
}
public string GetSomeData()
{
return _data;
}
}
}
Here is my epically huge view:
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>#ViewBag.SomeData</p>
I have this configuration in my project MVC4 Unity and a generic configucion for drivers.
Bootstrapper.cs
namespace MyProyect.Web
{
public static class Bootstrapper
{
public static void Initialise()
{
var container = BuildUnityContainer();
ServiceLocator.SetLocatorProvider(() => new UnityServiceLocator(container));
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
}
private static IUnityContainer BuildUnityContainer()
{
var container = new UnityContainer();
container.RegisterType<MyProyect.Model.DataAccessContract.ICountryDao, MyProyect.DataAccess.CountryDao>();
container.RegisterType<MyProyect.Model.DataAccessContract.IContactDao, MyProyect.DataAccess.ContactDao>();
return container;
}
}
}
Global.asax:
protected void Application_Start()
{
...
Bootstrapper.Initialise();
...
}
GenericModelBinder.cs:
namespace MyProyect.Web.ModelBinder
{
public class GenericModelBinder : DefaultModelBinder//, IValueProvider
{
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
{
var resolver = (Unity.Mvc4.UnityDependencyResolver)DependencyResolver.Current;
if (modelType == null)
{
return base.CreateModel(controllerContext, bindingContext, null);
}
return resolver.GetService(modelType);
}
}
}
Now that I need is to resolve a dependency in another project within the solution. My question is how I can do to that recognize the settings Unity in another project?. I currently I have this class but the current configuration does not bring in the MVC project.
namespace MyProyect.Model.ListData
{
public abstract class ListDataGenericResolver
{
protected T ResolverType<T>()
{
IUnityContainer container = new UnityContainer();
UnityServiceLocator locator = new UnityServiceLocator(container);
ServiceLocator.SetLocatorProvider(() => locator);
//return unity.Resolve<T>();
return (T)container.Resolve(typeof(T));
}
}
}
this is a example how to use ListDataGenericResolver:
namespace MyProyect.Model.ListData.Types
{
public class CountryListData : ListDataGenericResolver, IGetListData
{
private readonly ICountryDao countryDao;
private string defaultValue;
public CountryListData(object defaultValue)
{
// Resolver
this.countryDao = this.ResolverType<ICountryDao>();
this.defaultValue = defaultValue == null ? string.Empty : defaultValue.ToString();
}
public IList<SelectData> GetData()
{
var data = this.countryDao.GetAllCountry(new Entity.Parameters.CountryGetAllParameters());
return data.Select(d => new SelectData
{
Value = d.CountryId.ToString(),
Text = d.Description,
Selected = this.defaultValue == d.CountryId.ToString()
}).ToList();
}
}
}
Thank you.
Here is how I do this.
In Application_Start, I create the unity container. I have a custom library that I use for all of my MVC projects that I import through NuGet, so I make the call to its configure method, then call the other project's Configure() methods. You could simply omit the custom library and add that code in here as well. All of that keeps my Application_Start nice and clean.
protected void Application_Start()
{
// Standard MVC setup
// <removed>
// Application configuration
var container = new UnityContainer();
new CompanyName.Mvc.UnityBootstrap().Configure(container);
new AppName.ProjectName1.UnityBootstrap().Configure(container);
new AppName.ProjectName2.UnityBootstrap().Configure(container);
// <removed>
}
This is the code for the custom MVC library's UnityBootstrap class
namespace CompanyName.Mvc
{
/// <summary>
/// Bootstraps <see cref="CompanyName.Mvc"/> into a Unity container.
/// </summary>
public class UnityBootstrap : IUnityBootstrap
{
/// <inheritdoc />
public IUnityContainer Configure(IUnityContainer container)
{
// Convenience registration for authentication
container.RegisterType<IPrincipal>(new InjectionFactory(c => HttpContext.Current.User));
// Integrate MVC with Unity
container.RegisterFilterProvider();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
return container;
}
}
}
Then, in the other projects, I have a UnityBootstrap there, that was called from Application_Start:
ProjectName1:
namespace AppName.ProjectName1
{
public class UnityBootstrap : IUnityBootstrap
{
public IUnityContainer Configure(IUnityContainer container)
{
return container.RegisterType<IDocumentRoutingConfiguration, DocumentRoutingConfiguration>();
}
}
}
ProjectName2: - and you can see in here, that this one depends on some other projects in another library and it is calling their Configure() methods to get them set up too...
namespace AppName.ProjectName2
{
public class UnityBootstrap : IUnityBootstrap
{
public IUnityContainer Configure(IUnityContainer container)
{
new CompanyName.Security.UnityBootstrap().Configure(container);
new CompanyName.Data.UnityBootstrap().Configure(container);
container.RegisterSecureServices<AuthorizationRulesEngine>(typeof(UnityBootstrap).Assembly);
return container
.RegisterType<IAuthorizationRulesEngine, AuthorizationRulesEngine>()
.RegisterType<IDateTimeFactory, DateTimeFactory>()
.RegisterType<IDirectoryInfoFactory, DirectoryInfoFactory>()
.RegisterType<IDirectoryWrapper, DirectoryWrapper>()
.RegisterType<IEmailService, EmailService>()
.RegisterType<IEntryPointService, EntryPointService>();
}
}
}
Here is the IUnityBootstrap interface that is used throughout the code above (for your reference)
/// <summary>
/// Defines a standard interface for bootstrapping an assembly into a Unity container.
/// </summary>
public interface IUnityBootstrap
{
/// <summary>
/// Registers all of the assembly's classes to their public interfaces and performs any other necessary configuration.
/// </summary>
/// <param name="container">The Unity container instance to configure.</param>
/// <returns>The same IUnityContainer object that this method was called on.</returns>
IUnityContainer Configure(IUnityContainer container);
}
I hope this helps you out.
I am using Ninject together with ASP.NET MVC 4. I am using repositories and want to do constructor injection to pass in the repository to one of the controllers.
This is my Repository interface:
public interface IRepository<T> where T : TableServiceEntity
{
void Add(T item);
void Delete(T item);
void Update(T item);
IEnumerable<T> Find(params Specification<T>[] specifications);
IEnumerable<T> RetrieveAll();
void SaveChanges();
}
The AzureTableStorageRepository below is an implementation of IRepository<T>:
public class AzureTableRepository<T> : IRepository<T> where T : TableServiceEntity
{
private readonly string _tableName;
private readonly TableServiceContext _dataContext;
private CloudStorageAccount _storageAccount;
private CloudTableClient _tableClient;
public AzureTableRepository(string tableName)
{
// Create an instance of a Windows Azure Storage account
_storageAccount = CloudStorageAccount.Parse(ConfigurationManager.ConnectionStrings["StorageConnectionString"].ConnectionString);
_tableClient = _storageAccount.CreateCloudTableClient();
_tableClient.CreateTableIfNotExist(tableName);
_dataContext = _tableClient.GetDataServiceContext();
_tableName = tableName;
}
Note the tableName parameter needed because I was using a generic table repository to persist data to Azure.
And finally I have the following controller.
public class CategoriesController : ApiController
{
static IRepository<Category> _repository;
public CategoriesController(IRepository<Category> repository)
{
if (repository == null)
{
throw new ArgumentNullException("repository");
}
_repository = repository;
}
Now I want to inject a repository into the controller. So I have created a module that contains the bindings:
/// <summary>
/// Ninject module to handle dependency injection of repositories
/// </summary>
public class RepositoryNinjectModule : NinjectModule
{
public override void Load()
{
Bind<IRepository<Category>>().To<AzureTableRepository<Category>>();
}
}
The loading of the module is done in the NinjectWebCommon.cs
/// <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)
{
// Load the module that contains the binding
kernel.Load(new RepositoryNinjectModule());
// Set resolver needed to use Ninject with MVC4 Web API
GlobalConfiguration.Configuration.DependencyResolver = new NinjectResolver(kernel);
}
The DependencyResolver was created because Ninject's DependencyResolver implements System.Web.Mvc.IDependencyResolver and this cannot be assigned to GlobalConfiguration.Configuration of the WebApi Application.
So with all this in place, the Ninject part is actually injecting the right type in the Controller but Ninject cannot inject the tableName parameter in the constructor of AzureTableRepository.
How would I be able to do this in this case? I have consulted a lot of articles and the ninject documentation to see how I could use parameters, but I cannot seem to get it working.
Any help would be appreciated.
I'd use the WithConstructorArgument() method like...
Bind<IRepository<Category>>().To<AzureTableRepository<Category>>()
.WithConstructorArgument("tableName", "categories");
The rest of the repository design is probably another question. IMHO It seems like a big no no to create a table or do any heavy lifting in a ctor.
Meanwhile I have been playing around with Providers to try and do the trick and it seems to work.
I don't know if this is good idea or if it is overkill but here is what I have done:
I have created a generic provider class:
public abstract class NinjectProvider<T> : IProvider
{
public virtual Type Type { get; set; }
protected abstract T CreateInstance(IContext context);
public object Create(IContext context)
{
throw new NotImplementedException();
}
object IProvider.Create(IContext context)
{
throw new NotImplementedException();
}
Type IProvider.Type
{
get { throw new NotImplementedException(); }
}
}
And then I implemented that one in the AzureTableRepositoryProvider. (T to support having the same repository for multiple entity types.)
public class AzureTableRepositoryProvider<T> : Provider<AzureTableRepository<T>> where T : TableServiceEntity
{
protected override AzureTableRepository<T> CreateInstance(IContext context)
{
string tableName = "";
if (typeof(T).Name == typeof(Category).Name)
{
// TODO Get the table names from a resource
tableName = "categories";
}
// Here other types will be addedd as needed
AzureTableRepository<T> azureTableRepository = new AzureTableRepository<T>(tableName);
return azureTableRepository;
}
}
By using this provider I can pass in the right table name for the repository to work with. But for me, two questions remain:
Is this good practice or could we do things much simpler?
In the NinjectProvider class I have two notImplementedException cases. How could I resolve these? I used sample code from the following link but that does not work as the Provider is abstract and the code does not have a body for the create method... enter link description here
I upgraded from ninject 2.0 to 2.2 and nothing works anymore.
When I use nuget it makes this
[assembly: WebActivator.PreApplicationStartMethod(typeof(MvcApplication3.App_Start.NinjectMVC3), "Start")]
[assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(MvcApplication3.App_Start.NinjectMVC3), "Stop")]
namespace MvcApplication3.App_Start
{
using System.Reflection;
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using Ninject;
using Ninject.Web.Mvc;
public static class NinjectMVC3
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
/// <summary>
/// Starts the application
/// </summary>
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestModule));
DynamicModuleUtility.RegisterModule(typeof(HttpApplicationInitializationModule));
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();
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)
{
}
}
}
I use this
/// <summary>
/// Application_Start
/// </summary>
protected void Application_Start()
{
// Hook our DI stuff when application starts
IKernel kernel = SetupDependencyInjection();
}
public IKernel SetupDependencyInjection()
{
IKernel kernel = CreateKernel();
// Tell ASP.NET MVC 3 to use our Ninject DI Container
DependencyResolver.SetResolver(new NinjectDependencyResolver(kernel));
return kernel;
}
protected IKernel CreateKernel()
{
var modules = new INinjectModule[]
{
new NhibernateModule(),
new ServiceModule(),
new RepoModule()
};
public class NinjectDependencyResolver : IDependencyResolver
{
private readonly IResolutionRoot resolutionRoot;
public NinjectDependencyResolver(IResolutionRoot kernel)
{
resolutionRoot = kernel;
}
public object GetService(Type serviceType)
{
return resolutionRoot.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return resolutionRoot.GetAll(serviceType);
}
}
So when I try to use my way(what worked before the changes) when I load it up now I get some no parameterless controller.
When I use their I get
Error occured: Error activating SomeController
More than one matching bindings are available.
Activation path:
1) Request for SomeController
Suggestions:
1) Ensure that you have defined a binding for SomeController only once.
I hope you know that there is a documentation at https://github.com/ninject/ninject.web.mvc/wiki/Setting-up-an-MVC3-application where this question is explained.
Move your module array into the
var modules = new INinjectModule[]
{
new NhibernateModule(),
new ServiceModule(),
new RepoModule()
};
into the RegisterServices and add
kernel.Load(modules);
Those are two different approaches into configuring the kernel. The approach you were using requires modifying Global.asax. The NuGet package uses this new feature of ASP.NET 4 which allows dynamic modules to be registered at application startup. Because the authors of the NuGet package didn't want to mess up with Global.asax as there might be some other existing code, they preferred to use this separate file for configuring the kernel.
The two approaches are not compatible and you should never use them both in the same application. The new version also already contains a NinjectDependencyResolver so you no longer need to write or set any custom DependencyResolver.SetResolver.
All you need to do is use the RegisterServices static method in the bootstrapper class to configure your kernel:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<ISomeControllerDependency>().To<SomeConcreteImpl>();
}
And if you had some NInject modules that you wanted to load:
private static void RegisterServices(IKernel kernel)
{
kernel.Load(
new NhibernateModule(),
new ServiceModule(),
new RepoModule()
);
}
That's it. Don't forget to remove any NInject trace from your Global.asax to avoid any conflicts.
I guess the reason your code didn't work with the first approach is because you didn't load the modules in the RegisterServices method.