363

I'm relatively new at .NET, and I decided to tackle .NET Core instead of learning the "old ways". I found a detailed article about setting up AutoMapper for .NET Core here, but is there a more simple walkthrough for a newbie?

Boann
  • 48,794
  • 16
  • 117
  • 146
theutz
  • 11,872
  • 4
  • 17
  • 22
  • 5
    See https://dotnetcoretutorials.com/2017/09/23/using-automapper-asp-net-core/ – Michael Freidgeim Dec 08 '17 at 06:15
  • For newer versions of core (>v1) check out @Saineshwar's answer https://stackoverflow.com/a/53455699/833878 – Robbie Feb 16 '19 at 21:01
  • 1
    A complete answer with an example [click this link](https://stackoverflow.com/a/56299926/7487135) – Iman Bahrampour May 25 '19 at 06:08
  • If you already have Identity in your project, you already have an implicit reference to Automapper via that. Adding AutoMapper.Extensions.Microsoft.DependencyInjection can change the dependency to a later version of AutoMapper and break Identity. Be careful to choose a DI version that has the same dependency. See also https://stackoverflow.com/questions/63519439/automapper-issue-with-identityserver4-missingmethodexception-method-not-found – Daz Dec 03 '20 at 12:30
  • 1
    AutoMapper Usage Guidelines for people who need to know it well https://jimmybogard.com/automapper-usage-guidelines/ – Kevin Xiong Mar 19 '21 at 09:39

20 Answers20

773

I figured it out! Here's the details:

  1. Add the main AutoMapper Package to your solution via NuGet.

  2. Add the AutoMapper Dependency Injection Package to your solution via NuGet.

  3. Create a new class for a mapping profile. (I made a class in the main solution directory called MappingProfile.cs and add the following code.) I'll use a User and UserDto object as an example.

     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 the AutoMapperConfiguration in the Startup.cs as shown below:

     public void ConfigureServices(IServiceCollection services) {
         // .... Ignore code before this
    
        // Auto Mapper Configurations
         var mapperConfig = new MapperConfiguration(mc =>
         {
             mc.AddProfile(new MappingProfile());
         });
    
         IMapper mapper = mapperConfig.CreateMapper();
         services.AddSingleton(mapper);
    
         services.AddMvc();
    
     }
    
  5. To invoke the mapped 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!
         }
     }
    
Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
theutz
  • 11,872
  • 4
  • 17
  • 22
  • 2
    You should include the constructor for MappingProfile to contain the calls to CreateMap – Brian Seim at EvoDynamic Inc Nov 02 '16 at 01:37
  • I'm not entirely certain. That'd be a great question for someone more experienced than me. But I'm guessing they scan the assembly where it's invoked for any classes that inherit from the Profile class. – theutz Dec 21 '16 at 20:54
  • 5
    The detailed article linked, https://lostechies.com/jimmybogard/2016/07/20/integrating-automapper-with-asp-net-core-di/, explains how `Profile` classes are located – Kieren Johnstone Dec 22 '16 at 08:25
  • 32
    @theutz You can merge those two CreateMap lines with a .ReverseMap() at the end of, well, either. Maybe comment it, but I find it more intuitive. – Astravagrant Mar 31 '17 at 12:40
  • 6
    It might be helpful on Step 3 to mention adding a "using AutoMapper;" at the top so that the extension method is imported. – Rocklan May 30 '17 at 01:47
  • I am getting one error : "AutoMapper Extension Dependency injection is incompatible with asp.net core 1.1 ". Please help! – Rohit Arora Aug 31 '17 at 04:37
  • 11
    This worked fine with .net core 1.1, not anymore once I upgraded to .net core 2.0. I think, I need to explicitly specify the logic profile class assembly. Still researching how to accomplish that. Update: Ah the answer resides on your comment, I have to pass the typeof class which is my profile. // services.AddAutoMapper(typeof(Startup)); // <-- newer automapper version uses this signature – Esen Sep 23 '17 at 16:35
  • 1
    Just to add, in Visual Studio Code 1.17.2, after following these tips, it was still underlining "using AutoMapper" as though it was an error. I needed to close Code, then reopen it, for the error to go away. (One day all this stuff might actually work properly...) – Mike Gledhill Nov 08 '17 at 09:15
  • @MauricioAviles define a root namespace for MappingPrifle.cs – George Paoli Mar 13 '18 at 20:58
  • I particularly liked this answer because the controller is fully testable so is the Startup.cs class. The segregation of Create() into Profile class is an excellent feature. – Yawar Murtaza Apr 01 '18 at 12:11
  • 1
    Very good answer. As of july 2018 this answer is working fine with ASP Net Core 2.1 and the last version of Automapper. – Eliaquín Jul 29 '18 at 03:26
  • 4
    In AutoMapper v8 and the Dependency Injection v5 add on, the only thing needed is the services.AddAutoMapper(); line in the ConfigureServices method of the Startup class. For me, it was even able to find Profile classes in dependent class library projects. – stricq Dec 17 '18 at 05:06
  • 2
    Why did you Add the AutoMapper Dependency Injection Package? you added mapper service manually and didn't use services.AddAutoMapper method! – Omid.Hanjani Jul 09 '19 at 12:07
  • 1
    You don't need step 1. The dependency injection package already installs the dependencies. – ataravati Oct 13 '19 at 21:54
  • Thank you very much, when I started using view models as suggested i could not believe there was no auto mapping tool already built in and available. This reduced a lot of extra code in my project. – Mr. EZEKIEL Jan 07 '20 at 04:13
  • 4
    Yes in latest versions of AutoMapper you can register service very easy like services.AddAutoMapper(typeof(MappingProfile)); – mr_squall Nov 11 '20 at 09:57
  • 1
    Some comments reference AddAutoMapper, but the answer does not. I assume the answer did originally reference that mthod, but that the answer was significantly updated at some point. Sadly, this exposes a hole in stack overflow: edits can make the overall answer inconsistent and confusing. ... also, to @Omid-RH comment: this change would explain the inclusion of 'AutoMapper Dependency Injection' package. But I suspect it is not needed for the implementation as-is. – steve Jan 11 '22 at 15:46
101

Step To Use AutoMapper with ASP.NET Core.

Step 1. Installing AutoMapper.Extensions.Microsoft.DependencyInjection from NuGet Package.

enter image description here

Step 2. Create a Folder in Solution to keep Mappings with Name "Mappings".

enter image description here

Step 3. After adding Mapping folder we have added a class with Name "MappingProfile" this name can anything unique and good to understand.

In this class, we are going to Maintain all Mappings.

enter image description here

Step 4. Initializing Mapper in Startup "ConfigureServices"

In Startup Class, we Need to Initialize Profile which we have created and also Register AutoMapper Service.

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

  services.AddAutoMapper();

Code Snippet to show 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 Output.

To Get Mapped result we need to call AutoMapper.Mapper.Map and pass Proper Destination and Source.

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

CodeSnippet

    [HttpPost]
    public void Post([FromBody] SchemeMasterViewModel schemeMaster)
    {
        if (ModelState.IsValid)
        {
            var mappedresult = AutoMapper.Mapper.Map<SchemeMaster>(schemeMaster);
        }
    }
Saineshwar Bageri - MVP
  • 3,851
  • 7
  • 41
  • 47
57

I want to extend @theutz's answers - namely this line :

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

There is a bug (probably) in AutoMapper.Extensions.Microsoft.DependencyInjection version 3.2.0. (I'm using .NET Core 2.0)

This is tackled in this GitHub issue. If your classes inheriting AutoMapper's Profile class exist outside of assembly where you Startup class is they will probably not be registered if your AutoMapper injection looks like this:

services.AddAutoMapper();

unless you explicitly specify which assemblies to search AutoMapper profiles for.

It can be done like this in your Startup.ConfigureServices:

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

where "assemblies" and "type_in_assemblies" point to the assembly where Profile classes in your application are specified. E.g:

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

I suppose (and I put emphasis on this word) that due to 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 CLR having already JITed assembly containing AutoMapper profiles which might be or might not be true as they are only jitted when needed (more details in this StackOverflow question).

RJFalconer
  • 10,890
  • 5
  • 51
  • 66
GrayCat
  • 1,749
  • 3
  • 19
  • 30
  • 9
    Thats the correct answer for latest version of AutoMapper and AspNetCore – Joshit May 07 '19 at 09:31
  • 1
    this was the answer I was looking for for AutoMapper 8.1 (latest version) – Tinaira Jun 16 '19 at 16:08
  • What if I want to call CompileMappings*( on MapperConfiguration before calling AddAutoMapper? – John Demetriou Sep 14 '20 at 07:31
  • FYI: 1) this answer says theutz answer references AddAutoMapper() but it doesn't, 2) the parameterless AddAutoMapper() extension method has been removed; I'm using version 11.0 ... FWIW the automapper API seems to change alot over time (which is a PITA) and I think theutz updated his answer at some point – steve Jan 11 '22 at 15:38
35

I solved it this way (similar to above but I feel like it's a cleaner solution) Works with .NET Core 3.x

Create MappingProfile.cs class and populate constructor with Maps (I plan on using a single class to hold all my mappings)

    public class MappingProfile : Profile
    {
        public MappingProfile()
        {
            CreateMap<Source, Dest>().ReverseMap();
        }
    }

In Startup.cs, add below to add to DI (the assembly arg is for the class that holds your mapping configs, in my case, it's the MappingProfile class).

//add automapper DI
services.AddAutoMapper(typeof(MappingProfile));

In Controller, use it like you would any other DI object

    [Route("api/[controller]")]
    [ApiController]
    public class AnyController : ControllerBase
    {
        private readonly IMapper _mapper;

        public AnyController(IMapper mapper)
        {
            _mapper = mapper;
        }
        
        public IActionResult Get(int id)
        {
            var entity = repository.Get(id);
            var dto = _mapper.Map<Dest>(entity);
            
            return Ok(dto);
        }
    }


Coy Meeks
  • 700
  • 9
  • 10
  • 2
    I like your answer. I think wrapping `MappingProfiles` with `new Type[]{}` as shown in [this answer](https://stackoverflow.com/a/56518813/5482465) is unnecessary. – Second Person Shooter Aug 29 '19 at 12:18
  • 1
    Don't forget install DI at the beginning: `AutoMapper.Extensions.Microsoft.DependencyInjection` – John Jang Apr 27 '21 at 03:00
  • you also need to add `services.AddScoped();` in your Startup.cs, IMapper is AutoMapper interface and Mapper is from AutoMapper, so we don't need to do anything – milos Aug 26 '21 at 00:04
32

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

If you let your mapping profile inherit from MapperConfigurationExpression instead of Profile, you can very simply add a test to verify your mapping setup, which is always handy:

[Fact]
public void MappingProfile_VerifyMappings()
{
    var mappingProfile = new MappingProfile();

    var config = new MapperConfiguration(mappingProfile);
    var mapper = new Mapper(config);

    (mapper as IMapper).ConfigurationProvider.AssertConfigurationIsValid();
}
Arve Systad
  • 5,471
  • 1
  • 32
  • 58
  • I am getting one error : "AutoMapper Extension Dependency injection is incompatible with asp.net core 1.1 ". Please help! – Rohit Arora Aug 31 '17 at 04:38
  • It seems the definition of "verify" is up for debate. This blows up when certain properties are ommitted by design to prevent mapping. – Jeremy Holovacs Mar 21 '18 at 19:36
  • 2
    If you don’t want a property mapped, set it up with .Ignore(). That way, it forces you to actively think about handling each case - making sure you don’t miss out on stuff when changes are being made. Super practical, actually. So yes, the verify-test is a larger safety net than many people realise. It’s not foolproof, but it takes care of the first 90%. – Arve Systad Mar 23 '18 at 05:13
18

I like a lot of answers, particularly @saineshwar 's one. I'm using .net Core 3.0 with AutoMapper 9.0, so I feel it's time to update its answer.

What worked for me was in Startup.ConfigureServices(...) register the service in this way:

    services.AddAutoMapper(cfg => cfg.AddProfile<MappingProfile>(), 
                               AppDomain.CurrentDomain.GetAssemblies());

I think that rest of @saineshwar answer keeps perfect. But if anyone is interested my controller code is:

[HttpGet("{id}")]
public async Task<ActionResult> GetIic(int id)
{
    // _context is a DB provider
    var Iic = await _context.Find(id).ConfigureAwait(false);

    if (Iic == null)
    {
        return NotFound();
    }

    var map = _mapper.Map<IicVM>(Iic);

    return Ok(map);
}

And my mapping class:

public class MappingProfile : Profile
{
    public MappingProfile()
    {
        CreateMap<Iic, IicVM>()
            .ForMember(dest => dest.DepartmentName, o => o.MapFrom(src => src.Department.Name))
            .ForMember(dest => dest.PortfolioTypeName, o => o.MapFrom(src => src.PortfolioType.Name));
            //.ReverseMap();
    }
}

----- EDIT -----

After reading the docs linked in the comments by Lucian Bargaoanu, I think it's better to change this answer a bit.

The parameterless services.AddAutoMapper() (that had the @saineshwar answer) doesn't work anymore (at least for me). But if you use the NuGet assembly AutoMapper.Extensions.Microsoft.DependencyInjection, the framework is able to inspect all the classes that extend AutoMapper.Profile (like mine, MappingProfile).

So, in my case, where the class belong to the same executing assembly, the service registration can be shortened to services.AddAutoMapper(System.Reflection.Assembly.GetExecutingAssembly());
(A more elegant approach could be a parameterless extension with this coding).

Thanks, Lucian!

Vic
  • 337
  • 3
  • 9
18

At the latest versions of asp.net core you should use the following initialization:

services.AddAutoMapper(typeof(YourMappingProfileClass));
martcs
  • 259
  • 3
  • 6
  • Thanks.This works. I am using Net core 3.0. My object is not even complicate. it has only 2 properties, id and name. For some reason, in one of the Youtube totorial, I followed the project 100% include this line, AppDomain.CurrentDomain.GetAssemblies(), and it worked. However, when I started from the scratch. Your solution works – user12345 Aug 24 '20 at 16:50
  • 1
    we can use `services.AddAutoMapper(Assembly.GetExecutingAssembly());` to get all mapping classes that derive from the Profile class in this assembly. – Sayyed Dawood Apr 29 '21 at 12:27
12

Need to install a package for setting up the automapper.

dotnet add package AutoMapper.Extensions.Microsoft.DependencyInjection

After the AddAutoMapper will be available in services.

public void ConfigureServices(IServiceCollection services)
{
     services.AddAutoMapper(typeof(Startup));
}

Create mapper from Employee class to EmployeeDTO.

using AutoMapper;

public class AutomapperProfile: Profile
{
    public AutomapperProfile()
    {
        //Source to destination.
        CreateMap<Employee,EmployeeDTO>();
    }
}

EmployeeController maps from Employee to EmployeeDTo

using System.Collections.Generic;
using AutoMapper;
using Microsoft.AspNetCore.Mvc;

[Route("api/[controller]")]
[ApiController()]
public class EmployeeController : ControllerBase
{
    private readonly IMapper _mapper;

    public EmployeeController(IMapper mapper)
    {
        _mapper = mapper;
    }

    [HttpGet]
    public IEnumerable<EmployeeDTO> GetEmployees()
    {
        /* 
        Assume it to be a  service call/database call
        it returns a list of employee, and now we will map it to EmployeeDTO
        */
        var employees = Employee.SetupEmployee();
        var employeeDTO = _mapper.Map<IEnumerable<EmployeeDTO>>(employees);
        return employeeDTO;

    }
}

Employee.cs for reference

using System.Collections.Generic;

public class Employee
{
    public int EmployeeId { get; set; }
    public string EmployeeName { get; set; }
    public int Salary { get; set; }

    public static IEnumerable<Employee> SetupEmployee()
    {
        return new List<Employee>()
        {
            new Employee(){EmployeeId = 1, EmployeeName ="First", Salary=10000},
            new Employee(){EmployeeId = 2, EmployeeName ="Second", Salary=20000},
            new Employee(){EmployeeId = 3, EmployeeName ="Third", Salary=30000},
            new Employee(){EmployeeId = 4, EmployeeName ="Fourth", Salary=40000},
            new Employee(){EmployeeId = 5, EmployeeName ="Fifth", Salary=50000}
        };
    }

}

EmployeeDTO.cs for reference

public class EmployeeDTO
{
    public int EmployeeId { get; set; }
    public string EmployeeName { get; set; }
}
10

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
    {
        ...
    }
Brian Rice
  • 3,107
  • 1
  • 35
  • 53
  • Why don't you just use `services.AddAutoMapper( typeof(DAL.MapperProfile) ); ` instead of `services.AddAutoMapper(new Type[] { typeof(DAL.MapperProfile) });` ? – Second Person Shooter Aug 29 '19 at 12:13
10

For AutoMapper 9.0.0:

public static IEnumerable<Type> GetAutoMapperProfilesFromAllAssemblies()
    {
        foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
        {
            foreach (var aType in assembly.GetTypes())
            {
                if (aType.IsClass && !aType.IsAbstract && aType.IsSubclassOf(typeof(Profile)))
                    yield return aType;
            }
        }
    }

MapperProfile:

public class OrganizationProfile : Profile
{
  public OrganizationProfile()
  {
    CreateMap<Foo, FooDto>();
    // Use CreateMap... Etc.. here (Profile methods are the same as configuration methods)
  }
}

In your Startup:

services.AddAutoMapper(GetAutoMapperProfilesFromAllAssemblies()
            .ToArray());

In Controller or service: Inject mapper:

private readonly IMapper _mapper;

Usage:

var obj = _mapper.Map<TDest>(sourceObject);
Nicolae Lupei
  • 161
  • 2
  • 5
7

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

First of all, define Profile classes inherited by Profile Class of Automapper. I Created IProfile interface which is empty, the purpose is only to find the classes of this type.

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

Now create a separate class e.g 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 MVC Core web Project in Startup.cs file, in the constructor, call Mapping class which will initialize all mappings at the time of application loading.

Mappings.RegisterMappings();
Roy Scheffers
  • 3,832
  • 11
  • 31
  • 36
Aamir
  • 695
  • 10
  • 11
  • You can just create a subclass from profile class, and when program is running services.AddAutoMapper(); line of codes The automapper automatically knows them. – isaeid Oct 01 '17 at 13:49
  • I don't think this is necessary if you use AutoMapper.Extensions.Microsoft.DependancyInjection which is available in nuget. – Greg Gum Aug 18 '18 at 10:43
6

In .NET 6 you'll need to add the following to the Program.cs file:

builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
Tachyon
  • 2,171
  • 3
  • 22
  • 46
5

For ASP.NET Core (tested using 2.0+ and 3.0), if you prefer to read the source documentation: https://github.com/AutoMapper/AutoMapper.Extensions.Microsoft.DependencyInjection/blob/master/README.md

Otherwise following these 4 steps works:

  1. Install AutoMapper.Extensions.Microsoft.DependancyInjection from nuget.

  2. Simply add some profile classes.

  3. Then add below to your startup.cs class. services.AddAutoMapper(OneOfYourProfileClassNamesHere)

  4. Then simply Inject IMapper in your controllers or wherever you need it:

public class EmployeesController {

    private readonly IMapper _mapper;

    public EmployeesController(IMapper mapper){

        _mapper = mapper;
    }

And if you want to use ProjectTo its now simply:

var customers = await dbContext.Customers.ProjectTo<CustomerDto>(_mapper.ConfigurationProvider).ToListAsync()
dalcam
  • 1,027
  • 11
  • 28
3

Let’s have a look at how to add Auto mapper into our .NET Core application.

step: 1 The first step is to install the corresponding NuGet package:

Install-Package AutoMapper.Extensions.Microsoft.DependencyInjection

step: 2

After installing the required package, the next step is to configure the services. Let’s do it in the Startup.cs class:

public void ConfigureServices(IServiceCollection services)
{
    services.AddAutoMapper(typeof(Startup));
    services.AddControllersWithViews();
}

step: 3

Let’s start usage we have a domain object named User:

public class User
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }
    public string Address { get; set; }
}

In the UI layer, we would have a View Model to display the user information:

public class UserViewModel
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }
}

step: 4

A good way to organize our mapping configurations is with Profiles. We need to create classes that inherit from Profile class and put the configuration in the constructor:

public UserProfile()
{
    CreateMap<User, UserViewModel>();
}

step: 5

Now, let’s define a Controller and use the Auto-Mapping capabilities that we just added:

public class UserController : Controller
{
    private readonly IMapper _mapper;
    public UserController(IMapper mapper)
    {
        _mapper = mapper;
    }
    public IActionResult Index()
    {
        // Populate the user details from DB
        var user = GetUserDetails();
        UserViewModel userViewModel = _mapper.Map<UserViewModel>(user);
        return View(userViewModel);
    }
}

First, we inject the mapper object into the controller. Then, we call the Map() method, which maps the User object to the UserViewModel object. Furthermore, pay attention to a local method GetUserDetails that we use for the local data storage. You can find its implementation in our source code.

2

Asp.Net Core 2.2 with AutoMapper.Extensions.Microsoft.DependencyInjection.

public class MappingProfile : Profile
{
  public MappingProfile()
  {
      CreateMap<Domain, DomainDto>();
  }
}

In Startup.cs

services.AddAutoMapper(typeof(List.Handler));
Sras
  • 1,686
  • 2
  • 19
  • 29
1

services.AddAutoMapper(); didn't work for me. (I am using Asp.Net Core 2.0)

After configuring as below

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

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

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

this way I am able to add a DI to controller

  private IMapper autoMapper = null;

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

and I have used as below in my action methods

  ClientCustomer customerObj = autoMapper.Map<ClientCustomer>(customer);
Venkat pv
  • 113
  • 1
  • 6
  • Hi @venkat you probably just needed to add the AutoMapper.Extensions.Microsoft.DependancyInjection package to your project – dalcam Sep 25 '19 at 18:25
1

For AutoMapper 11.0.1 using .NET 7 I started getting this exception:

System.ArgumentException: 'GenericArguments[0], 'System.DateTime', on 'T MaxInteger[T](System.Collections.Generic.IEnumerable`1[T])' violates the constraint of type 'T'.'

Inner Exception
VerificationException: Method System.Linq.Enumerable.MaxInteger: type argument 'System.DateTime' violates the constraint of type parameter 'T'.

See this question:

System.DateTime on 'T MaxInteger[T](System.Collections.Generic.IEnumerable`1[T])' violates the constraint of type T for .NET 7 using AutoMapper 11.0.1

This meant that I could no longer use services.AddAutoMapper(typeof(MappingProfile).Assembly); without an exception.

For AutoMapper.Extensions.Microsoft.DependencyInjection I solved it like this:

services.AddAutoMapper(cfg => cfg.Internal().MethodMappingEnabled = false, typeof(MappingProfile).Assembly);

For Blazor WebAssembly client the solution looked like this:

var mapperConfig = new MapperConfiguration(mc =>
{
    //Needed for https://github.com/AutoMapper/AutoMapper/issues/3988
    mc.Internal().MethodMappingEnabled = false;
    mc.AddProfile(new MappingProfile());
});
//mapperConfig.AssertConfigurationIsValid();

IMapper mapper = mapperConfig.CreateMapper();
builder.Services.AddSingleton(mapper);
Ogglas
  • 62,132
  • 37
  • 328
  • 418
1

First step is to install the corresponding nuget package for the AutoMapper

Install-Package AutoMapper.Extensions.Microsoft.DependencyInjection

After installing the package,we need to configure in program.cs file

builder.Services.AddAutoMapper(typeof(Program));
builder.Services.AddControllersWithViews()

Here is my customer class and getCustomerDto

public class User
{
  public int Id { get; set; }
  public string FirstName { get; set; }
  public string LastName { get; set; }
}
 
public class getCustomerDto
{
  public string FirstName { get; set; }
  public string LastName { get; set; }
}

We can create a new file 'AutoMapperProfiles.cs' for all automapper configuration .In this file we need to create a class that inherits Profiles. And In the Constructor we can have our automapper configurations.

public class AutoMapper: Profile {
public AutoMapper() 
  {
    CreateMap < Customer, getCustomerDto > ();
  }
}

In our controller we can make use of the auto mapper configuration that we have defined

public class CustomerController : Controller
{
  private readonly IMapper _mapper;

  public CustomerController(IMapper mapper)
  {
    _mapper = mapper;
  }

  public IActionResult Index()

  {
    
    var customer = GetCustomerDetails();

    var customerDetails = _mapper.Map<getCustomerDto>(customer);
    
    return View(customerDetails);

  }
}

Now By doing these the properties in Customer class are automatically mapped to the customerDetailsDto.

0

To add onto what Arve Systad mentioned for testing. If for whatever reason you're like me and want to maintain the inheritance structure provided in theutz solution, you can set up the MapperConfiguration like so:

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

I did this in NUnit.

LandSharks
  • 397
  • 1
  • 4
  • 13
-2

About theutz answer, there is no need to specify the IMapper mapper parameter at the controllers constructor.

You can use the mapper as it is a static member at any place of the code.

public class UserController : Controller 
{
    public someMethod()
    {
        Mapper.Map<User, UserDto>(user);
    }
}
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
yaronmil
  • 39
  • 1
  • 5
  • 11
    But statics are a bit anti-testable, no? – Scott Fraley May 17 '17 at 17:40
  • 3
    Yep. This will work in many cases, but if you have no configured mapping when invoking this method in a test, It'll throw an exception (and thus failing the test for the wrong reason). With an injected `IMapper` you can mock that and, for example, just make it return null if it's irrelevant for the given test. – Arve Systad May 29 '17 at 20:48