How should I use ninject in a multiproject mvc app? - asp.net-mvc

My app is set up this way
Web
Data
Services
POCO Entities
Controllers use services (so they should be injected)
Services use Repositories (which I assume should also be injected)
I have this already set up so that the Controllers receive the service they need through Ninject but I not sure how to get this done with the services =>repositories
any help with this?

You could use the ninject.web.mvc extension. It contains a sample application which illustrates how you could register the container in Global.asax.

Bob has several blogs about repository pattern with Ninject and NHibernate. It's pretty much the same for all other OR Mappers:
http://blog.bobcravens.com/2010/06/the-repository-pattern-with-linq-to-fluent-nhibernate-and-mysql/
http://blog.bobcravens.com/2010/07/using-nhibernate-in-asp-net-mvc/
http://blog.bobcravens.com/2010/09/the-repository-pattern-part-2/

Simply set up your services' dependencies as well as the controller's dependencies. Ninject will walk the dependency chain and resolve all of them.
for example,
ProductController has dependency on IProductService
IProductService is implemented with ProductService that has a dependency on IProductRepository
IProductRepository is implemented with NHibernateProductRepository that has a dependency on ISession.
when your NinjectControllerFactory attempts to resolve ProductController, it sees the dependency on IProductService. it resolves that dependency as ProductService, and sees that it has a dependency on IProductRepository. and it will continue on down the chain until it can resolve completely an argument.
so the important part is to Bind ANY dependencies, not just those in a Controller.

Related

ServiceStack: container.AutoWire(this) gives a NullReferenceException

If I in my AppHostBase descendant (web api project ) use container.AutoWire(this), it will result in a NullReferenceException in the ServiceStack code, if I am using a web project, thus starting it with the CreateHostBuilder(args).Build().Run(); in the main method.
The error is reproduced in this Github project: https://github.com/tedekeroth/ServiceStackAutoWireTest
The error occurs in AppHostBase.Netcore.Cs, line 158:
If I remove the container.AutoWire(this); in TestAppHost.cs, the error goes away, but then the dependency injection does not work, meaning the Logger in TestAppHostproperty is not assigned:
I am not sure why this happens or what I can do about it. I'd appreciate some input, thanks.
Setup
Visual Studio 2019
Target framework: .NET 5.0 (Console Application)
Project SDK: Microsoft.NET.Sdk.Web
ServiceStack 5.11.0
The IOC AutoWire API attempts to autowire all public property dependencies of an object which is definitely something you should never attempt to do with the AppHost which encapsulates the configuration and behavior of your ServiceStack App where indiscriminatingly overriding every public property is going to leave it in a corrupted state.
Registering your AppHost in the IOC shouldn't be necessary as it's available everywhere via the HostContext.AppHost singleton. It's also a bad idea trying to reference any type defined in your Host Project, (the AppHost being the canonical example) since it creates a circular reference to your Host project in your App logic dependencies which shouldn't have any references back to its Host project, your Host project is supposed to reference all your projects .dll's, configure your App's and all its dependencies, not the other way around.
Should you need access to any Plugins it's recommended to use the GetPlugin<T>() API in your Service for optional plugins or AssertPlugin<T>() for required plugins. If you need to resolve any deps manually you can use TryResolve<T>() API in your Service class. For any of your App's custom config I'd recommend registering them in a custom AppConfig class for your Services to access like any other dependencies.
Otherwise if you really need access to the AppHost you can use the HostContext.AppHost singleton. If you absolutely need to have the AppHost in the IOC, just register it as a normal singleton, i.e. don't try to autowire it:
container.Register<IAppHost>(c => this);
However as mentioned earlier I'd strongly advise against it, have everything your App needs in a custom class (e.g. AppConfig) that is accessed like a normal dependency.

How to resolve Dependency within Dependency

I have 4 Projects in a solution
DAL_Project
BLL_Project
Interface_Project
WebApi_Project
Interface_Project has two interfaces ICar_DAL and ICar_BLL
DAL_Project has a class Car_DAL that implements ICar_DAL
BLL_Project has a class Car_BLL that implements ICar_BLL and its constructor takes in ICar_DAL
WebApi_Project has an api controller CarApiController and its constructor takes in ICar_BLL
the dependency resolution of WebApi Controller's constructor is done by Unity.WebApi using this in Bootstrapper.cs:
container.RegisterType<ICar_BLL, Car_BLL>();
this would have worked if my Car_BLL further didn't require ICar_DAL in its constructor.
to make it work i can do some thing like this:
container.RegisterType<ICar_BLL, Car_BLL>();
container.RegisterType<ICar_DAL, Car_DAL>();
but that would mean that i need to add reference to DAL_Project in my WebApi_Project which is something i would never want to do. DAL_Project should only be referred by BLL_Project
How can i solve this issue?
but that would mean that i need to add reference to DAL_Project in my
WebApi_Project which is something i would never want to do.
Oh you seem to have some misunderstanding about how Dependency should be done if you don't want to do that. The DI container is configured in the outermost layer of your application which is actually the host. It is also referred to as the Composition Root. In your case this is the hosting application of your Web API. If you are using ASP.NET to host your Web API then this is the right place to do the composition root and reference all the other underlying projects.
Personally in complex project I tend to have a ProjectName.Composition class library which serves me as a Composition root. this is where I configure my DI container and this is the project that references all the others - coz obviously in order to configure your DI root you need all the dependent projects and implementations. This .Composition assembly is then references in the hosting application and the Bootstrapper.Initialize method called in the Initialize method of the hosting application.
In the case of ASP.NET host that would be Application_Start in Global.asax
In case of a desktop application or a self-host that would be the Main method which is the entry point.

Hitting error: An instance of IControllerFactory was found in the resolver as well as a custom registered provider

We are hitting the following error in some of our environments, seemingly after the app pool recycles.
An instance of IControllerFactory was found in the
resolver as well as a custom registered provider in
ControllerBuilder.GetControllerFactory. Please set only one or the other.
We are not using the ControllerBuilder to register our controller factory, only the IDependencyResolver as pointed out in the this blog
We are using Castle Windsor (seemingly unrelated), as our container, and in the Application_Start of the Global.asax, first registering all of our dependencies and calling the following to register the IDepencencyResolver.
DependencyResolver.SetResolver(new WindsorDependencyResolver(IoC));
What could be causing this exception? Any help would be appreciated.
Using the MVC DependencyResolver with Castle Windsor is not recommended as it has a design flaw: it does not release service instances when it should. See this article for a full explanation.
Instead, use the method illustrated in the Windsor documentation which uses a custom factory to inject dependencies into controllers.
For information, I had the same error message (with ninject). I don't understand why because the application started well in other machine. I tried to clear caches... but error was still present. I had redo a checkout in my repository and it was OK...

How to properly decouple Structure Map dependency resolver from ASP.NET MVC web project?

While developing web project using ASP.NET MVC, I came up against a coupling problem.
When I build custom controller factory (or dependency resolver if using MVC 3), I need this factory to know somehow where to get dependencies from. Here's my code:
//from Global.asax.cs
DependencyResolver.SetResolver(new StructureMapControllerFactory());
class StructureMapControllerFactory: IDependencyResolver {
Container repositories;
public StructureMapControllerFactory()
{
repositories = new RepositoriesContainer();
}
//... rest of the implementation
}
class RepositoriesContainer: Container
{
public RepositoriesContainer()
{
For<IAccountRepository>().Use<SqlAccountRepository>();
//...
}
}
StructureMapControllerFactory class is responsible for injecting dependencies into a controller. As I said, it needs to know where to find these dependencies (I mean concrete classes, like services and repositories implementations).
I have a separate class library called MySite.Data, where all the implementation details live. Contracts, like IAccountRepository, live in library MySite.Contracts. Now, if I reference this MySite.Data library directly from MVC project, there will be a dependency between my site and implementation of its data retrieval. The question is how can I remove it? What are best practices in this situation?
I'm sure it does have a bunch of workarounds, just I haven't found any yet.
Well, as I see it, you can't do exactly that. Your MVC project really really needs to know about concrete classes it is going to use.
You will anyway have to provide those container registrations somewhere and you'll get the dependency on the project/assembly where that type is defined. Shortly, you have to reference MySite.Data from MVC project. Like that:
MySite.Data knows nothing about MVC project
MVC project knows the concrete repositories types to provide correct container registrations.
You can make life simpler with StructureMap Registry objects but you need to include those Registries somewhere as well. Typically those are in the main project or some "StructureMap-adapter" project but you'd need to make reference anyway.
I'd advise that you:
Use MVC3 and drop your custom IControllerFactory if you only use it for DI into your Controllers.
Use StructureMap Registry objects to provide each and every IoC registration ever needed.
Use StructureMap Assembly scanning capabilities to provide components discovery.
Use something much more common as a DependencyResolver, i.e. not a StructureMapControllerFactory but a CommonServiceLocator with StructureMap adapter instead.
Try to abstract from StructureMap itself inside your main app.
And, of course, don't be afraid of making references inside the main project - they have nothing about coupling. It doesn't decrease maintainability. But the wrong architecture does, so be worried about that, not simple reference.

Dependency resolution as a separate project ..How to?

I am creating a new application using asp.net mvc, I'm using munq IOC container as my dependency injection..The issue is i want to create a new project for dependency resolution where i can register all the controllers of mvc project and the repositories of infrastructure project..I have to add Dependency Resolution project as a reference in my mvc app as thats the starting point... but the prob is in order to register the controllers in this separate app i need to have the reference of the mvc in the dependency Resolution project itself...but such a thing is not possible because that would cause a circular reference..
so how to resolve this issue? or what is the best way of managing the dependency resolution?
I don't want to end up registering everything in the Global.asax
Get the latest version from the source tab at Munq.Codeplex.com. This version has a view improvements and it is the version I am most familiar with, and I wrote it.
To prevent circular references for registration, create a class project that includes reverences to Munq.Interfaces and the interfaces and implementations you wish to register.
Create a class that implements IMunqConfig. It has one method void RegisterIn(IIocContainer container). Implement this method.
public class MyRegistration : IMuncConfig
{
public void RegisterIn(IIocContainer container)
{
container.Register<IMyInterface>(c => new MyImplementation());
// OR
container.Register<IMyInterface, MyImplementation>();
// Repeat as required for each thing to register
}
}
Then in global.asax
protected void Application_Start()
{
IocContainer = new Container();
Munq.COnfigurationLoader.FindAndRegisterDependencies(container);
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
}
This will search the bin directory for any dlls that have classes implementing IMunqConfig and execute the RegisterIn method on each. So just drop the registration dlls into the bin directory and registration happens automagically :)
Matthew
i want to create a new project for dependency resolution where i can
register all the controllers of mvc project and the repositories of
infrastructure project.
I wouldn't register MVC controllers in the same project as your repositories. The MVC app should "own" its composition, including registering its internal dependencies.
Registrations for your infrastructure project should ideally be in that project, especially if it's not something you're going to make available to other projects that use different DI containers. If that project needs to remain DI-agnostic then maybe it might make sense to separate DI registration into a separate project.
But I definitely wouldn't make a service (like your repository) responsible for registering the internal dependencies of its consumers (like your MVC app.)

Resources