How to configure Automapper in ASP.NET Core

I am relatively new to .NET, and decided to solve .NET Core instead of learning the “old ways”. I found a detailed article on configuring AutoMapper for .NET Core here , but is there a simpler walkthrough for beginners?

+211
c # asp.net-core automapper
Oct 27 '16 at 2:34
source share
12 answers

I understood! Here are the details:

  1. Add the core AutoMapper package to your solution through NuGet .
  2. Add the AutoMapper dependency injection package to your solution using NuGet .

  3. Create a new class for the mapping profile. (I created a class in the main solutions directory with the name MappingProfile.cs and added the following code.) As an example, I will use the User object and UserDto .

     public class MappingProfile : Profile { public MappingProfile() { // Add as many of these lines as you need to map your objects CreateMap<User, UserDto>(); CreateMap<UserDto, User>(); } } 
  4. Then add AutoMapperConfiguration to Startup.cs as shown below:

     public void ConfigureServices(IServiceCollection services) { // .... Ignore code before this // Auto Mapper Configurations var mappingConfig = new MapperConfiguration(mc => { mc.AddProfile(new MappingProfile()); }); IMapper mapper = mappingConfig.CreateMapper(); services.AddSingleton(mapper); services.AddMvc(); } 
  5. To call the associated object in code, do something like the following:

     public class UserController : Controller { // Create a field to store the mapper object private readonly IMapper _mapper; // Assign the object in the constructor for dependency injection public UserController(IMapper mapper) { _mapper = mapper; } public async Task<IActionResult> Edit(string id) { // Instantiate source object // (Get it from the database or whatever your code calls for) var user = await _context.Users .SingleOrDefaultAsync(u => u.Id == id); // Instantiate the mapped data transfer object // using the mapper you stored in the private field. // The type of the source object is the first type argument // and the type of the destination is the second. // Pass the source object you just instantiated above // as the argument to the _mapper.Map<>() method. var model = _mapper.Map<UserDto>(user); // .... Do whatever you want after that! } } 

I hope this helps someone get started with ASP.NET Core! I welcome any feedback or criticism since I'm still new to the .NET world!

+477
Oct 27 '16 at 2:34
source share

Step Use AutoMapper with ASP.NET Core.

Step 1. Install AutoMapper.Extensions.Microsoft.DependencyInjection from the NuGet package.

enter image description here

Step 2. Create a folder in the solution to save the mappings with the name "mappings".

enter image description here

Step 3. After adding the Mapping folder, we added a class called " MappingProfile ", this name can be unique and useful for understanding.

In this class we are going to save all displays.

enter image description here

Step 4. Initializing Mapper When Starting "ConfigureServices"

In the launch class, we need to initialize the profile we created, as well as register the AutoMapper service.

  Mapper.Initialize(cfg => cfg.AddProfile<MappingProfile>()); services.AddAutoMapper(); 

Code snippet to show the ConfigureServices method, where we need to initialize and register AutoMapper.

 public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services) { services.Configure<CookiePolicyOptions>(options => { // This lambda determines whether user consent for non-essential cookies is needed for a given request. options.CheckConsentNeeded = context => true; options.MinimumSameSitePolicy = SameSiteMode.None; }); // Start Registering and Initializing AutoMapper Mapper.Initialize(cfg => cfg.AddProfile<MappingProfile>()); services.AddAutoMapper(); // End Registering and Initializing AutoMapper services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); }} 

Step 5. Get the conclusion.

To get the Mapped result, we need to call AutoMapper.Mapper.Map and pass the correct destination and source.

 AutoMapper.Mapper.Map<Destination>(source); 

Code snippet

  [HttpPost] public void Post([FromBody] SchemeMasterViewModel schemeMaster) { if (ModelState.IsValid) { var mappedresult = AutoMapper.Mapper.Map<SchemeMaster>(schemeMaster); } } 
+49
Nov 24 '18 at 6:18
source share

I want to expand on @theutz answers, namely:

 // services.AddAutoMapper(typeof(Startup)); // <-- newer automapper version uses this signature. 

There is an error (probably) in AutoMapper.Extensions.Microsoft.DependencyInjection version 3.2.0. (I am using .NET Core 2.0)

This is being addressed in this GitHub issue. If your classes that inherit the AutoMapper profile class exist outside the assembly where you use the run class, they probably won't be registered if your AutoMapper injection looks like this:

 services.AddAutoMapper(); 

unless you explicitly specify which assemblies to look for in AutoMapper profiles.

You can do this in your Startup.ConfigureServices:

 services.AddAutoMapper(<assembies> or <type_in_assemblies>); 

where "assemblies" and "type_in_assemblies" indicate the assembly where the profile classes in your application are indicated. For example:

 services.AddAutoMapper(typeof(ProfileInOtherAssembly), typeof(ProfileInYetAnotherAssembly)); 

I suppose (and I emphasize this word) that due to the following implementation of parameterless overload (source code from GitHub ):

 public static IServiceCollection AddAutoMapper(this IServiceCollection services) { return services.AddAutoMapper(null, AppDomain.CurrentDomain.GetAssemblies()); } 

we rely on the fact that the CLR already has a JIT assembly containing AutoMapper profiles, which may or may not be true, since they only connect when necessary (more details on this StackOverflow question).

+33
May 04 '18 at 15:30
source share

theutz 'answer here is very good, I just want to add this:

If you allow your mapping profile to inherit from MapperConfigurationExpression instead of Profile , you can simply add a test to check the display setting, which is always convenient:

 [Fact] public void MappingProfile_VerifyMappings() { var mappingProfile = new MappingProfile(); var config = new MapperConfiguration(mappingProfile); var mapper = new Mapper(config); (mapper as IMapper).ConfigurationProvider.AssertConfigurationIsValid(); } 
+27
Mar 30 '17 at 12:39 on
source share

In my Startup.cs (Core 2.2, Automapper 8.1.1)

 services.AddAutoMapper(new Type[] { typeof(DAL.MapperProfile) }); 

In my data access project

 namespace DAL { public class MapperProfile : Profile { // place holder for AddAutoMapper (to bring in the DAL assembly) } } 

In my model definition

 namespace DAL.Models { public class PositionProfile : Profile { public PositionProfile() { CreateMap<Position, PositionDto_v1>(); } } public class Position { ... } 
+10
Jun 09 '19 at 22:25
source share

I am using AutoMapper 6.1.1 and asp.net Core 1.1.2.

First of all, define the profile classes inherited by the Automapper profile class. I created an IProfile interface that is empty, the goal is only to find classes of this type.

  public class UserProfile : Profile, IProfile { public UserProfile() { CreateMap<User, UserModel>(); CreateMap<UserModel, User>(); } } 

Now create a separate class, for example, Mappings

  public class Mappings { public static void RegisterMappings() { var all = Assembly .GetEntryAssembly() .GetReferencedAssemblies() .Select(Assembly.Load) .SelectMany(x => x.DefinedTypes) .Where(type => typeof(IProfile).GetTypeInfo().IsAssignableFrom(type.AsType())); foreach (var ti in all) { var t = ti.AsType(); if (t.Equals(typeof(IProfile))) { Mapper.Initialize(cfg => { cfg.AddProfiles(t); // Initialise each Profile classe }); } } } } 

Now in the MVC Core web project, in the Startup.cs file in the constructor, call the Mapping class, which will initialize all mappings during application loading.

 Mappings.RegisterMappings(); 
+6
Jul 25 '17 at 1:19 on
source share

For ASP.NET Core, the following is direct from Automapper and takes 1 line in your startup class: https://github.com/AutoMapper/AutoMapper.Extensions.Microsoft.DependencyInjection/blob/master/README.md

Just add some profile classes. Then add below to your startup.cs class. services.AddAutoMapper(OneOfYourProfileClassNamesHereSoItCanFindYourProfileAssembly)

Then just insert IMapper into your controllers or wherever you need:

 public class EmployeesController { private readonly IMapper _mapper; public EmployeesController(IMapper mapper){ _mapper = mapper; } 

And if you want to use ProjectTo now, simply:

 var customers = await dbContext.Customers.ProjectTo<CustomerDto>(_mapper.ConfigurationProvider).ToListAsync() 
+4
Feb 19 '19 at 6:26
source share

services.AddAutoMapper (); not working for me (I am using Asp.Net Core 2.0)

After setting as below

  var config = new AutoMapper.MapperConfiguration(cfg => { cfg.CreateMap<ClientCustomer, Models.Customer>(); }); 

initialize the IMapper converter mapper = config.CreateMapper ();

and add the mapper object to the services as singleton services.AddSingleton (mapper);

that way I can add DI to the controller

  private IMapper autoMapper = null; public VerifyController(IMapper mapper) { autoMapper = mapper; } 

and I used, as shown below, in my action methods

  ClientCustomer customerObj = autoMapper.Map<ClientCustomer>(customer); 
+1
Mar 24 '18 at 15:27
source share

about theutz answer, there is no need to specify the IMapper mapper parammer in the controller constructor.

you can use mapper as it is a static member anywhere in the code.

 public class UserController : Controller { public someMethod() { Mapper.Map<User, UserDto>(user); } } 
0
May 10 '17 at 5:38 a.m.
source share

To add what Arve Sistad mentioned for testing. If for some reason you are like me and want to keep the inheritance structure presented in theutz solution, you can configure MapperConfiguration as follows:

 var mappingProfile = new MappingProfile(); var config = new MapperConfiguration(cfg => { cfg.AddProfile(mappingProfile); }); var mapper = new Mapper(config); 

I did this on NUnit.

0
Mar 09 '18 at 20:18
source share

I found it hard to get started with a gun. When I was unable to insert it into the constructor of the Test class, I completely dropped it. Instead, I will use ModelBindings for properties that cannot be edited, and Data Transfer Classes for properties that must be hidden and handle the mapping myself.

0
May 08 '19 at 15:07
source share

Mistake:

 NullReferenceException: Object reference not set to an instance of an object. NullReferenceException: Object reference not set to an instance of an object. DatingApp.API.Controllers.UsersController.GetUsers() in UsersController.cs, line 29 Stack Query Cookies Headers NullReferenceException: Object reference not set to an instance of an object. DatingApp.API.Controllers.UsersController.GetUsers() in UsersController.cs + [HttpGet] public async Task<IActionResult> GetUsers() { var users = await _repo.GetUsers(); var usersToReturn = _mapper.Map<IEnumerable<UserForListDto>>(users); return Ok(usersToReturn); } [HttpGet("{id}")] public async Task<IActionResult> GetUser(int id) Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor+TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, object controller, object[] arguments) System.Threading.Tasks.ValueTask<TResult>.get_Result() Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeActionMethodAsync() Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeNextActionFilterAsync() Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context) Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted) Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeInnerFilterAsync() Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResourceFilter() Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context) Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted) Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync() Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync() Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke(HttpContext httpContext) Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware.Invoke(HttpContext httpContext) Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context) Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)' 'at DatingApp.API.Controllers.UsersController.GetUsers() in H:\Projects\DatingApp.API\Controllers\UsersController.cs:line 29 at Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments) at System.Threading.Tasks.ValueTask'1.get_Result() at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeActionMethodAsync() at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeNextActionFilterAsync() at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context) at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeInnerFilterAsync() at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResourceFilter() at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context) at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync() at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync() at Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke(HttpContext httpContext) at Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware.Invoke(HttpContext httpContext) at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context) 

AutoMapperProfiles.cs:

 using System.Linq; using AutoMapper; using DatingApp.API.Dtos; using DatingApp.API.Models; namespace DatingApp.API.Helpers { public class AutoMapperProfiles : Profile { public AutoMapperProfiles() { AllowNullCollections = true; CreateMap<User, UserForListDto>() .ForMember(dest => dest.PhotoUrl, opt => { opt.MapFrom(src => src.Photos.FirstOrDefault(p => p.IsMain).Url); }) .ForMember(dest => dest.Age, opt =>{ opt.MapFrom(src => src.DateOfBirth.CalculateAge()); }); CreateMap<User, UserForDetailDto>() .ForMember(dest => dest.PhotoUrl, opt => { opt.MapFrom(src => src.Photos.FirstOrDefault(p => p.IsMain).Url); }) .ForMember(dest => dest.Age, opt =>{ opt.MapFrom(src => src.DateOfBirth.CalculateAge()); }); CreateMap<Photo, PhotosForDetailDto>(); } } } 

UserForListDto.cs:

 using System; namespace DatingApp.API.Dtos { public class UserForListDto { public int Id { get; set; } public string Username { get; set; } public string Gender { get; set; } public int Age { get; set; } public string KnownAs { get; set; } public DateTime Created { get; set; } public DateTime LastActive { get; set; } public string City { get; set; } public string Country { get; set; } public string PhotoUrl { get; set; } } } 

PhotosForDetailDto.cs

 using System; namespace DatingApp.API.Dtos { public class PhotosForDetailDto { public int Id { get; set; } public string Url { get; set; } public string Description { get; set; } public DateTime DateAdded { get; set; } public bool IsMain { get; set; } } } 

Photo.cs:

 using System; namespace DatingApp.API.Models { public class Photo { public int Id { get; set; } public string Url { get; set; } public string Description { get; set; } public DateTime DateAdded { get; set; } public bool IsMain { get; set; } public User User { get; set; } public int UserId { get; set; } } } 

User.cs

 using System; using System.Collections.Generic; namespace DatingApp.API.Models { public class User { public int Id { get; set; } public string Username { get; set; } public byte[] PasswordHash { get; set; } public byte[] PasswordSalt { get; set; } public string Gender { get; set; } public DateTime DateOfBirth { get; set; } public string KnownAs { get; set; } public DateTime Created { get; set; } public DateTime LastActive { get; set; } public string Introduction { get; set; } public string LookingFor { get; set; } public string Interests { get; set; } public string City { get; set; } public string Country { get; set; } public ICollection<Photo> Photos { get; set; } } } 

Extensions.cs:

 using System; using Microsoft.AspNetCore.Http; namespace DatingApp.API.Helpers { public static class Extensions { public static void AddApplicationError(this HttpResponse response, string message) { response.Headers.Add("Application-Error", message); response.Headers.Add("Access-Control-Expose-Headers", "Application-Error"); response.Headers.Add("Access-Control-Allow-Origin", "*"); } public static int CalculateAge(this DateTime theDateTime) { var age = DateTime.Today.Year - theDateTime.Year; if (theDateTime.AddYears(age) > DateTime.Today) { age--; } return age; } } } 

IDatingRepository.cs:

 using System.Collections.Generic; using System.Threading.Tasks; using DatingApp.API.Models; namespace DatingApp.API.Data { public interface IDatingRepository { void Add<T>(T entity) where T : class; void Delete<T>(T entity) where T : class; Task<bool> SaveAll(); Task<IEnumerable<User>> GetUsers(); Task<User> GetUser(int id); } } 

DatingRepository.cs:

 using System.Collections.Generic; using System.Threading.Tasks; using AutoMapper; using DatingApp.API.Models; using Microsoft.EntityFrameworkCore; namespace DatingApp.API.Data { public class DatingRepository : IDatingRepository { private readonly DataContext _context; private readonly IMapper _mapper; public DatingRepository(DataContext context, IMapper mapper) { _context = context; _mapper = mapper; } public void Add<T>(T entity) where T : class { _context.Add(entity); } public void Delete<T>(T entity) where T : class { _context.Remove(entity); } public async Task<bool> SaveAll() { return await _context.SaveChangesAsync() > 0; } public async Task<IEnumerable<User>> GetUsers() { var users = await _context.Users.Include(p => p.Photos).ToListAsync(); return users; } public async Task<User> GetUser(int id) { var user = await _context.Users.Include(p => p.Photos) .FirstOrDefaultAsync(u => u.Id == id); return user; } } } 
0
May 11 '19 at 11:26
source share



All Articles