ASP.NET Core 3.1 Clean Architecture – Invoice Management App (Part 4 AutoMapper – Map object properties to another object)

In the previous article ASP.NET Core 3.1 Clean Architecture – Invoice Management App (Part 3 MediatR and FluentValidation) we created an API with the help of MediatR and Fluenvalidation. Now we will enhance our code by removing the manual mapping of properties by using AutoMapper.

Advertisements

AutoMapper is a library that can map your object properties with the other object. By default, It maps the value of one object to another by looking on the properties with similar names from the source object to destination object.

To start using AutoMapper in our project install the following libraries in Application layer and Api

  • AutoMapper
  • AutoMapper.Extensions.Microsoft.DependencyInjection
Advertisements

AutoMapper look on mapping profiles to know how it will map the object to another object. That’s why we need to register our mapping in the mapping profile.

Create a new folder inside the Invoices folder and name it MappingProfiles. Inside the MappingProfiles folder, create a new class called InvoiceMappingProfile

public class InvoiceMappingProfile: Profile
    {
        public InvoiceMappingProfile()
        {
            CreateMap<Invoice, InvoiceVm>();
            CreateMap<InvoiceItem, InvoiceItemVm>().ConstructUsing(i => new InvoiceItemVm
            {
                Id = i.Id,
                Item = i.Item,
                Quantity = i.Quantity,
                Rate = i.Rate
            });

            CreateMap<InvoiceVm, Invoice>();
            CreateMap<InvoiceItemVm, InvoiceItem>();

            CreateMap<CreateInvoiceCommand, Invoice>();
        }
    }

By default AutoMapper can map properties with similar name, but in case you need to do a manual mapping, like when the properties of the object have different names. You can use the method ConstructUsing to define how the object will map to another object.

Open DependencyInjection class in Application layer to register the AutoMapper in the services.

public static class DependecyInjection
    {
        public static IServiceCollection AddApplication(this IServiceCollection services)
        {
            services.AddMediatR(Assembly.GetExecutingAssembly());
            services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>));
            services.AddValidatorsFromAssembly(Assembly.GetExecutingAssembly());
            services.AddAutoMapper(Assembly.GetExecutingAssembly());
            return services;
        }
    }
Advertisements

Update the CreateInvoiceCommandHandler to use AutoMapper. We need to inject IMapper in the constructor and use the method Map to map CreateInvoiceCommand properties to Invoice.

public class CreateInvoiceCommandHandler : IRequestHandler<CreateInvoiceCommand, int>
    {
        private readonly IApplicationDbContext _context;
        private readonly IMapper _mapper;

        public CreateInvoiceCommandHandler(IApplicationDbContext context, IMapper mapper)
        {
            _context = context;
            _mapper = mapper;
        }
        public async Task<int> Handle(CreateInvoiceCommand request, CancellationToken cancellationToken)
        {
            var entity = _mapper.Map<Invoice>(request);

            _context.Invoices.Add(entity);
            await _context.SaveChangesAsync(cancellationToken);
            return entity.Id;
        }
    }

Now that the properties mapping was remove. Our code in CreateInvoiceCommandHandler becomes cleaner and easier to read.

Update the GetUserInvoicesQueryHandler.

public class GetUserInvoicesQueryHandler : IRequestHandler<GetUserInvoicesQuery, IList<InvoiceVm>>
    {
        private readonly IApplicationDbContext _context;
        private readonly IMapper _mapper;

        public GetUserInvoicesQueryHandler(IApplicationDbContext context, IMapper mapper)
        {
            _context = context;
            _mapper = mapper;
        }
        public async Task<IList<InvoiceVm>> Handle(GetUserInvoicesQuery request, CancellationToken cancellationToken)
        {
            var result = new List<InvoiceVm>();
            var invoices = await _context.Invoices.Include(i => i.InvoiceItems)
                .Where(i => i.CreatedBy == request.User).ToListAsync();
            if(invoices != null)
            {
                result = _mapper.Map<List<InvoiceVm>>(invoices);
            }

            return result;
        }
    }
Advertisements

Now test our application, to see if we breaks anything. Login in the app and copy the token.

Using the token that you got from logging in.

Send a POST request to the API to create a new Invoice.

Advertisements

Now try to send a GET request to get user invoices.

Now that we successfully used the AutoMapper in our application. This will make our development a lot faster by eliminating the manual typing of the property mapping. In the next part ASP.NET Core 3.1 Clean Architecture – Invoice Management App (Part 5 NSwag – Setting up Swagger and Auto generate API client code) we will use NSwag to create API specification and generate API client code for our ReactJs project.

Advertisements

SOURCE CODE: https://github.com/alexcalingasan/InvoiceManagementApp/tree/feature/add_automapper

RELATED ARTICLES:

ASP.NET Core 3.1 Clean Architecture – Invoice Management App (Part 1)

ASP.NET Core 3.1 Clean Architecture – Invoice Management App (Part 2 Auditing in EF Core with CreatedBy and LastModifiedBy)

ASP.NET Core 3.1 Clean Architecture – Invoice Management App (Part 3 MediatR and FluentValidation)

ASP.NET Core 3.1 Clean Architecture – Invoice Management App (Part 4 AutoMapper – Map object properties to another object)

ASP.NET Core 3.1 Clean Architecture – Invoice Management App (Part 5 NSwag – Setting up Swagger and Auto generate API client code)

ASP.NET Core 3.1 Clean Architecture – Invoice Management App (Part 6 React – How To Convert ReactJs To Typescript)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s