Multiple BaseControllers with IoC - asp.net-mvc

I read this question, and the answer helps me but not completely. What if I have 20 repositories with different responsibilities, like for example:
ICountryRepository
ICityRepository
and
IUserRepository
IPersonRepository
I can have all the methods of this repositories in the BaseController, but I would prefer something like having a TerritoriesBaseController, whit the ICoutnryRepository and ICityRepository and PersonsBaseController IUserRepository and IPersonRepository, than inherits from BaseController.7
My problem is that, if I have a controller that wants to use the TerritoryBaseController and PersonBaseController, I can't make it inherit from both controllers.
The reason why I want to separate the base controllers, is for structure, order and for not having a controller with 200 methods, but 20 controllers with 10 methods, and with separated responsibilities.
Some ideas how can it be organized?
EDIT:
I think I didn't explain the question properly.
Let's take this example:
I have a project with IoC, and let's say I have 4 repositories.
ICountryRepository, ICityRepository, IUserRepository, IPersonRepository.
I have a controller that needs methods of the 4 repositories, for example, UserController, it will use IUserRepository and IPersonRepository to save the user, and ICountryRepository and ICityRepository to show a list of countries and cities that the user has to select.
I also have a BaseController, where i have the generic methods of the controllers, and UserController inherits of BaseController, so:
UerController : BaseController
What I would like to do is, have a TerritoriesBaseController, where i would have all the methods that are repeated in my controlers of ICouuntrRepository and ICityRepository, like:
public JsonResult GetCountriesSelectList()
{
List<Country> listCountryLanguage = _applicationCountry.GetAll().ToList();
return Json(new SelectList(listCountryLanguage, "IdCountry", "Name"), JsonRequestBehavior.AllowGet);
}
And the same with IPersonRepository and IUserRepository, with a UserBaseController.
But I Can't use:
Usercontroler : BaseController, TerritoriesBaseController, UserBaseController
Because in c# you can only inherit from one class.
How can i reorganize it or what solution can I use?

What if I have 20 repositories with different responsibilities,
If you have a controller that needs to use 20 repositories, there is something wrong with your design. That controller will violate the Single Responsibility Principle.
There are a few solutions to this problem:
Split the logic in the controller up into multiple smaller, more focused controllers that each have just a few dependencies.
Move part of the logic to an aggregate service. In your case your controller probably has a lots of business logic in it. You should extract that business logic to a different class. The command/handler pattern is very suited for implementing business logic.
If you have code that uses multiple repositories, there's a special well-known pattern that for this: the Unit of Work pattern. What you can do is make those repositories accessible as properties on a Unit of Work class and inject only that unit of work.
UPDATE
UserController, it will use IUserRepository and IPersonRepository to
save the user, and ICountryRepository and ICityRepository to show a
list of countries and cities that the user has to select.
In that case you should extract the logic of saving the user into a new class and you should do the same with the logic for getting the list of countries. In that case your UserController will only depend on two more specific dependencies and the code inside the UserController will be minimized.
Don't use base controllers. Using base classes is often a sign of a glitch in your design. Your code becomes much harder to test when using base classes, and those base classes will often grow into god classes. Besides, you already noticed that multiple inheritance is not possible in .NET.
So what you can do is the following:
public class UserController : Controller
{
private ICommandHandler<SaveUser> saveUserHandler;
private IQueryProcessor queryProcessor;
public UserController(ICommandHandler<SaveUser> saveUserHandler,
IQueryProcessor queryProcessor)
{
this.saveUserHandler = saveUserHandler;
this.queryProcessor = queryProcessor;
}
public ActionResult Save(SaveUserViewModel model)
{
this.saveUserHandler.Handle(new SaveUser
{
UserId = model.UserId,
Name = model.UserName,
});
Redirect("/Success");
}
public JsonResult Countries()
{
var listCountryLanguage = queryProcessor.Execute(new GetAllCountries());
return Json(new SelectList(listCountryLanguage, "IdCountry", "Name"),
JsonRequestBehavior.AllowGet);
}
}
Do note that for this example I use the query/handler and command/handler patterns, but that's optional.

Related

ApiController and Controll inherit from same base class

I have multiple controllers and apicontrollers in my project.
How to make both types of controllers inherit a base class, as there is more than some methods, that I need in both?
Composition might be a better option.
Basically instead of inheriting to gain the functionality stick it in a common class, that can be included as a property in both the Api and standard controller.
You can then inject the dependancy into both.
For example:
public class CommonControllerLogic : ICommonControllerLogic
{
public ActionResult SomeSortOfMethod()
{
// etc..
}
}
public class MobileApiController: ApiController
{
public ICommonControllerLogic CommonControllerLogic {get;set;}
// etc..
}
public class HomeController: Controller
{
public ICommonControllerLogic CommonControllerLogic {get;set;}
// etc..
}
Composition is often favoured over inheritence, there are loads of articles on it, just do a quick google search, have a read of this article.
MVC controllers inherit from Controller, whereas API controllers inherit from ApiController. C# does not support multiple inheritance easily. I would recommend moving the shared logic into a static class that both can call. Otherwise you could provide more detail about what is shared; in some cases other design patterns may be more appropriate.

IoC in MVC: How do I handle the flow of service objects from controllers through models?

I am using MVC3 and have implemented IoC to provide service/manager objects to controllers through constructor arguments. These in turn, may get passed to models.
The problem I am having is that passing these objects all over the place can get cumbersome.
Example:
public CartController(
ICartManager cartManager,
IProductManager productManager,
IUpsellManager upsellManager,
IAccountManager accountManager,
... more ...)
{
... store to class variables ...
}
public ActionResult Index()
{
...
CartModel model = new CartModel(
cartManager,
accountManager,
upsellManager,
productManager,
... );
return View(model);
}
And the cart model may have sub models to which it must pass parameters. As you see, it all gets very cumbersome. I've ready if you have so many constructor arguments, your controller may be doing too much, but this is a complex page, and the site will contain many other complex pages. I don't want to have to pass so many things, but how can I not pass them and maintain a control?
I'm tempted to use the DependencyResolver in the models but that defeats the purpose and Service Locator is known anti-pattern.
How can I avoid passing so many arguments without giving up the benefits of IoC?
The advantage of using dependency inversion is to enforce clear separation of responsibilities between the various roles in the application. The Controller it is really just interested in dealing with HTTP Request and the HTTP Response. All other logic is dealt with elsewhere and the controller delegates to types it is dependent upon to do this work. This pattern is then repeated for each function in the system. One way to detect that this pattern isn't being followed is to use the new operator to create a type and pass in dependencies to the constructor. This is the job for the IoC container you are using.
I would suggest swapping the logic around and having the CartManager return a CartModel for the view. This could be some kind of DTO which is specific to the view. How the data gets put in to this object is the responsibility of the CartManager. If it needs the use of other services they can be injected in to it's constructor.
public CartController : Controller
private ICartManager _cartManager;
public CartController(ICartManager cartManager) {
_cartManager = cartManager;
}
[HttpGet]
public ActionResult Index(int userId) {
var model = _cartManager.CreateCart(int userId);
return View(model);
}
...
public class CartManager : ICartManager {
IDbService _dbService;
public CartManager(IDbService dbService){
_dbService = dbSerivce;
}
CartModel CreateCart(int userId) {
var user = _dbService.FindTheUser(int user);
var cartModel = new CartModel { userId = userId, Name = user.Name };
/* other stuff to map up a cartmodel
return cartModel;
}
}
This idea is not just specific to the use of IoC containers but is also good practice for creating MVC applications. I also found this post by Rob Ashton to be a good guide.
I like using a factory pattern for this scenario, where you need to instantiate class B (CartModel) within class A (CartController), and there are a bunch of dependencies in B that A doesn't need.
public CartController(
ICartModelFactory factory
... more ...)
{
... store to class variables ...
}
public ActionResult Index()
{
...
CartModel model = factory.GetInstance(
... );
return View(model);
}
You shouldn't be passing all those services to your view. What that means is that your template now has to perform actions to call this data, which complicates things (as you've seen). In addition to needless complexity, it also creates a dependency of these services in the view, and tighly couples the view to these services. If you change the services, you then have to change all the views that use it.
First thing you need to do is create a ViewModel that contains all the Data the view will need. Then, you need to find a way to map your manager classes returned data into this view. You can do it manually in the controller, or use something like AutoMapper to do the translations.
Another option is to either refactor ICartManager so that it returns all the data (your CartManager class would then have constructor injection of the other services) or create a different service that aggregates them and constructs an object that you can map to your View model.
You should never have to pass those methods around. They should always be injected into an object.

How are you populating/validating your ViewModels?

I'm curious of all of the various ways people are building their ViewModels and why they choose that method.
I can think of several ways here:
-1. Injected repository - the controller loads the model and maps to the ViewModel. Here the ViewModel constructor could take various collections to interally set for ex. in a select list such as:
public CustomerController(ISomeRepository repository)
{
_repository = repository;
}
public ActionResult Create()
{
CustomerCreateViewModel model = new CustomerCreateViewModel(_repository.GetShipTypes,
_repository.GetStates);
..
..
}
-2. ViewModelBuilder - Either injected or instantiated in the controller with an instance of the injected repository. Called via something like
>var orderViewModel = orderViewModelBuilder.WithStates().Build(orderId);
or,
var orderViewModel = orderViewModelBuilder.WithStates().Build(orderId);
-3. Directly in controller (no code required - its messy)
-4. Some other service (injected or not) that returns domain model which the controller then maps or a ViewModel (anyone doing this to return a view model that isn't specifically named/noted as a ViewModel builder class?)
public JobCreateViewModel BuildJobCreateViewModel(int parentId)
{
JobCreateViewModel model = new JobCreateViewModel();
model.JobStatus = _unitOfWork.JobRepository.GetJobStatuses();
model.States=_unitOfWork.StateRepository.GetAll();
return model;
}
Now on the return trip - regarding validating your view models - are you inheriting from a base ViewModel class for standard validations, or copying your validations (ex. data annotation attributes) between all of your ViewModels, or simply relying on server side validation so it can all be validated againt your domain object?
Any others? Anything better? Why?
EDIT
Based on a link below, I did find a nice article from Jimmy Bogard on the architecture of ViewModels. While it doesn't address the question above directly, it's a great reference for anyone coming here for ViewModel information.
http://lostechies.com/jimmybogard/2009/06/30/how-we-do-mvc-view-models/
I inject a service into the controller, not a repository, and then use AutoMapper to convert it into a view model. The benefit of the service layer in this case is that it could aggregate multiple simple operations from one or more repositories into a single operation exposing a domain model. Example:
private readonly ICustomerService _service;
public CustomerController(ICustomerService service)
{
_service = service;
}
[AutoMap(typeof(Customer), typeof(CustomerViewModel))]
public ActionResult Create(int id)
{
Customer customer = _service.GetCustomer(id);
return View(customer);
}
in this example AutoMap is a custom action filter that I can write which executes after the controller action, inspects the returned object and uses defined AutoMapper mappings to map it to the specified destination type. So the view gets the corresponding CustomerViewModel as model type. Would have been equivalent to:
public ActionResult Create(int id)
{
Customer customer = _service.GetCustomer(id);
CustomerViewModel vm = Mapper.Map<Customer, CustomerViewModel>(customer);
return View(vm);
}
it's just that it is too much plumbing and repetitive code that could be centralized.
I would also recommend you watching the putting your controllers on a diet video from Jimmy Bogard.
I just finished a project where we did a variation on #4. We had a service class injected into the controller. The service class held dependencies on the repository and a model builder class (we called it model factory).
The controller called into the service class, which handled business validation logic, and then fetched view models from the appropriate factory. The models themselves relied on data annotations for input validation.
It worked really well for our team. There was enough separation of concerns to allow the devs to do their work without affecting one another, but it was manageable enough to understand what was going on.
It's the first time we tried it and we'll be sticking with it. I'm interested to see how others respond.
Our method is to inject the repository in to the controller and map it to the ViewModel using Automapper http://automapper.org/. Our ViewModels contain data annotation attributes to allow the validation to occur on the client.
We call methods on the repository which return Domain objects (Entity Framework). The domain objects are mapped to the ViewModel. We tend to use the same ViewModel for edits and adds so the data annotations are needed once. In its simplest form it looks like the following code:
public ActionResult List(int custId, int projId)
{
var users = _userRepository.GetByCustomerId(custId);
var userList = Mapper.Map<IEnumerable<CMUser>, IEnumerable<UserListViewModel>>(users);
return View(userList);
}
I use a service layer that hides the domain model from the controller returning ViewModels from the service methods. This allows me to make changes to the domain model without impacting the client.

In asp.net-mvc, is there a more elegant way using IOC to inject mutiple repositories into a controller?

I have an asp.net-mvc website and i am using ninject for IOC and nhibernate for my ORM mapping
Here is my IOC binding code:
internal class ServiceModule : NinjectModule
{
public override void Load()
{
Bind(typeof(IIntKeyedRepository<>)).To(typeof(Repository<>)).InRequestScope();
}
}
and here is an example of how I am doing IOC into my controller code:
public FAQController(IIntKeyedRepository<FAQ> faqRepository, IUnitOfWork unitOfWork)
{
_faqRepository = faqRepository;
_unitOfWork = unitOfWork;
}
The issue is that up until now, each controller had a single table that it was pointing to so i only needed on repository class passed into it...
Now, I have a number of tables and classes that are all just have 2 fields:
Id
Name
for each of these classes, i simply inherit from a base class called:
BaseModel
which is just:
public class BaseModel
{
public virtual string Name { get; set; }
public virtual int Id { get; set; }
}
I want to have one:
StaticDataController
class that can do all of the CRUD for every class that simply inherits from BaseModel (with no extra fields)
The dumb simple way would be to do this:
private readonly IIntKeyedRepository<Object1> _object1Repository;
private readonly IIntKeyedRepository<Object2> _object2Repository;
private readonly IIntKeyedRepository<Object3> _object3Repository;
private readonly IIntKeyedRepository<Object4> _object4Repository;
private readonly IIntKeyedRepository<Object5> _object5Repository;
public StaticDataController(IIntKeyedRepository<Object1> obj1Repository, IIntKeyedRepository<Object2> obj2Repository, IIntKeyedRepository<Object3> obj3Repository, IIntKeyedRepository<Object4> obj4Repository, IIntKeyedRepository<Object5> obj5Repository)
{
_obj1Repository= obj1Repository;
_obj2Repository= obj2Repository;
_obj3Repository= obj3Repository;
_obj4Repository= obj4Repository;
_obj5Repository= obj5Repository;
}
Since I am passing the table in as a parameter to my methods, I would have to have some switch statement in my controller to get the right repository class based on the string of the parameter.
I assume there must be a much more elegant way to support what I am trying to do so I wanted to see if there is any best practice here (controller inheritance, reflection, etc.)?
If you need to do this it means that your controller does too many things and a strong indication that it requires a service layer. In this case I deport those repositories into the service layer. So my controller takes a service instead of multiple repositories:
private readonly IStatisticDataService _service;
public StaticDataController(IStatisticDataService service)
{
_service = service;
}
The service has business that could be composed of multiple atomic repository CRUD methods.
I know that you might say: yes, but now I have to inject all those repositories into the implementation of the IStatisticDataService interface. Yes, but it would make more sense to aggregate those atomic CRUD operations into the service layer rather than the controller.
But if need 5 or more repositories in order to perform a some business operations, maybe you have to rethink your domain architecture. Probably you could use composition in your domain models and define relations between them in order to reduce the number of repositories. It's difficult to provide more concrete advice without knowing the specifics of your domain.
Now, I have a number of tables and classes that are all just have 2 fields:
Great, make them derive all from the same base domain model and have a single repository to serve them. You could use descriminator columns, etc...
Darin is absolutely right. I'd just like to add though, if you're using MVC 3, you should be using the Ninject.MVC3 nuget package rather than creating your own Service Module.
As Mark Seemann mentioned: "It's quite OK, but once you feel that the Controller becomes too cluttered, you can refactor its dependencies to an Aggregate Service."
Look at: BestPractices: Is it acceptable to use more than one repository in a MVC-Controller?

MVC Retrieve Model On Every Request

Let’s say I'm developing a helpdesk application that will be used by multiple departments. Every URL in the application will include a key indicating the specific department. The key will always be the first parameter of every action in the system. For example
http://helpdesk/HR/Members
http://helpdesk/HR/Members/PeterParker
http://helpdesk/HR/Categories
http://helpdesk/Finance/Members
http://helpdesk/Finance/Members/BruceWayne
http://helpdesk/Finance/Categories
The problem is that in each action on each request, I have to take this parameter and then retrieve the Helpdesk Department model from the repository based on that key. From that model I can retrieve the list of members, categories etc., which is different for each Helpdesk Department. This obviously violates DRY.
My question is, how can I create a base controller, which does this for me so that the particular Helpdesk Department specified in the URL is available to all derived controllers, and I can just focus on the actions?
I have a similar scenario in one of my projects, and I'd tend to use a ModelBinder rather than using a separate inheritance hierarchy. You can make a ModelBinder attribute to fetch the entity/entites from the RouteData:
public class HelpdeskDepartmentBinder : CustomModelBinderAttribute, IModelBinder {
public override IModelBinder GetBinder() {
return this;
}
public object GetValue(ControllerContext controllerContext, string modelName, Type modelType, ModelStateDictionary modelState) {
//... extract appropriate value from RouteData and fetch corresponding entity from database.
}
}
...then you can use it to make the HelpdeskDepartment available to all your actions:
public class MyController : Controller {
public ActionResult Index([HelpdeskDepartmentBinder] HelpdeskDepartment department) {
return View();
}
}
Disclaimer: I'm currently running MVC Preview 5, so some of this may be new.
The best-practices way: Just implement a static utility class that provides a method that does the model look-up, taking the RouteData from the action as a parameter. Then, call this method from all actions that require the model.
The kludgy way, for only if every single action in every single controller needs the model, and you really don't want to have an extra method call in your actions: In your Controller-implementing-base-class, override ExecuteCore(), use the RouteData to populate the model, then call the base.ExecuteCore().
You can create a base controller class via normal C# inheritance:
public abstract class BaseController : Controller
{
}
public class DerivedController : BaseController
{
}
You can use this base class only for controllers which require a department. You do not have to do anything special to instantiate a derived controller.
Technically, this works fine. There is some risk from a design point of view, however. If, as you say, all of your controllers will require a department, this is fine. If only some of them will require a department, it might still be fine. But if some controllers require a department, and other controllers require some other inherited behavior, and both subsets intersect, then you could find yourself in a multiple inheritance problem. This would suggest that inheritance would not be the best design to solve your stated problem.

Resources