1

This is going to be a long question, but in short, I still cannot figure out why it is BETTER to use View Model instead of Model when dealing with CRUD actions

This is what I've learnt so far, please correct me along the way. So when trying to implement a "Create" action method, it is "best practice" to do the following(I am using entity framework code first here):

DAL

  1. You create your entities
  2. You map these entities to the database
  3. You interact with the database in DAL using the repository pattern
  4. You create your interface

BLL(Controller)

  1. You do dependency injection to access the methods created in DAL using Unity/Ninject/Nhibernate etc...
  2. Now you go on create your View Model(optional) Views and Controller actions

When creating controller actions for example you can do this:

public ActionResult Create()  
{  
    return View();  
}  

//  
// POST: /CRUD/Create  

[HttpPost]  
[ValidateAntiForgeryToken]  
public ActionResult Create(Employee employee) ---- Using actual entities  
{  
    if (ModelState.IsValid)  
    {  
        repository.Add(employee);   
        return RedirectToAction("Index");  
    }  

    return View(employee);  
}

In view you do:

@model foo.Entities.Employee

Or:

public ActionResult Create()  
{  
    var model = new EmployeeViewModel();
    return View(model);  
}  

//  
// POST: /CRUD/Create  

[HttpPost]  
[ValidateAntiForgeryToken]  
public ActionResult Create(EmployeeViewModel model) ---- Using viewmodel  
{  
    if (ModelState.IsValid)  
    {  
        //map here or use automapper
        var employee = new Employee()
        employee.Name = model.Name;

        repository.Add(employee);  
        return RedirectToAction("Index");  
    }  

    return View(employee);  
}

In view you do this:

@model foo.Model.EmployeeViewModel

What exactly is the difference? why use the View Model with more code involved??

and also I am trying to implement update controller action using view model as well:

public ActionResult Edit(int jobId)
{
    Job job = repository.FindJob(jobId);

    if (job == null)
    {
        return HttpNotFound();
    }

    var model = new JobEditViewModel();

    //mapping to get information from database and display
    ConfigureEditViewModel(job, model);

    return View(model);
}

private void ConfigureCreateViewModel(JobCreateViewModel model)
{
        model.Title = job.Title;
        model.NumberOfPosition = job.NumberOfPosition;
        model.Salary = job.Salary;
        model.SelectedSalaryPeriodId = job.SalaryPeriodId;
        model.PostCode = job.PostCode;
        model.SelectedLocationId = job.LocationId;
        model.IndustryExperiencePeriod = job.IndustryExperiencePeriod;
        model.Role = job.Role;
        model.Description = job.Description;
        model.SelectedEmploymentHourId = job.EmploymentHourId;
        model.SelectedDurationId = job.DurationId;
        model.SelectedShiftId = job.ShiftId;
        model.SelectedWorkDayId = job.WorkDayId;
}

and when posting

[HttpPost]  
[ValidateAntiForgeryToken]  
public ActionResult Edit(JobEditViewModel model) ---- Using viewmodel  
{  
    if (ModelState.IsValid)  
    {  
        //mapping model back to the entity...
        var job = new Job()

        job.Title = model.Title;
        job.NumberOfPositions = .......


        repository.Edit(job); 
        return RedirectToAction("Index");  
    }  

    return View(job);  
}

When using view model, you are mapping entity to model to display information and then mapping model back to the entity when updating(post action). I think i am missing something during the mapping process, to me it just seems like I am constantly mapping back and forth between view model and actual entity, am i missing something(is that why automapper is used?).

I searched online and using View Model seems like the better approach(strongly-typed view?), but there is just so much more code involved, it that suppose to happen or am i doing it wrong.

Mindless
  • 2,352
  • 3
  • 27
  • 51
  • 1
    The Model is just a representation of your Entities. It should not have to deal with any business logic, hence the BLL. In other words, the Model is 'dumb'. Everything related to logic should be handled by the ViewModel. (Very simplistic answer, but you should read on the MVVM/MVC architecture) – trinaldi Nov 05 '14 at 04:50
  • 1
    Lots of good answers explaining the benefits of using a view model [here](http://stackoverflow.com/questions/11064316/what-is-viewmodel-in-mvc) –  Nov 05 '14 at 04:54
  • @Tico Yes I understand model is just my entities, but why it should not deal with business logic? people just say you shouldn't, but why?? – Mindless Nov 05 '14 at 04:54
  • @Stephen Thanks for the link, it is very helpful, just one thing, is my updating logic correct??? You have to constantly map back and forth??? – Mindless Nov 05 '14 at 04:57
  • 1
    @EricWang, by using layers (DAL, BLL) your code will be easily reusable. It's not that you can't use. But it would defeat the purpose of the architecture. Dealing with changes in the future would be less prone to error. I had the same feeling when I first started, but when things started to grow I understood the purpose of each layer. Want to implement a new logic? Use the BLL, DAL wil be intact and vice-versa. – trinaldi Nov 05 '14 at 04:59
  • 1
    You can use automapper both ways to make it a little easier. Yes it's a bit of extra code (often you can just cut and paste the properties and then add validation attributes, `SelectList` properties etc) but I find the benefits outweigh the extra few minutes of coding. –  Nov 05 '14 at 05:03
  • Another link: http://martinfowler.com/eaaDev/uiArchs.html – trinaldi Nov 05 '14 at 05:09

1 Answers1

1

Yes, The right approach is to map your entities into viewModel or DTO.

And why this is a good approach, because if you have a table with 20 columns, and your screen for example uses just 3 columns of those twenty, then you can map those 3 used columns and send them to the client, and you expect the same ViewModel/DTO back from the client, so you can build a validation around those 3 columns only in that case.

If you didn't use this appraoch, then your client needs to send the 20 columns set even if the client screen didn't use/set more than 3 columns (maybe you will say that I will set those unused columns on the server, which may end-up with a spaghetti code to cover all the cases that your client uses that entity).

Hope that helps.

Omar.Alani
  • 4,050
  • 2
  • 20
  • 31