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.
Related
I am developing an MVC app to serve multiple domains - each is a branch of a larger company.
A LocalBranch class stores details such as phone, address, email, location coordinates etc.
I want to create a single instance of this class per http request and have it available throughout the application - from within controllers, views, some helper classes and other code.
Is there a recommended way of doing this?
Right now I have it as a property on a BaseController and use ViewBagto pass it to views. But I would prefer it strongly typed in Views if possible.
I don't want to put it in an application variable, because we need to serve different values to different domains.
I would rather avoid a session variable if possible because we might scale up to use multiple servers in the future, and I've heard this doesn't play well with sessions.
Please feel free to update tags / title if you think there is a clearer way of expressing what I'm after. Thank you.
The best way to maintain your state in a web application per request is simply use the HttpContext class.
You need to store your state(LocalBranch) as an Item in the HttpContext:
HttpContext.Current.Items.Add("LocalBranch", GetLocalBranch());
You can fetch the Item all across your application like this:
LocalBranch branch = HttpContext.Current.Items["LocalBranch"] as LocalBranch;
The Items property is simply a key value Dictionary. The value is an object. You will have to check for nulls and this is really similar to the Session object you know. The main difference is the scope. The HttpContext is a dot net object that has a lifetime of an http request.
Now using the HttpContext the way I've shown you is the simplest way to do it.
You can go two steps forward and use a framework called Unity and add a lifetime to your objects.
Unity does much more and the lifetime management is just one gem.
You can create a custom HttpContext lifetime that generates objects per request. Something like this.
And them all you need to do is:
1.Register you LocalBranch class with the HttpContext lifetime.
2.Add a static Current property which will use the Unity container and resolve the correct instance of LocalBranch.
3.Use it something like this: LocalBranch.Current
BTW, you can use Unity's dependency injection for injecting objects into controllers and other modules. That's a better practice then just using the static Current property.
You kind of have two questions here. The first is "How do I create a single instance of this class per HttpRequest?" The second is "How do I make this available to strongly typed views?"
The first has pretty much been answered by #amir-popovich to use dependency injection. However, FWIW I would probably use Ninject instead of Unity (just preference, really) and I would probably implement it differently. I would not use HttpContext, and simply build a service (which is instanciated using Ninject's OnePerHttpRequest Module, passing the domain as an argument to get the proper values).
Then, in order to add these LocalBranch values to your strongly typed View Model, you can first create a base view model which holds this type:
public class BaseViewModel
{
public LocalBranch Branch {get;set;}
}
Then, make all of your current view models inherit this base type
public MyViewModel : BaseViewModel
{
public string SomeValue {get;set;}
}
Then in your controller, it is easy enough to add these values from the service you created from the first step
public ActionResult SomeAction()
{
var vm = new MyViewModel();
vm.Branch = LocalBranchService.GetLocalBranchValues(); //Local Branch Service has been injected with Ninject
//do other stuff
return View(vm);
}
However, that gets pretty tedious to add that to each controller action, so you can instead create a Result Filter to add it for you:
public class LocalBranchResultFilter : FilterAttribute, IResultFilter
{
public void OnResultExecuting(ResultExecutingContext filterContext)
{
//This method gets invoked before the ActionResult is executed.
filterContext.Controller.ViewData.Model.Branch = LocalBranchService.GetLocalBranchValues(); //Local Branch Service has been injected with Ninject
}
}
Now, you can just decorate your Controller and/or Actions with the filter (you could even set it in the Global Filters if you want).
You can embed the child actions into your layout or a view. You can even cache its output so you don't keep re-querying the database.
controller
[ChildActionOnly]
[OutputCache(Duration=500, VaryByParam="*")]
public ActionResult Info()
{
var localBranch = db.GetLocalBranch();
return PartialView("_Info", localBranch);
}
_Info view
This bit will get inserted into your other views
#model LocalBranch
<span>#Model.address</span>
<span>#Model.phone</span>
Use in _Layout or other view
<p>lorem ipsum...</p>
#Html.Action("Info")
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.
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.
I'm writing an ASP.NET MVC 3 app and I'm finding myself writing this line rather often in my action methods:
var user = _session.Single<User>(u => u.UserName == User.Identity.Name);
(Obviously used in conjunction with the AuthorizeAttribute)
There are other things that get repeated quite often but this one is the most prominent and I end up having 3 actions next to each other, each needing to retrieve the authorized user.
So this needs DRY-ing up:
Should I write an ApplicationContoller from which all other controller inherit and expose a User property there or should I add this to my IAdminService and expose it as a method?
Is an ApplicationController something to avoid or to embrace in ASP.NET MVC?
If you are finding yourself repeating this logic then a custom model binder for the User type might help:
public class UserModelBinder : DefaultModelBinder
{
private readonly ISession _session;
public UserModelBinder(ISession session)
{
_session = session;
}
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var username = controllerContext.HttpContext.User.Identity.Name;
return _session.Single<User>(u => u.UserName == username);
}
}
and once you register the binder your controller action might look like this:
[Authorize]
public ActionResult Foo(User user)
{
// ...
}
As a person who doesn't really like controller super-types I would consider using Dependency Injection and use constructor injection to "inject" the user.
o/c this has some drawbacks. This means you'll have to a field for every use in your controller, and also have to create a binding in your IOC tool. This also assumes you're using an IOC container.
Regarding the other options:
Exposing it in the IAdminService gives you the added benefit of being availiable in other places, and not just in the Controller. So that's a plus. Just be certain that you don't clutter your interface too much.
Using it in a base controller is also tempting at first, but I've found that controller base types get bloated and mismanaged as more and more functionality is added, because there's no multiple inheritance and people need some of this and some of that... Things can get ugly. Not to mention that if you use the AsyncController you'll have two base-types to manage.
Basically, between your two option's I'd use the interface.
No matter what you do, you can still add a method to the interface and also abstract it behind a User property in a base Controller.
Currently I'm passing my domain objects to my views, and binding directly to them from POSTs. Everyone says this is bad, so I'm attempting to add in the ViewModel concept.
However, I can't find a way to do this very elegantly, and I'd like to know what other people's solutions are to not ending up with a very messy controller action.
the typical process for say some "add person" functionality looks like this:
make a GET request for a view representing a blank Person viewmodel
post back (in)valid data
controller binds posted data onto a person viewmodel
if binding fails, i need to do the same action as in (1) but with some data, not a blank object and errors
if the binding suceeded, i need to map the properties from the VM onto a real model
validate the model
if validation passed: save the person, commit, map the users details to a display VM and return it in a view
if validation failed, do the same actions as in (1) but with some data and errors
Doing all this in a controller action (ignoring the GET) certainly isnt SRP or DRY.
Im trying to think of a way of breaking this process up so that it does abide by SRP, is clean, modular and above all testable.
What are peoples solution to this?
I've been experimenting with custom controller-action-invokers to separate the concerns up into individual methods, smart modelbinders and just plain brute force but i havent yet come across a solution in happy with.
P.S. as it adds so much complexity, convince me why i even need to bother
I've felt the same discomfort. My only way around it has been to do the following:
Create a binder to bind and validate the view model
Create a binder to get the entity from the database (or just do this in the controller)
Call an inherited Save method in the superclass. This method takes the viewmodel and the entity that will be updated, and does all the work you listed in your steps.
The action method looks like this:
public ActionResult Whatever(TViewModel viewModel, TEntity entity)
{
return Save(viewModel, entity);
}
The base controller has a generic definition, like so:
public abstract BaseController<TEntity, TViewModel>
where TEntity : Entity
where TViewModel : ViewModel
The constructor has two dependencies, one for the entity repository and another for the model mapper, like so:
protected BaseController(IRepository<TEntity> repository, IMapper<TEntity, TViewModel> mapper)
With this in place, you can then write a protected Save method that can be called from the controller actions in the subclass, like so:
protected ActionResult Save(TViewModel viewModel, TEntity entity)
{
if (!ModelState.IsValid)
return View(viewModel);
_mapper.Map(viewModel, entity);
if (!entity.IsValid)
{
// add errors to model state
return View(viewModel);
}
try
{
_repository.Save(entity);
// either redirect with static url or add virtual method for defining redirect in subclass.
}
catch (Exception)
{
// do something here with the exception
return View(viewModel);
}
}
As far as testability, you can test the save method passing in valid/invalid view models and entities. You can test the implementation of the model mapper, the valid state of the view model, and the valid state of the entity separately.
By making the base controller generic, you can repeat this pattern for each entity/viewmodel combo in your domain, if you're creating many controllers to do the same thing.
I'm very interested to hear what others have to say about this. Great question.
The MVVM (ViewModel) pattern is definitely the one to go for, I had a similar question about POSTing back to an action a few days back - here is the link: MVVM and ModelBinders in the ASP.NET MVC Framework
The result was that you can use the Bind attribute to post back the complex type you want.
I have many good solutions in the asp.net mvc sample application which is in the download of valueinjecter (mapper that I use to map ViewModels to/from Entities, you can also map FormCollection/Request to Entities)
here's one:
public class TinyController :Controller
{
private readonly IModelBuilder<Person, PersonViewModel> modelBuilder;
public TinyController()
{
modelBuilder = new PersonModelBuilder();
}
public ActionResult Index()
{
return View(modelBuilder.BuildModel(new PersonRepository().Get()));
}
[HttpPost]
public ActionResult Index(PersonViewModel model)
{
if (!ModelState.IsValid)
return View(modelBuilder.RebuildModel(model));
var entity = modelBuilder.BuildEntity(model);
...
//save it or whatever
}
}