How to Set Up Automapper in ASP.NET Core

How to set up Automapper in ASP.NET Core

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!
    }
    }

How to setup AutoMapper in ASP.Net Core 6

Using this line instead: typeof(Program).Assembly

How to configure AutoMapper in Asp.Net 5 Core app?

2 things are needed:

  1. In the Startup.cs file:

    services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
  2. You may create a folder for your mappings and call it MappingProfiles or anything you want. And then add your mapping profile classes, note, the class should inherit from Profile object of the AutoMapper namespace and do the mappings in the constructor.

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

In your case, it doesn't work because you are doing the wrong mapping direction. You need to make it opposite.

Change to:

MapperExpression.CreateMap(typeof(UserViewModel), typeof(User));

AutoMapper doesn't work in asp net core 5.0.2

Recomended way of registering Autommaper is described in their docs: https://docs.automapper.org/en/stable/Dependency-injection.html#asp-net-core

Create mapping profile and register it using

services.AddAutoMapper(profileAssembly1, profileAssembly2 /*, ...*/);

In your case looks like you registered mapper instance, your example says that you injected mapper instance but exception says that you want to resolve IConfiguration. Check your code, if you don't try to inject IConfiguration (which is not registered).

Configuring AutoMapper in ASP.NET Core

Only adding services.AddAutoMapper(); to the ConfigureServices method would not work for you. You have to configure AutoMapper as follows:

public void ConfigureServices(IServiceCollection services)
{
// Auto Mapper Configurations
var mappingConfig = new MapperConfiguration(mc =>
{
mc.AddProfile(new MappingProfile());
});

IMapper mapper = mappingConfig.CreateMapper();
services.AddSingleton(mapper);

services.AddMvc();
}

And also don't forget to install the AutoMapper.Extensions.Microsoft.DependencyInjection nuget package.

How to initialize AutoMapper in a multi-layer web application based on ASP.NET Core 5?

If you really don't want to use dependency injection, you can handle this with a static bootstrapper class to setup the mappings and to access the mapper instance:

// DataAccess project
public static class MapperBootstrapper
{
private static IMapper _instance;
internal static IMapper Instance => _instance;

public static void Configure()
{
if (_instance != null)
throw new InvalidOperationException("Already configured");

var config = new MapperConfiguration(
cfg =>
{
cfg.AddProfile<ProjectProfile>();
// Add more profiles and other mapping
});
_instance = config.CreateMapper();
}
}

With profiles you can group your related mapping logic, such as mapping related to the Project model:

// DataAccess project
public class ProjectProfile : Profile
{
public ProjectProfile()
{
CreateMap<ProjectEntity, Model.Project>()
.ForMember(
dest => dest.FullName,
opt => opt.MapFrom(src => $"{src.Area}\\{src.Name}"));
}
}

In your Startup.cs you can then use the bootstrapper class to setup the mappings as early as possible in the application's lifecycle (if you don't want the WebApplication project to reference the DataAccess project, you'll need an intermediate class in the BusinessLogic project):

public void ConfigureServices(IServiceCollection services)
{
DataAccess.MapperBootstrapper.Configure();
// ...
}

In your ProjectDataAccessor you can then use the mapper like so:

public List<Model.Project> GetProjects()
{
var dbCollection = // Get data from the source

return MapperBootstrapper.Instance
.Map<List<Model.Project>>(dbCollection);
}

The examples are based on some dummy models:

// DataAccess project
public class ProjectEntity
{
public Guid ID { get; set; }
public string Area { get; set; }
public string Name { get; set; }
}

// Model project
public class Project
{
public Guid ID { get; set; }
public string FullName { get; set; }
}

To see an example in action, check out this fiddle.

ASP.NET CORE Automapper Profile with Scoped Dependency

I'll answer my own question for future reference:

Thanks to @lucian-bargaoanu for providing the link in the comments: https://docs.automapper.org/en/latest/Queryable-Extensions.html#parameterization

Dynamic parameters can be passed via the ProjectTo method.

I ended up creating extension methods for all my DTO Projections

public static class DestinationProjection 
{
public static IQueryable<Destination> ProjectToDestination(IQueryable source, IConfiguration configuration, int currentUserId) {
return source.ProjectTo<Destination>(configuration, new { currentUserId });
}
}

And in the mapping I used this parameter

public class MappingProfile : Profile 
{
public MappingProfile() {
int? currentUserId = null;
CreateMap<Source, Destination>()
.ForMember(vm => vm.NumOwnComments, opts => opts.MapFrom(s => s.Comments.Count(c => c.UserId == currentUserId.GetValueOrDefault()))
;
}
}

This way I can inject my ICurrentUserService in the handler class.

public class DestinationListQueryHandler  
{
public DestinationListQueryHandler(IMapper mapper, IDbContext dbContext, ICurrentUserService currentUserService)
{
// field initialization logic
}

public async Task<IEnumerable<Destination>> Handle(CancellationToken cancellationToken)
{
return await dbContext.Sources.ProjectToDestination(mapper.ConfigurationProvider, currentUserId).ToListAsync(cancellationToken);
}
}

An issue with AutoMapper in ASP.Net Core

Ok, I've managed to solve the problem, it had nothing to do with the code above. Just passed the wrong assembly to the profile constructor

Using Automapper with ASP.NET Core


Mapper.AssertConfigurationIsValid();

This calls the static IMapper instance which is used in situations where you don’t use dependency injection. Since you never set up the static mapper, using it there will fail.

What you want to do instead is call AssertConfigurationIsValid on the actual mapper instance, the one that you are registering as a singleton. So you should remove the assert from the mapper profile and instead call it within your AddApplicationMappings method:

IMapper mapper = mapperConfig.CreateMapper();
mapper.AssertConfigurationIsValid();
services.AddSingleton(mapper);


Related Topics



Leave a reply



Submit