I need to inject out of constructor, everything I declared in Setup.
Ho can I do it ? How can I inject services out of constructor ?
Something like Injector service in Angular 2.
INJECT SERVICES WITHOUT CONSTRUCTOR IN CONTROLLERS
something like this
public class ControllerBase : Controller
{
protected IRepository<Test> _test;
protected IRepository<Test1> _test1;
protected IRepository<Test2> _test2;
public ControllerBase(INJECTOR injector)
{
_test = injector.inject(IRepository<Test>);
_test1 = injector.inject(IRepository<Test1>);
_test2 = injector.inject(IRepository<Test2>);
}
}
public class SomeController : ControllerBase
{
public SomeController(INJECTOR injector)
: base(injector)
{
}
}
THANKS FOR ANSWER #Rick van den Bosch
FOR THOSE WHO STILL CAN'T GET WHAT I WANTED:
public class ControllerBase : Controller
{
protected IRepository<Test> _test;
protected IRepository<Test1> _test1;
protected IRepository<Test2> _test2;
public ControllerBase(IServiceProvider injector)
{
_test = injector.GetService<IRepository<Test>>();
_test1 = injector.GetService<IRepository<Test1>>();
_test2 = injector.GetService<IRepository<Test2>>();
}
}
public class SomeController : ControllerBase
{
public SomeController(IServiceProvider injector)
: base(injector)
{
//HERE I HAVE ALL 3 REPO NOW WITHOUT EXTRA LINES
}
}
public class SomeController1 : ControllerBase
{
public SomeController1(IServiceProvider injector)
: base(injector)
{
//HERE I HAVE ALL 3 REPO NOW WITHOUT EXTRA LINES
}
}
You can inject the service as a parameter to the action method. This is done by marking the parameter with the attribute [FromServices].
This looks something like this:
public IActionResult About([FromServices] IDateProvider dateProvider)
{
ViewData["Message"] = $"Current date is {dateProvider.CurrentDate}";
return View();
}
If you're looking for default services in a BaseController: you could go about that several ways:
1. Still use a constructor
This would look something like this:
public class HomeController : BaseController
{
public HomeController(IDateProvider dateProvider) : base(dateProvider)
{
}
}
and
public class BaseController
{
protected IDateProvider _dateProvider;
protected BaseController(IDateProvider dateProvider)
{
_dateProvider = dateProvider;
}
}
This way the IDateProvider is available to both the BaseController and all inheriting Controllers.
2. Resolve services manually
This way you resolve the service manually. This could be in the BaseController, and only when you need them (lazy). For more info, see this post.
For simplicity and readability I would probably choose the constructor one.
Related
I have multiple models for state,country,city ,roles,emails etc.( 30 models)
I have single controller which handles multiple api calls with single API method.
I created 30 different Interfaces which implements to return List of objects.
public interface state
{
IEnumerable<state> GetState();
}
public interface city
{
IEnumerable<city> GetCity();
}
From the controller , through constructor injection , I'm injecting dependency and calling each method based on api parameter "section" using switch .
[Microsoft.AspNetCore.Mvc.HttpGet("{section}")]
public ActionResult GetModelBySection(string section)
{
switch(section)
{
case "country":
return Ok(countryDAL.GetCountry());
...
...
default:
return Ok("Not Found");
}
}
Instead of injecting all 30 interfaces here , I tried using IGeneric . when I use IGeneric , I need to create multiple controller . I dont want to create multiple controller. Please help me here
Created IGeneric interface and implemented in each DAL , and made Controller generic .
public interface IGenericDAL<T> where T : class
{
Task<IEnumerable<T>> GetAllAsync();
Task<T> GetByNameAsync(string name);
long Add(T item);
long Update(T item);
long Delete(long id);
}
public class CityDAL : IGenericDAL<City>
{
.......
}
[Microsoft.AspNetCore.Mvc.Route("api/[controller]")]
[ApiController]
public class CommonController<T> : Controller where T : class
{
private IGenericDAL<T> _generic;
}
I tried as below:
public class GenericDAL<T> : IGenericDAL<T> where T : class
{
......
}
Regist in startup:
public void ConfigureServices(IServiceCollection services)
{
.....
services.AddTransient(typeof(IGenericDAL<>), typeof(GenericDAL<>));
....
}
In controller:
public class HomeController : Controller
{
private readonly IServiceProvider _serviceProvider;
public HomeController( IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public IActionResult SomeController()
{
var someservice = (GenericDAL<City>)_serviceProvider.GetService(typeof(IGenericDAL<City>));
var cities = someservice.GetAllAsync().Result;
return OK();
}
}
The Codes excuted successfully:
I have the following problem and I currently have a solution using conditional dependency injection. I have read that this is a bad idea, such as here in the SimpleInjector docs. I have read a large number of posts now and have seen various things suggesting using Strategy, Factory patterns, etc. What I am really looking for is some specifics - i.e. an example of some code - about how to solve without conditional injection. I need more that "use a factory". Here's a simplified version of my code. This is in an MVC web app, thus the controllers.
public abstract class QAControllerBase : Controller
{
protected readonly QABusinessLayer _blQA;
public QAControllerBase(QABusinessLayer bl)
{
_blQA = bl;
}
[HttpGet]
public ActionResult PPR(string accession, string site)
{
var m = _blQA.popPPRViewModel(accession);
return View(m);
}
}
public class QASouthController : QAControllerBase
{
public QASouthController([QASouthBinding] QABusinessLayer bl) : base(bl)
{
}
// some actions that are specific to South
}
public class QANorthController : QAControllerBase
{
public QANorthController([QANorthBinding] QABusinessLayer bl) : base(bl)
{
}
// some actions that are specific to North
}
public abstract class QABusinessLayer
{
protected readonly IFullBaseRepo _repo;
public QABusinessLayer(IFullBaseRepo repo)
{
_repo = repo;
}
public abstract PPRViewModel popPPRViewModel(string accession);
protected PPRViewModel DoSomeCommonStuff(PPRViewModel model)
{
...
return model;
}
}
public class SouthBusinessLayer: QABusinessLayer
{
public SouthBusinessLayer([QASouthBinding] IFullBaseRepo repo) : base(repo)
{
}
public override PPRViewModel popPPRViewModel(string accession)
{
var m = new PPRViewModel();
// do some stuff that is specific to South
DoSomeCommonStuff(m);
return m;
}
}
public class NorthBusinessLayer : QABusinessLayer
{
public NorthBusinessLayer([QANorthBinding] IFullBaseRepo repo) : base(repo)
{
}
public override PPRViewModel popPPRViewModel(string accession)
{
var m = new PPRViewModel();
// do some stuff that is specific to North
DoSomeCommonStuff(m);
return m;
}
}
and here is the Ninject binding code that is pertinent:
kernel.Bind<QABusinessLayer>()
.To<SouthBusinessLayer>()
.WhenTargetHas<QASouthBinding>()
.InRequestScope();
kernel.Bind<QABusinessLayer>()
.To<NorthBusinessLayer>()
.WhenTargetHas<QANorthBinding>()
.InRequestScope();
The QASouthBinding and QANorthBinding are just simple attributes. I am not asking for Ninject specific example. Any code sample as to how this might be handled without using conditional or context based injection as I am now.
Make your QABusinessLayer class abstract.
Change your startup configuration to:
kernel
.Bind<SouthBusinessLayer>()
.To<SouthBusinessLayer>()
.InRequestScope();
kernel
.Bind<NorthBusinessLayer>()
.To<NorthBusinessLayer>()
.InRequestScope();
Change your controller constructors to accept a concrete business layer type:
public class QANorthController : QAControllerBase
{
public QANorthController(NorthBusinessLayer businessLayer) : base(businessLayer)
{
}
}
public class QASouthController : QAControllerBase
{
public QASouthController(SouthBusinessLayer businessLayer) : base(businessLayer)
{
}
}
Few things:
If Ninject auto-binds concrete types to the same type, then you don't need to manually configure the dependencies during startup.
You may want to use an interface rather than just passing your concrete BusinessLayer type.
I have following interfaces, abstract classes etc.
public interface IAggregateRootMapping<T> : IAggregateDefinition where T : AggregateRoot
{
IEnumerable<Expression<Func<T, object>>> IncludeDefinitions { get; }
}
public abstract class AggregateRootMapping<T> : IAggregateRootMapping<T> where T : AggregateRoot
{
public abstract IEnumerable<Expression<Func<T, object>>> IncludeDefinitions { get; }
}
public class OrderAggregateRootMapping : AggregateRootMapping<Order>
{
public override IEnumerable<Expression<Func<Order, object>>> IncludeDefinitions
{
get
{
return new Expression<Func<Order, object>>[] {
order => order.Supplier
};
}
}
}
I use those in another class like this:
public class Repository<TAggregateRoot> : IRepository<TAggregateRoot> where TAggregateRoot : AggregateRoot
{
private readonly AggregateRootMapping<TAggregateRoot> _aggregateRootMapping;
public Repository(AggregateRootMapping<TAggregateRoot> aggregateRootMapping)
{
_aggregateRootMapping = aggregateRootMapping;
}
Do something...
}
How do I use the dependency injection of ASP.NET Core so that on runtime the matching class is injected?
For example if the AggregateRoot type class is Order than for the Repository class the OrderAggregateRootMapping class should be injected.
How do I use the ServiceCollection in ConfigureServices of the Startup class in .NET Core to accomplish this?
The dependency injection that comes by default is very basic. If you want to start wiring up rules based on generics, you will need to use a different implementation.
But, what you're after is still possible if you're willing to code the dependencies one by one.
In your Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<AggregateRootMapping<Order>, OrderAggregateRootMapping>();
services.AddScoped<Repository<Order>>();
// Add framework services.
services.AddMvc();
}
And then you can use your Repository class by injecting it into a controller, for example.
In ValuesController.cs
[Route("api/[controller]")]
public class ValuesController : Controller
{
private Repository<Order> _repository;
public ValuesController(Repository<Order> repository)
{
_repository = repository;
}
}
ValuesController will then receive an instance of Repository<Order> which will have been created with a OrderAggregateRootMapping.
Update
Tried to clarify my problem
I have a ASP.NET 5 Web Api application. I'm trying to create a controller class that makes use of a custom base controller. As soon as I add a constructor to the base controller then MVC can no longer find the Get() end point defined in the Generic class.
This works:
When I navigate to /api/person then the Get() end point is triggered defined in the Generic class
Generic:
public class Generic
{
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
}
PersonController
[Route("api/[controller]")]
public class PersonController : Generic
{
}
This doesn't work
When I navigate to /api/person then the Get() end point is not triggered. The only thing that is added is a constructor in both the Generic class and the PersonController class.
public class Generic
{
protected DbContext Context { get; set; }
public Generic(DbContext context)
{
Context = context;
}
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
}
PersonController
[Route("api/[controller]")]
public class PersonController : Generic
{
public PersonController(DbContext context) : base(context) { }
}
Is this a bug or am I doing something wrong?
Your problem has nothing to do with inheriting from another base class. I think the problem is, a proper implementation of your DbContext is not being injected to the constructor. Since asp.net 5 is so modular/dependency injectable, you need to explicitly configure it.
In the ConfigureServices method in your Startup.cs class, register your DbContext service so MVC will use that and inject that to your class controller when needed.
public void ConfigureServices(IServiceCollection services)
{
services.AddEntityFramework()
.AddDbContext<DbContext>();
services.AddMvc();
}
I have a service class :
public class MyService : IService
{
private IRepoA repoA;
private IRepoB repoB;
public MyService(IRepoA repoA,IRepoB repoB)
{
this.repoA=repoA;
this.repoB=repoB;
}
}
my Controller depends on the MyService classL
public MyController : DefaultController
{
IService myService;
public MyController(IService service)
{
myService=service;
}
}
how do I inject the MyService class into the controller ?
should i do this ? :
Bind<IPostService>()
.To<PostService>();
Bind<IPostsRepository>()
.To<SqlPostsRepository>()
.WithConstructorArgument("connectionString",
ConfigurationManager.ConnectionStrings[0].ConnectionString);
Bind<IUserRepository>()
.To<FakeUserRepository>();
Look at Ninject.Extensions.Mvc. Read the read me and documentation. It has everything you need. From the looks of it, all you'll need is to properly setup your HttpApplication to inherit from NinjectHttpApplication and add the proper config code (all located in the readme/documenation)
You'll want to create your own controller factory that injects the dependencies for you and register that factory in Global.asax.
If you're using structure map, that could look like this:
public class IoCControllerFactory : DefaultControllerFactory
{
protected override IController GetControllerInstance(Type controllerType)
{
return (Controller)ObjectFactory.GetInstance(controllerType);
}
}