I'm trying to use the new ASP.Net MVC 4 Web API project template with Ninject but have hit a wall on the following error:
Method 'GetFilters' in type 'Ninject.Web.WebApi.Filter.DefaultFilterProvider' from assembly 'Ninject.Web.WebApi, Version=3.0.0.0, Culture=neutral, PublicKeyToken=c7192dc5380945e7' does not have an implementation.
I am creating a brand new project in Visual Studio 2010 using the ASP.Net MVC 4 -> Web API template and I am using the latest Ninject NuGet packages:
Ninject 3.0.1.10
Ninject.Web.Common 3.0.0.7
Ninject.Web.WebApi 3.0.0.2
I have attempted the solution presented in this question however I've not had any luck - if I remove the reference to Ninject.Web.WebApi then MVC never engages Ninject. I also notice they mention Ninject.MVC3 however I am using the new Ninject.WebApi plugin.
I am using the default binding code in NinjectWebCommon.cs that is created during the NuGet install and attempting to register one simple service in RegisterServices()
[assembly: WebActivator.PreApplicationStartMethod(typeof(mkts.web.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(mkts.web.App_Start.NinjectWebCommon), "Stop")]
namespace mkts.web.App_Start
{
using System;
using System.Web;
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using Ninject;
using Ninject.Web.Common;
using mkts.service;
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)
{
//Test binding
kernel.Bind<IStudentService>().To<StudentService>();
}
}
}
My controller:
namespace mkts.web.Controllers
{
public class HomeController : Controller
{
private readonly IStudentService studentService;
public HomeController(IStudentService studentService)
{
this.studentService = studentService;
}
public ActionResult Index()
{
return View();
}
}
}
Many thanks in advance for any help with this.
Ninject.WebApi was written against the Beta and is deprecated now.
Remove that, install Ninject.MVC3.
Now you will need a homebrewed IDependencyResolver and IDependencyScope. I posted a walkthrough here - http://www.strathweb.com/2012/05/using-ninject-with-the-latest-asp-net-web-api-source/
Related
I am working on a project and using N-Layer architecture (web layer, service layer, data access layer).
I am facing an issue regarding the use of session storage in the data access layer.
I am storing data in the web layer (controller) and I want to use the session stored data in data access layer. Is this possible? If yes then please let me know...
Thanks in advance.
Shortly: this is possible.
Easy (and really bad) way is to reference web libraries in your data layer and use HttpContext.Current.Session. This will break all the flexibility you got before with your code structure when separating layers.
A bit longer (but much nicer way) is to install some IOC container. It will allow to declare some interfaces in data layer, and register session providers in the presentation layer.
I am going to show the workflow with Ninject. For example, you have some service (SomeService) in the data layer, that needs to operate on data from session. We can use abstractions since SomeService does not really care about origin of the data, it is not that important.
namespace DataLayer
{
public interface ISomeDataProvider
{
string GetData();
}
}
namespace DataLayer
{
public class SomeService
{
private readonly ISomeDataProvider someDataProvider;
public SomeService(ISomeDataProvider someDataProvider)
{
this.someDataProvider = someDataProvider;
}
public void DoThing()
{
var data = someDataProvider.GetData();
}
}
}
Lets move on to presentation layer. Now we should create implementation for our interface from data layer.
using DataLayer;
using System.Web;
namespace WebProject.App_Start
{
internal class SessionDataProvider : ISomeDataProvider
{
public string GetData()
{
return HttpContext.Current.Session["data"].ToString();
}
}
}
Finally, we need to configure dependency injection to use our implementation, whenever ISomeDataProvider is used in the constructor. There are plenty of articles about installing Ninject on the web, I recommend Ninject.MVC3 package. Once you install it, you will have NinjectWebCommon.cs look something similar to this.
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(WebProject.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethodAttribute(typeof(WebProject.App_Start.NinjectWebCommon), "Stop")]
namespace WebProject.App_Start
{
using System;
using System.Web;
using DataLayer;
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)
{
kernel.Bind<ISomeDataProvider>().To<SessionDataProvider>().InRequestScope();
}
}
}
What is the most important here is this line kernel.Bind<ISomeDataProvider>().To<SessionDataProvider>().InRequestScope();. It will configure SomeService to use SessionDataProvider in data layer without actually referencing all the web dlls in the data layer and bypassing circular dependency
Finally, inject your service in the controller`s constructor
using DataLayer;
using System.Web.Mvc;
namespace WebProject.Controllers
{
public class HomeController : Controller
{
private readonly SomeService someService;
public HomeController(SomeService someService)
{
this.someService = someService;
}
public ActionResult Index()
{
someService.DoThing();
return View();
}
}
}
I believe what you want to do here is implement a custom SessionStateStoreProvider.
https://learn.microsoft.com/en-us/dotnet/api/system.web.sessionstate.sessionstatestoreproviderbase?view=netframework-4.8
Then Session can be implemented as a data layer abstraction and easily shared in that layer.
SO I had a perfectly working WebApi service with Unity. I decided to take Nuget package update which overwrote the UnityConfig.cs, However, i added my code back and it works all fine when I try to run it from VisualStudio. Problem is when i deploy the bin and try to run the api from IIS. I get a 500, with following exception :
Exception.Source = System.Web.Http.Dispatcher.DefaultHttpControllerActivator
Exception.Message = An error occurred when trying to create a controller of type 'StateController'. Make sure that the controller has a parameterless public constructor.
/// <summary>
/// Specifies the Unity configuration for the main container.
/// </summary>
public static class UnityConfig
{
#region Unity Container
private static Lazy<IUnityContainer> container =
new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer();
RegisterTypes(container);
return container;
});
/// <summary>
/// Configured Unity Container.
/// </summary>
public static IUnityContainer Container => container.Value;
#endregion
public static void RegisterTypes(IUnityContainer container)
{
string dbConnectionString = WebConfigurationManager.ConnectionStrings["abc"].ConnectionString;
StateRepository stateRepository = new StateRepository(dbConnectionString);
// Register a default (un-named) type mapping with a singleton lifetime
container.RegisterInstance<IStateRepository>(stateRepository);
}
}
Hers is my UnityWebApiActivator.cs
using System.Web.Http;
using Unity.AspNet.WebApi;
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(PowerManagementServices.UnityWebApiActivator), nameof(PowerManagementServices.UnityWebApiActivator.Start))]
[assembly: WebActivatorEx.ApplicationShutdownMethod(typeof(PowerManagementServices.UnityWebApiActivator), nameof(PowerManagementServices.UnityWebApiActivator.Shutdown))]
namespace PowerManagementServices
{
/// <summary>
/// Provides the bootstrapping for integrating Unity with WebApi when it is hosted in ASP.NET.
/// </summary>
public static class UnityWebApiActivator
{
/// <summary>
/// Integrates Unity when the application starts.
/// </summary>
public static void Start()
{
// Use UnityHierarchicalDependencyResolver if you want to use
// a new child container for each IHttpController resolution.
// var resolver = new UnityHierarchicalDependencyResolver(UnityConfig.Container);
var resolver = new UnityDependencyResolver(UnityConfig.Container);
GlobalConfiguration.Configuration.DependencyResolver = resolver;
}
/// <summary>
/// Disposes the Unity container when the application is shut down.
/// </summary>
public static void Shutdown()
{
UnityConfig.Container.Dispose();
}
}
}
what is missing ? As I mentioned this service was working perfectly before I took the nuget update. Now it works from VS but not when deployed.
Thanks In Advance.
I've read every Stack Overflow question I can find but to no avail. When I installed the Ninject packages through NuGet, the NinjectWebCommon.cs class was not installed, so I coded up my own (below). I installed Ninject, Ninject.WebCommon, Ninject.Webcommon.Webhost, Ninject.WebApi, Ninject.WebApi.DependencyResolver. However, I am getting the well-known message in my controller that I must have a parameterless controller, which of course I don't want since I want to require DI.
Here's the Ninject class I created:
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);
System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver = new Ninject.WebApi.DependencyResolver.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.Load(Assembly.GetExecutingAssembly());
kernel.Bind<IUnitsSL>().To<UnitsSL>();
kernel.Bind<IForecastLogic>().To<ForecastLogic>();
kernel.Bind<IForecastRepositoryAsync>().To<ForecastRepositoryAsync>();
}
}
Here is the controller
namespace ForecastApi.Controllers
{
public class ForecastController : ApiController
{
private IUnitsSL _serviceLayer { get; set; }
private readonly IForecastLogic _forecastLogic;
public ForecastController(IForecastLogic forecastLogic)
{
_forecastLogic = forecastLogic;
_serviceLayer = new UnitsSL();
}
[Route("projection")]
[HttpPost]
public async Task<IHttpActionResult> GetDemandForecast([FromBody]
ProjectionRequestModel model)
{
var retVal = await _forecastLogic.GetDemandForecastData(model);
return Ok(retVal);
}
}
The exact wording of the error message when I test this through Postman is: An error occurred when trying to create a controller of type 'ForecastController'. Make sure that the controller has a parameterless public constructor."
If it helps, I am mocking my unit tests for the business calls and they are working with the Ninject library and Moq. It is the constructor that seems to fail.
TIA
For whatever reason, uninstalling Ninject entirely and reinstalling it (this is version 3.3) solved the problem. Leaving this here in the event that anyone else has a similar issue. I had originally installed
Ninject
Ninject.Web.Common
Ninject.Web.Common.WebHost
Ninject.Web.WebApi
Ninject.Web.WebApi.WebHost
When I uninstalled all of these packages, then re-installed them v3.3 again, the NinjectWebCommon.cs file was added and all worked ok. I can only assume that there was something missing when I rolled my own common file to make up for Ninject not installing it the first go around.
I have an ASP.NET MVC application, which serving http pages and provides REST API using Web API.
I have a "service" class, which supposed to be a singleton and to be used both in ASP.NET MVC and Web API parts.
For dependency injection, I using Unity. I installed from NuGet Unity, Unity.AspNet.Mvc and Unity.AspNet.WebApi packages.
I registering my service as singleton:
container.RegisterType<IService, ServiceImp>(new ContainerControlledLifetimeManager());
What I see is that different instances of "ServiceImp" created for ASP.NET MVC and for Web API. The constructor called twice. It looks like there are two separate containers there...
All contents of UnityConfig.cs, UnityMvcActivator.cs and UnityWebApiActivator.cs remained unchanged as initial template, except the place where I register my services.
Any idea how to solve this issue? What I doing wrong?
UnityConfig.cs
namespace Management.App_Start
{
/// <summary>
/// Specifies the Unity configuration for the main container.
/// </summary>
public class UnityConfig
{
#region Unity Container
private static 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)
{
container.RegisterType<IService, ServiceImp>(new ContainerControlledLifetimeManager());
}
}
}
UnityMvcActivator.cs
using System.Linq;
using System.Web.Mvc;
using Microsoft.Practices.Unity.Mvc;
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(Management.App_Start.UnityWebActivator), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethod(typeof(Management.App_Start.UnityWebActivator), "Shutdown")]
namespace Management.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));
// TODO: Uncomment if you want to use PerRequestLifetimeManager
// Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));
}
/// <summary>Disposes the Unity container when the application is shut down.</summary>
public static void Shutdown()
{
var container = UnityConfig.GetConfiguredContainer();
container.Dispose();
}
}
}
UnityWebApiActivator.cs
using System.Web.Http;
using Microsoft.Practices.Unity.WebApi;
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(Management.App_Start.UnityWebApiActivator), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethod(typeof(Management.App_Start.UnityWebApiActivator), "Shutdown")]
namespace Management.App_Start
{
/// <summary>Provides the bootstrapping for integrating Unity with WebApi when it is hosted in ASP.NET</summary>
public static class UnityWebApiActivator
{
/// <summary>Integrates Unity when the application starts.</summary>
public static void Start()
{
// Use UnityHierarchicalDependencyResolver if you want to use a new child container for each IHttpController resolution.
// var resolver = new UnityHierarchicalDependencyResolver(UnityConfig.GetConfiguredContainer());
var resolver = new UnityDependencyResolver(UnityConfig.GetConfiguredContainer());
GlobalConfiguration.Configuration.DependencyResolver = resolver;
}
/// <summary>Disposes the Unity container when the application is shut down.</summary>
public static void Shutdown()
{
var container = UnityConfig.GetConfiguredContainer();
container.Dispose();
}
}
}
UPDATE 9.9.17
After some digging, I see that Application_Start called twice - first time when any http page requested and second time when REST API called. As a result, everything initialized twice, including Unity. Now I need to find out why this happens...
I'm using NinjectWebCommon to perform the injections in my controllers. I installed the package via Nuget and he created the NinjectWebCommon.cs in my App_Start as it says in the own documentation. I need to know why it does not work as it should, because I follow the documentation step by step. Follows some snippets:
NinjectWebCommon.cs:
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)
{
//kernel.Load(AppDomain.CurrentDomain.GetAssemblies());
kernel.Bind<IFooService>().To<FooService>();
}
}
Controller:
public class FooController : Controller
{
private readonly IFooService fooService;
public FooController(IFooService fooService)
{
this.fooService = fooService;
}
public ActionResult Index()
{
return View(this.fooService.All());
}
}
This generates this error:
Error activating IFooService No matching bindings are available, and
the type is not self-bindable. Activation path:
2) Injection of
dependency IFooService into parameter fooService of constructor of
type FooController
1) Request for FooController
Suggestions:
1) Ensure that you have defined a binding for
IFooService.
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.
Use IoC to resolve instances, but it works only in my HomeController, if I change to another controller using EXACTLY the same code (with the IoC), it generates the error again. Follows the code using the IoC.
using IoC:
private readonly IFooService fooService;
public HomeController()
{
this.fooService = IoC.Instance.Resolve<IFooService>();
}
public ActionResult Index()
{
ViewBag.MyFoos = this.fooService.All();
return View();
}
generates this error:
No matching bindings are available, and the type is not self-bindable.
Error activating IFooService
No matching bindings are available,
and the type is not self-bindable.
Activation path:
1) Request for IFooService
Suggestions:
1) Ensure
that you have defined a binding for IFooService.
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.
Are you sure you have a binding for ISetorService? I don't see one in the code you've posted.
I solved the problem by loading all "NinjectModule" of my application hierarchy.
I thought it was sufficient loading only the main module, then created another statico method within the "NinjectWebCommon" just to separate responsibilities and organizing the code. Below is the code used:
var kernel = new StandardKernel(new Repository(), new Service(), new ValidationAndBusinessRules());
which carry all their Repositories, Services and Validators in creating the Kernel.
private static void RegisterObrigatoryServices(IKernel kernel)
{
kernel.Bind<IIdentityProvider>().To<ServiceIdentityProvider>();
kernel.Bind<Guid>().ToMethod(ctx => default(Guid)).Named("CurrentProcessId");
kernel.Bind<ISession>().ToMethod(ctx =>
{
SessionPoolManager.Update();
Guid processId = kernel.Get<Guid>("CurrentProcessId", new Parameter[] { });
if (processId == default(Guid))
{
return SessionFactoryBuilder.SessionFactory(kernel.Get<IIdentityProvider>()).OpenSession();
}
else
{
ISession session = SessionPoolManager.Get(processId);
if (session == null)
{
session = SessionFactoryBuilder.SessionFactory(kernel.Get<IIdentityProvider>()).OpenSession();
SessionPoolManager.Register(processId, session);
}
return session;
}
});
}
method created by me within the NinjectWebCommon as mentioned above, only to record the required dependencies.
All this code is basically native and has been inserted into the Nuget Ninject.MVC4 package (installed via Package Manager Console within Visual Studio). This package inserts a class in App_Start directory called "NinjectWebCommon," and it is that I made these changes.
the controler is set to send the package documentation, as follows:
public class HomeController : Controller
{
private readonly IFooService fooService;
public HomeController(IFooService fooService)
{
this.fooService = fooService; //Daqui para frente é possível usar normalmente o service.
}
}