Blake Rivell Blake Rivell - 3 months ago 613
ASP.NET (C#) Question

Configuring AutoMapper 4.2 with built in IoC in ASP.NET Core 1.0 MVC6

I am trying to figure out the proper way to configure AutoMapper in my application's Startup.cs file and then use it throughout my application.

I am trying to use this documentation which somewhat explains how to still give AutoMapper a static feel without the old static API. The example uses StructureMap.

I would like to know how I can do something similar, but in a Core 1.0 app using the built in services container.

I am assuming that in the Configure function I would configure AutoMapper and then in the ConfigureServices function I would add it as a transient.

I am assuming in the end the cleanest and most proper way to do this is using dependency injection. Here is my current attempt but it is not working:

Startup.cs

public IMapper Mapper { get; set; }
private MapperConfiguration MapperConfiguration { get; set; }
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<IMapper, Mapper>();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
MapperConfiguration MapperConfiguration = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Product, ProductViewModel>().ReverseMap();
});

Mapper = MapperConfiguration.CreateMapper();
}


In my controller:

private IMapper _mapper { get; set; }
// Constructor
public ProductsController(IMapper mapper)
{
_mapper = mapper;
}

public IActionResult Create(ProductViewModel vm)
{
Product product = _mapper.Map<ProductViewModel, Product>(vm);
}


It just isn't working at all... I must be missing some step or doing something wrong.

Answer

This answer suits the MVC 6 approach a little more around the Controller layer:

I migrated from AutoMapper 4.1.1 to 4.2.0, had a few issues figuring out the intricacies but got there in the end.

First I separated the AutoMapper Profile build into a new class (see below) to save clogging up the Startup class.

using AutoMapper;
using YourModels;
using YourViewModels;

namespace YourNamespace
{
    public class AutoMapperProfileConfiguration : Profile
    {
        protected override void Configure()
        {
            CreateMap<Application, ApplicationViewModel>();
            CreateMap<ApplicationViewModel, Application>();
            ...
        }
    }
}

I made the following amendments to the Startup class.

I added private member variable of type MapperConfiguration.

private MapperConfiguration _mapperConfiguration { get; set; }

In the Startup constructor I added the following code to instantiate my new AutoMapper Profile.

_mapperConfiguration = new MapperConfiguration(cfg =>
{
    cfg.AddProfile(new AutoMapperProfileConfiguration());
});

In ConfigureServices() I dropped my new AutoMapper Profile into a Singleton.

services.AddSingleton<IMapper>(sp => _mapperConfiguration.CreateMapper());

It was then just a simple operation to inject it the relevant controllers.

using AutoMapper;
using ...

namespace YourNamespace
{
    public class ApplicationsController : BaseController
    {
        [FromServices]
        private IMapper _mapper { get; set; }

        [FromServices]
        private IApplicationRepository _applicationRepository { get; set; }

        public ApplicationsController(
            IMapper mapper,
            IApplicationRepository applicationRepository)
        {
            _mapper = mapper;
            _applicationRepository = applicationRepository;
        }

        // GET: Applications
        public async Task<IActionResult> Index()
        {
            IEnumerable<Application> applications = await _applicationRepository.GetForIdAsync(...);

            if (applications == null)
                return HttpNotFound();

            List<ApplicationViewModel> viewModel = _mapper.Map<List<ApplicationViewModel>>(applications);

            return View(viewModel);
        }

        ...
}

Thanks to Rexebin over at https://pintoservice.wordpress.com/2016/01/31/dependency-injection-for-automapper-4-2-in-asp-net-vnext-mvc-project/ for his post which help enourmously.