Who should be responsible for getting the data in MVC? - asp.net-mvc-3

Learning ASP.NET MVC with a new project, and a little unsure of where some things should happen. I've read that ViewModels are a Good Thing (tm) and had planned on doing it in a similar fashion anyway, but I'm still not entirely clear on the responsibilities of the Model vs. the Controller.
Should the ViewModel be responsible for actually loading itself from the ORM? Thus the controller would just call ViewModel.GetObject() and pass the result back to the view?
Or should I load the data in the Controller, and then transform it into the ViewModel? Seems like that puts a lot of work in the Controller though, which is supposed to be kept somewhat lightweight.
I guess I could also have a third party that is responsible for pulling the data, then the Controller would call that and transform it for the appropriate ViewModel.
So any thoughts on what is the "best" approach?

The controller will create the viewmodel object and fill it out using the model. The model should use the ORM to get the data.
The ViewModel is always specific to the view only, and the model is specific to the domain. In CQRS you would actually just get the ViewModel and send it to the view.
From the controller you can do what ever it takes to make your CRUD happen for the view. If you use the Repo pattern thats ok, if you use NHibernate or EF directly thats cool tool. Once the ViewModel goes to the view it will be disconnected from everything like the DB, so fill it out before it gets there.

Personally I use a repository. So the controller queries a repository and gets a model, then maps the model to a view model and passes the view model to the view. Example:
public class ProductsController: Controller
{
private readonly IProductsRepository _repository;
private readonly IMapperEngine _mapper;
public ProductsController(IProductsRepository repository, IMapperEngine mapper)
{
_repository = repository;
_mapper = mapper;
}
public ActionResult Index(int id)
{
Product product = _repository.GetProduct(id);
ProductViewModel viewModel = _mapper.Map<Product, ProductViewModel>(product);
return View(viewModel);
}
}
And because this is repetitive logic I use custom action filters:
public class ProductsController: Controller
{
private readonly IProductsRepository _repository;
public ProductsController(IProductsRepository repository)
{
_repository = repository;
}
[AutoMap(typeof(Product), typeof(ProductViewModel))]
public ActionResult Index(int id)
{
Product product = _repository.GetProduct(id);
return View(product);
}
}
in this case the custom action filter intercepts the result of the action and replaces it using the corresponding mapping layer.
The way this repository is implemented is not the responsibility of the controller (whether it is an ORM, direct SQL queries, or even distant web service calls). As long as it is injected some proper implementation it will work which allows for weaker coupling between the different parts of the application and easier unit testing in isolation. So in this example it is the implementation of the repository that is responsible for fetching data.

Related

What is the best way to create EF DbContext instance for ASP.NET MVC

In order to support lazy loading feature in EF, what is the best way to instantiate DbContext?
I know HttpContext's current item is good place to create DbContext via Application_BeginRequest method and Application_EndRequest method, but in some sample codes of MSDN and official asp.net mvc site, they just create DbContext in Controller's constructor and dispose it in controller's Dispose() method.
I think the both ways are not too different because all of those all implement session per request pattern.
I just want to make sure that my understanding is correct or not.
The Dispose() method in the controller isn't always reliable. By the same token, Session is probably not a good idea either. "Best" is probably subjective, but we've had the best success by using dependency injection (Castle Windsor) and following a Unit of Work Repository pattern.
Setup the unit of work along the following lines:
public class UnitOfWork : IUnitOfWork
{
public UnitOfWork()
{
this.Context = new MyEFEntities();
this.Context.ContextOptions.LazyLoadingEnabled = true;
}
public void Dispose()
{
this.Context.Dispose();
}
public ObjectContext Context { get; internal set; }
}
Setup your repository:
public class Repository<TEntity> : IRepository<TEntity>
where TEntity : class
{
public Repository(IUnitOfWork unitOfWork)
{
Context = unitOfWork.Context;
ObjectSet = Context.CreateObjectSet<TEntity>();
}
public ObjectContext Context { get; set; }
public IObjectSet<TEntity> ObjectSet { get; set; }
}
Register with Castle in Global.asax:
void Application_Start()
{
this.Container.Register(
Component.For<IUnitOfWork>()
.UsingFactoryMethod(() => new UnitOfWork())
.LifeStyle
.Is(LifestyleType.PerWebRequest)
);
ControllerBuilder.Current.SetControllerFactory(
new WindsorControllerFactory(this.Container));
}
And use in your controller (or wherever you're using it, as long as it's injectable):
public class SomeController
{
public SomeController(IRepository<MyEntity> repository)
{
this.Repository = repository;
}
public IRepository<MyEntity> Repository { get; set; }
public ActionResult MyAction()
{
ViewData.Model = this.Repository.ObjectSet.Single(x => x.Condition); //or something...
}
}
Any lazy loading here could potentially be a trap for a future issue. Without DI, without a repository - its hard to see anything working without it being a hack for lazy loading. Also do you you plan on passing your entities to your view. If so this is going to create a bad overlap. The controller should package data for your view, not have things evaluated later in your view.
For MVC best practices, you should flatten out your domain model as much as possible into a viewmodel (if flattening makes sense) and use the view model. Since you would ideally then know what would be lazy loaded, it may make more sense to take the hit up front and use .Include() in your query to eager load, otherwise you can issue many many queries to the database.
I've used a session factory pattern and saved the DBContext in the session object. It will stay open per session. I haven't had problems with it so far.

Constructor injection of a View Model instance used as an Action method parameter

When a view model is created you can populate the options (e.g. used in a dropdown list) into a setter property of the view model.
The problem is that when that view model is later passed as a parameter (by the framework!) into an action method, those property values has not become automagically
repopulated, so if you need to redisplay the form because of validation errors, you need to repopulate those options again.
One potential solution, which I am asking for specifically in this question, is how to make the MVC framework instantiate the view model with constructor injection, which would provide the view model constructor with an implementation of some kind of data access object (e.g. a repository) that can be used for retrieving the options when they are requested by the view (e.g. in the helper method "DropDownListFor") ?
I think the solution might have something to do with implementations of IModelBinderProvider or IModelBinder but after having experimented with these things from example code snippets here and there on the net, I am still looking for a completely working example, with downloadable executable code without any missing piece of how putting all things together.
If you are looking for some alternative discussion about how to populate a select list, e.g. with "Dependecy Lookup" instead of "Dependecy Injection" you may want to check out the following discussion:
Best way to populate SelectList for ViewModel on GET/POST
Best way to populate SelectList for ViewModel on GET/POST
Some days ago I wrote the following follow-up-question in that thread about the "Dependecy Injection" I am now looking for in this thread:
https://stackoverflow.com/a/8674525/310457
(which provides a code example about the problem I am looking for a solution of)
But instead of hoping that someone will find that old thread with a less specific title, I have created this new question with a more specific subject about what I am looking for.
And I will also provide a link from that thread into this new question for anyone that want to follow-up regarding this specific solution I am looking for.
I'm assuming you want to have your ViewModels automatically injected with something via their Constructor - for example some kind of configuration object that the View will use to determine what to show. I'm also assuming that this approach is causing a "No parameterless constructor defined for this object" error when MVC tries to automatically create and bind a model instance, from the arguments of your Controller Action. Let's also then assume that we will use a DI framework to inject the SiteConfig object into our Controllers automatically at runtime.
This means that the only problem we have to solve is how to get the injected object from our Controller into its Actions' ViewModels when they are automatically bound.
So let's define a base model for others to inherit from.
BaseViewModel
public class BaseViewModel
{
public ISiteConfig SiteConfig { get; set; }
public BaseViewModel(ISiteConfig siteConfig)
{
this.SiteConfig = siteConfig;
}
}
And now let's create a model that inherits from it.
IndexViewModel
public class IndexViewModel : BaseViewModel
{
public string SomeIndexProperty { get; set; }
public IndexViewModel (ISiteConfig siteConfig) : base(siteConfig) {}
}
And now let's define a Base Controller that our Controllers will inherit from.
BaseController
public abstract class BaseController : Controller
{
protected BaseController(ISiteConfig siteConfig)
{
_siteConfig = siteConfig;
}
private readonly ISiteConfig _siteConfig;
public ISiteConfig SiteConfig
{
get
{
return _siteConfig;
}
}
}
Now we define our actual controller.
HomeController
public HomeController: BaseController
{
public HomeController(ISiteConfig siteConfig): base(siteConfig) {}
}
Assuming we're using Ninject for DI, Ninject would be configured to automatically create the Controller and pass a concrete ISiteConfig object into its Constructor at runtime.
Now we add our Action to the Controller.
Index Action
public ActionResult Index(IndexViewModel model)
{
return View(model);
}
And so this is the point where without doing anything else, MVC will explode with a "Parameterless Constructor" error if you try to call the Index Action, because MVC can't find a ViewModel constructor that takes no arguments.
And so, the answer. We need to override the default ModelBinder.
BaseViewModelBinder
public class BaseViewModelBinder : DefaultModelBinder
{
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
{
if (modelType == typeof(BaseViewModel) || modelType.IsSubclassOf(typeof(BaseViewModel)))
{
var baseControl = controllerContext.Controller as BaseController;
if (baseControl == null)
{
throw new Exception("The Controller must derive from BaseController");
}
var instance = Activator.CreateInstance(modelType, baseControl.SiteConfig);
bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => instance, modelType);
return instance;
}
else
{
return base.CreateModel(controllerContext, bindingContext, modelType);
}
}
}
And we need to set this as the default model binder in global.asax.cs :
protected void Application_Start()
{
...
ModelBinders.Binders.DefaultBinder = new BaseViewModelBinder();
}
That's all. As you can see, when you view the Index Action now, MVC will use our custom model binder. It will realise that the IndexViewModel derives from BaseViewModel, and so will attempt to spin up an IndexViewModel instance using the ISiteConfig it can find in the Action's Controller (because the Controller derives from BaseController).

Unittesting MVC controller

Im trying to learn MVC combined with IoC and DI. In my project I also use Castle, Automapper, NHibernate, NHibernateIntegration.
Thanks to the excellent example "ToBeSeen" app by Kozmic I think I have the solution pretty much set up now. But now I want to unittest basic save operation at the controller method level. I just dont get how to go about this. I expect my problem is pretty simple but Im a novice at this and any help is appreciated.
I have a dossiercontroller like this:
[Authorize]
[Transactional]
public class DossierController : BaseController
{
private readonly IRepository repository;
private readonly IMappingEngine mappingEngine;
private readonly ILogger logger;
public DossierController(IRepository repository, IMappingEngine mappingEngine, ILogger logger)
{
this.repository = repository;
this.mappingEngine = mappingEngine;
this.logger = logger;
}
As you can see it needs a repostitory, mappingengine and logger. As I understand all this is configured and wired up at runtime.
Next I have a controller method that is used to save a dossier:
[HttpPost]
[ActionName("Dossier")]
[Transaction]
[AcceptVerbs(HttpVerbs.Post)]
[AcceptParameter(Name = "button", Value = "save")]
public ActionResult Dossier_Save(string button, DossierModel dossierModel, string returnUrl)
{
if (!Request.IsAuthenticated)
return RedirectToAction("Index", "Home");
if (!ModelState.IsValid) return View(dossierModel);
Dossier dossier = mappingEngine.Map<DossierModel, Dossier>(dossierModel);
repository.Save(dossier);
return View();
}
Here I just want to automap the dossiermodel into a dossier and save it using the repository.
Now I want to unit test this using Nunit. I dont want to mock anything, I want a real persistence test from the controller level. For this I have to create a new dossiercontroller and pass in the correct arguments. Now Im lost. How do I create and configure the arguments so they work exactly like in the web application. For instance: How do I create a correctly configured Automapper in a Unittest? How do I create a correctly configured repository? Should I use a container?
Any help, especcialy a code example is highly appreciated!
Thanks in advance.
If you don't want to mock anything, you will need to instantiate concrete versions of the services required by the constructor of your controller.
e.g.
IRepository repository = GetRepository();
IMappingEngine mappingEngine = GetMappingEngine();
ILogger logger = GetLogger();
DossierController controller = new DossierController(repository, mappingEngine, logger);
ActionResult rsult = controller.Save(...etc...);
As to how you are to configure and instantiate these, you will essentially need to do this in exactly the same way that your MVC app is doing this.
If you are unsure where in your MVC app these are being configured, I'd suggest that the first place to look is in the IoC configuration and work backword from there.

MVC 3 + EF 4.1 + POCOs + ViewModel pattern + Controller with scaffolding == confusion!

I'm [finally!] tackling MVC (version 3) after years of ASP.NET forms development. I have a strong background in n-tier application architecture, and I'm trying to approach this new project properly, with a clear separation of concerns, etc.
What I've done is start out with code-first by creating my POCOs. From this, the framework created my database.
Then, I implemented the Repository pattern by putting all my EF query and CRUD methods in a Repository class for each of my POCO classes in my Models assembly. This way, my Controllers don't need to know a thing about how I access my data via the EF. Great.
Finally, I created a few ViewModel classes in my Models assembly. My intent is, for certain actions (such as create and edit), I reference my ViewModel classes from the RAZOR views, instead of my POCO classes. This way, I can have my POCO class as well as a SelectList for populating a Drop Down within my ViewModel. Both populated by references to the associated Repository classes, which are called from my Controller Actions. I think I'm on a roll now:
class MyObject
{
public int ID {get;set}
[Required]
[StringLength(512)]
public string Name {get;set;}
}
class MyViewModel // ViewModel for a specific view
{
public MyObject MyModel {get;set;} // the model that is being edited
// other data the view might need, set by the controller
public string SomeMessage { get; set; }
public List<SomeObject> SomeObjects {get;set;} /// e.g. for a drop-down list
// My constructor below that populates the "SomeObjects" list, and accepts the
// "MyObject" class as a parameter in order to set the "MyModel" property above...
// ..........
}
The Problem...
Before I started using my ViewModel classes from my Controller Create and Edit actions, I passed in the POCO class directly. Everything worked fine when I hit the save button from my Edit form within my view:
Old Code:
[HttpPost]
public ActionResult Edit(MyObject mine)
{
if (ModelState.IsValid)
{
myRepository.Update(mine);
myRepository.SaveChanges();
return RedirectToAction("Index");
}
return View(mine);
}
When I hit save, my POCO class (MyObject) would be returned, automagically populated with values from the form, it would successfully save, and life was peachy.
When I switched to passing in my ViewModel (MyViewModel), everything fell apart.
I was able to refer to my ViewModel (MyViewModel) by setting the #model reference at the top of my Edit view. I was then able to populate my form fields from my POCO class (MyObject) that is part of the ViewModel. I was even able to populate the DropDownList from the SomeObjects collection in the ViewModel and preselect the correct one from my MyObject class I was editing. Everything seemed fine UNTIL...
When I hit the save button and my Controller's Edit ActionResult (POST action) was called, the MyObject class that is passed in to the ActionResult (public ActionResult Edit(MyObject mine)) was null.
Then, I tried changing the passed in object to my ViewModel (public ActionResult Edit(MyViewModel myVM)), which had the referenced MyObject class (MyModel) as null.
What am I missing?
I know it has to be something so incredibly simple that it's staring me in the face and I cannot see it!
Look at the FormCollection, the names of the keys should match the properties of the class you want to fill. This is how the default modelbinding of MVC works.
Wim,
Thanks so much for your help. I did have s parameter-less constructor, I had just omitted it from the example.
I actually tracked down the issue. In all fairness, the code I typed in was not the actual code since I didn't have it in front of me when I posted this. What the issue was is that my entity model class reference in my ViewModel actually had its set accessor as private:
public MyObject MyModel {get;private set;}
This had prevented the modelbinder from populating that property when posting back during the controller's save method.
What I'm left to do now is to move my validation logic from my EF POCO to my ViewModel, as seems to be the recommended action in this type of pattern.
Thanks for your time, and I hope this helps out other people with similar issues who are new to this framework.

Best Practices for Struts 2 CRUD

So I've found a bunch of Struts 2 CRUD examples around the web:
Struts 2 CRUD Demo
and a few books:
Apache Struts 2 Web Application Development ISBN: 978-1847193391
Struts 2 Design and Programming ISBN: 978-0980331608
But all of them differ a little bit on how to do form population.
Some suggest implementing the Java interfaces ModelDriven or Prepareable to call come prepare function to pre-populate any needed data members.
Others suggest creating your own PrepareForUpdate action that calls a pre-populate function then redirects to the main edit view.
They also very on how to pass around an object identifier to indicate what object to retrieve for editing. SOme suggest intercepters what others throw it in the URL parameters and retrieve it through ActionContext or pass it around through a s:hidden field.
Is there a Best Practices way to do form population in Struts 2?
What are the advantages/disadvantages to the methods mentioned above?
I'm not aware of any documented best practices, but I've been using Webwork and Struts2 for about three years now, so I can tell you what I've used in my projects. By the way, the CRUD demo documentation you linked to strikes me as a bit out of date (I realize its from the project site).
I split my CRUD work into three different actions:
An action that lists the entities. It supports pagination and populates some type of a table or grid view.
An action that handles both add and edit functionality. Uses a prepare() method to set up dropdowns, etc.
An action that handles delete functionality.
Some suggest implementing the Java interfaces ModelDriven or Prepareable to call come prepare function to pre-populate any needed data members.
That's the approach that I would advocate, although I don't use the ModelDriven interface. For details, check out how Struts2 ModelDriven interface works and the comments on my answer. Whether you use ModelDriven or not is just a personal choice. Also, check out why is model-driven action preferred over object backed bean properties.
Others suggest creating your own PrepareForUpdate action that calls a pre-populate function then redirects to the main edit view.
I have not seen that before and based on your description, I would avoid that technique. It seems wasteful to do a redirect and create an additional HTTP request to achieve the same thing that the prepare() method was designed to handle.
They also very on how to pass around an object identifier to indicate what object to retrieve for editing.
Just pass the identifier in the URL or the form. That's the standard approach for web applications.
I've been using Struts 2 for about 3 years. I use ModelDriven and Prepareable together in the same action. Each domain object (model) has a struts action class that returns a list or single object depending on if the id was passed to the action. This works pretty well for me, and the only time it's been problematic is when using Ajax. I usually separate my Ajax actions into a separate action for the model, if I am using them. I store the model id, as well as any related objects that I might need as hidden HTML fields in the view.
Using this approach, the action and the view are restful. You can leave the page for a long period of time and invoke the action without fear that the action will fail. Here's an example:
public class ApplicationAction extends MyBaseAction
implements ModelDriven<Application>, Preparable {
private static final long serialVersionUID = 7242685178906659449L;
private ApplicationService applicationService;
private Application application;
private Integer id;
List<Application> allApplications;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Application getModel() {
return application;
}
public void prepare() throws Exception {
if(id == null || id.intValue() == 0){
application= new Application();
}else{
application= applicationService.getApplication(id);
}
}
#SkipValidation
public String list() throws Exception {
allApplications = applicationService.getApplications();
return SUCCESS;
}
#Validations( visitorFields = {#VisitorFieldValidator(message = "Validation Error", fieldName = "model", appendPrefix = false)})
public String update() throws Exception {
applicationService.saveApplication(application);
addActionMessage("Application Saved Successfully.");
return SUCCESS;
}
public void setApplicationService(ApplicationService applicationService) {
this.applicationService = applicationService;
}
public List<Application> getAllApplications() {
return allApplications;
}
}

Resources