How to call model methods in controller in asp.net mvc - asp.net-mvc

I am working on an asp.net mvc application.
This is the approach that i am following right through the application.
Here is my model:
public class EmployeeModel
{
//Properties
// Constructors
// Methods
}
My View: (strongly typed with model Properties) for example : Some Edit View
My Controller:
[httppost]
public void save(Employeemodel m) // ajax call that gets updated model details
{
m.update() // making database call from controller action
}
Are there any serious design issues with my approach of MVC. May be i mis understood MVC?
Is it appropriate to call model methods(m.update() ) in controller action?
Model contains methods that manipulate data ? IS it correct?
please help/suggest the correct approach to follow in MVC

I would recommend you to have separate layer to save data to the database, because its not just MVC that one should follow.
You should use Model(with function only) as a provider whose duty is to perform database task.
ViewModel that hold your entities (properties only)
Controller that can handle your application logic.
View to render HTML/UI.
So its not about MVC rather the best practice one should follow to architect an application.
Further we have several options that we must consider before planning architecture of an application.
Service/Business Layer - Interact b/w Application layer and Repository
Providers/Repository Layer - Interact b/w Service layer and Database
So, it depends on the level of abstraction you want, but as far as MVC concern I would recommend you to have extra layer of separation of ViewModel MVVM.
Its better to ask these type of questions in stachexchange chat.
Example
ViewModel
public class User
{
public Guid Id {get;set;}
public string Name {get;set;}
}
Model
public class UserModel
{
public void AddUser(User user)
{
//add to the database
}
public void UpdateUser(User user)
{
//update in the database
}
}
Controller
[HttpPost]
public ActionResult UpdateUser(User user)
{
UserModel user = new UserModel();
user.UpdateUser(user);
}

In general practice you should now follow this methodology.
Although this is the default MVC behavior of accepting entire model as an argument you should have a middle layer called as DTO(Data Transfer Object) or ViewModel which represents UI.
And after accepting and validating View model you can transform it to your main business entity.
Offcouse it depends how you have written code in your update method but the main hack is this case is that.... any body can pass any known property value to this method and can hack your system. for example suppose you have following values in your Employeemodel
{
Id,
Name,
SecurityCode,
...
}
and your edit screen just have Name input to update it. Any body can add extra html for SecurityCode and can add bad value to it :)
I hope i didn't confused you.
For start try to implement Repository pattern MVC... Google it and you'll find the basic usage of it. :)
Cheers

Your logic is fine. But as K D said, you should have viewmodel that represents view. I would suggest you write your methods in view model since you will pass only model entity to database or anywhere else.
public class Employee
{
//Properties
}
public class EmployeeViewmodel
{
// Employee model object
//Constructors
//Methods
}
return view("View name", EmployeeViewModel);
So you can update model, pass Employee alone to Database via OR/M ..This is basic flexible approach. You can have a utility model class which contains common data retrival like City, state, gender .. so you wont mix entity with other models.

Related

In MVC where to perform calculations when data is coming from UI?

I have been reading about where to put business logic in ASP.NET MVC Project and I still can't get clear on some things. Especially performing the calculations or business logic when the data is coming from UI.
I have ASP.NET MVC application using EF. The application is typical 3 tier application.
UI - has View Models
Domain (aka Service Layer) - has DTO classes
DAL - has EF entities
Each layer has its own C# classes used for transferring data between the layers.
UI has reference to Domain and Domain has reference to DAL
The business logic of the application is in Domain (service layer)
Typically any kind of business logic/calculations are done in service layer. And that is correct when the data is coming from the database.
But what if the data is coming from UI?
Lets say the view is already rendered with several fields. There is corresponding view model in UI layer. A user update some fields and click a button, which makes a ajax POST to controller action. So server now has populated view model that is coming from UI. Now i want to do some calculations and return json data.
[HttpGet]
public ActionResult Index(int id)
{
MyViewModel model = _service.GetModel(id);
return View(model);
}
[HttpPost]
public ActionResult Calculate(MyViewModel model)
{
// preform calculations but where??
var differentmodel = PerformCalculations(model);
return Json(someDifferentmodel);
}
Since Domain Layer cannot have access to View Models i can not pass MyViewModel to Domain and do the calculation there.
One option i see here like below
public ActionResult Calculate(MyViewModel model)
{
1> Convert MyViewModel to DTO
2> pass DTO to service layer for calculations
3> get calculated DTO from service layer.
4> Convert DTO to differentViewModel
return Json(differentViewModel);
}
There is lot of back & forth mapping, which seems unnecessary.
Is there any better approach?
In terms of design practice, Is it okay to introduce a new layer between UI and Domain that has reference to both UI and Domain. This new layer will be responsible to do the business logic/calculations. In-fact then i can use this layer for calculations regardless the data is coming from UI or domain. What would be this layer? (I know technically i can do that but i am asking is it recommended design practice)
You're making this unnecessarily complex. The first question to ask is: "Is this calculation logic relevant only to the view or is it applicable in other places, such as the DAL? If it's only relevant to the view, put it on your view model. If it has broader applicability then put it in a class library or something that is reference by all projects that need it. In that latter case, you'd likely just create a helper class that does the calculations, and you'd pass in only the relevant data to make those calculations.
Then, in your UI layer, you can either utilize the view model or another helper class to specifically handle the view model. For example:
Class Library
public static class CalculationHelper
{
public static int Add(int a, int b)
{
return a + b;
}
}
UI
public class MyViewModel
{
...
public FooBarSum
{
get { return CalculationsHelper.Add(Foo, Bar); }
}
}
OR
public static class UICalculationsHelper
{
public static int Add(MyViewModel model)
{
return CalculationsHelper.Add(model.Foo, model.Bar);
}
}

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.

How to mock a model in ASP.NET MVC?

I've made a custom model, and I want to mock it. I'm fairly new to MVC, and very new to unit testing. Most approaches I've seen create an interface for the class and then make a mock that implements the same interface. However I can't seem to get this to work when actually passing the interface into the View. Cue "simplified" example:
Model-
public interface IContact
{
void SendEmail(NameValueCollection httpRequestVars);
}
public abstract class Contact : IContact
{
//some shared properties...
public string Name { get; set; }
public void SendEmail(NameValueCollection httpRequestVars = null)
{
//construct email...
}
}
public class Enquiry : Contact
{
//some extra properties...
}
View-
<%# Page Language="C#" Inherits="System.Web.Mvc.ViewPage<project.Models.IContact>" %>
<!-- other html... -->
<td><%= Html.TextBoxFor(model => ((Enquiry)model).Name)%></td>
Controller-
[HttpPost]
public ActionResult Index(IContact enquiry)
{
if (!ModelState.IsValid)
return View(enquiry);
enquiry.SendEmail(Request.ServerVariables);
return View("Sent", enquiry);
}
Unit Testing-
[Test]
public void Index_HttpPostInvalidModel_ReturnsDefaultView()
{
Enquiry enquiry = new Enquiry();
_controller.ModelState.AddModelError("", "dummy value");
ViewResult result = (ViewResult)_controller.Index(enquiry);
Assert.IsNullOrEmpty(result.ViewName);
}
[Test]
public void Index_HttpPostValidModel_CallsSendEmail()
{
MockContact mock = new MockContact();
ViewResult result = (ViewResult)_controller.Index(mock);
Assert.IsTrue(mock.EmailSent);
}
public class MockContact : IContact
{
public bool EmailSent = false;
void SendEmail(NameValueCollection httpRequestVars)
{
EmailSent = true;
}
}
Upon a HttpPost I get a "Cannot create an instance of an interface" exception. I seems that I can't have my cake (passing a model) and eat it (pass mock for unit testing). Maybe there's a better approach to unit testing models bound to views?
thanks,
Med
I'm going to throw it out there, if you need to mock your models you're doing it wrong. Your models should be dumb property bags.
There is absolutely no reason that your model should have a SendEmail method. That is functionality that should be invoked from a controller calling to an EmailService.
Responding to your question:
After years of working with Separation of Concern (SOC) patterns like MVC, MVP, MVVM and seeing articles from people brighter than me (I wish I could find the one I'm thinking off about this but maybe I read it in a magazine). You will eventually conclude in an enterprise application you will end up with 3 distinct sets of model objects.
Previously I was a very big fan of doing Domain Driven Design (DDD) using a single set of business entities that were both plain old c# objects (POCO) and Persistent Ignorant (PI). Having domain models that are POCO/PI leaves you with a clean slate of objects where there is no code related to accessing the object storage or having other attributes that have schematic meaning for only 1 area of the code.
While this works, and can work fairly well for a period of time, there is eventually a tipping point where the complexity of expressing the relationship between View, Domain Model, and Physical Storage Model becomes too complex to express correctly with 1 set of entities.
To solve the impedance mismatches of View, Domain and Storage you really need 3 sets of models. Your ViewModels will exactly match your views binding to facilitate it to be easy to work with the UI. So this will frequently have things such as adding a List to populate drop downs with values that are valid for your edit view/action.
In the middle is the Domain Entities, these are the entities that you should validate against your business rules. So you will map to/from them on both sides to/from the view and to/from the storage layer. In these entities is where you could attach your code to do validation. I personally am not a fan of using attributes and coupling validation logic into your domain entities. It does make alot of sense to couple validation attributes into your ViewModels to take advantage of the built in MVC client side validation functionality.
For validation I would recommend using a library like FluentValidation (or your own custom one, they're not hard to write) that lets you separate your business rules from your objects. Although with new features with MVC3 you can do remote validation severside and have it display client side, this is an option to handle true business validation.
Finally you have your storage models. As I said previously I was very zealous on having PI objects being able to be reused through all layers so depending on how you setup your durable storage you might be able to directly use your domain objects. But if you take advantage of tools like Linq2Sql, EntityFramework (EF) etc you will most likely have auto generated models with code for interacting with the data provider so you will want to map your domain objects to your persistence objects.
So wrap all of this up this would be a standard logic flow in MVC actions
User goes to edit product page
EF queries the database to get the existing product information, inside the repository layer the EF data objects are mapped to the Business Entities (BE) so all the data layer methods return BEs and have no external coupling to the EF data objects. (So if you ever change your data provider you don't have to alter a single line of code except for the internal implementation)
The controller gets the Product BE and maps it to a Product ViewModel (VM) and adds collections for the different options that can be set for drop down lists
Return View(theview, ProductVM)
User edits the product and submits the form
Client side validation is passed (useful for date validation / number validation instead of having to submit the form for feedback)
The ProductVM gets mapped back to ProductBE at this point you would validate the business rules along the lines ValidationFactory.Validate(ProductBE), if it's invalid return messages back to view and cancel edit, otherwise continue
You pass the ProductBE into your repository model, inside the internal implementation of the data layer you map the ProductBE to the Product Data Entity for EF and update the database.
2016 edit: removed usages of Interface as separation of concerns and interfaces are entirely orthogonal.
Your issue is here:
public ActionResult Index(IContact enquiry)
MVC in the background has to create a concrete type to pass to the method when calling it. In this method's case, MVC needs to create a type which implements IContract.
Which type? I dunno. Neither does MVC.
Instead of using interfaces in order to be able to mock your models, use normal classes that have protected methods which you can override in mocks.
public class Contact
{
//some shared properties...
public string Name { get; set; }
public virtual void SendEmail(NameValueCollection httpRequestVars = null)
{
//construct email...
}
}
public class MockContact
{
//some shared properties...
public string Name { get; set; }
public bool EmailSent {get;private set;}
public override void SendEmail(NameValueCollection vars = null)
{
EmailSent = true;
}
}
and
public ActionResult Index(Contact enquiry)
It is possible to use interfaces.
See: http://mvcunity.codeplex.com/

Fetching data within an ASP.NET MVC ViewModel class?

For those that create ViewModels (for use by typed views) in ASP.NET MVC, do you prefer to fetch the data from a service/repository from within the ViewModel, or the controller classes?
For example, we started by having ViewModels essentially being DTOs and allowing our Controllers to fetch the data (grossly oversimplified example assumes that the user can only change employee name):
public class EmployeeViewModel
{
public String Name; //posted back
public int Num; //posted back
public IEnumerable<Dependent> Dependents; //static
public IEnumerable<Spouse> Spouses; //static
}
public class EmployeeController()
{
...
public ActionResult Employee(int empNum)
{
Models.EmployeeViewModel model = new Models.EmployeeViewModel();
model.Name = _empSvc.FetchEmployee(empNum).Name;
model.Num = empNum;
model.Dependents = _peopleSvc.FetchDependentsForView(empNum);
model.Spouses = _peopleSvc.FetchDependentsForView(empNum);
return View(model);
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Employee(Models.EmployeeViewModel model)
{
if (!_empSvc.ValidateAndSaveName(model.Num, model.Name))
{
model.Dependents = _peopleSvc.FetchDependentsForView(model.Num);
model.Spouses = _peopleSvc.FetchDependentsForView(model.Num);
return View(model);
}
this.RedirectToAction(c => c.Index());
}
}
This all seemed fine until we started creating large views (40+ fields) with many drop downs and such. Since the screens would have a GET and POST action (with POST returning a view if there was a validation error), we'd be duplicating code and making ViewModels larger than they probably should be.
I'm thinking the alternative would be to Fetch the data via the Service within the ViewModel. My concern is that we'd then have some data populated from the ViewModel and some from the Controller (e.g. in the example above, Name would be populated from the Controller since it is a posted value, while Dependents and Spouses would be populated via some type of GetStaticData() function in the ViewModel).
Thoughts?
I encountered the same issue. I started creating classes for each action when the code got too big for the action methods. Yes you will have some data retrieval in classes and some in the controller methods. The alternative is to have all the data retrieval in classes, but half the classes you won't really need, they will have been created for consistency sake or have all the data retrieval in the controller methods, but again, some of those methods will be too complex and needed to have been abstracted into classes... so pick your poison. I would rather have a little inconsistency and have the right solution for the job.
As for putting behavior into the ViewModel, I don't, the point of the ViewModel is to be a thin class for setting and extracting values from the View.
There have been cases where I've put conversion methods in the ViewModel. For instance I need to convert the ViewModel to the corresponding entity or I need to load the ViewModel with data from the Entity.
To answer your question, I prefer to retrieve data from with in the controller/action methods.
Typically with DropDowns, I create a dropdown service. DropDowns tend to be the same data that spans views. With the dropdowns in a service I can use them on other views and/or Cache them.
Depending on the layout, 40 plus fields could create a cluttered view. Depending the type of data, I would try to span that many fields across multiple views with some sort of tabbed or wizard interface.
There's more than that ;-) You can fetch in model binder or action filter. For the second option, check Jimmy Bogard's blog somewhere around here. I personally do it in model binders. I use ViewModel like this: My custom ASP.NET MVC entity binding: is it a good solution?. It is processed by my custom model binder:
public object BindModel(ControllerContext c, BindingContext b)
{
var id = b.ValueProvider[b.ModelName]; // don't remember exact syntax
var repository = ServiceLocator.GetInstance(GetRepositoryType(b.ModelType));
var obj = repository.Get(id);
if (obj == null)
b.ModelState.AddModelError(b.ModelName, "Not found in database");
return obj;
}
public ActionResult Action(EntityViewModel<Order> order)
{
if (!ModelState.IsValid)
...;
}
You can also see an example of model binder doing repository access in S#arp Architecture.
As for static data in view models, I'm still exploring approaches. For example, you can have your view models remember the entities instead of lists, and
public class MyViewModel
{
public MyViewModel(Order order, IEmployeesSvc _svc)
{
}
public IList<Employee> GetEmployeesList()
{
return _svc.GetEmployeesFor(order.Number);
}
}
You decide how you inject _svc into ViewModel, but it's basically the same as you do for controller. Just beware that ViewModel is also created by MVC via parameterless constructor, so you either use ServiceLocator or extend MVC for ViewModel creation - for example, inside your custom model binder. Or you can use Jimmy Bogard's approach with AutoMapper which does also support IoC containers.
The common approach here is that whenever I see repetative code, I look to eliminate it. 100 controller actions doing domain-viewmodel marshalling plus repository lookup is a bad case. Single model binder doing it in generic way is a good one.
I wouldn't be fetching data from the database in your ViewModel. The ViewModel exists to promote separation of concerns (between your View and your Model). Tangling up persistance logic in there kind of defeats the purpose.
Luckily, the ASP.NET MVC framework gives us more integration points, specifically the ModelBinder.
I've got an implementation of a generic ModelBinder pulling information from the service layer at:-
http://www.iaingalloway.com/going-further-a-generic-servicelayer-modelbinder
It doesn't use a ViewModel, but that's easily fixed. It's by no means the only implementation. For a real-world project, you're probably better off with a less generic, more customised solution.
If you're diligent, your GET methods don't even need to know that the service layer exists.
The solution probably looks something like:-
Controller action method:-
public ActionResult Details(MyTypeIndexViewModel model)
{
if( ModelState.IsValid )
{
return View(model);
}
else
{
// Handle the case where the ModelState is invalid
// usually because they've requested MyType/Details/x
// and there's no matching MyType in the repository
// e.g. return RedirectToAction("Index")
}
}
ModelBinder:-
public object BindModel
(
ControllerContext controllerContext,
BindingContext bindingContext
)
{
// Get the Primary Key from the requestValueProvider.
// e.g. bindingContext.ValueProvider["id"]
int id = ...;
// Get an instance of your service layer via your
// favourite dependancy injection framework.
// Or grab the controller's copy e.g.
// (controllerContext.Controller as MyController).Service
IMyTypeService service = ...;
MyType myType = service.GetMyTypeById(id)
if (myType == null)
{
// handle the case where the PK has no matching MyType in the repository
// e.g. bindingContext.ModelState.AddModelError(...)
}
MyTypeIndexViewModel model = new MyTypeIndexViewModel(myType);
// If you've got more repository calls to make
// (e.g. populating extra fields on the model)
// you can do that here.
return model;
}
ViewModel:-
public class MyTypeIndexViewModel
{
public MyTypeIndexViewModel(MyType source)
{
// Bind all the properties of the ViewModel in here, or better
// inherit from e.g. MyTypeViewModel, bind all the properties
// shared between views in there and chain up base(source)
}
}
Build your service layer, and register your ModelBinder as normal.
Here's another solution: http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/06/29/how-we-do-mvc-view-models.aspx
Main points there:
Mapping is done by a mediator - in this case it is AutoMapper but it can be your own class (though more to code). This keeps both Domain and ViewModel concentrated on the domain/presentation logic. The mediator (mapper) will contain (mostly automatic) logic for mapping, including injected services.
Mapping is applied automatically, all you do is tell the action filter the source/destination types - very clean.
(Seems to be important for you) AutoMapper supports nested mappings/types, so you can have your ViewModel combined of several independent view models, so that your "screen DTO" is not messy.
Like in this model:
public class WholeViewModel
{
public Part1ViewModel ModelPart1 { get; set; }
public Part2ViewModel ModelPart2 { get; set; }
}
you re-use mappings for specific parts of your View, and you don't write any new line of code, since there're already mappings for the partial view models.
If you don't want AutoMapper, you have have IViewModelMapper interfaces, and then your IoC container will help your action filter to find appropriate
container.Resolve(typeof(IViewModelMapper<>).MakeGenericType(mysourcetype, mydesttype))
and it will also provide any required external services to that mapper (this is possible with AutoMapper, too). But of course AutoMapper can do recursions and anyway, why write additional AutoMapper ;-)
Consider passing your services into the custom ViewModel on its constructor (ala Dependency Injection). That removes the model population code from your controller and allows it to focus on controlling the logical flow of the application. Custom ViewModels are an ideal place to abstract the preparation of things like SelectLists that your droplists will depend on.
Lots of code in the controller for things like retrieving data isn't considered a best practice. The controller's primary responsibility is to "control" the flow of the application.
Submitting this one late... Bounty is almost over. But...
Another mapper to look at is Automapper: http://www.codeplex.com/AutoMapper
And overview on how to use it: http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/01/22/automapper-the-object-object-mapper.aspx
I really like it's syntax.
// place this somewhere in your globals, or base controller constructor
Mapper.CreateMap<Employee, EmployeeViewModel>();
Now, in your controller, I would use multiple viewmodels. This enforces DRY by allowing you to reuse those viewmodels elsewhere in your application. I would not bind them all to 1 viewmodel. I would refactor to something like:
public class EmployeeController()
{
private IEmployeeService _empSvc;
private ISpouseService _peopleSvc;
public EmployeeController(
IEmployeeService empSvc, ISpouseService peopleSvc)
{
// D.I. hard at work! Auto-wiring up our services. :)
_empSvc = empSvc;
_peopleSvc = peopleSvc;
// setup all ViewModels here that the controller would use
Mapper.CreateMap<Employee, EmployeeViewModel>();
Mapper.CreateMap<Spouse, SpouseViewModel>();
}
public ActionResult Employee(int empNum)
{
// really should have some validation here that reaches into the domain
//
var employeeViewModel =
Mapper.Map<Employee, EmployeeViewModel>(
_empSvc.FetchEmployee(empNum)
);
var spouseViewModel =
Mapper.Map<Spouses, SpousesViewModel>(
_peopleSvc.FetchSpouseByEmployeeID(empNum)
);
employeeViewModel.SpouseViewModel = spouseViewModel;
return View(employeeViewModel);
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Employee(int id, FormCollection values)
{
try
{
// always post to an ID, which is the employeeID
var employee = _empSvc.FetchEmployee(id);
// and bind using the built-in UpdateModel helpers.
// this will throw an exception if someone is posting something
// they shouldn't be posting. :)
UpdateModel(employee);
// save employee here
this.RedirectToAction(c => c.Index());
}
catch
{
// check your domain model for any errors.
// check for any other type of exception.
// fail back to the employee screen
RedirectToAction(c => c.Employee(id));
}
}
}
I generally try to stay away from saving multiple entities on a controller action. Instead, I would refactor the employee domain object to have AddSpouse() and SaveSpouse() methods, that would take an object of Spouse. This concept is known as AggregateRoots, controlling all dependancies from the root - which is the Employee() object. But, that is just me.

using ViewModels for POST actions in MVC elegantly

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
}
}

Resources