Use AutoMapper to Map ViewModels to Entities – MVC3 and Razor

0

Posted on : 23-09-2011 | By : Chris | In : MVC

Quite often it is prudent to create ViewModel classes to encapsulate multiple pieces of data (represented by instances of classes) into one easy to manage object that you can pass to your View. This is all well and good but additions and deletes must then  map the data back to the corresponding entities.

  • Mapping code is tedious to write
  • Mapping code is tedious to test

In fact, some of the most boring code in the world to write is mapping between two objects. Enter AutoMapper, described as:

…an object-object mapper. Object-object mapping works by transforming an input object of one type into an output object of a different type. What makes AutoMapper interesting is that it provides some interesting conventions to take the dirty work out of figuring out how to map type A to type B. As long as type B follows AutoMapper’s established convention, almost zero configuration is needed to map two types.

See https://github.com/AutoMapper/AutoMapper/wiki/Getting-started

Here’s an uber simple example of it in use:

 

VIEWMODEL
—————-

namespace BenefitsBenchmarkingTool.ViewModels
{
    public partial class CompanyDepartments
    {
        public int CompanyID { get; set; }
        public IEnumerable<SelectListItem> Companies { get; set; }
        public string DepartmentName { get; set; }
        public string DepartmentEmail { get; set; }
    }
}

VIEW
——–

The View then references the ViewModel: @model BenefitsBenchmarkingTool.ViewModels.CompanyDepartments

 

CONTROLLER
—————–

[HttpPost]
public ActionResult Create(CompanyDepartments departmentToCreate)
{
    if (ModelState.IsValid)
    {
        AutoMapper.Mapper.CreateMap<CompanyDepartments, Department>();
        Department newDepartment = new Department();
        AutoMapper.Mapper.Map(departmentToCreate, newDepartment);
        db.Departments.AddObject(newDepartment);
        db.SaveChanges();
    }
    return RedirectToAction("Index", new { id = departmentToCreate.CompanyID });
}

For more information, check out this excellent post: http://lostechies.com/jimmybogard/2009/01/23/automapper-the-object-object-mapper/

http://chriscurrie.co.uk/blog/wp-content/plugins/sociofluid/images/digg_48.png http://chriscurrie.co.uk/blog/wp-content/plugins/sociofluid/images/reddit_48.png http://chriscurrie.co.uk/blog/wp-content/plugins/sociofluid/images/dzone_48.png http://chriscurrie.co.uk/blog/wp-content/plugins/sociofluid/images/stumbleupon_48.png http://chriscurrie.co.uk/blog/wp-content/plugins/sociofluid/images/delicious_48.png http://chriscurrie.co.uk/blog/wp-content/plugins/sociofluid/images/blinklist_48.png http://chriscurrie.co.uk/blog/wp-content/plugins/sociofluid/images/blogmarks_48.png http://chriscurrie.co.uk/blog/wp-content/plugins/sociofluid/images/furl_48.png http://chriscurrie.co.uk/blog/wp-content/plugins/sociofluid/images/newsvine_48.png http://chriscurrie.co.uk/blog/wp-content/plugins/sociofluid/images/technorati_48.png http://chriscurrie.co.uk/blog/wp-content/plugins/sociofluid/images/magnolia_48.png http://chriscurrie.co.uk/blog/wp-content/plugins/sociofluid/images/google_48.png http://chriscurrie.co.uk/blog/wp-content/plugins/sociofluid/images/myspace_48.png http://chriscurrie.co.uk/blog/wp-content/plugins/sociofluid/images/facebook_48.png http://chriscurrie.co.uk/blog/wp-content/plugins/sociofluid/images/yahoobuzz_48.png http://chriscurrie.co.uk/blog/wp-content/plugins/sociofluid/images/twitter_48.png

@Html.DropDownListFor SelectedValue in a MVC Razor View

2

Posted on : 23-09-2011 | By : Chris | In : MVC

Although ViewBag is often a quick and dirty way to pass values between the controller and the view be careful not to think of it as your friend. In many (most) occasions this approach is just too simplistic to offer the functionality you require.  More often than not you are best implementing a more robust solution. Auto selecting a dropdownlist value in the view is a perfect example.

If you accept the default code Visual Studio (Express 2010) creates for you when you create a controller from a model “with Read Write Actions and Views” you get something like this:

CONTROLLER
—————–
public ViewResult Index()

        {
            var departments = db.Departments.Include("Company");
            return View(departments.ToList());
        }

VIEW
——–
@Html.DropDownList(“CompanyID”, String.Empty)

 

As you can see quick (very quick – auto generated in fact) but dirty…

The correct approach is to forget the ViewBag and go for a more robust approach using a ViewModel…

 

1. Create a View Model (I placed my in a ‘ViewModel’ folder and called it CompanyDepartments.cs)

using System;
using System.Web.Mvc;
using System.Collections.Generic;

namespace BenefitsBenchmarkingTool.ViewModels
{
    public class CompanyDepartments
    {
        public int SelectedCompanyId { get; set; }
        public IEnumerable<SelectListItem> Companies { get; set; }
        public string DepartmentName { get; set; }
        public string DepartmentEmail { get; set; }
        public int CompanyID { get; set; }
    }
}

2. Populate the View Model from the Controller - if, like me you have your View Model in it’s own namespace don’t forget to include it in the controller (e.g. using BenefitsBenchmarkingTool.ViewModels;)

public ActionResult Create(int id)
        {
            var companies = db.Companies;

            var model = new CompanyDepartments
            {
                SelectedCompanyId = id,
                Companies = companies.AsEnumerable().Select(x => new SelectListItem
                {
                    Value = x.CompanyID.ToString(),
                    Text = x.CompanyName
                })
            };
            return View(model);

        }

(Interestingly, if I didn’t add ‘.AsEnumerable()’ I got the error LINQ to Entities does not recognize the method 'System.String ToString()' method, and this method cannot be translated into a store expression)

3. In the View you reference your View Model:

@model BenefitsBenchmarkingTool.ViewModels.CompanyDepartments

Then use the strongly typed DropDownListFor helper:

@Html.DropDownListFor( x => x.SelectedCompanyId, Model.Companies) 
http://chriscurrie.co.uk/blog/wp-content/plugins/sociofluid/images/digg_48.png http://chriscurrie.co.uk/blog/wp-content/plugins/sociofluid/images/reddit_48.png http://chriscurrie.co.uk/blog/wp-content/plugins/sociofluid/images/dzone_48.png http://chriscurrie.co.uk/blog/wp-content/plugins/sociofluid/images/stumbleupon_48.png http://chriscurrie.co.uk/blog/wp-content/plugins/sociofluid/images/delicious_48.png http://chriscurrie.co.uk/blog/wp-content/plugins/sociofluid/images/blinklist_48.png http://chriscurrie.co.uk/blog/wp-content/plugins/sociofluid/images/blogmarks_48.png http://chriscurrie.co.uk/blog/wp-content/plugins/sociofluid/images/furl_48.png http://chriscurrie.co.uk/blog/wp-content/plugins/sociofluid/images/newsvine_48.png http://chriscurrie.co.uk/blog/wp-content/plugins/sociofluid/images/technorati_48.png http://chriscurrie.co.uk/blog/wp-content/plugins/sociofluid/images/magnolia_48.png http://chriscurrie.co.uk/blog/wp-content/plugins/sociofluid/images/google_48.png http://chriscurrie.co.uk/blog/wp-content/plugins/sociofluid/images/myspace_48.png http://chriscurrie.co.uk/blog/wp-content/plugins/sociofluid/images/facebook_48.png http://chriscurrie.co.uk/blog/wp-content/plugins/sociofluid/images/yahoobuzz_48.png http://chriscurrie.co.uk/blog/wp-content/plugins/sociofluid/images/twitter_48.png