DEV Community

Cover image for How to Integrate AutoFac 5 and AutoMapper 10 on your MVC 5 Project using Visual Studio 2019
Willy David Jr
Willy David Jr

Posted on • Updated on

How to Integrate AutoFac 5 and AutoMapper 10 on your MVC 5 Project using Visual Studio 2019

Did you love my post?
Hello devs!

Today we will be integrating AutoFac and AutoMapper to our ASP.NET MVC 5 projects using Visual Studio 2019.

But first, let us know, what these frameworks are.

AutoFac - is a framework mostly used for IoC or Inversion of Controls. This system design is also commonly known as Dependency Injection. DI allows you to build loosely-coupled, testable and maintainable applications. It reduces dependencies among software components and also keeps most of your functionalities reusable. If you want to learn more on DI, I highly recommend Dependency Injection in .NET by Mark Seemann. All types of DI were discussed in the book, with different .NET Solutions included.

AutoMapper - is simply a library to convert another object to similar object. One major example that I can share is that you want to convert your Model class to another ViewModel class that you want to use on your application. We usually do this to hide properties that are not needed, to add additional properties which does not need to modify the main class, and other similar requirements.

So let's get started on implementing both of these. We need to use AutoFac to inject AutoMapper on our Controllers!

First, let's create ASP.NET MVC 5 project using Visual Studio 2019 and add the following packages from NuGet.

AutoFac 5

Alt Text

AutoMapper 10

Alt Text

Next let's add new Module from AutoFac. Here we are adding a new class which inherits from Module class of AutoFac assembly.

using Autofac;
using AutoMapper;

public class AutoFacModule : Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            builder.Register(context => new MapperConfiguration(cfg =>
            {
                //Register Mapper Profile
                cfg.AddProfile<AutoMapperProfile>();
            }
            )).AsSelf().SingleInstance();

            builder.Register(c =>
            {
                //This resolves a new context that can be used later.
                var context = c.Resolve<IComponentContext>();
                var config = context.Resolve<MapperConfiguration>();
                return config.CreateMapper(context.Resolve);
            })
            .As<IMapper>()
            .InstancePerLifetimeScope();
        }
    }
Enter fullscreen mode Exit fullscreen mode

Next let's add the AutoMapperProfile which inherits from Profile of AutoMapper. (The definition of Person and PersonViewModel will be discussed in awhile)

using AutoFacAndAutoMapperMVC.Models;
using AutoMapper;

namespace AutoFacAndAutoMapperMVC.Infrastructure
{
    public class AutoMapperProfile : Profile
    {
        public AutoMapperProfile()
        {
            CreateMap<Person, PersonViewModel>();

            CreateMap<PersonViewModel, Person>();
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Registration of AutoMapper

After all those configuration, we definitely need to register those configuration on Global.asax file of MVC solution:

protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            var builder = new ContainerBuilder();

            // Register your MVC controllers. (MvcApplication is the name of
            // the class in Global.asax.)
            builder.RegisterControllers(typeof(MvcApplication).Assembly);

            //Register AutoMapper here using AutoFacModule class (Both methods works)
            //builder.RegisterModule(new AutoMapperModule());
            builder.RegisterModule<AutoFacModule>();

            // Set the dependency resolver to be Autofac.
            var container = builder.Build();
            DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
        }
Enter fullscreen mode Exit fullscreen mode

Subsequently, we need to create two classes for our Demo which are Person and PersonViewModel class. Here are the definitions of those two classes:


public class PersonViewModel
    {
        public string FirstName { get; set; }

        public string LastName { get; set; }

        public string Country { get; set; }

        public string MaritalStatus { get; set; }

        public string HighestEducation { get; set; }
    }

public class Person
    {
        public int Id { get; set; }

        public string FirstName { get; set; }

        public string LastName { get; set; }

        public DateTime? DateOfBirth { get; set; }

        public string PhoneNumber { get; set; }

        public string Address { get; set; }

        public string City { get; set; }

        public string State { get; set; }

        public string Country { get; set; }

        public string MaritalStatus { get; set; }

        public string HighestEducation { get; set; }

    }
Enter fullscreen mode Exit fullscreen mode

So what's the purpose of AutoMapper here? Let's say we are getting list of Person from a results set, either from database repository or from an in memory data. And we want to project those results to send to our View page but with different model but with same properties? You might want to do this because you want to hide some properties. You can do this via projection:


//new List<Person>() only assumes that this results came from a results set of Person objects
var model = new List<Person>().Select(x => new PersonViewModel()
            {
                FirstName = x.FirstName,
                LastName = x.LastName,
                Country = x.Country,
                HighestEducation = x.HighestEducation,
                MaritalStatus = x.MaritalStatus
            });
Enter fullscreen mode Exit fullscreen mode

Mapping each properties can be easy but it's not quite productive until you see a long list of properties for every projection that you will make on each of your implementation.

With AutoMapper, you can do this with one code only:


//This entity object can come from Database or any related source
            var person = new Person()
            {
                Id = 1,
                FirstName = "Cecilia",
                LastName = "Chapman",
                Address = "32 West Court Street",
                City = "Dallas",
                State = "GA",
                Country = "USA",
                DateOfBirth = new DateTime(1981, 1, 5),
                HighestEducation = "College Graduate",
                MaritalStatus = "Married",
                PhoneNumber = "+1-541-754-3010"
            };

          var model = _mapper.Map<PersonViewModel>(person);
Enter fullscreen mode Exit fullscreen mode

That was easy, you can easily map two classes with the same properties without doing a long list of projection.

Here's the screenshot of their actual mapping during debug mode:

Alt Text

Lastly, we are injecting the IMapper interface directly on the Controller constructor to use Dependency Injection. So that every request on HomeController will inject a new instance of IMapper until the request is finish.

You can take a look on the simple final solution here on my Github Repository: https://github.com/willydavidjr/AutoFacAndAutoMapperMVC

Top comments (7)

Collapse
 
zorgoz profile image
zorgoz

Well, there is one little thing missing: where is _mapper field coming from?

Collapse
 
willydavidjr profile image
Willy David Jr

Hi @zorgoz ,

You need to declare _mapper field whenever you instantiate your Controller class. This is the initial code:

Alt Text

You can also see the complete code here: github.com/willydavidjr/AutoFacAnd...

Collapse
 
zorgoz profile image
zorgoz

Of course, if you have some IoC experience, you can figure this out. However, in my opinion, this article is targeting a less experienced audience. This is why I missed this part.

Thread Thread
 
willydavidjr profile image
Willy David Jr

Hi @zorgoz ,

I appreciate your feedback. I will update the article so that nothing will be missed out for future readers :)

Collapse
 
intexx profile image
Jeff Bowman

How are you getting code like this to work:

builder.Register(c =>
{
  //This resolves a new context that can be used later.
  var context = c.Resolve<IComponentContext>();
})
Enter fullscreen mode Exit fullscreen mode

For me at least, c is always of type System.Object, which of course doesn't have a Resolve<IComponentContext>() method.

Collapse
 
intexx profile image
Jeff Bowman • Edited

OK, got it.

For some odd reason, in VB.NET we have to explicitly cast the incoming context as IComponentContext. You can read more on this delicious topic here.

If you hadn't shared your full working solution, I'd have never figured this out.

Thank you.

Collapse
 
jpsolaresjp profile image
Jayπ

Mr. thanks, what i was looking for, just my two cents, u can add reverse on automapper,
cfg.CreateMap().ReverseMap();