pavanarya

Let us share the knowledge

Object to Object Mapping using AutoMapper

with one comment

Hi,
Today i want to explain about object to object mapping using AutoMapper.

Let me explain you the problem that this post addresses.

Model Code:

I am having few classes that i am planning to make use in my code.
1.Person class present inside Person.cs
2.Address class present inside Person.cs
3.MyModel class present inside MyModel.cs
4.initializePersonClass class present inside MyModel.cs

Note i am having these two cs files inside Model folder
Person.cs and Address.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MvcApplication2.Models
{
   public class Person
    {
        public string firstname { set; get; }
        public string lastname { set; get; }
        public string middlename { set; get; }
        public Address Address { set; get; }
        public int age { set; get; }
        public string nickname { set; get; }
    }
   public class Address
    {
        public string street { set; get; }
        public string village { set; get; }
        public string city { set; get; }
    }
}

MyModel.cs and initializePersonClass.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Entity;

namespace MvcApplication2.Models
{
    public class MyModel
    {
        public string firstname{set;get;}
        public string lastname{set;get;}
        public string AddressCity { set; get; }
        public string FullName { set; get; }
        public string nicknameFirstNmae { set; get; }

        public string profession { set; get; }
        public string designation { set; get; }
        public string experience { set; get; }

    }

    public class initializePersonClass
    {
       public Person returnPerson()
        {
            Models.Person objPerson = new Person();
            objPerson.firstname = "pavan";
            objPerson.lastname = "Kumar";
            objPerson.middlename = "Aryasomayajulu";
            objPerson.age = 10;
            objPerson.nickname = "Arya";
          Models.Address address = new Address();
            objPerson.Address = address;
            objPerson.Address.city = "Vizag";
            return objPerson;
        }
        
    }
}

In the class initializePersonClass there is a static method called returnPerson() which initializes Person class with some data.

View Code:

Inside the view i am trying to display all the properties of MyModel class.
MyFirstView.cshtml

@{
        //Layout = null;
}
@model MvcApplication2.Models.MyModel
    <div>
Hi My FirstNmae is<h1> @Model.firstname</h1> </br>
Hi My last name is <h1>@Model.lastname</h1></br>
Hi My Nick Name + First Name is<h1> @Model.nicknameFirstNmae</h1></br>
Hi My full Nmae is <h1>@Model.FullName</h1></br>
Hi My City is<h1> @Model.AddressCity</h1></br>
Hi My profession is<h1> @Model.profession</h1></br>
Hi My experience is<h1> @Model.experience</h1></br>
Hi My designation is<h1> @Model.designation</h1></br>
    </div>

Controller Code:

If we see MyModel class and person class. Both these classes have same properties to some extent. MyModel class is having almost all the properties of Person class and in addition we have few more properties.
in order to highlight the problem i am initializing Person class with some default properties in the initializePersonClass’s return Person().

FirstController.cs

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

namespace MvcApplication2.Controllers
{
    public class FirstController : Controller
    {
        public ActionResult Index()
        {

            MvcApplication2.Models.initializePersonClass init = new Models.initializePersonClass();
            Models.Person per = init.returnPerson();
            Models.MyModel mod = new Models.MyModel();
            mod.AddressCity = per.Address.city;
            mod.nicknameFirstNmae = per.nickname + "" + per.firstname;
            mod.firstname = per.firstname;
            mod.FullName = per.firstname + "" + per.lastname;
            mod.lastname = per.lastname;

            mod.experience = "2yrs";
            mod.designation="Associate s/w engineer";
            mod.profession="Information Technology";
            return View("myFirstView",mod);
        }

    }  
}

So in my FirstController’s index() i am calling returnPerson() that returns Person class object with some default values.
once the person class is obtained i am trying to map the properties of Person class to MyModel class(which are common)

            MvcApplication2.Models.initializePersonClass init = new Models.initializePersonClass();
            Models.Person per = init.returnPerson();
            Models.MyModel mod = new Models.MyModel();
            mod.AddressCity = per.Address.city;
            mod.nicknameFirstNmae = per.nickname + "" + per.firstname;
            mod.firstname = per.firstname;
            mod.FullName = per.firstname + "" + per.lastname;
            mod.lastname = per.lastname;

            mod.experience = "2yrs";
            mod.designation="Associate s/w engineer";
            mod.profession="Information Technology";

I feel that this assigning is an extra burden.and if we have some 20-30 properties in common between these two objects(person and myModel) then we should end up having 20-30 lines in just mapping them.
The answer to this problem is making use of AutoMapper tool.

AutoMapper

AutoMapper is a tool that was developed to address the above problem.We can download required dlls from this site AutoMapper.zip. Zip file consist of few dll and from them we can choose AutoMapper.dll and add that to our MVC project.

Basic Object Mapping

namespace MvcApplication2.Controllers
{
    public class FirstController : Controller
    {
        public ActionResult Index()
        {
            MvcApplication2.Models.initializePersonClass init = new Models.initializePersonClass();
            Models.Person per = init.returnPerson();//This will return the object of Person class with default values
            AutoMapper.Mapper.CreateMap<Models.Person, Models.MyModel>();
            Models.MyModel mod = AutoMapper.Mapper.Map<Models.Person, Models.MyModel>(per);
            return View("myFirstView",mod);
        }
    }  
}

If we see the above code we are returning an object of Person Class using the method returnPerson(). Next step would be to create an object of MyModal class with some values. Previously we used to assign each value individually but with AutoMapper we can map Person class to MyModal Class.

Step 1:

AutoMapper.Mapper.CreateMap<source, destination>();//source=Fully qualifying name of source class
//destination=Fully qualifying name of the class to which the data is supposed to be mapped.

step2:

destiantion obj= AutoMapper.Mapper.Map<source, destination>(objOfSource);

If we see the above image we can see only the firstname and lastname fields were filled with the values from person class and remaining fields were null.
This is because firstname and lastname are the only fields that were common in both the classes Person and MyModel.

Mapping properties from different classes
If we observe person class there is a property Address that sets or gets object of Address class. And inside Address class there is a property called city.

Now if we observer MyModel class we have a property called AddressCity. So can we Map MyModel’s city property to address class city property.
The answer to this question is perfectly “Yes”.

So what we are supposed to do for achieving this. The answer to this question is Nothing in special. We can follow the same process as mentioned under the heading AutoMapper.

But there are few things we are supposed to keep in mind.

1. The destination property(in our case AddressCity of Person class) is supposed to follow the naming convention.
SourcePropertyClassNmae+Propertyname(For example we are trying to map city property of address to person class so the person class should have the name AddressCity).
Note:SourcePropertyClassNmae+Propertyname here property name should always have first letter as capital letter irrespective of the source class propertyname.

In our example Address class has a property “city”. Here city is completely in small case. But in person class the property name should be AddressCity.Here City should have first letter as capital.

Custom Property Mapping

If we observe MyModel class we can see few properties like FullName and nickNameFirstName. We know that FullName is nothing but combination of firstname and lastname. In the same way NickNameFirstName.

So can we map Person class firstname and lastname to FullName?? of MyModel class
Yes. But it needs some extra coding.

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

namespace MvcApplication2.Controllers
{
    public class FirstController : Controller
    {
        public ActionResult Index()
        {

            MvcApplication2.Models.initializePersonClass init = new Models.initializePersonClass();
            Models.Person per = init.returnPerson();
            AutoMapper.Mapper.CreateMap<Models.Person, Models.MyModel>().ForMember(dest => dest.FullName, person => person.MapFrom(pers => pers.firstname + "" + pers.lastname));
            AutoMapper.Mapper.CreateMap<Models.Person, Models.MyModel>().ForMember(dest => dest.nicknameFirstNmae, person => person.MapFrom(pers => pers.nickname + "" + pers.firstname));
            //AutoMapper.Mapper.CreateMap<Models.Person, Models.MyModel>().BeforeMap((pers, mymod) => { pers.firstname = "ModifiedFirstname"; });
            AutoMapper.Mapper.CreateMap<Models.Person, Models.MyModel>();
            Models.MyModel mod = AutoMapper.Mapper.Map<Models.Person, Models.MyModel>(per);
            return View("myFirstView",mod);
        }
    }
}

There is a method called ForMemeber(). This method is used to customize the mapping of individual attributes from source class to destination class.

Mapper
    .CreateMap<TSource, TDestination>()
    .ForMember(
        dest => dest.SomeDestinationProperty,
        source=> source.MapFrom(src => src.SomeSourceProperty)
    );

So if we see above image both the properties FullName and nickNameFirstName were filled with values from Person class.
Also we can see few more fields like designation,Profession,experience were still null and we dont have these properties either in Person class or Address class.

So we are supposed to manually assign values to these properties.

public ActionResult Index()
        {

            MvcApplication2.Models.initializePersonClass init = new Models.initializePersonClass();
            Models.Person per = init.returnPerson();
            AutoMapper.Mapper.CreateMap<Models.Person, Models.MyModel>().ForMember(dest => dest.FullName, person => person.MapFrom(pers => pers.firstname + "" + pers.lastname));
            AutoMapper.Mapper.CreateMap<Models.Person, Models.MyModel>().ForMember(dest => dest.nicknameFirstNmae, person => person.MapFrom(pers => pers.nickname + "" + pers.firstname));

            //AutoMapper.Mapper.CreateMap<Models.Person, Models.MyModel>().BeforeMap((pers, mymod) => { pers.firstname = "ModifiedFirstname"; });
            AutoMapper.Mapper.CreateMap<Models.Person, Models.MyModel>();
            Models.MyModel mod = AutoMapper.Mapper.Map<Models.Person, Models.MyModel>(per);
            mod.experience = "2yrs";
            mod.designation="Associate s/w engineer";
            mod.profession="Information Technology";
            return View("myFirstView",mod);
        }

Thanks,
Pavan

Written by pavanarya

June 23, 2012 at 9:29 pm

Posted in MVC

One Response

Subscribe to comments with RSS.

  1. Good one… Did you got any chance to apply this in your project(s) ?

    Bala

    June 25, 2012 at 3:58 pm


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 68 other followers

%d bloggers like this: