This question already has answers here:
How to use Ninject with ASP.NET Web API?
(4 answers)
Closed 8 years ago.
I've installed the Ninject.Web.WebAPI package using Nuget and i cant figure out how to bind my dependencies.
I regularly use Ninject with my MVC apps and when i install the Ninject package it creates a NinjectWebCommon.cs file where i set up my bindings. This file doesnt appear to generate for the WebAPI project.
Anyone help me out on where to put my bindings.
cheers
Create a class to fix NinjectDependencyResolver issue of web api.
public class NinjectDependencyResolverHelper : IDependencyScope
{
IResolutionRoot resolver;
public NinjectDependencyResolverHelper(IResolutionRoot resolver)
{
this.resolver = resolver;
}
public object GetService(Type serviceType)
{
if (resolver == null)
throw new ObjectDisposedException("this", "This scope has been disposed");
return resolver.TryGet(serviceType);
}
public System.Collections.Generic.IEnumerable<object> GetServices(Type serviceType)
{
if (resolver == null)
throw new ObjectDisposedException("this", "This scope has been disposed");
return resolver.GetAll(serviceType);
}
public void Dispose()
{
var disposable = resolver as IDisposable;
if (disposable != null)
disposable.Dispose();
resolver = null;
}
}
public class NinjectDependencyResolver : NinjectDependencyResolverHelper, IDependencyResolver
{
IKernel kernel;
public NinjectDependencyResolver(IKernel kernel)
: base(kernel)
{
this.kernel = kernel;
}
public IDependencyScope BeginScope()
{
return new NinjectDependencyResolverHelper(kernel.BeginBlock());
}
}
Then create NinjectWebCommon class
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>();
GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
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)
{
//Bind your stuff
}
}
Hope this helps.
Related
I'm developing a web app that uses Ninject Data injection in my ASP.NET MVC5 project. I set up an NinjectDependencyResolver that inherits from IDependencyResolver like this:
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()
{
// here I have all my bindings set up
kernel.Bind<ProConnect.Domain.Abstract.IMyRepository>().To<MyRepository>();
}
}
and here is the NinjectWebCommon class that is fired on application launch and that registers the services:
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(MyApp.WebUI.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethodAttribute(typeof(MyApp.WebUI.App_Start.NinjectWebCommon), "Stop")]
namespace ProConnect.WebUI.App_Start
{
using System;
using System.Web;
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using Ninject;
using Ninject.Web.Common;
using Ninject.Web.Common.WebHost;
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)
{
// creating the bridge between the NinjectDependencyResolver class and the MVC support for dependency injection.
System.Web.Mvc.DependencyResolver.SetResolver(new
MyApp.WebUI.Infrastructure.NinjectDependencyResolver(kernel));
// maybe I have to add some code here to create the bridge between
// NinjectDependencyResolver class and my standard classes that
// have nothing to do with MVC????
}
}
}
I use this to inject Repository object coming from the domain into my MVC controllers and this all works perfectly well.
The problem I have is that I would like to inject some other Repository Objects into a Settings Class that will retrieve some settings data from the database. Since my settings class is not a MVC controller but just a plain old class, it doesn't figure out how to inject the data.
Could some one help me on this one? I tried to set up again data injection like this but it didn't work:
public class Settings
{
private Domain.Abstract.ISettingRepository settingRepository;
private StandardKernel kernel;
public Settings()
{
this.kernel = new StandardKernel();
// I don't know if this loads a new kernel or the one that is used in the rest of the MVC application
kernel.Load(Assembly.GetExecutingAssembly());
// I tryed re-specifying the bindings but this didn't help
kernel.Bind<Domain.Abstract.ISettingRepository>().To<Domain.Concrete.SettingRepository>();
this.settingRepository = kernel.Get<Domain.Abstract.ISettingRepository>();
}
public void DoSomethigWithSettings(){
this.settingRepository.Settings()......
}
}
Ok I figured out the answer thanks to https://stackoverflow.com/a/19585471/11011693
I simply had get the object I wanted to inject in a non MVC class from the current MVC DependencyResolver that is set up on Application Start
public class Settings
{
private Domain.Abstract.ISettingRepository settingRepository;
public Settings()
{
// simply get the object you want to inject in a non MVC class
// from the current MVC DependencyResolver that is set up on Application Start
this.settingRepository = (Domain.Abstract.IAppSettingService)System.Web.Mvc.DependencyResolver.Current.GetService(typeof(Domain.Abstract.IAppSettingService));
}
public void DoSomethigWithSettings(){
this.settingRepository.Settings()......
}
}
I have a project with three-level architecture:
project.Data
project.Domain
project.Web
I need to implement Quartz.Net to user interface level.
And use it following way:
public class EmailSender : IJob
{
ISomeService _service;
public EmailSender(ISomeService service)
{
_service = service;
}
public void Execute(IJobExecutionContext context)
{
_service.Create();
}
}
public class EmailScheduler
{
public static void Start()
{
IScheduler scheduler = StdSchedulerFactory.GetDefaultScheduler();
scheduler.Start();
IJobDetail job = JobBuilder.Create<EmailSender>().Build();
ITrigger trigger = TriggerBuilder.Create()
.WithIdentity("trigger1", "group1")
.StartNow()
.WithSimpleSchedule(x => x
.WithIntervalInMinutes(1)
.RepeatForever())
.Build();
scheduler.ScheduleJob(job, trigger);
}
}
In global.asax.cs
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
EmailScheduler.Start();
}
}
In project.Data
I use pattern of repositories. As I use few repositories for each entity, I use Unit of Work pattern to make easier connection to database.
public interface IUnitOfWork : IDisposable
{
ISomeRepository SomeRepository { get; }
void Save();
}
EFUnitOfWork class in constructor receives string with name of connection, which will be sent to data context constructor
So we will interact with database through EFUnitOfWork class.
public class EFUnitOfWork : IUnitOfWork
{
private Context db;
private SomeRepository _someRepository;
public EFUnitOfWork(string connectionString)
{
db = new Context(connectionString);
}
public ISomeRepository SomeRepository
{
get
{
if (_someRepository == null)
_someRepository = new SomeRepository(db);
return _someRepository;
}
}
}
In project.Domain
ServiceModule is a special module Ninject, which is used for organizing dependencies matching.
It replaces EFUnitOfWork with IUnitOfWork.
public class ServiceModule : NinjectModule
{
private string connectionString;
public ServiceModule(string connection)
{
connectionString = connection;
}
public override void Load()
{
Bind<IUnitOfWork>().To<EFUnitOfWork>().WithConstructorArgument(connectionString);
}
}
public interface ISomeService
{
void Create();
}
public class SomeService : ISomeService
{
IUnitOfWork Database { get; set; }
public LetterService(IUnitOfWork uow)
{
Database = uow;
}
public void Create(){
}
}
In project.Web
To set dependencies I use following class:
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<ISomeService>().To<SomeService>();
}
}
In App_Start folder
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(evenafter.WEB.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethodAttribute(typeof(evenafter.WEB.App_Start.NinjectWebCommon), "Stop")]
namespace project.WEB.App_Start
{
using System;
using System.Web;
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using Ninject;
using Ninject.Web.Common;
using Util;
using Ninject.Modules;
using Domain.Infrastructure;
using Quartz.Impl;
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()
{
// set connection string
var modules = new INinjectModule[] { new ServiceModule("DefaultConnection") };
var kernel = new StandardKernel(modules);
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 NinjectDependencyResolver(kernel));
}
}
}
I have a custom AuthorizationFilter Attribute on my Web Api project like this
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
public class GenericAuthenticationFilter : AuthorizationFilterAttribute
{
/// <summary>
/// Public default Constructor
/// </summary>
public GenericAuthenticationFilter()
{
}
private readonly bool _isActive = true;
/// <summary>
/// parameter isActive explicitly enables/disables this filter.
/// </summary>
/// <param name="isActive"></param>
public GenericAuthenticationFilter(bool isActive)
{
_isActive = isActive;
}
/// <summary>
/// Checks basic authentication request
/// </summary>
/// <param name="filterContext"></param>
public override void OnAuthorization(HttpActionContext filterContext)
{
if (!_isActive) return;
var identity = FetchAuthHeader(filterContext);
if (identity == null)
{
ChallengeAuthRequest(filterContext);
return;
}
var genericPrincipal = new GenericPrincipal(identity, null);
Thread.CurrentPrincipal = genericPrincipal;
if (!OnAuthorizeUser(identity.Name, identity.Password, filterContext))
{
ChallengeAuthRequest(filterContext);
return;
}
base.OnAuthorization(filterContext);
}
My StartUpClass is like this
public class Startup
{
public void Configuration(IAppBuilder app)
{
// For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=316888
// Get your HttpConfiguration. In OWIN, you'll create one
// rather than using GlobalConfiguration.
var config = new HttpConfiguration();
WebApiConfig.Register(config);
IoC.Instance.RegisterApiControllers(Assembly.GetExecutingAssembly());
config.DependencyResolver =
new AutofacWebApiDependencyResolver(IoC.Instance.GetComponentsContainer());
// Register your Web Api controllers.
IoC.Instance.RegisterApiControllers(Assembly.GetExecutingAssembly());
IoC.Instance.RegisterWebApiModelBinders(Assembly.GetExecutingAssembly());
IoC.Instance.RegisterWebApiModelBinderProvider();
IoC.Instance.RegisterWebApiFilterProvider(config);
// Register the Autofac middleware FIRST, then the Autofac Web API middleware,
// and finally the standard Web API middleware.
app.UseAutofacMiddleware(IoC.Instance.GetComponentsContainer());
app.UseAutofacWebApi(config);
app.UseWebApi(config);
}
}
and my IoC class where all dependencies are resolved is like this
public class IoC : ContainerBuilder
{
/// <summary>
///
/// </summary>
private readonly static IoC _instance = new IoC();
/// <summary>
///
/// </summary>
private static object _lock;
/// <summary>
///
/// </summary>
private IContainer _componentsContainer;
/// <summary>
///
/// </summary>
public static IoC Instance
{
get
{
return _instance;
}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public IContainer GetComponentsContainer()
{
if (_componentsContainer == null)
{
lock (_lock)
{
if (_componentsContainer == null)
_componentsContainer = this.Build();
}
}
return _componentsContainer;
}
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public T Resolve<T>() where T : class
{
return GetComponentsContainer().Resolve<T>();
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public ILifetimeScope BeginLifetimeScope()
{
return GetComponentsContainer().BeginLifetimeScope();
}
/// <summary>
///
/// </summary>
private IoC()
{
_lock = new object();
ConfigureDependencies();
}
/// <summary>
///
/// </summary>
private void ConfigureDependencies()
{
//Configure all your depedendencies here!!
//Database connection
var connectionString = ConfigurationManager.ConnectionStrings["DBConnectionStringName"].ConnectionString;
this.Register(c => new SqlConnection(connectionString)).As<IDbConnection>().InstancePerRequest();// InstancePerLifetimeScope();
//Database Connection OrmLite
OrmLiteConfig.DialectProvider = SqlServerDialect.Provider;
//Register Repositories
this.RegisterType<Repository>().As<IRepository>().InstancePerRequest();// InstancePerLifetimeScope();
// Register Services
this.RegisterType<UserService>().As<IUserService>().InstancePerRequest();// InstancePerLifetimeScope();
this.RegisterType<TokenService>().As<ITokenService>().InstancePerRequest();
this.RegisterType<DKMenuService>().As<IDKMenuService>().InstancePerRequest();// InstancePerLifetimeScope();
this.RegisterType<DKGRIDTblService>().As<IDKGRIDTblService>().InstancePerRequest();// InstancePerLifetimeScope();
this.RegisterType<FKService>().As<IFKService>().InstancePerRequest();// InstancePerLifetimeScope();
this.RegisterType<LOVService>().As<ILOVService>().InstancePerRequest();// InstancePerLifetimeScope();
this.RegisterType<JobService>().As<IJobService>().InstancePerRequest();// InstancePerLifetimeScope();
this.RegisterType<MADEService>().As<IMADEService>().InstancePerRequest();// InstancePerLifetimeScope();
}
}
And I decorate my Controllers with this filter like this
[GenericAuthenticationFilter]
public AuthenticateController(ITokenService tokenService)
{
_tokenService = tokenService;
}
My Problem is that the OnAuthorazation method of the GenericAuthenticationFilter is never fired.
If on the IoC Class class I change InstancePerRequest to InstancePerLifetimeScope everything works ok, but I want my dependencies to work per Request
Any Ideas?
I'm not sure if this is part or all of your issue, but... you can only build a ContainerBuilder once. In Startup.Configuration() I see on lines 11-12:
config.DependencyResolver =
new AutofacWebApiDependencyResolver(IoC.Instance.GetComponentsContainer());
And IoC.Instance.GetComponentsContainer() calls Build() to create the container.
But just two lines later I see you're adding more components to the container, and after that I see a second call:
app.UseAutofacMiddleware(IoC.Instance.GetComponentsContainer());
Based on your code, that's going to be the same container that was built before you added the new registrations. The container won't include the API controllers, the model binders, or the filter provider.
I'm actually not sure why you're not having more problems than you're having now.
Try moving the setting of the containers (the calls to IoC.Instance.GetComponentsContainer()) until all the way at the end, after you've finished registering all of your dependencies.
The only configuration that worked was the following
public class Startup
{
public void Configuration(IAppBuilder app)
{
// For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=316888
// Get your HttpConfiguration. In OWIN, you'll create one
// rather than using GlobalConfiguration.
var config = new HttpConfiguration();
WebApiConfig.Register(config);
// Register your Web Api controllers.
IoC.Instance.RegisterApiControllers(Assembly.GetExecutingAssembly());
IoC.Instance.RegisterWebApiModelBinders(Assembly.GetExecutingAssembly());
IoC.Instance.RegisterWebApiModelBinderProvider();
config.DependencyResolver =
new AutofacWebApiDependencyResolver(IoC.Instance.GetComponentsContainer());
// Register your Web Api controllers.
//IoC.Instance.RegisterApiControllers(Assembly.GetExecutingAssembly());
//IoC.Instance.RegisterWebApiModelBinders(Assembly.GetExecutingAssembly());
//IoC.Instance.RegisterWebApiModelBinderProvider();
// Register the Autofac middleware FIRST, then the Autofac Web API middleware,
// and finally the standard Web API middleware.
app.UseAutofacMiddleware(IoC.Instance.GetComponentsContainer());
app.UseAutofacWebApi(config);
app.UseWebApi(config);
}
}
I am still not sure whether it is right.
Examples of usage. I have a filter like the following
public class ApiAuthenticationFilter : GenericAuthenticationFilter
{
/// <summary>
/// Default Authentication Constructor
/// </summary>
public ApiAuthenticationFilter()
{
}
}
A method in this filter is using a service which is resolved like this
protected override bool OnAuthorizeUser(string username, string password, HttpActionContext actionContext)
{
var provider = actionContext.Request.GetDependencyScope().GetService(typeof(IUserService)) as IUserService;
}
My controllers on the other hand do not have parameterless constructors and the dependencies are resolved automatically
public class DKMenuController : ApiController
{
#region Private variable.
private readonly ITokenService _tokenService;
private readonly IDKMenuService _dkMenuService;
private readonly IUserService _userservice;
private const string Token = "Token";
#endregion
#region Public Constructor
/// <summary>
/// Public constructor to initialize DKMenu service instance
/// </summary>
public DKMenuController(ITokenService tokenService, IUserService userservice, IDKMenuService dkMenuService)
{
_tokenService = tokenService;
_dkMenuService = dkMenuService;
_userservice = userservice;
}
}
I don't know whether it is correct but it works
I have created a basic Web API project with a single controller and trying to use the Unity MVC Bootstrapper package from NuGet. Unfortunately when I try and visit the URL http://localhost/api/runtypes it throws the error
{"Message":"An error has occurred.","ExceptionMessage":"Type
'SE.FlexApplication.WebApi.Controllers.RunTypeController' 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)"}
My controller class
public class RunTypeController : ApiController
{
private readonly IStaticTypesRepository _staticTypesRepository;
private readonly IDataModelConverter _dataModelConverter;
private readonly IBusinessModelConverter _businessModelConverter;
public RunTypeController(IStaticTypesRepository staticTypesRepository, IDataModelConverter dataModelConverter, IBusinessModelConverter businessModelConverter)
{
_staticTypesRepository = staticTypesRepository;
_dataModelConverter = dataModelConverter;
_businessModelConverter = businessModelConverter;
}
public RunType[] Get()
{
return _staticTypesRepository.GetRunTypes().Select(r => _dataModelConverter.Convert(r)).ToArray();
}
public HttpResponseMessage Post(RunType type)
{
_staticTypesRepository.AddRunType(_businessModelConverter.Convert(type));
_staticTypesRepository.Save();
var response = Request.CreateResponse(System.Net.HttpStatusCode.Created, type);
return response;
}
}
And the Unity activator
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(SE.FlexApplication.WebApi.App_Start.UnityWebActivator), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethod(typeof(SE.FlexApplication.WebApi.App_Start.UnityWebActivator), "Shutdown")]
namespace SE.FlexApplication.WebApi.App_Start
{
/// <summary>Provides the bootstrapping for integrating Unity with ASP.NET MVC.</summary>
public static class UnityWebActivator
{
/// <summary>Integrates Unity when the application starts.</summary>
public static void Start()
{
var container = UnityConfig.GetConfiguredContainer();
FilterProviders.Providers.Remove(FilterProviders.Providers.OfType<FilterAttributeFilterProvider>().First());
FilterProviders.Providers.Add(new UnityFilterAttributeFilterProvider(container));
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
/// <summary>Disposes the Unity container when the application is shut down.</summary>
public static void Shutdown()
{
var container = UnityConfig.GetConfiguredContainer();
container.Dispose();
}
}
}
Unity Config class
public class UnityConfig
{
#region Unity Container
private static readonly Lazy<IUnityContainer> Container = new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer();
RegisterTypes(container);
return container;
});
/// <summary>
/// Gets the configured Unity container.
/// </summary>
public static IUnityContainer GetConfiguredContainer()
{
return Container.Value;
}
#endregion
/// <summary>Registers the type mappings with the Unity container.</summary>
/// <param name="container">The unity container to configure.</param>
/// <remarks>There is no need to register concrete types such as controllers or API controllers (unless you want to
/// change the defaults), as Unity allows resolving a concrete type even if it was not previously registered.</remarks>
public static void RegisterTypes(IUnityContainer container)
{
try
{
//container.RegisterInstance<IUnitOfWork>(new ProdUnitOfWork());
container.RegisterType<IEventRepository, EventRepository>();
container.RegisterType<IModelRepository, ModelRepository>();
container.RegisterType<ISecurityRepository, SecurityRepository>();
container.RegisterType<IStaticTypesRepository, StaticTypesRepository>();
container.RegisterType<IDataModelConverter, DataToModelConverter>();
container.RegisterType<IBusinessModelConverter, ModelToDataConverter>();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
It seems like the Controller isn't picking up that it should be using the Unity Dependency resolver for constructor injection. I've followed all the steps on the tutorials online. Have I missed something basic?
In MVC 5 we get this account controller that looks like this.
public class AccountController : Controller
{
public AccountController()
: this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new DatePickerDbContext())))
{
}
public AccountController(UserManager<ApplicationUser> userManager)
{
UserManager = userManager;
}
}
I installed Ninject to handle my dependency injection. I have two repositories, that I want to use in my AccountController
and the code now looks like this
public class AccountController : Controller
{
private readonly ILicenserepository _licenserepository;
private readonly IUserRepository _userRepository;
public AccountController(ILicenserepository licenserepository, IUserRepository userRepository)
: this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new DatePickerDbContext())))
{
_licenserepository = licenserepository;
_userRepository = userRepository;
}
public AccountController(UserManager<ApplicationUser> userManager)
{
UserManager = userManager;
}
}
in ninject.web.common this is what i've done
private static void RegisterServices(IKernel kernel)
{
kernel.Bind(typeof (ILicenserepository)).To(typeof (Licenserepository));
kernel.Bind(typeof (IUserRepository)).To(typeof (UserRepository));
}
but when I run the application i get the error on browser that says no parametereless constructor found. And if i create parameter less constructor my repositories doesn't get instantiated. So wherever i called the method from repository the value is null.
How can I solve this problem? Or make MVC or Ninject know which constructor to call?
You need a DependencyResolver registered in Global.asax.cs
Registration would look something like this:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
RegisterDependencyResolver();
}
private void RegisterDependencyResolver()
{
var kernel = new StandardKernel();
// you may need to configure your container here?
RegisterServices(kernel);
DependencyResolver.SetResolver(new NinjectDependencyResolver(kernel));
}
And the DependencyResolver
public class NinjectDependencyResolver : IDependencyResolver
{
private readonly IKernel kernel;
public NinjectDependencyResolver(IKernel kernel)
{
this.kernel = kernel;
}
public object GetService(Type serviceType)
{
return this.kernel.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return this.kernel.GetAll(serviceType);
}
catch (Exception)
{
return new List<object>();
}
}
}
This is an update:
If your are using MVC5 and WebAPI 2 then all you need to do is use NuGet Manager and add NinjectMVC5 and NinjectWebApi2 into your project. Then the error goes away. (Using Visual Studio 2013)
Cheers
I just got this working without issue using .NET MVC 5 and Ninject 3.3.4.
Steps Taken:
Install Ninject 3.3.4
Install Ninject.Web.Common 3.3.1
Install Ninject.Web.Common.WebHost 3.3.1
Install Ninject.MVC5 3.3.0 (for use with an MVC Controller)
(Optional) Api Controller Steps
Install Ninject.Web.WebApi 3.3.0 (for use with an api ApiController)
Install Ninject.Web.WebApi.WebHost (for use with an ApiController)
The important distinction here is whether your project uses Api Controllers or Mvc Controllers. If you are unfamiliar with the difference please check out the below post:
Difference between ApiController and Controller in ASP.NET MVC.
Note: I did not have to do any extra configuration to my Ninject.Web.Common.cs file. Below is my configuration omitting my bindings
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(YourProject.Web.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethodAttribute(typeof(YourProject.Web.App_Start.NinjectWebCommon), "Stop")]
namespace YourProject.Web.App_Start
{
using System;
using System.Web;
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using Ninject;
using Ninject.Web.Common;
using Ninject.Web.Common.WebHost;
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)
{
// Common
// Repositories
// Services
// Factories
// Misc
}
}
}