I can’t think to the last ASP.NET project I worked on that didn’t involve Automapper in one way or another. In some ways, it’s become a bit like JSON.net where it’s just a defacto package to install when you start a new project. Automapper has, over time, been moving away from it’s static class origins into a more dependency injection type interface. This of course then lends itself perfectly for ASP.NET Core’s new Service Collection framework!
This post will go over getting things up and running in ASP.NET Core, but it does presume you already have quite a bit of knowledge about Automapper already. Let’s jump right in!
Setup
Inside your project, install the following Nuget package from the Package Manager console :
Install-Package AutoMapper.Extensions.Microsoft.DependencyInjection
This will also in turn install the Automapper nuget package if you don’t have it already.
Inside your ConfigureServices method of your startup.cs, add a call to add the AutoMapper required services like so :
public void ConfigureServices(IServiceCollection services) { services.AddAutoMapper(); services.AddMvc(); }
If you want to see what this call does, the actual code is open source and available here. In short, it trawls through your code finding all configuration profiles (See below), and registers the IMapper interface to be used in your classes. It is also rather particular about which scopes it will register them under – which we will also talk about shortly.
Adding Profiles
Automapper Profiles haven’t changed when you move to .NET Core. Take the example profile below where I have created a class called “DomainProfile” to add mappings, and inside the constructor setup a mapping.
public class DomainProfile : Profile { public DomainProfile() { CreateMap<DomainUser, UserViewModel>(); } }
When your application runs, Automapper will go through your code looking for classes that inherit from “Profile”, and will load their configuration. Simple!
Using IMapper
Once you’ve loaded up your profiles, using the IMapper interface is exactly the same if you used Automapper with any other DI Framework. You inject in IMapper to your constructor of your class, and are then able to map objects.
public class HomeController : Controller { private readonly IMapper _mapper; public HomeController(IMapper mapper) { _mapper = mapper; } public IActionResult Index() { //Do some work here. //And when we want to map do something like the following. var result = _mapper.Map<TypeIWantToMapTo>(originalObject); } }
Again, it may look like a bit of black magic since you never registered IMapper in the ServiceCollection. But the Nuget package and the call to “AddAutoMapper” in your ConfigureServices takes care of all of this for you.
Scopes
One final thing to end on is how scopes work inside Automapper. Great care has been given so that you can write custom resolvers that rely on things like repositories that may be of transient scope. Confused? Let’s break it down a bit more.
Your configuration (e.g. Automapper Profiles) are singletons. That is, they are only ever loaded once when your project runs. This makes sense since your configurations will not change while the application is running.
The IMapper interface itself is “scoped”. In ASP.NET terms, it means that for every individual request, a new IMapper is created but then shared across the entire app for that whole request. So if you use IMapper inside a controller and inside a service for a single request, they will be using the same IMapper instance.
But what is really important, is that anything that derives from IValueResolver, ITypeConverter or IMemberValueResolver will be of transient scope. They will also be created using the .NET Core Service Collection DI. Take the following code that may be used to resolve a particular mapping whereby I want to map across a username based on the source models “Id”. To do this I want to access my UserRepository.
public class UsernameResolver : IValueResolver<DomainUser, UserViewModel, string> { private readonly IUserRepository _userRepository; public UsernameResolver(IUserRepository userRepository) { _userRepository = userRepository; } public string Resolve(DomainUser source, UserViewModel destination, string destMember, ResolutionContext context) { return _userRepository.GetById(source.Id).Username; } }
Because this is instantiated as a transient instance using .NET Core’s Service Collection, my repository will also be resolved correctly and I will be able to do mappings that are more than just mapping across simple values. Super handy!
Have I missed anything? Drop a comment below and let me know!
UsernameResolver with injecting constructor does not work in asp.net core 2. Or I am doing something wrong.
Could you post a Github Gist of your code so others can take a look?
Since IMapper (request scope) is the only piece of code (I am assuming) that asks for IValueResolver, the resolver itself should be also resolved only once per request––it might be registered as transient but it seems logical that when casting collection of objects to different collection, only one instance of resolver should be used. Am I missing something?
Ah, perfect question! I actually had exactly the same reaction when working in .NET Core with IMapper for the first time. I actually had a piece written up about how that worked for this post but didn’t want to overload people with information. And I’m actually glad someone asked this because understanding how child objects are sort of “tied” to their parent objects scopes is something that I grapple how to explain to new developers.
The short answer is no. Resolvers are still transient.
But to get to the bottom of “how” they are still transient takes a bit of digging. Luckily Automapper is open source!
So first let’s head over to the source code to make sure the registration of the actual resolvers is correct. That line in the source code can be seen here.
Or copied here it looks like :
OK so we are 100% registering the resolvers as transient. So how does the actual mapper registration look? That line of code is highlighted here.
And copied here :
OK so our IMapper is definitely resolved once per scope (Or per request as it may be). But we can see that it actually runs as a factory, and it passes in a couple of parameters. The first is the configuration, and the second, we are actually passing in a function that resolves “things”. Interesting! To get a better grip on what this actually does, let’s actually go to the constructor of the Mapper class and just check out what it’s called, and if there are any comments to help us.
The line we are looking for here is here or :
Honestly, not that helpful. But atleast we can say one thing. The second parameter takes a “type” and should return an object. And it’s called serviceCtor (Or Service Constructor). At this point, given we know we are passing in our “GetService” method from the Service Collection in .NET Core, we can probably assume that it’s used to “create” instances of objects rather than relying on them being injected into constructors.
Then honestly, everything gets hazy. But the main line *I think* is this one here. That line to “CreateInstance” in the background then goes and uses the ServiceCtor we passed it to create our instance of the value resolver (I think).
In anycase, the main point is, AutoMapper gets around the scope issue by passing in the ServiceCollection essentially and calling “GetService” everytime it needs something (e.g. The Service Locator Pattern) rather than using constructor injection. Hope that makes sense!
Why even use DI for AutoMapper? DI is for solving 2 problems: Make large projects compilable, and make external services like a a database visible and replaceable. But AutoMapper, that is just something that you need in typed languages, it could even be part of the language. I use AutoMapper in aspnet core, and I just create a class that inherits from Profile, create an dummy instance early, like in StartUp, and then use it with AutoMapper.Map. Why have more services dependency injected than necessary? What am I missing?
Actually, the only thing Dependency Injection solves is keeping to the Dependency Inversion principle. Because both are “DI”, people often get them confused. Dependency Inversion states that we should rely on abstractions. Pre this whole IMapper business from Automapper itself, I would often hide the Mapper details behind my own interface/service, and inject that in, ala depending on an abstraction.
But I feel like you want a more “practical” example, which is fair enough! The most common use case for using dependency injection if you don’t care about dependency inversion is the ability to Unit Test. You *can* unit test without using the IMapper interface, but it’s a lot harder to use since you actually need to create real mappings, rather than just using mocks/fakes.
Very useful! Thank you!
Hi
I would like to know how can I ignore some property while mapping .
ex: _mapper.Map(projectList);
what if the no of properties are different in these two objects.
Appreciate any help
issue in below line
_mapper.Map(projectList);
no of property are different in source and target object
Thanks for sharing! what if the service inside the value resolver is async? seems not support.