| name | abp-object-mapping |
| description | ABP Framework v10.x (10.4/10.5) object mapping: IObjectMapper, Mapperly (default since v10.4, MapperBase), AutoMapper profiles, entity↔DTO conversion, AutoMap attributes. Use when you need object mapping or DTO mapping in ABP. |
ABP Framework — Object Mapping
ABP Framework v10.x (10.4/10.5) object mapping guide. Entity↔DTO conversion via the IObjectMapper abstraction. Since v10.4, Mapperly (compile-time, source-generated) is the default provider; AutoMapper is also supported. Stick with whichever one the solution already uses.
Trigger
- "ABP object mapping"
- "ABP entity to DTO mapping"
- "ABP DTO mapping"
- "ABP Mapperly"
- "ABP AutoMapper"
- "ABP IObjectMapper"
The IObjectMapper Abstraction
ABP base classes (ApplicationService, etc.) come with an ObjectMapper property out of the box:
public class BookAppService : ApplicationService
{
public async Task<BookDto> GetAsync(Guid id)
{
var book = await _bookRepository.GetAsync(id);
return ObjectMapper.Map<Book, BookDto>(book);
}
public async Task<List<BookDto>> GetAllAsync()
{
var books = await _bookRepository.GetListAsync();
return ObjectMapper.Map<List<Book>, List<BookDto>>(books);
}
public void Update(Book book, UpdateBookDto input)
=> ObjectMapper.Map(input, book);
}
In places without a base class, inject IObjectMapper.
Mapperly (Default Since v10.4)
A compile-time source generator — no reflection, fast. ABP integration uses MapperBase<TSource, TDestination>:
[Mapper]
public partial class BookToBookDtoMapper : MapperBase<Book, BookDto>
{
public override partial BookDto Map(Book source);
public override partial void Map(Book source, BookDto destination);
}
[Mapper]
public partial class CreateUpdateBookDtoToBookMapper : MapperBase<CreateUpdateBookDto, Book>
{
public override partial Book Map(CreateUpdateBookDto source);
public override partial void Map(CreateUpdateBookDto source, Book destination);
}
Module configuration:
[DependsOn(typeof(AbpMapperlyModule))]
public class MyApplicationModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddMapperlyObjectMapper<MyApplicationModule>();
}
}
Since the mappers derive from MapperBase, an ObjectMapper.Map<Book, BookDto>(...) call uses them automatically.
Custom Field Mapping (Mapperly)
[Mapper]
public partial class BookMapper : MapperBase<Book, BookDto>
{
[MapProperty(nameof(Book.Name), nameof(BookDto.Title))]
public override partial BookDto Map(Book source);
public override partial void Map(Book source, BookDto destination);
}
AutoMapper (Alternative)
If the solution uses AutoMapper, define a profile:
public class MyApplicationAutoMapperProfile : Profile
{
public MyApplicationAutoMapperProfile()
{
CreateMap<Book, BookDto>();
CreateMap<CreateUpdateBookDto, Book>();
}
}
Module configuration:
[DependsOn(typeof(AbpAutoMapperModule))]
public class MyApplicationModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddAutoMapperObjectMapper<MyApplicationModule>();
Configure<AbpAutoMapperOptions>(options =>
{
options.AddMaps<MyApplicationModule>(validate: true);
});
}
}
Attribute-Based Mapping (AutoMapper)
On the DTO:
[AutoMapFrom(typeof(Book))]
public class BookDto : EntityDto<Guid>
{
public string Name { get; set; }
}
[AutoMapTo(typeof(Book))]
public class CreateBookDto { public string Name { get; set; } }
Best Practices
- Use the
ObjectMapper abstraction — don't depend directly on the provider (Mapperly/AutoMapper)
- Stick with the solution's provider — for new projects, prefer Mapperly (default since v10.4)
- Keep mappings in the Application layer — entity↔DTO conversion is an application responsibility
- Use
validate: true with AutoMapper — catch unmapped fields early
- Map entity to DTO, do the reverse carefully — on create/update, only map allowed fields
Related