I have classes such as AccountsController, ProductsController etc that all inherit from BaseController. Unity sets up my services as needed. These classes also all require a _sequence service. As it is a common requirement for all classes I would like to code this in the BaseController.
public class AccountsController : BaseController
{
public AccountsController(
IService<Account> accountService) {
_account = accountService;
}
public class ProductsController : BaseController
{
public ProductsController(
IService<Account> productService) {
_product = productService;
}
public class BaseController : Controller
{
public IService<Account> _account;
public IService<Product> _product;
protected ISequenceService _sequence;
public BaseController(
ISequenceService sequenceService) {
_sequence = sequenceService;
}
But how can I do this? Should I set up a call to the BaseController inside the constructors of each of the AccountsController and ProductsController?
You can chain constructors:
public class ProductsController : BaseController
{
public ProductsController(
IService<Account> productService) : base(productService)
{
_product = productService;
}
}
Note that the chained BaseController (using the base keyword) has been passed the productService parameter, tough this can be anything.
Update:
You could do the following (poor mans' dependency injection):
public class ProductsController : BaseController
{
public ProductsController(
IService<Account> productService) : base(new SequenceService())
{
_product = productService;
}
}
Or, pass in the dependency on ISequenceService through your inheriting types:
public class ProductsController : BaseController
{
public ProductsController(
IService<Account> productService, ISequenceService sequenceService)
: base(sequenceService)
{
_product = productService;
}
}
Related
Given the following ASP.NET Core controller :
public class MyController : Controller {
public MyController(IDependency dependency) { this.dependency = dependency; }
}
public interface IDependency;
public class DependencyImplementation : IDependency {
public DependencyImplementation(Controller controller) { ... }
}
I want MyController to have a new instance of DependencyImplementation injected, constructed with the controller it's being passed to. Ideally using Ninject.
The non-IoC version would be:
public class MyController : Controller {
public MyController() { this.dependency = new DependencyImplementation(this); }
}
This would cause circular dependency. Only idea I have is to introduce factory:
public interface IDependencyFactory
{
IDependency Create(Controller controller);
}
public class MyController : Controller
{
private IDependency dependency;
public MyController(IDependencyFactory dependencyFactory)
{
this.dependency = dependencyFactory.Create(this);
}
}
var kernel = new StandardKernel();
kernel.Bind<Controller>().To<MyController>();
kernel.Bind<IDependency>().To<DependencyImplementation>();
kernel.Bind<IDependencyFactory>().ToFactory();
var controller = kernel.Get<Controller>();
Or maybe rather reconsider whole design.
public class BaseController : Controller
{
[Inject]
public IUnitOfWork UnitOfWork { get; set; }
private readonly ISomeService _someService ;
public BaseController(ISomeService someService)
{
_someService = someService;
}
public void Contacts()
{
contacts = _someService .GetById(1);
ViewBag.someThing = contacts; //Add whatever
}
public BaseController()
{
}
}
While I'm sending someService in the :base I can get the data from it. However I don't want to send someService from each controller like AboutController to the BaseController and to write too much code.
public class HomeController : BaseController
{
private readonly ISomeService someService;
public HomeController(ISomeService someService) : base(someService)
{
_someService = someService;
}
}
public class AboutController : BaseController
{
private readonly IAboutService _aboutService;
public AboutController (IAboutService aboutService)
{
_aboutService = aboutService;
}
}
So in AboutController view still i wanna get someService's data without sending parameter to the BaseController
The short answer would be separated in two cases:
If you want to use ISomeService from the base controller you are obliged to pass that service through base constructor like this:
public class AboutController : BaseController
{
private readonly IAboutService _aboutService;
public AboutController (IAboutService aboutService, ISomeService someService) : base(someService)
{
_aboutService = aboutService;
}
}
If you dont want to use that service you use the default base constructor like this otherwise it will be null if you try to access it:
public class AboutController : BaseController
{
private readonly IAboutService _aboutService;
public AboutController (IAboutService aboutService) : base()
{
_aboutService = aboutService;
}
}
You are in the first scenario so you need to pass it through the constructor in order to initialize it!
But if you like to break the pattern you would choose other ways of injecting the services into your base controller:
First one by using auto-properties:
For example:
public ISomeService SomeService { get; set;}
Another way is to get the instance of the service by using DependecyResolver but this would 'break' somehow the DI pattern and it will make harder for testing etc. But if you choose to do so here is the code for that:
public class BaseController : Controller
{
[Inject]
public IUnitOfWork UnitOfWork { get; set; }
private readonly ISomeService _someService ;
public BaseController(ISomeService someService)
{
_someService = someService;
}
public void Contacts()
{
contacts = _someService .GetById(1);
ViewBag.someThing = contacts; //Add whatever
}
public BaseController()
{
_someService = DependencyResolver.Current.GetService<ISomeService >();
}
}
For more info refer to this question here
I am using Ninject to do some IoC in my ASP.NET MVC application.
I have an interface "IService.cs" :
public interface IService
{
string method();
}
I have the corresponding implementation "Service.cs" :
public class Service
{
string method()
{
return "result";
}
}
I have done the binding in another class heriting from NinjectModule :
public class MyNinjectModule : NinjectModule
{
public override void Load()
{
RegisterServices();
}
private void RegisterServices()
{
Kernel.Bind<IService>().To<Service>();
}
}
I have my class A which use this service :
public class A
{
private readonly IService _service;
private int i;
public A(IService service, int i)
{
this._service=service;
this.i=i;
}
}
The problem is that now, I don't know how to instantiate my class A in my application. This is where am I stuck, how can I call Ninject
to tell my app to go get the implementation of my interface:
var myClass=new A(????)
The main problem is that your Service class does not implement IService.
public class Service
{
string method()
{
return "result";
}
}
It should be
public class Service : IService
{
public string method()
{
return "result";
}
}
But as for instantiating a class, the best approach is to use a composition root to build an object graph. In MVC, that is best handled by implementing IControllerFactory.
public class NinjectControllerFactory : DefaultControllerFactory
{
private readonly IKernel kernel;
public NinjectControllerFactory(IKernel kernel)
{
this.kernel = kernel;
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
return controllerType == null
? null
: (IController)this.kernel.Get(controllerType);
}
}
Usage
using System;
using Ninject;
using DI;
using DI.Ninject;
using DI.Ninject.Modules;
internal class CompositionRoot
{
public static void Compose()
{
// Create the DI container
var container = new StandardKernel();
// Setup configuration of DI
container.Load(new MyNinjectModule());
// Register our ControllerFactory with MVC
ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory(container));
}
}
In Application_Start, add:
CompositionRoot.Compose();
You will also need to create an interface for your class A and register it. An integer cannot be resolved automatically, you have to do that explicitly.
Kernel.Bind<IClassA>().To<A>()
.WithConstructorArgument("i", 12345);
And then you would add your dependency to a controller. Dependencies of dependencies are resolved automatically.
public class HomeController : Controller
{
private readonly IClassA classA;
public HomeController(IClassA classA)
{
if (classA == null)
throw new ArgumentNullException("classA");
this.classA = classA;
}
public ActionResult Index()
{
// Use this.classA here...
// IService will be automatically injected to it.
ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";
return View();
}
}
I have two different controller --> Controller A,Controller B
And I have different methods each controller and their return values IHttpActionResult (Method A controller A ,Method B and Controller B)
How can I access another controller method and take its content from another controller
Controller B ,and Inside Method B
IHttpActionResult result = ControllerA.MethodA()
and I want to read result.content inside controller B
When request comes, only controller which should process request is instantiated automatically. You can instantiate second controller manually, but I would recommend to move MethodA functionality either to base controller class
public class BaseController : ApiController
{
// ...
public IHttpActionResult MethodA(int id)
{
var foo = repository.Get(id);
if (foo == null)
return NotFound();
return Ok(foo);
}
}
public class ControllerA : BaseController
{
//...
}
public class ControllerB : BaseController
{
public IHttpActionResult MethodB(int id)
{
var result = MethodA();
//..
}
}
or move common logic to separate class (e.g. service), so you would be able to call it from both controllers.
public class ControllerA : ApiController
{
private IFooService fooService;
public ControllerA(IFooService fooService)
{
this.fooService = fooService;
}
public IHttpActionResult MethodA(int id)
{
// use fooService.Method()
}
}
public class ControllerB : ApiController
{
private IFooService fooService;
public ControllerB(IFooService fooService)
{
this.fooService = fooService;
}
public IHttpActionResult MethodB(int id)
{
// use fooService.Method()
}
}
I would consider using a common base class for the two controllers (if there is a method you want to use on both)
for example
public abstract class MyBaseController
{
public void CommonMethod()
{
// Do something here
}
}
then use them like
public class ControllerA : MyBaseController
{
public void MethodA()
{
base.CommonMethod();
// Do something else
}
}
public class ControllerB : MyBaseController
{
public void MethodB()
{
base.CommonMethod();
// Do Something else
}
}
1) You can use static class and static method inside to share it for another controllers
public static class CommonMethods
{
public static string SomeMethod(string s)
{
string RetString;
...
return (RetString);
}
}
Now you can use it in any controllers
string SomeMethodResult = CommonMethods.SomeMethod("Say Hello");
2) And another method is to create an instance of a controller class and call instances methods:
public class V1Controller : ApiController
{
public void Put(int id, [FromBody]string value)
{
HomeController hc = new HomeController();
hc.SomeMethod();
}
}
AController aController = new AController();
var getResponse = aController.YourMethod(values);
If your method returns Json then you can easily solve it with
JavaScriptSerializer().Deserialize
I am doing unit testing.And i have a controller which is depended on multiple repositories(means there are multiple dependencies).
Below is the piece of code of controller :-
public class TestController : BaseController
{
//Declaring dependencies
private IProductService _productService;
private IStudenctService _studentService;
private ITeacherService _teacherService;
private IClassService _classService;
private ITaxService _taxService;
private ICategoryService _categoryService;
private ISchoolService _schoolService;
//Constructor calling…
public TestController ()
{
}
public TestController (IProductService productService)
{
this._ productService = productService;
}
public TestController (IStudenctService studenctService)
{
this._ studentService = studenctService;
}
public TestController (ITeacherService teacherService)
{
this._ teacherService = teacherService;
}
public TestController (IClassService classService)
{
this._ classService = classService;
}
public TestController (ITaxService taxService)
{
this._ taxService = taxService;
}
public TestController (ICategoryService categoryService)
{
this._ categoryService = categoryService;
}
public TestController (ISchoolService schoolService)
{
this._ schoolService = schoolService;
}
public TestController (ISchoolService schoolService, ICategoryService categoryService)
{
this._ schoolService = schoolService;
this._ categoryService = categoryService;
}
public TestController (ISchoolService schoolService, ICategoryService categoryService, ITaxService taxService, IClassService classService) {
this._ schoolService = schoolService;
this._ categoryService = categoryService;
this._ taxService = taxService;
this._ classService = classService;
}
}
In the above code i have made separate constructor for each dependencies.Where there 2 constructor taking multiple arguments(dependency arg).
By this my unit test method is working well. But when i run application then its giving me below error :-
Uh-oh, something went wrong! Error Code: 500
But when i call only one parameter constructor then its working.Can anyone let me know what is wrong here ? What should do in case of multiple dependencies ?
If these are dependencies of your class, then you should have a single constructor that takes all of the dependencies as parameters.
In other words, you can not instantiate to a valid state without all of your dependencies. They are not optional, they are dependencies.
I would start with taking this approach, and then ask a separate question if your application still throws an error.