Click here to Skip to main content
12,254,932 members (59,982 online)
Click here to Skip to main content
Add your own
alternative version

Stats

132.3K views
7.1K downloads
135 bookmarked
Posted

CRUD Opearations using AutoMapper in an MVC Application

, 26 Nov 2014 CPOL
Rate this:
Please Sign up or sign in to vote.
How to do custom mapping and entity to entity mapping with the help of AutoMapper.

Introduction

In our article series of Learning MVC, we learnt a lot about MVC, about various techniques to communicate to a database in MVC applications, and a few internal concepts too.

When we indulge into real-time programming environments, we face not only one but many types of challenges in the code. This article explains a new concept, Auto Mapper in MVC applications, to overcome one of the major challenges we face while communicating with data entities and binding them to our model.

Challenge

Sometimes while interacting with real time (database) entities and binding our model to them, we end up in a situation like:

var dbContext = new MyDBDataContext();
var userDetails = dbContext.Users.FirstOrDefault(userId => userId.UserId == id);
var user = new LearningMVC.Models.User();
if (userDetails != null)
{
    user.UserId = userDetails.UserId;
    user.FirstName = userDetails.FirstName;
    user.LastName = userDetails.LastName;
    user.Address = userDetails.Address;
    user.PhoneNo = userDetails.PhoneNo;
    user.EMail = userDetails.EMail;
    user.Company = userDetails.Company;
    user.Designation = userDetails.Designation;
}
return View(user);

The above mentioned code is not very hard to understand. In the above code, an instance var dbContext = new MyDBDataContext(); is created from the LINQ to SQL Context class, thereafter the user details are fetched  from a user specific table and stored in the var userDetails variable. We have an existing model named User (LearningMVC.Models.User()) that has similar properties as that of the Users class generated from the database. Now we initialize properties of the instance of our model from properties of instance of the User class from the database so that we can populate our View in an MVC application.

We see here that there are eight properties that are similar to each other but each set lies in a separate class, one in the Model, and one in the Users class. And what we do is one by one we bind these properties to our model and pass it to the View. Now the problem is what if we have 100 column records coming from the database, and also our model has the same number of properties, and the code has to be repeated 6-7 times at different scenarios? Now do we still follow such a strategy of binding each property from the database to the model? Trust me, the code will be 100 pages large, and will be charging five times the effort just to bind the model from the domain entities.

To overcome this tedious situation AutoMapper is introduced. It not only reduces the effort, but also limits the execution time that has been taken by such a large number of lines to execute.

Auto Mapper

AutoMapper is an open source library provided in GitHub.

As per the AutoMapper CodePlex webpage: "AutoMapper is 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 conventions, almost zero configuration is needed to map two types." Therefore, it provides the solution for our mapping issue.

Install AutoMapper

Firstly install the NuGet Package Manager in your Visual Studio IDE. Once done, go to:

Tools -> Library Packet Manager -> Packet manager Console

Then in the console window opened at the bottom of Visual Studio, type:

PM> Install-Package AutoMapper

Press Enter, this will install AutoMapper and the next time you open an MVC application in Visual Studio, it will automatically add a DLL reference to the project.

AutoMapper in Action

Let's create an MVC application first. You can create an MVC application and connect it with the database using LINQ to SQL following my article: http://www.codeproject.com/Articles/620197/Learning-MVC-Part-2-Creating-MVC-Application-and-P 

I have also attached the code for an existing MVC application used without AutoMapper. Now let’s evaluate all the Controller Actions one by one and convert the code using AutoMapper.

Step 1: Create a database for the existing application, the database script is attached with the source code:

Open the existing MVC application in Visual Studio:

See that AutoMapper is referenced in the project, now use that namespace in MyController, as:

Step 2: Index Action:

In the very first Action of our controller MyController (found under the Controllers folder), Index Action, we see the code:

public ActionResult Index()
{
    var dbContext = new MyDBDataContext();
    var userList = from user in dbContext.Users select user;
    var users = new List<LearningMVC.Models.User>();
    if (userList.Any())
    {
        foreach (var user in userList)
        {
            users.Add(new LearningMVC.Models.User()
                {
                    UserId = user.UserId, 
                    Address = user.Address, 
                    Company = user.Company, 
                    FirstName = user.FirstName,
                    LastName = user.LastName,
                    Designation = user.Designation,
                    EMail = user.EMail, 
                    PhoneNo = user.PhoneNo
                });
        }
    }
  
    return View(users);
}

Now where will AutoMapper fit in here? You know that it will be used to replace the property mapping done one by one in the code, therefore, at the first line of code, define an AutoMap. To create the default mapping, call Mapper.CreateMap<T1, T2>() with proper types. In this case, T1 will be LearningMVC.User and T2 will be LearningMVC.Models.User.

Mapper.CreateMap<LearningMVC.User, LearningMVC.Models.User>();
  • LearningMVC.User -> DTO Object Class
  • LearningMVC.Models.User -> Model Class to bind the View

So, here we define a mapping between DTO and the Model class with the help of the AutoMapper class.

Now inside the foreach loop, replace the whole code by:

LearningMVC.Models.User userModel = Mapper.Map<LearningMVC.User, LearningMVC.Models.User>(user);
users.Add(userModel);

Finally call the Mapper.Map<T1, T2>(obj1) to get the mapped object of T2.

So, our final Action code:

public ActionResult Index()
{
    Mapper.CreateMap<LearningMVC.User, LearningMVC.Models.User>();
    var dbContext = new MyDBDataContext();
    var userList = from user in dbContext.Users select user;
    var users = new List<LearningMVC.Models.User>();
    if (userList.Any())
    {
        foreach (var user in userList)
        {
            LearningMVC.Models.User userModel = 
              Mapper.Map<LearningMVC.User, LearningMVC.Models.User>(user);
            users.Add(userModel);
        }
    }
    return View(users);
}

We see now, we escaped the boring work of matching properties one by one. Now run the application, and you’ll see the application running as before.

Step 3: Details Action:

Existing code
public ActionResult Details(int? id)
{
    var dbContext = new MyDBDataContext();
    var userDetails = dbContext.Users.FirstOrDefault(userId => userId.UserId == id);
    var user = new LearningMVC.Models.User();
    if (userDetails != null)
    {
        user.UserId = userDetails.UserId;
        user.FirstName = userDetails.FirstName;
        user.LastName = userDetails.LastName;
        user.Address = userDetails.Address;
        user.PhoneNo = userDetails.PhoneNo;
        user.EMail = userDetails.EMail;
        user.Company = userDetails.Company;
        user.Designation = userDetails.Designation;
    }
    return View(user);
}
New code with AutoMapper
public ActionResult Details(int? id)
{
    var dbContext = new MyDBDataContext();
    Mapper.CreateMap<LearningMVC.User, LearningMVC.Models.User>();
    var userDetails = dbContext.Users.FirstOrDefault(userId => userId.UserId == id);
    LearningMVC.Models.User user = 
      Mapper.Map<LearningMVC.User, LearningMVC.Models.User>(userDetails);
    return View(user);
}

Step 4: Create Action (POST)

Existing code:
[HttpPost]
public ActionResult Create(LearningMVC.Models.User userDetails)
{
    try
    {
        var dbContext = new MyDBDataContext();
        var user = new User();
        if (userDetails != null)
        {
            user.UserId = userDetails.UserId;
            user.FirstName = userDetails.FirstName;
            user.LastName = userDetails.LastName;
            user.Address = userDetails.Address;
            user.PhoneNo = userDetails.PhoneNo;
            user.EMail = userDetails.EMail;
            user.Company = userDetails.Company;
            user.Designation = userDetails.Designation;
        }
        dbContext.Users.InsertOnSubmit(user);
        dbContext.SubmitChanges();
        return RedirectToAction("Index");
    }
    catch
    {
        return View();
    }
}
New code with AutoMapper:
[HttpPost]
public ActionResult Create(LearningMVC.Models.User userDetails)
{
    try
    {
        Mapper.CreateMap<LearningMVC.Models.User, LearningMVC.User>();
        var dbContext = new MyDBDataContext();
        var user = Mapper.Map<LearningMVC.Models.User, LearningMVC.User>(userDetails);
        dbContext.Users.InsertOnSubmit(user);
        dbContext.SubmitChanges();
        return RedirectToAction("Index");
    }
    catch
    {
        return View();
    }
}

Note that, in here we interchange the mapping because now we have to read from the Model and bind to our DTO for Create Action, so just interchange the mapping and run the application. Now our T1 is Model and T2 is DTO.

Step 5: Edit Action:

Existing Code
public ActionResult Edit(int? id)
{
    var dbContext = new MyDBDataContext();
    var userDetails = dbContext.Users.FirstOrDefault(userId => userId.UserId == id);
    var user = new LearningMVC.Models.User();
    if (userDetails != null)
    {
        user.UserId = userDetails.UserId;
        user.FirstName = userDetails.FirstName;
        user.LastName = userDetails.LastName;
        user.Address = userDetails.Address;
        user.PhoneNo = userDetails.PhoneNo;
        user.EMail = userDetails.EMail;
        user.Company = userDetails.Company;
        user.Designation = userDetails.Designation;
    }
    return View(user);
}
New code with AutoMapper
public ActionResult Edit(int? id)
{
    Mapper.CreateMap<LearningMVC.User, LearningMVC.Models.User>();
    var dbContext = new MyDBDataContext();
    var userDetails = dbContext.Users.FirstOrDefault(userId => userId.UserId == id);
    var user = Mapper.Map<LearningMVC.User, LearningMVC.Models.User>(userDetails)
    return View(user);
}

Step 6: Delete Action:

Existing code
public ActionResult Delete(int? id)
{
    var dbContext = new MyDBDataContext();
    var user = new LearningMVC.Models.User();
    var userDetails = dbContext.Users.FirstOrDefault(userId => userId.UserId == id);
    if (userDetails != null)
    {
        user.FirstName = userDetails.FirstName;
        user.LastName = userDetails.LastName;
        user.Address = userDetails.Address;
        user.PhoneNo = userDetails.PhoneNo;
        user.EMail = userDetails.EMail;
        user.Company = userDetails.Company;
        user.Designation = userDetails.Designation;
    }
    return View(user);
}
New code using AutoMapper
public ActionResult Delete(int? id)
{
    var dbContext = new MyDBDataContext();
    Mapper.CreateMap<LearningMVC.User, LearningMVC.Models.User>();
    var userDetails = dbContext.Users.FirstOrDefault(userId => userId.UserId == id);
    var user = Mapper.Map<LearningMVC.User, LearningMVC.Models.User>(userDetails);
    return View(user);
}

ForMember() and MapFrom() in AutoMapper

Two important functions in AutoMapper play an important role in object mapping. Suppose our model/viewmodel class has a property FullName, and from the DTO we want to add the First Name and Last Name of the user to make it a full name and bind it to the model. For these kinds of scenarios ForMember() and MapFrom() come in handy. See below code:

Mapper.CreateMap<LearningMVC.User, LearningMVC.Models.User>().ForMember(emp => emp.Fullname,
map => map.MapFrom(p => p.FirstName + " " + p.LastName));

Here we are saying that ForMember FullName in our model class maps properties from FirstName and LastName of User DTO.

The code itself is self-explanatory. This kind of mapping is also called Custom Mapping.

Conclusion

In this article we learnt how to do custom mapping and entity to entity mapping with the help of AutoMapper. Since this was just a glimpse of the concept there is a lot more to explore in this topic in detail.

I have skipped the POST methods for Edit and Delete, this will be a kind of homework for you. Once you completely follow and understand, you can easily complete those two pending Actions as well. 

This article has been selected as Article of the Day on Microsoft's site http://www.asp.net/community/articles[^] on 29 October 2013. 

Read More

 

For more technical articles you can reach out to CodeTeddy

Learn   Code First Approach using Entity Framework 4.1, Inversion of Control, Unity Framework, Repository & Unit of Work Pattern and MVC3 Razor View   , a complete end to end solution to develop enterprise level application.  

 

Happy coding!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Akhil Mittal
Product Manager
India India
I am a Microsoft MVP, C# Corner MVP,a Code project MVP,blogger,programmer by heart and currently working as a Sr. Analyst in Magic Software and have an experience of more than 8 years in C#.Net. I am a B.Tech in Computer Science and hold a diploma in Information Security and Application Development. My work experience includes Development of Enterprise Applications using C#,.Net and Sql Server,Analysis as well as Research and Development. I am a MCP in Web Applications(MCTS-70-528,MCTS-70-515) and .Net Framework 2.0 (MCTS-70-536). Visit my personal blog CodeTeddy for more informative articles.
____________________________________________________________________________________________________
Article of Day http://www.asp.net/community/articles on 04 April 2016.
Article of Day http://www.asp.net/community/articles on 26 March 2016.
Article of Day http://www.asp.net/community/articles on 29 Jan 2016.
Article of Day http://www.asp.net/community/articles on 01 Aug 2015.
Article of Day http://www.asp.net/community/articles on 28 July 2015.
Article of Day http://www.asp.net/community/articles on 28 June 2015.
Article of Day http://www.asp.net/community/articles on 08 June 2015.
Article of Day http://www.asp.net/community/articles on 02 June 2015.
Article of Day http://www.asp.net/community/articles on 01 June 2015.
Article of Day http://www.asp.net/community/articles on 19 July 2014.
Article of Day http://www.asp.net/community/articles on 21 May 2014.
Article of Day http://www.asp.net/community/articles on 29 Oct 2013.
Article of Day http://www.asp.net/community/articles on 29 Sept 2013.
Article of Day http://www.asp.net/community/articles on 08 Sept 2013.
Article of Day http://www.asp.net/community/articles on 28 Aug 2013.
Article of Day http://www.asp.net/community/articles on 16 Aug 2013.
Winner http://www.c-sharpcorner.com/News/3067/july-2013-month-winners-announc
Group type: Collaborative Group

385 members


You may also be interested in...

Comments and Discussions

 
QuestionGetting Error pls help Pin
sunil314-Apr-16 19:12
membersunil314-Apr-16 19:12 
QuestionBest Artical Pin
sunil313-Apr-16 2:19
membersunil313-Apr-16 2:19 
AnswerRe: Best Artical Pin
Akhil Mittal 13-Apr-16 3:08
mvp Akhil Mittal 13-Apr-16 3:08 
GeneralMy Vote of 4 Pin
Alireza_13621-Mar-16 15:57
memberAlireza_13621-Mar-16 15:57 
GeneralRe: My Vote of 4 Pin
Akhil Mittal 1-Mar-16 19:08
mvp Akhil Mittal 1-Mar-16 19:08 
QuestionMapping ViewModel to Entities Pin
Clement Gitonga17-Oct-15 19:11
professionalClement Gitonga17-Oct-15 19:11 
QuestionAuto mapper impact on performance Pin
Kashif Ansari 1232-Aug-15 2:11
memberKashif Ansari 1232-Aug-15 2:11 
Questiondropped it Pin
CarelAgain20-Jul-15 10:12
memberCarelAgain20-Jul-15 10:12 
Questiona much better choice would be Value Injecter or Emit Mapper Pin
Member 82213721-Feb-15 22:15
memberMember 82213721-Feb-15 22:15 
AnswerRe: a much better choice would be Value Injecter or Emit Mapper Pin
Akhil Mittal 1-Feb-15 22:19
mvp Akhil Mittal 1-Feb-15 22:19 
GeneralRe: a much better choice would be Value Injecter or Emit Mapper Pin
Bahram Ettehadieh9-Apr-15 1:59
memberBahram Ettehadieh9-Apr-15 1:59 
QuestionHow to make it work in VS2013? Pin
Lechuss9-Dec-14 10:26
memberLechuss9-Dec-14 10:26 
GeneralMy vote of 4 Pin
cercoreca29-Nov-14 4:48
membercercoreca29-Nov-14 4:48 
AnswerRe: My vote of 4 Pin
Akhil Mittal 29-Nov-14 7:16
mvp Akhil Mittal 29-Nov-14 7:16 
QuestionMon vote de 5 Pin
BLeguillou26-Nov-14 20:45
memberBLeguillou26-Nov-14 20:45 
AnswerRe: Mon vote de 5 Pin
Akhil Mittal 26-Nov-14 20:48
mvp Akhil Mittal 26-Nov-14 20:48 
Question[My vote of 2] Vote of 2 Pin
tesnep24-Aug-14 20:34
professionaltesnep24-Aug-14 20:34 
AnswerRe: [My vote of 2] Vote of 2 Pin
Akhil Mittal 24-Aug-14 20:40
mvp Akhil Mittal 24-Aug-14 20:40 
AnswerRe: [My vote of 2] Vote of 2 Pin
Antonio Ripa4-Nov-14 7:04
professionalAntonio Ripa4-Nov-14 7:04 
AnswerRe: [My vote of 2] Vote of 2 Pin
Antonio Ripa4-Nov-14 7:04
professionalAntonio Ripa4-Nov-14 7:04 
GeneralMy vote of 5 Pin
Humayun Kabir Mamun13-Jul-14 23:35
memberHumayun Kabir Mamun13-Jul-14 23:35 
GeneralRe: My vote of 5 Pin
Akhil Mittal13-Jul-14 23:36
mvpAkhil Mittal13-Jul-14 23:36 
GeneralMy vote of 5 Pin
dpalash13-Jul-14 20:36
professionaldpalash13-Jul-14 20:36 
GeneralRe: My vote of 5 Pin
Akhil Mittal13-Jul-14 21:25
mvpAkhil Mittal13-Jul-14 21:25 
GeneralMy vote of 5 Pin
Member 1019738312-Jul-14 7:41
memberMember 1019738312-Jul-14 7:41 
GeneralRe: My vote of 5 Pin
Akhil Mittal13-Jul-14 17:55
mvpAkhil Mittal13-Jul-14 17:55 
QuestionImplementing Edit action for HttpPost Pin
Zbynek Sulc15-May-14 2:59
memberZbynek Sulc15-May-14 2:59 
Questionhow could be custom mapping using automapper Pin
waqar908-May-14 2:17
memberwaqar908-May-14 2:17 
AnswerRe: how could be custom mapping using automapper Pin
Akhil_Mittal9-May-14 7:13
mvpAkhil_Mittal9-May-14 7:13 
GeneralMy vote of 5 Pin
Larry E5-May-14 4:56
memberLarry E5-May-14 4:56 
GeneralRe: My vote of 5 Pin
Akhil_Mittal9-May-14 7:17
mvpAkhil_Mittal9-May-14 7:17 
GeneralMy vote of 2 Pin
ijaz_ysmf5-May-14 2:35
memberijaz_ysmf5-May-14 2:35 
GeneralRe: My vote of 2 Pin
Akhil_Mittal9-May-14 7:17
mvpAkhil_Mittal9-May-14 7:17 
QuestionAmazing Article Pin
hisham ahmed26-Apr-14 16:51
memberhisham ahmed26-Apr-14 16:51 
AnswerRe: Amazing Article Pin
Akhil_Mittal27-Apr-14 19:15
mvpAkhil_Mittal27-Apr-14 19:15 
GeneralGreat Article! Pin
Willian Arsenio13-Feb-14 6:56
memberWillian Arsenio13-Feb-14 6:56 
GeneralRe: Great Article! Pin
Akhil_Mittal14-Feb-14 1:07
mvpAkhil_Mittal14-Feb-14 1:07 
GeneralMy vote of 5 Pin
devbinu26-Sep-13 4:43
memberdevbinu26-Sep-13 4:43 
GeneralRe: My vote of 5 Pin
Akhil_Mittal26-Sep-13 22:19
groupAkhil_Mittal26-Sep-13 22:19 
GeneralMy vote of 5 Pin
crou12-Sep-13 3:32
membercrou12-Sep-13 3:32 
GeneralRe: My vote of 5 Pin
Akhil_Mittal12-Sep-13 6:54
groupAkhil_Mittal12-Sep-13 6:54 
GeneralMy vote of 5 Pin
learner'sbug26-Aug-13 7:23
memberlearner'sbug26-Aug-13 7:23 
GeneralRe: My vote of 5 Pin
Akhil_Mittal26-Aug-13 17:43
groupAkhil_Mittal26-Aug-13 17:43 
GeneralNice, simple and to the point Pin
Ken__Clark22-Aug-13 18:24
memberKen__Clark22-Aug-13 18:24 
GeneralRe: Nice, simple and to the point Pin
Akhil_Mittal22-Aug-13 18:24
groupAkhil_Mittal22-Aug-13 18:24 
Questionconcurrency check (timestamp) and skip fields Pin
gicalle7520-Aug-13 3:50
membergicalle7520-Aug-13 3:50 
AnswerRe: concurrency check (timestamp) and skip fields Pin
Akhil_Mittal20-Aug-13 21:08
groupAkhil_Mittal20-Aug-13 21:08 
AnswerRe: concurrency check (timestamp) and skip fields Pin
Dewey21-Aug-13 14:48
memberDewey21-Aug-13 14:48 
GeneralMy vote of 5 Pin
rediffAM20-Aug-13 2:21
memberrediffAM20-Aug-13 2:21 
GeneralMy vote of 5 Pin
Ekta Garg20-Aug-13 0:08
memberEkta Garg20-Aug-13 0:08 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.160426.1 | Last Updated 27 Nov 2014
Article Copyright 2013 by Akhil Mittal
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid