ASP.NET Core 2.2: Unable to resolve service for type 'AutoMapper.IMapper'
Asked Answered
P

3

19

ASP.NET Core (Version: 2.2.102)

I am building an API to return Portos and Especies, but anytime that I access /api/portos (as defined in the controller), I get this error:

InvalidOperationException: Unable to resolve service for type 'AutoMapper.IMapper' while attempting to activate 'fish.Controllers.PortosController'.

Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetService(IServiceProvider sp, Type type, Type requiredBy, bool isDefaultParameterRequired)

I am not sure what am I doing wrong, so any help is appreciated.


Models


Especie.cs

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace fish.Models
{
    [Table("Especies")]
    public class Especie
    {
        public int Id { get; set; }
        [Required]
        [StringLength(255)]
        public string Nome { get; set; }

        public Porto Porto { get; set; }
        public int PortoId { get; set; }
    }
}

Porto.cs

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel.DataAnnotations;

namespace fish.Models
{
    public class Porto
    {
        public int Id { get; set; }
        [Required]
        [StringLength(255)]
        public string Nome { get; set; }
        public ICollection<Especie> Models { get; set; }

        public Porto()
        {
            Models = new Collection<Especie>();
        }
    }
}

Controller


PortoController.cs

using System.Collections.Generic;
using System.Threading.Tasks;
using AutoMapper;
using AutoMapper.QueryableExtensions;
using fish.Controllers.Resources;
using fish.Models;
using fish.Persistence;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace fish.Controllers
{
    public class PortosController : Controller
    {
        private readonly FishDbContext context;
        private readonly IMapper mapper;
        public PortosController(FishDbContext context, IMapper mapper)
        {
            this.mapper = mapper;
            this.context = context;
        }


        [HttpGet("/api/portos")]
        public async Task<IEnumerable<PortoResource>> GetPortos()
        {
            var portos = await context.Portos.Include(m => m.Models).ToListAsync();

            return mapper.Map<List<Porto>, List<PortoResource>>(portos);
        }

    }
}

Controller>Resources

PortoResources.cs

using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace fish.Controllers.Resources
{
    public class PortoResource
    {
        public int Id { get; set; }
        public string Nome { get; set; }
        public ICollection<EspecieResource> Models { get; set; }

        public PortoResource()
        {
            Models = new Collection<EspecieResource>();
        }
    }
}

EspecieResource.cs

namespace fish.Controllers.Resources
{
    public class EspecieResource
    {
        public int Id { get; set; }
        public string Nome { get; set; }
    }
}

More Relevant Code


Stratup.cs

public void ConfigureServices(IServiceCollection services)
{
        services.AddAutoMapper();

        services.AddDbContext<FishDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("Default")));

        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

        // In production, the Angular files will be served from this directory
        services.AddSpaStaticFiles(configuration =>
        {
            configuration.RootPath = "ClientApp/dist";
        });
}

MappingProfile.cs

using AutoMapper;
using fish.Controllers.Resources;
using fish.Models;

namespace fish.Mapping
{
    public class MappingProfile : Profile
    {
        public MappingProfile()
        {
            CreateMap<Porto, PortoResource>();
            CreateMap<Especie, EspecieResource>();
        }
    }
}

FishDbContext.cs

using fish.Models;
using Microsoft.EntityFrameworkCore;

namespace fish.Persistence
{
    public class FishDbContext : DbContext
    {
        public FishDbContext(DbContextOptions<FishDbContext> options) : base(options)
        {

        }

        public DbSet<Porto> Portos { get; set; }
    }
}
Phillada answered 17/1, 2019 at 15:56 Comment(0)
M
43

You will have to use automapper package as shown below:

Install-Package AutoMapper.Extensions.Microsoft.DependencyInjection

This will also in turn install the Automapper nuget package if you don’t have it already.

Then, inside your ConfigureServices method of your startup.cs, you will have to add a call to it as shown below.

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

Refer this blog for more details.

EDIT:

There is very nice description from this thread.

You need to add code like below in startup.cs.

You have missed to add IMapper in DI. Please refer add Singleton call from below code.

public void ConfigureServices(IServiceCollection services) {
    // .... Ignore code before this

   // Auto Mapper Configurations
    var mappingConfig = new MapperConfiguration(mc =>
    {
        mc.AddProfile(new MappingProfile());
    });

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

    services.AddMvc();

}

EDIT: 06-07-21: Refer this blogpost which explains how to use AutoMapper with latest .NET

Mckee answered 17/1, 2019 at 16:0 Comment(3)
IMapper should be scoped, not a singletonUpsilon
Been a minute since I started a new project and needed to include AutoMapper. Got a depreciation warning when I added services.AddAutoMapper(); to startup.cs. Your edited answer was extremely helpful. Thank you!Taft
After wasting almost full day and found your answer and for sure edited part is very helpful.Cyclotron
I
7

In case you are using .NET CORE 5. First go to nuget packages, find and install AutoMapper.Extensions.Microsoft.DependencyInjectionenter image description here

Then you should extend Profile from Automapper and write mappings for your classes. Something like this belowenter image description here Then you should add Automapper in ConfigureServices method in Startup class.This typeof(CommonMappingProfile) can be omitted if your nuget package for AutoMapper is in the same project as your mapping profile class.

 services.AddAutoMapper(typeof(CommonMappingProfile));
Indispose answered 19/5, 2021 at 22:49 Comment(3)
Give a code snippet would be great rather than a picture.Qintar
this is picture of my code , so basically it is similarIndispose
@mapaic96 If you give code snippet it would be easier to copy and paste the code.Umbilical
M
0

My problem was I mistyped the dependency injection AutoMapper type in the controller class. I had it set as

public ExampleController(Mapper mapper)

when it should have been

public ExampleController(IMapper mapper)

It was giving me the error

System.InvalidOperationException: Unable to resolve service for type 'AutoMapper.Mapper' while attempting to activate 'example.Controllers.ExampleController'.

For reference, I'm using .NET 8.0 with AutoMapper 13.0. I did not install the DependencyInjection package, as this is deprecated. In Program.cs, I call

builder.Services.AddAutoMapper(typeof(MappingExampleProfile));
Matey answered 30/7 at 15:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.