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
AutoMapper 10
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();
}
}
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>();
}
}
}
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));
}
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; }
}
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
});
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);
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:
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)
Well, there is one little thing missing: where is
_mapper
field coming from?Hi @zorgoz ,
You need to declare _mapper field whenever you instantiate your Controller class. This is the initial code:
You can also see the complete code here: github.com/willydavidjr/AutoFacAnd...
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.
Hi @zorgoz ,
I appreciate your feedback. I will update the article so that nothing will be missed out for future readers :)
How are you getting code like this to work:
For me at least,
c
is always of typeSystem.Object
, which of course doesn't have aResolve<IComponentContext>()
method.OK, got it.
For some odd reason, in VB.NET we have to explicitly cast the incoming
context
asIComponentContext
. 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.
Mr. thanks, what i was looking for, just my two cents, u can add reverse on automapper,
cfg.CreateMap().ReverseMap();