4

I have read here http://lostechies.com/jimmybogard/2009/09/18/the-case-for-two-way-mapping-in-automapper/ about how you probably shouldn't be trying to un-flatten a flattened object, but considering how I am using a repository with Entity Framework, the Entity models are expected, not the ViewModels.

I started wondering whether I should be taking a different approach, does anyone have any best practices for this sort of thing? or is it just time to start using ValueInjector Using AutoMapper to unflatten a DTO ? and not being too concerned with mapping RecipeCreateViewModel back to Recipe?

Below is my code to give you an idea of what I have at the moment.

// Entities
public class Recipe {
    public int Id { get; set; }

    public string Name { get; set; }
    public Course Course { get; set; }
}

public class Course {
    public int Id { get; set; }
    public string Name { get; set; }
}

// View Model
public class RecipeCreateViewModel {
    // Recipe properties
    public int Id { get; set; }
    public string Name { get; set; }

    // Course properties, as primitives via AutoMapper
    [Required]
    public int CourseId { get; set; }
    // Don't need CourseName in the viewmodel but it should probably be set in Recipe.Course.Name
    //public string CourseName { get; set; }

    // For a drop down list of courses
    public SelectList CourseList { get; set; }
}


// Part of my View
@model EatRateShare.WebUI.ViewModels.RecipeCreateViewModel
...
<div class="editor-label">
    Course
</div>
<div class="editor-field">
    @* The first param for DropDownListFor will make sure the relevant property is selected *@
    @Html.DropDownListFor(model => model.CourseId, Model.CourseList, "Choose...")
    @Html.ValidationMessageFor(model => model.CourseId)
</div>
...


// Controller actions

public ActionResult Create() {
    // map the Recipe to its View Model
    var recipeCreateViewModel = Mapper.Map<Recipe, RecipeCreateViewModel>(new Recipe());
    recipeCreateViewModel.CourseList = new SelectList(courseRepository.All, "Id", "Name");
    return View(recipeCreateViewModel);
}

[HttpPost]
public ActionResult Create(RecipeCreateViewModel recipe) {
    if (ModelState.IsValid) {
        // set the course name based on the id that was posted
            // not currently checking if the repository doesn't find anything.
    recipe.CourseName = courseRepository.Find(recipe.CourseId).Name;
            var recipeEntity = Mapper.Map<RecipeCreateViewModel, Recipe>(recipe);
        recipeRepository.InsertOrUpdate(recipeEntity);
        recipeRepository.Save();
        return RedirectToAction("Index");
    } else {
        recipe.CourseList = new SelectList(courseRepository.All, "Id", "Name");
        return View(recipe);
    }
}
Community
  • 1
  • 1
Pricey
  • 5,799
  • 12
  • 60
  • 84

1 Answers1

3

If you follow the 'natural' (very subjective) flow it's like this

To create domain model

ViewModel -> Mapper -> Domain Entity -> Repository -> Mapper -> Persistence Entity

To display the update view model

Persistence Entity -> Mapper -> ViewModel

In the first situation you process a dto into a domain entity (apply business rules etc) then send it to the repository where it's persisted in a specific way (EF entities)

In the second situation, you want to load a view model (a DTO) which will be used to update the domain model. Instead of reloading the whole domain entity and then map it to the DTO you're doing it directly from the repository.

You'll probably say this cases don't apply to you as you're working directly against EF. Well, that's the trick, the domain model != persistence model != view model. They are all different and have different concerns.

So, with proper separation you'll always have: view model -> map -> domain entity -> map -> persistnence entity and in opposite direction: persistence entity -> map -> view model

MikeSW
  • 16,140
  • 3
  • 39
  • 53
  • Thanks for the answer Mike, my question wasn't very clear because I'm unsure about a few things and asking several things at once.. im closing this off and you have given a nice clear idea of the create and display layers. The problem i was struggling with was the mapping back from viewmodel. – Pricey Mar 29 '12 at 15:53
  • @MikeSW Why are you skipping domain model when converting back from PM to VM? Isn't it better to map your VM from DM? That way you do it only once in your upper layer. – Joao Leme Apr 19 '13 at 14:59
  • @JoaoLeme It's not. Displaying the update view model requires only saved data from the model which is already available from the persistence entity. so instead of populating the whole object I query directly the storage to get the relevant data. It's pretty much CQRS – MikeSW Apr 19 '13 at 15:15