Ninject not working in Web API contructor in ASP.NET MVC 4 - asp.net-mvc-4

I am new to ASP.NET Web API.
I have upgraded my ASP.NET MVC 3 project to ASP.NET MVC 4 by using this tutorial.
Now I am trying to use Web Api here, as you can see I am trying to use ninject here, but when I declare ProductsController constructor in such a way, this does not work.
public class ProductsController : ApiController
{
private readonly IProductService _productService;
public ProductsController(IProductService productService)
{
this._productService = productService;
}
public List<Product> GetProducts()
{
return _productService.GetAllProducts();
}
}
Please help me on this.
If I add this constructor there is no call made to Web Api methods, I confirmed this by using breakpoints and it makes call otherwise.
Browser shows an xml error which reads
<Error><Message>An error has occurred.</Message></Error>
My NinjectWebCommon.cs class code is
[assembly: WebActivator.PreApplicationStartMethod(typeof(Web.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(Web.App_Start.NinjectWebCommon), "Stop")]
namespace Web.App_Start
{
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)
{
kernel.Bind<IProductService>().To<ProductService>();
}
}
}

You can follow these steps to get WebApi and Ninject up and running:
1 Create a new WebApi project
2 Add the following code for a field and a constructor to the default ValuesController:
private IFooService _foo;
public ValuesController(IFooService foo)
{
_foo = foo;
}
3 Create an interface IFooService and a class FooService
public interface IFooService
{
}
public class FooService : IFooService
{
}
4 Run the following command in your Nuget Packag Manager Console to install Ninject
Install-Package Ninject.MVC3
5 Add the following binding to App_Start\NinjectWebCommon.cs in method RegisterServices(IKernel kernel)
kernel.Bind<IFooService>().To<FooService>().InRequestScope();
In your code, you are probably not calling the NInject configuration at the right moment. When you use the Nuget package you get the following lines at the top of your Ninject file:
[assembly: WebActivator.PreApplicationStartMethod(typeof(WebApiNinjectTest.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(WebApiNinjectTest.App_Start.NinjectWebCommon), "Stop")]
These lines will make sure your code is executed at the right time.

Update : A super awesome explanation at : http://www.strathweb.com/2012/05/using-ninject-with-the-latest-asp-net-web-api-source/, Now I no longer have to use ProductsController(): this(new ProductService()).
Ah alas got this working now :)
Here is what I did...
I have two constructor of each of my WebApiController. For example for my ProductsController now the constructor I needed to define were as follows...
public class ProductsController : ApiController
{
private readonly IProductService _productService;
public ProductsController(): this(new ProductService())
{
}
public ProductsController(IFolderService productService)
{
this._polderService = productService;
}
public List<Product> GetProducts()
{
return _productService.GetAllProducts();
}
}
:)

Related

MVC4 / Ninject - How to change bindings after Authentication

I am using MVC4 with Ninject (4.0.30319) and NinjectWebCommon.cs. I have Ninject set up and working with a common set of bindings for MVC and the WebAPI.
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
// Install our Ninject-based IDependencyResolver into the Web API config
GlobalConfiguration.Configuration.DependencyResolver = new NinjectWebAPIDependencyResolver(kernel);
// Install our Ninject-based IDependencyResolver into the MVC config
DependencyResolver.SetResolver(new NinjectMVCDependencyResolver(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)
{
kernel.Bind<DBDataContext>().To<DBDataContext>();
kernel.Bind<IChecksRepository>().To<ChecksRepository>();
kernel.Bind<IDepartmentsRepository>().To<DepartmentsRepository>();
kernel.Bind<IEmployeesRepository>().To<EmployeesRepository>();
kernel.Bind<IScheduleRepository>().To<ScheduleRepository>();
kernel.Bind<IVacanciesRepository>().To<VacanciesRepository>();
kernel.Bind<IVacancyTypes>().To<VacancyTypesRepository>();
}
public static void RegisterAuthenticatedServices()
{
bootstrapper.Kernel.Bind<DBDataContext>().To<DBDataContext>().WithPropertyValue("ChangedByPKID", Globals.UserPKID);
}
In Global.asax I have some one-shot code to determine when the user is authenticated and it calls RegisterAuthenticatedServices to change the binding and it executes without an exception. The problem is that after the binding is changed and a controller is requested MVC complains that "No parameterless constructor defined for this object" which I am guessing means the DBDataContext binding is trashed in Ninject. Not sure what I am doing wrong.
Unbind the context and then bind it back with the changes:
public static void RegisterAuthenticatedServices()
{
bootstrapper.Kernel.Unbind<DBDataContext>();
bootstrapper.Kernel.Bind<DBDataContext>().To<DBDataContext>().WithPropertyValue("ChangedByPKID", Globals.UserPKID);
}

Why do I get an Ninject InvalidOperation exception after my API Controller has completed its request?

I have an MVC4 web app project as part of a larger solution. I also have a test project. I am working with a bunch of code that is not going to be reworked, so I can't always make the changes I would like to make.
The MVC4 web app has "normal" Controllers, and Web API Controllers. We are using the RTM version of the Web API, and not an RC.
I attempted to introduce IoC into the project. Using the NuGet installation technique (as opposed to downloading the DLLs and referencing them directly), I installed:
Ninject v3.0.1.10,
Ninject.MVC3 v3.0.0.6
Ninject.Extensions.Factory v3.0.1.0
Ninject.Web.Common v 3.0.0.7
I have no other referenced component in my solution that makes use of Ninject.
Then, following the advice given by Brad Wilson, and his Github Gist https://gist.github.com/2417226, and similar advice given by Filip W here http://www.strathweb.com/2012/05/using-ninject-with-the-latest-asp-net-web-api-source/, I have implemented a NinjectResolver, and "registered" in with the global configuration.
When I fire up the web app, the default page maps to an Index action on the ProjectController. This renders a view, which uses Knockout to populate a ViewModel via a call to an ApiController action called ApiProjectController.Get().
My NinjectWebCommon.cs code looks like this:
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Web.Http;
using System.Web.Http.Dependencies;
using Ninject.Extensions.Factory;
using Ninject.Syntax;
using OfficeWebApp.Utilities;
[assembly: WebActivator.PreApplicationStartMethod(typeof(OfficeWebApp.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(OfficeWebApp.App_Start.NinjectWebCommon), "Stop")]
namespace OfficeWebApp.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);
GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(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)
{
kernel.Bind<IDataManagerConnection>().To<DataManagerConnection>().WithConstructorArgument("overriddenConnectionString", string.Empty);
kernel.Bind<IDataManagerConnectionFactory>().ToFactory();
}
}
public class NinjectDependencyScope : IDependencyScope
{
private IResolutionRoot resolver;
internal NinjectDependencyScope(IResolutionRoot resolver)
{
Contract.Assert(resolver != null);
this.resolver = resolver;
}
public void Dispose()
{
IDisposable disposable = resolver as IDisposable;
if (disposable != null)
disposable.Dispose();
resolver = null;
}
public object GetService(Type serviceType)
{
if (resolver == null)
throw new ObjectDisposedException("this", "This scope has already been disposed");
return resolver.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
if (resolver == null)
throw new ObjectDisposedException("this", "This scope has already been disposed");
return resolver.GetAll(serviceType);
}
}
public class NinjectDependencyResolver : NinjectDependencyScope, IDependencyResolver
{
private IKernel kernel;
public NinjectDependencyResolver(IKernel kernel)
: base(kernel)
{
this.kernel = kernel;
}
public IDependencyScope BeginScope()
{
return new NinjectDependencyScope(kernel.BeginBlock());
}
}
}
The ProjectController code is:
public class ProjectController : Controller
{
private readonly IDataManagerConnectionFactory _dataManagerConnectionFactory;
public ProjectController(IDataManagerConnectionFactory dataManagerConnectionFactory)
{
_dataManagerConnectionFactory = dataManagerConnectionFactory;
}
[HttpGet]
public ActionResult Index()
{
//TODO:
ViewBag.Organisation = "Preview";
return View();
}
}
... and the ApiProjectController:
public class ApiProjectController : ApiController
{
private readonly IDataManagerConnectionFactory _dataManagerConnectionFactory;
public ProjectsController(IDataManagerConnectionFactory dataManagerConnectionFactory)
{
_dataManagerConnectionFactory = dataManagerConnectionFactory;
}
[HttpGet]
public IEnumerable<ProjectTileModel> Get()
{
using (IDataManagerConnection connection = _dataManagerConnectionFactory.Create())
{
List<ProjectTileModel> projectViewModels = connection.DataManager.GetProjectInfos()
.ToList();
return projectViewModels;
}
}
}
After the ApiProjectController.Get() action method has comepleted, Ninject throws the following exception at me:
Error loading Ninject component ICache
No such component has been registered in the kernel's component container.
Suggestions:
1) If you have created a custom subclass for KernelBase, ensure that you have properly
implemented the AddComponents() method.
2) Ensure that you have not removed the component from the container via a call to RemoveAll().
3) Ensure you have not accidentally created more than one kernel.
The call stack looks like this:
Ninject.dll!Ninject.Components.ComponentContainer.Get(System.Type component) Line 160 C#
Ninject.dll!Ninject.Components.ComponentContainer.Get<Ninject.Activation.Caching.ICache>() Line 116 + 0x46 bytes C#
Ninject.Web.Common.dll!Ninject.Web.Common.OnePerRequestHttpModule.DeactivateInstancesForCurrentHttpRequest.AnonymousMethod__1(Ninject.IKernel kernel) Line 74 + 0x27 bytes C#
Ninject.dll!Ninject.GlobalKernelRegistration.MapKernels(System.Action<Ninject.IKernel> action) Line 75 + 0xe bytes C#
Ninject.Web.Common.dll!Ninject.Web.Common.OnePerRequestHttpModule.DeactivateInstancesForCurrentHttpRequest() Line 76 C#
Ninject.Web.Common.dll!Ninject.Web.Common.OnePerRequestHttpModule.Init.AnonymousMethod__0(object o, System.EventArgs e) Line 56 + 0x9 bytes C#
This exception is being thrown in the following piece of Ninject code, in the ComponentContainer.cs file:
Type implementation = _mappings[component].FirstOrDefault(); // <-- see note below...
if (implementation == null)
throw new InvalidOperationException(ExceptionFormatter.NoSuchComponentRegistered(component)); // <-- exception thrown here
Note: at the line indicated above, the _mappings collection contains exactly one item; the key matches the Type we are looking for (ICache), but the Values member (which is a List<Type>) is empty (0 count)
Should I not be using the OnePerRequestHttpModule? Is there something funny happening because I'm using .ToFactory() in my bindings? I don't really know why the OnePerRequestHttpModule is calling DeactivateInstancesForCurrentHttpRequest() but then Ninject seems to be wanting to get at it's internal cache (maybe??)
What is it that I am doing wrong?
I never really got to the bottom of this. I don't know if it is a bug in Ninject, or whether I was simply using it incorrectly. I have, however, worked around my problem by switching IoC Containers to AutoFAC.

SignalR dependency injection via Spring.Net

I'm trying to inject dependencies via Spring.NET.
First I created a custom DependencyResolver:
public class SignalRSpringNetDependencyResolver : DefaultDependencyResolver
{
private IApplicationContext _context;
public SignalRSpringNetDependencyResolver(IApplicationContext context)
{
_context = context;
}
/// <summary>
/// Gets the application context.
/// </summary>
/// <value>The application context.</value>
public IApplicationContext ApplicationContext
{
get
{
if (_context == null || _context.Name != ApplicationContextName)
{
if (string.IsNullOrEmpty(ApplicationContextName))
{
_context = ContextRegistry.GetContext();
}
else
{
_context = ContextRegistry.GetContext(ApplicationContextName);
}
}
return _context;
}
}
/// <summary>
/// Gets or sets the name of the application context.
/// </summary>
/// <remarks>
/// Defaults to using the root (default) Application Context.
/// </remarks>
/// <value>The name of the application context.</value>
public static string ApplicationContextName { get; set; }
/// <summary>
/// Resolves singly registered services that support arbitrary object creation.
/// </summary>
/// <param name="serviceType">The type of the requested service or object.</param>
/// <returns>The requested service or object.</returns>
public override object GetService(Type serviceType)
{
System.Diagnostics.Debug.WriteLine(serviceType.FullName);
if (serviceType != null && !serviceType.IsAbstract && !serviceType.IsInterface && serviceType.IsClass)
{
var services = ApplicationContext.GetObjectsOfType(serviceType).GetEnumerator();
services.MoveNext();
try
{
return services.Value;
}
catch (InvalidOperationException)
{
return null;
}
}
else
{
return base.GetService(serviceType);
}
}
/// <summary>
/// Resolves multiply registered services.
/// </summary>
/// <param name="serviceType">The type of the requested services.</param>
/// <returns>The requested services.</returns>
public override IEnumerable<object> GetServices(Type serviceType)
{
var services = ApplicationContext.GetObjectsOfType(serviceType).Cast<object>();
services.Concat(base.GetServices(serviceType));
return services;
}
Note that i escape interfaces and abstract classes so that I will get the default implementations of SignalR from the base DefaultDependencyResolver
and here I assigned the resolver using WebActivator:
public static void PostStart()
{
// Inject Dependencies to SignalR, should be always come before ASP.NET MVC configuration
var dependecyResolver = new SignalRSpringNetDependencyResolver(ContextRegistry.GetContext());
GlobalHost.DependencyResolver = dependecyResolver;
RouteTable.Routes.MapHubs();
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
However, SignalR is always trying to resolve it's own dependencies using the Resolver i assigned and i get the following error:
'myhub' hub could not be resolved.
I only need the resolver to be aware of other dependencies(my Repository for example) and keep the default implementation of SignalR services.
I think it's hard to get Spring.Net working with SignalR
for the current version (Spring.Net 1.3.2) it's difficult to support asynchronous programming. Spring.Net session management doesn't play well with Task<T> types.
I ended up injecting my dependencies in 2 steps:
1- registering the required type on WebActivator PostStart:
GlobalHost.DependencyResolver.Register(
typeof(IUserService),
() => (UserService)ctx.GetObject("UserService"))
2- picking them up in my Hub constructor:
public MyHub()
{
_userService =
DependencyResolver.Current.GetService<IUserService>();
}

nservicebus saga property injection with ninject

I am using ninject when configuring NSB. Here is how I register:
public class EndpointConfig : IConfigureThisEndpoint, AsA_Publisher, IWantCustomInitialization
{
#region Implementation of IWantCustomInitialization
public void Init()
{
var kernel = new StandardKernel();
Configure.With().NinjectBuilder(kernel);
kernel.Load(new BackendModule());
}
#endregion
}
public class BackendModule : NinjectModule
{
#region Overrides of NinjectModule
/// <summary>
/// Loads the module into the kernel.
/// </summary>
public override void Load()
{
Bind<IEventBus>().To<NsbBus>();
Bind<IRecordStorageConfig>().To<RegistrationEventStorageConfig>();
Bind<IRecordStorage>().To<RegistrationRecordStorage>();
Bind<IRecordStorageFactory>().To<RegistrationRecordStorageFactory>();
Bind<IAggregateRootFactory>().To<RegistrationFactory>();
}
#endregion
}
I need the IAggregateRootFactory in the saga.
public class RegistrationSaga : Saga<RegistrationSagaData>,
IAmStartedByMessages<StartRegistration>,
IHandleMessages<CreateRegistration>,
IHandleMessages<ValidateRegistration>,
IHandleMessages<CancelRegistration>
{
public RegistrationFactory Factory { get; set; }
// removed implementation
}
The saga is started successfully and the commands are handlers are invoked. But the IAggregateRootFactory property injection is not working. The Factory is always null. Am I wiring this wrong?
I'm not quite sure why your saga needs to have RegistrationFactory/IAggregateRootFactory in it, but it probably isn't a good idea.

NinjectWebCommon Bindings in RegisterServices not working for me in WebApi

I create a new ASP.NET Web API project. I then use nuget to pull Ninject.Web.Common, then I download and build Ninject.Web.WebApi from here. Included it in the project. I added a service and the injection via constructor, setup binding (the debugger shows that the code actually hits the bind) but still throws this error:
Error activating IValueService
No matching bindings are available, and the type is not self-bindable.
Activation path:
2) Injection of dependency IValueService into parameter valueService of constructor of type ValuesController
1) Request for ValuesController
Suggestions:
1) Ensure that you have defined a binding for IValueService.
2) If the binding was defined in a module, ensure that the module has been loaded into the kernel.
3) Ensure you have not accidentally created more than one kernel.
4) If you are using constructor arguments, ensure that the parameter name matches the constructors parameter name.
5) If you are using automatic module loading, ensure the search path and filters are correct.
Libraries in my project:
Ninject.dll
Ninject.Web.Common
Ninject.Web.Webapi
WebActivator
All ninject libraries are marked as version 3.
Here is the Code:
[assembly: WebActivator.PreApplicationStartMethod(typeof(MvcApplication3.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(MvcApplication3.App_Start.NinjectWebCommon), "Stop")]
namespace MvcApplication3.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)
{
kernel.Bind<IValueService>().To<ValueService>();
}
}
}
service:
public interface IValueService
{
List<string> GetStrings();
}
public class ValueService : IValueService
{
public List<string> GetStrings()
{
return new List<string>{"test", "test"};
}
}
controller:
public class ValuesController : ApiController
{
private readonly IValueService valueService;
// GET /api/values
public ValuesController(IValueService valueService)
{
this.valueService = valueService;
}
}
The downloaded project sample from github works but not when I create a new project. Am I missing a step?
I just checked that there is no issue with this extension (at least not with the lastest MVC4 preview):
Create a new MVC4 WEB Api project
Nuget Install-Package Ninject.Web.WebAPI
Change controller + add bindings
Your code looks good. There must be a problem somewhere else.
Do not bind directly in RegisterServices but first create a class from
IDependencyResolver en add your bindings in AddBindings
example
See in book Pro ASP.NET MVC5 from Adam Freeman