Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

ASP MVC with Automapper Profiles

3.91/5 (5 votes)
17 Sep 2016CPOL2 min read 46.1K  
IMapper interface is injected into constructors of my classes by Unity framework, but you can use any other DI framework or inject IMapper interface manually.

Introduction

I am using AutoMapper version 5.1.1.0 with IMapper interface (as opposed to static class Mapper).

IMapper interface is injected into constructors of my classes by Unity framework, but you can use any other DI framework or inject IMapper interface manually.

Motivation

I really like automapper functionality and I find it really useful especially when binding objects between layers. And I had a real struggle to make this work. So this should hopefully be a simple tutorial for those who would like to move from static Mapper class to IMapper interface. Or for those who never used AutoMapper before and would like to learn how to wire it all up. Because most of the tutorials I found were incomplete or out of date (using static Mapper class).

One Layer

If you have only one layer where you need to map between your models, I would recommend not to use AutoMapper Profiles and just go with a simple solution.

public static class MappingProfile
{
    public static MapperConfiguration InitializeAutoMapper()
    {
        MapperConfiguration config = new MapperConfiguration(cfg =>
        {
            cfg.CreateMap<Question, QuestionModel>();
            cfg.CreateMap<QuestionModel, Question>();
            /*etc...*/
        });
 
        return config;
    }
}

This way, you create your MapperConfiguration object with all your mappings.

You can then create IMapper object from this configuration and inject it into your DI framework (Unity in my case).

public static class UnityWebActivator
{
    /// <summary>Integrates Unity when the application starts.</summary>
    public static void Start()
    {
        var container = UnityConfig.GetConfiguredContainer();
        var mapper = MappingProfile.InitializeAutoMapper().CreateMapper();
        container.RegisterInstance<IMapper>(mapper);
 
        FilterProviders.Providers.Remove
        (FilterProviders.Providers.OfType<FilterAttributeFilterProvider>().First());
        FilterProviders.Providers.Add(new UnityFilterAttributeFilterProvider(container));
 
        DependencyResolver.SetResolver(new UnityDependencyResolver(container));
 
        // TODO: Uncomment if you want to use PerRequestLifetimeManager
        // Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule
        // (typeof(UnityPerRequestHttpModule));
    }
 
    /// <summary>Disposes the Unity container when the application is shut down.</summary>
    public static void Shutdown()
    {
        var container = UnityConfig.GetConfiguredContainer();
        container.Dispose();
    }
}

On line 7, MapperConfiguration is created and from that configuration by calling .CreateMapper() we get IMapper object.

On line 8, IMapper interface is binded to this mapper object (from line 7).

So from now, every time when DI sees IMapper object in constructor, it will provide this mapper object (line 7 again).

Now, example of object that requires IMapper:

public class BaseService
{
    protected IMapper _mapper;
 
    public BaseService(IMapper mapper)
    {
        _mapper = mapper;
    }
 
    public void AutoMapperDemo(){
        var questions = GetQuestions(token);
        return _mapper.Map<IEnumerable<Question>, 
        IEnumerable<QuestionModel>>(questions);
    }
 
    public IEnumerable<Question> GetQuestions(token){
        /*logic to get Questions*/
    }
}

This could be usage of automapper. You can use IMapper interface public method Map<> to map your classes. IMapper object is injected either by DI framework or manually when you create the BaseService object.

More Than One Layer

In the real world MVC application, you usually have more than one layer. You probably have something like WEB/BUSINESS/DB layer and WEB should not know about DB, because it talks only to BUSINESS layer.

That means with one configuration class you would have to reference DB project in your Web layer, otherwise you couldn’t map your objects.

And here comes for help automapper Profiles.

MappingProfile class again, now with profiles:

public static class MappingProfile
{
    public static MapperConfiguration InitializeAutoMapper()
    {
        MapperConfiguration config = new MapperConfiguration(cfg =>
        {
            cfg.AddProfile(new WebMappingProfile());  //mapping between Web and Business layer objects
            cfg.AddProfile(new BLProfile());  // mapping between Business and DB layer objects
        });
 
        return config;
    }
}
//Profile number one saved in Web layer
public class WebMappingProfile : Profile
{
    public WebMappingProfile()
    {
        CreateMap<Question, QuestionModel>();
        CreateMap<QuestionModel, Question>();
        /*etc...*/
    }
}
 
//Profile number two save in Business layer
public class BLProfile: Profile
{
    public BLProfile()
    {
        CreateMap<BLModels.SubModels.Address, DataAccess.Models.EF.Address>();
        /*etc....*/
    }
}

This way Web layer doesn’t need to reference DB layer.

All other steps are the same as for one layer.

Summary

I think that automapper can be a very useful tool if used properly, but it is sometimes really hard to find tutorials that are up to date. I highly recommend you to read autommaper wiki if you struggle.

I encourage you to write in comments how to wire this with for example Ninject or Castle Windsor.

License

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