I have a .Net MVC 3.0 application and I'm using Ninject 3.0. I didn't install any nuget. I'm referencing Ninject.dll, Ninject.Web.Common.dll and Ninject.Web.Mvc.dll (and 2 others). I want to have dependencies injected in a custom HttpModule and I can't figure out how to make it work with a NinjectHttpApplication.
I have this error:
Error activating IntPtr
No matching bindings are available, and the type is not self-bindable.
Activation path:
3) Injection of dependency IntPtr into parameter method of constructor of type Func{IKernel}
2) Injection of dependency Func{IKernel} into parameter lazyKernel of constructor of type HttpApplicationInitializationHttpModule
1) Request for IHttpModule
Here is the code:
Global.asax
public class MvcApplication: NinjectHttpApplication
{
...
protected override void OnApplicationStarted()
{
base.OnApplicationStarted();
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
protected override IKernel CreateKernel()
{
var modules = new INinjectModule[]
{
new ServiceModule()
};
IKernel kernel = new StandardKernel(modules);
return kernel;
}
}
Web.Config
<httpModules>
<add name="NinjectHttpModule" type="Ninject.Web.Common.NinjectHttpModule"/>
</httpModules>
CustomHttpModule.cs
public class CustomHttpModule : IHttpModule
{
private ITesttService service;
public CustomHttpModule(ITesttService service)
{
this.service = service;
}
...
}
ServiceModule.cs
public class ServiceModule : NinjectModule
{
public override void Load()
{
...
Kernel.Bind<ITestService>().To<TestService>();
Kernel.Bind<IHttpModule>().To<CustomHttpModule>().InSingletonScope();
}
}
This binding solves my problem:
kernel.Bind<Func<IKernel>>().ToMethod(c => () => this.Kernel);
But according to this post on github, I'm not supposed to do it.
Can you someone tell me what I'm doing wrong or missing?
Currently there is no good way to use the NinjectHttpModule when deriving from NinjectHttpApplication. The bootstrapper registers the HttpApplicationInitializationHttpModule for both ways and as soon as the NinjectHttpModule is loaded this module is loaded as well.
Unfortunately there is no good point where you can unload it.
I suggest you use the WebActivator instead on deriving from NinjectHttpApplication. It's the only proper way to get it running. You don't necessarily have to use nuget to setup your application that way. You can also add the same files manually and manually reference all required assemblies.
Related
I have the following class, which is compiled into a DLL called ExternalTask.dll and is housed externally in my filing system
public class ExampleJob : IJob
{
public void Execute(IJobExecutionContext context)
{
Console.WriteLine("ExampleJob is executing. {0}", System.DateTime.Now.ToUniversalTime());
}
}
I have placed the dll in the following directory : C:\External
I am attempting to use ninject to search the directoru and setup the bindings.
The following binding works if the class work in the same assembly as my main coded, but I want the dll to be separated off.
kernel.Bind<IJobSetup>().To<JobSetup<ExampleJob>>();
Does anyone know the correct binging to setup using the ninject conventions? I am currently trying this, but know I need more - I just cannot find much decent documentation to help.
kernel.Bind(scanner => scanner
.FromAssembliesInPath(
#"C:\External\")
.SelectAllClasses()
.BindAllInterfaces());
If your project is going to get bigger use Ninject Conventions:
public class ProjectRepository : IProjectRepository
{
....
}
and set binding as a module:
using Ninject.Extensions.Conventions;
public class RepositoryModule : NinjectModule
{
public override void Load()
{
IKernel ninjectKernel = this.Kernel;
ninjectKernel.Scan(kernel =>
{
kernel.FromAssemblyContaining<ProjectRepository>();
kernel.BindWithDefaultConventions();
kernel.AutoLoadModules();
kernel.InRequestScope();
});
}
}
then load it:
IKernel kernel = new StandardKernel(new RepositoryModule());
I have an asp.net MVC 4.5 application with Castle.Windsor 3.2.2 as DI and I'm trying to add FluentValidation version 5.0.0.1 for the first time.
I created the factory inheriting from ValidatorFactoryBase
public class WindsorFluentValidatorFactory : ValidatorFactoryBase
{
private readonly IKernel _kernel;
public WindsorFluentValidatorFactory(IKernel kernel)
{
_kernel = kernel;
}
public override IValidator CreateInstance(Type validatorType)
{
return _kernel.HasComponent(validatorType)
? _kernel.Resolve<IValidator>(validatorType)
: null;
}
}
Also created the installer for Castle:
public class FluentValidatorsInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Classes
.FromThisAssembly()
.BasedOn(typeof(IValidator<>))
.WithService
.Base());
}
}
Now, in the Global.asax, I tried (following documentation on web) to hook things like this:
var fluentValidationModelValidatorProvider = new FluentValidationModelValidatorProvider(new WindsorFluentValidatorFactory(container.Kernel));
ModelValidatorProviders.Providers.Add(fluentValidationModelValidatorProvider);
However, the second line gives the following error:
"The best overloaded method match for
'System.Collections.ObjectModel.Collection.Add(System.Web.Mvc.ModelValidatorProvider)'
has some invalid arguments Argument 1: cannot convert from
'FluentValidation.Mvc.WebApi.FluentValidationModelValidatorProvider'
to 'System.Web.Mvc.ModelValidatorProvider'"
So, it seems that this way of doing it is not working on the versions I use.
I also tried to hook this using the Configure method doing this:
FluentValidationModelValidatorProvider.Configure(x => x.ValidatorFactory = new WindsorFluentValidatorFactory(container.Kernel));
However, it's not working. Debugging I checked at ModelValidatorProviders.Providers and there is no new provider being add with the Configure method.
Any ideas on what I might be doing wrong?
Thanks,
Andres
Solved
I got a solution in another forum but I'll post the answer it's useful for someone else.
I was using the wrong Provider
There are two providers - one for MVC and one for WebApi. It seems that I was using the WebAPI one.
Changed it to FluentValidation.Mvc.FluentValidationModelValidatorProvide and the problem was solved
I am new to ASP.NET MVC 4. I have used a custom dependency resolver in my ASP.NET MVC 4 project in order to use Dependency injection framework.
What is the role of dependency resolver in ASP.NET MVC 4 ?
It allows you to abstract away from Dependency Injection implementation. Later if you decide to switch from Unity to Windsor, you can do it much easier without having to re-write lots of code
It means that you can resolve your instances using this code
DependencyResolver.Current.GetService<IMyController>();
I use a different approach using Ninject
Using NuGet I downloaded Ninject(just it without any special modification for MVC). So you will have Ninject in references.
Now I create a custom controller factory class (class derived from DefaultControllerFactory).My goal is to make MVC use my controller factory when it tries to create a controller object.
public class NinjectControllerFactory : DefaultControllerFactory
{
#region Member Variables
private IKernel ninjectKernel = null;
#endregion
public NinjectControllerFactory(IKernel kernel)
{
this.ninjectKernel = kernel;
AddBindings();
}
private void AddBindings()
{
//BO
ninjectKernel.Bind<IAuthenticationBO>().To<AuthenticationBO>();
//DAO
ninjectKernel.Bind<ISharedDAO>().To<SharedDAO>();
}
protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
{
return controllerType == null ? null : (IController)ninjectKernel.Get(controllerType);
}
}
Make MVC to use my custom controller factory. In Global.asax in Application_Start()
public class MvcApplication : System.Web.HttpApplication
{
private IKernel kernel = new StandardKernel();
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
//register a cutom controller factory
ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory(kernel));
}
}
So now when MVC creates controller objects it uses our custom controller factory and as you saw it resolves all dependencies using Ninject.
For example
public class MainController : Controller
{
#region Member Variables
private IAuthenticationBO authentication = null;
#endregion
public MainController(IAuthenticationBO authentication)
{
this.authentication = authentication;
}
}
Ninject injects the implementation of IAuthenticationBO (in our case AuthenticationBO) and we can use it. Also it's very easy to use mocking and TDD, but it's beyond the scope of the question.
I am attempting to do some basic constructor DI with Simple Injector, and it seems that it is unable to resolve the dependencies for Web API controllers.
I have an API controller in an "API" folder, that is outside the "Controllers" folder.
I have also tried placing it within the "Controllers" folder, but
that did not seem to make much of a difference. The stack trace that
I receive is similar to the one presented in this question.
I am using a fresh install of the "Simple Injector MVC Integration Quick Start" NuGet Package (v. 2.1.0).
I have the base SimpleInjectorWebApiDependencyResolver from the documentation, which is also the same as found here.
I am using Entity Framework, and have looked at the discussion
thread about changes to correctly load the context.
This does not
seem to be a problem, but I still receive the following error:
Type 'MyProject.API.ArticleController' does not have a default
constructor
System.ArgumentException at
System.Linq.Expressions.Expression.New(Type type) at
System.Web.Http.Internal.TypeActivator.Create[TBase](Type
instanceType) at
System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage
request, Type controllerType, Func`1& activator) at
System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage
request, HttpControllerDescriptor controllerDescriptor, Type
controllerType)
It would be appreciated if someone could offer me some suggestions, on whether anything should be modified from its current state/call order.
ArticleController (basic structure):
public class ArticleController : ApiController
{
private readonly IArticleRepository articleRepository;
private readonly IUserRepository userRepository;
private readonly IReleaseRepository releaseRepository;
public ArticleController(IArticleRepository articleRepository, IUserRepository userRepository, IReleaseRepository releaseRepository)
{
this.articleRepository = articleRepository;
this.userRepository = userRepository;
this.releaseRepository = releaseRepository;
}
// GET api/Article
public IEnumerable<Article> GetArticles(){ // code }
// GET api/Article/5
public Article GetArticle(int id){ // code }
// PUT api/Article/5
public HttpResponseMessage PutArticle(int id, Article article){ // code }
// POST api/Article
public HttpResponseMessage PostArticle(ArticleModel article){ // code }
// DELETE api/Article/5
public HttpResponseMessage DeleteArticle(int id){ // code }
}
SimpleInjectorInitializer:
public static class SimpleInjectorInitializer
{
public static void Initialize()
{
var container = new Container();
InitializeContainer(container);
container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
container.RegisterMvcAttributeFilterProvider();
container.Verify();
DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
}
private static void InitializeContainer(Container container)
{
container.Register<IArticleRepository, ArticleRepository>();
container.Register<IUserRepository, UserRepository>();
container.Register<IReleaseRepository, ReleaseRepository>();
}
}
Global.asax.cs:
public class WebApiApplication : System.Web.HttpApplication
{
private void ConfigureApi()
{
// Create the container as usual.
var container = new Container();
// Verify the container configuration
// container.Verify();
// Register the dependency resolver.
GlobalConfiguration.Configuration.DependencyResolver =
new SimpleInjectorWebApiDependencyResolver(container);
}
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
ConfigureApi();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
TLTR: the problem is caused by the implicit way Web API handles resolving controller types; register your Web API controllers explicitly and you'll see where the problem is.
Here is a step by step what is happening under the covers:
The System.Web.Http.DefaultHttpControllerActivator calls into the SimpleInjectorWebApiDependencyResolver and requests the creation of an API controller.
SimpleInjectorWebApiDependencyResolver forwards that call to the SimpleInjector.Container instance.
That Container instance however, does not have any explicit registrations for that API Controller (since you supplied an empty container to the resolver).
Since there is no explicit registration, the container tries to do a last minute registration for that type.
That Controller type however depends on interfaces that can't be resolved because they are not registered in the container (remember, your container is empty).
Although the container would normally throw an exception, null is returned in this case, because the type is requested through the IServiceProvider.GetService method and the type was not registered explictly.
The SimpleInjectorWebApiDependencyResolver's GetService method will return null as well, since it's by definition that it should return null; It should return null when no registration exists (which currently is the case).
Since the DependencyResolver returned null, DefaultHttpControllerActivator will fall back to its default behavior, which means creating that type itself, but this requires the controller to have a default constructor.
Long story short, the problem is caused by the implicit way Web API handles resolving controller types.
So the solution here is to:
Have only one single Container in your web application. This prevents all sorts of trouble and complication of your configuration.
Register all Web API Controllers explicitly in the container. Registering controllers explicitly will ensure that Simple Injector will throw an exception when a controller can't be resolved. Besides, this allows you to call container.Verify() which will make the application fail during startup when the configuration is invalid (a verifiable configuration is important). And this also allows you to diagnose the configuration which gives you even more confidence about the correctness of your configuration.
My advice is to place MVC and Web API in their own project. This will make things much easier.
Registering all Web API controllers can be done with the following code:
container.RegisterWebApiControllers(GlobalConfiguration.Configuration);
UPDATE:
Because this error is so common, newer versions of the SimpleInjectorWebApiDependencyResolver class will simply never return null when a controller type is requested. Instead it will throw a descriptive error. Because of this you should never see error anymore, as long as you use the official SimpleInjectorWebApiDependencyResolver.
Following setups work for me:
1) include Unity.WebAPI from https://www.nuget.org/packages/Unity.WebAPI/
2) in UnityConfig
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
// **** Important note -----
// register all your components with the container here
// e.g. container.RegisterType<ITestService, TestService>();
DependencyResolver.SetResolver(new Unity.Mvc5.UnityDependencyResolver(container));
GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
}
}
3) in Global.asax file
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
UnityConfig.RegisterComponents();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
Getting started with Unity.WebAPI
To get started, just add a call to UnityConfig.RegisterComponents() in the Application_Start method of Global.asax.cs
and the Web API framework will then use the Unity.WebAPI DependencyResolver to resolve your components.
e.g.
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
UnityConfig.RegisterComponents(); // <----- Add this line
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
Add your Unity registrations in the RegisterComponents method of the UnityConfig class. All components that implement IDisposable should be
registered with the HierarchicalLifetimeManager to ensure that they are properly disposed at the end of the request.
I have an ELMAH custom ErrorLog that uses an EF Code-First context to store the errors:-
class EntityFrameworkElmahErrorLog
{
public EntityFrameworkElmahErrorLog(IDictionary config) : this() { }
public override ErrorLogEntry GetError(string id)
{
using (var context = new MyContext())
{
var intId = Int64.Parse(id, CultureInfo.InvariantCulture);
var item = context.ErrorLog.Single(x => x.Id == intId);
return new ErrorLogEntry(this, id, ErrorXml.DecodeString(item.Details));
}
}
// etc.
}
The ErrorLog is wired up in the web.config:-
<errorLog type="MyProject.EntityFrameworkErrorLog, MyProject" />
I'm already using Ninject elsewhere in the project. I'd like to inject MyContext so that the ErrorLog isn't instantiating its own dependency, but I'm not having any luck finding a hook in the documentation. ELMAH appears to be instantiating the ErrorLog internally, so the only option I seem to have is using a ServiceLocator inside my custom ErrorLog, which I'd like to avoid if possible.
Are there any better hooks available in ELMAH that I can use to inject ?
The Service location/Depdency injection extension point in ELMAH is the ServiceCenter.Current property where you can provide a delegate with the following signature:
public delegate IServiceProvider ServiceProviderQueryHandler(object context);
ELMAH will use the System.IServiceProvider returned by the ServiceCenter.Current to resolve the ErrorLog isntances.
So you need to do 3 things to setup it with Ninject (or any DI container)
Create your own System.IServiceProvider implementation with Ninject the IKernel interface already derives from from System.IServiceProvider, so it's done.
You need to register your EntityFrameworkElmahErrorLog in your container as an ErrorLog implemenation, because ELMAH will try to resolve an instance of ErrorLog.
Provide your delegate to ServiceCenter.Current
So you need something like the following in your RegisterServices method:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<ErrorLog>().To<EntityFrameworkElmahErrorLog>();
ServiceCenter.Current = (httpContext) => kernel;
}
Note: in in the ServiceProviderQueryHandler delegate you get the current HttpContext and with that you can fine tune how your expediencies are resolved.
You should also note that with this approach you will lose the ability to configure your ErrorLog in your config file.
ELMAH will always use the resolved instance from your container, because the built in ServiceContainer reads the config file what you override with your custom logic.