I'm working on a MVC5 application and i'm trying to implement DI on my controller class. I have correctly put binding on Ninjectwebcommons. Still constructor of the controller class is receiving just null implementations.
public class AdServiceController : Controller
{
private IClientRequestPackage _clientReqPkg;
private ISearchAd _searchAd;
private ICreateConnection _createConnection;
private INewConnectionResult _newConnectionResult;
private IBuildDataObjects _buildDataObjects;
private IAdSearchResultObj _adSearchResultObj;
public AdServiceController (ICreateConnection createConnection)
{
_createConnection = createConnection;
}
This createConnection implementation has a dependency on Iconfigparams. I'm seeing Iconfigparams is just null.
Any help pl.
Chanu
Related
The way dependency injection works is very mysterious to me. In this simple example:
public class LeagueController : BaseController
{
private readonly IDocumentSession documentSession;
public LeagueController(IDocumentSession documentSession) //where is this parameter coming from?
{
this.documentSession = documentSession;
}
What I don't get is where the initialized parameter is coming from to initialize this.documentSession? If I wanted to initialise another class in the constructor how would I do it?
In the MVC project im working I use Fluent Validation to implement some validation logics and I defined my UnityValidatorFactory as following:
public class UnityValidatorFactory : ValidatorFactoryBase
{
private readonly IUnityContainer _container;
public UnityValidatorFactory(IUnityContainer container)
{
_container = container;
}
public override IValidator CreateInstance(Type validatorType)
{
if (_container.IsRegistered(validatorType))
{
return _container.Resolve(validatorType) as IValidator;
}
return null;
}
}
In global.asax i register my class like this:
var validationFactory = new UnityValidatorFactory(container);
var fluentValidationModelValidatorProvider = new FluentValidationModelValidatorProvider(validationFactory);
I defined my validator for my viewmodel:
public class ServiceRequestViewModelValidator : AbstractValidator<ServiceRequestViewModel>
{
public ServiceRequestViewModelValidator()
{
// many validation rules here...
}
}
I register my validator in unity:
container.RegisterType<IValidator<ServiceRequestViewModel>, ServiceRequestViewModelValidator>();
When i post data to the action with argument of type ServiceRequestViewModel the method CreateInstance is called so many times and the
constructor of ServiceRequestViewModelValidator as well.
Because the validatin rules I implemented are time consuming I don't wont they get executed more then one time. Moreover I don't understand why they are call more than one time.
I later found out that this is how MVC works. In MVC there are many place where MVC needs to get the validator for example it tries to get metadata for each property, and calls into the provider for each one.
Then to fix my problem I created my validators as singleton instances registering the validator in unity with ContainerControlledLifetimeManager
container.RegisterType<IValidator<ServiceRequestViewModel>, ServiceRequestViewModelValidator>(new ContainerControlledLifetimeManager());
I am trying to access an object created by ninject within my layout view but I have no idea how to access them.
Here is a brief outline of what I have tried so far:-
Created by service and bound them:
public interface IService
{
void SomeMethod();
}
public class Service : IService
{
public void SomeMethod
{
}
}
Bind<IService>().To<Service>();
Created a static class and use the [Inject] attribute:
public static class MasterLayout
{
[Inject]
public static IService Service { private get; set; }
public static void CallSomeMethod();
{
Service.SomeMethod
}
}
Everytime I call MasterLayout.CallSomeMethod() from my master view or partial view, the Service field is always null.
Is this even possible or should I be creating a base Controller and getting other controllers to inherit from it where I can set those values to be used within the master view and partial views? Is there an even better way of achieving this?
Does Ninject work if used with contructor injection?
( see http://ninject.codeplex.com/wikipage?title=Injection%20Patterns )
Something like
IUnitOfWork UnitOfWork;
public AccountController(IUnitOfWork unitOfWork)
{
this.UnitOfWork = unitOfWork;
}
Have you checked here?
bind to property always return null
When you say "on every page", you mean "on every controller"?
If yes, i think you could create a BaseController class, and all the controllers should inherit from it. I'm using this method.
You have to create a custom controller factory to have Ninject create the controllers. Once you do, this will work. There is also probably an extension for this already.
I've successfully implemented Ninject in an MVC3 application, but am running into some trouble doing the same thing with ASP.NET Web Forms. I'm getting null references every time I try to access an injected property in my business layer. After setting breakpoints within the CreateKernel method, as well as several places within the ServiceLocator class, it looks like none of them are ever getting hit, so it's not even loading.
I'm sure I'm just approaching this wrong, but there is very little documentation or info out there for wiring up Ninject in a Web Forms application.
Basically here's what I have so far:
code behind
public class ReviewManager
{
[Inject] private IReviewRepository _reviewRepository { get; set; }
public ReviewManager() { }
public ReviewManager(IReviewRepository reviewRepository)
{
_reviewRepository = reviewRepository;
}
public Review GetById(int id)
{
if (id <= 0) throw new ArgumentException("ID must be greater than zero");
**I get a null reference exception on the next line. _reviewRepository is null**
return _reviewRepository.GetById(id);
}
}
global.asax.cs
public class Global : NinjectHttpApplication
{
protected override IKernel CreateKernel()
{
return ServiceLocator.Kernel;
}
// deleted for brevity
}
ServiceLocator.cs (edited for brevity, the relevant parts are here)
public static class ServiceLocator
{
public static IKernel Kernel { get; set; }
public static ILogger Logger { get; set; }
static ServiceLocator()
{
Kernel = new StandardKernel(new INinjectModule[] {
new LoggerBindings(),
new DataBindings()
});
if (Logger == null)
Logger = Kernel.Get<ILogger>();
}
}
public class LoggerBindings : NinjectModule
{
public override void Load()
{
Bind<ILogger>().To<NLogLogger>();
}
}
public class DataBindings : NinjectModule
{
public override void Load()
{
Bind<IReviewRepository>().To<ReviewRepository>();
}
}
ASP.Net via WebForms does not allow you to manage the lifecycle of all object instances (like MVC does). For example, the framework instantiates page objects. This means you probably can't implement DI in quite the same way as you would in MVC/WPF/Silverlight (the same problem is present in WinForms IIRC). You will likely have to initiate the dependency graph directly in each of your code behinds.
Translation: you will want to call ServiceLocator.Kernel.Get<IReviewRepository> when your page loads (or as lazy-init on the property).
The cool thing about MVC ist that it can run side a side of ASP.NET WebForm pages in the same application. In my opinion the best way to extend ASP.NET WebForms websites is to create new pages using MVC3 and to refactor every page that needs major changes to MVC3.
If this is no option go and use the Ninject.Web extension. It contains a IHttpModule that property injects all web pages and controlls after they are initialized. That way you can property inject the services als have them created by Ninject.
A potential workaround, by changing your DataBindings class as follows:
public class DataBindings : NinjectModule
{
public override void Load()
{
Bind<IReviewRepository>().To<ReviewRepository>();
Bind<ReviewManager>().ToSelf();
}
}
And within your caller, instead of
var rm = new ReviewManager();
Try using
var rm = ServiceLocator.Kernel.Get<ReviewManager>();
I havent tested this code, but i think it'll solve your null reference problem.
I use property injection for pages, masterpages and usercontrols. All my pages, for example, inherit from a base class that overrides RequestActivation method with the following code:
''' <summary>
''' Asks the kernel to inject this instance.
''' </summary>
Protected Overridable Sub RequestActivation()
ServiceLocator.Kernel.Inject(Me)
End Sub
And in each page I declare injectable properties:
<Inject()>
Property repo As IMyRepository
Can anyone see what I'm doing wrong here? I'm trying to learn how to have specs/ services and domain projects in general but in this case it's ASP.NET MVC.
I have the following code in my controller but I getting Object reference not set to an instance of an object on the following line of code. I would appreciate any suggestions where I'm going wrong!?
// Error
Line 22: var profiles = _profileService.GetProfile();
// code below
namespace Whitepages.Controllers
{
[HandleError]
public class HomeController : Controller
{
private readonly IProfileService _profileService;
public HomeController(IProfileService profileService)
{
_profileService = profileService;
}
public HomeController()
{
}
public ActionResult Index()
{
var profiles = _profileService.GetProfile();
return View("Index");
}
}
}
using Domain;
namespace Services.Spec
{
public interface IProfileService
{
Profile GetProfile();
}
}
Many thanks,
It looks like the controller factory you are using to build your controllers passes null at the constructor of HomeController. In ASP.NET MVC controllers are built by a controller factory which by default is the DefaultControllerFactory class which simply invokes the default constructor.
The fact that you are getting a NullReferenceException instead of the class HomeController doesn't have a default constructor indicates that you have setup a custom controller factory in your Global.asax which is supposed to provide instances of your controllers but this custom controller factory doesn't passes null to the HomeController constructor, so when later you try to access this service _profileService.GetProfile() you get the exception. You are probably using some dependency injection framework and in your Application_Start you have something like this:
ControllerBuilder.Current.SetControllerFactory(new SomeCustomControllerFactory());
So if you are using a DI framework you need to setup this framework to pass a specific implementation of the IProfileService interface to the constructor. How this is done would totally depend on the framework you are using.