AutoMapper is a powerful object-to-object mapping library that simplifies the mapping between models and DTOs in .NET applications. However, when used with Dependency Injection (DI), developers occasionally face a common yet tricky issue: ambiguous method call errors.

In this article, we'll explore.

The Problem: Ambiguous Method Calls

An ambiguous method call occurs when the compiler can’t decide between overloaded methods.

The call is ambiguous between the following methods or properties: 
'AutoMapper.IMapper.Map<TSource, TDestination>(TSource)' 
and 
'AutoMapper.IMapper.Map<TDestination>(object)'

This often happens when AutoMapper can’t resolve which overload to use based on the input parameters.

AutoMapper and Dependency Injection

In modern .NET apps, AutoMapper is typically registered and resolved via DI.

Registering AutoMapper in .NET Core / .NET 6+

services.AddAutoMapper(typeof(Startup));

Injecting AutoMapper

public class UserService
{
    private readonly IMapper _mapper;
    public UserService(IMapper mapper)
    {
        _mapper = mapper;
    }
    public UserDto GetUserDto(User user)
    {
        return _mapper.Map<UserDto>(user); // Might trigger ambiguity
    }
}

What Causes Ambiguity?

AutoMapper's Overloads

AutoMapper offers these two common overloads

TDestination Map<TSource, TDestination>(TSource source);
TDestination Map<TDestination>(object source);

If the compiler sees both as valid options, it throws an ambiguity error.

Example That Fails

object user = GetUser();
var dto = _mapper.Map<UserDto>(user); // Error: Ambiguous call

The compiler can’t decide between.

Solutions to Fix the Ambiguity

1. Specify Both Generic Types

Always prefer the Map<TSource, TDestination>() overload explicitly.

var dto = _mapper.Map<User, UserDto>((User)user);

2. Avoid Mapping from object or dynamic

Instead of

object user = GetUser();
_mapper.Map<UserDto>(user); // Ambiguous

Do this

var user = (User)GetUser();
_mapper.Map<UserDto>(user);

Or better,

User user = GetUser();
_mapper.Map<UserDto>(user);

3. Use Helper Extension for Explicit Mapping

public static class AutoMapperExtensions
{
    public static TDestination MapExplicit<TSource, TDestination>(this IMapper mapper, TSource source)
    {
        return mapper.Map<TSource, TDestination>(source);
    }
}

Usage

var dto = _mapper.MapExplicit<User, UserDto>(user);

4. Configure Mapping Profiles

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

And register,

services.AddAutoMapper(typeof(UserProfile));

5. Update AutoMapper Package

Make sure you're using the latest version.

dotnet add package AutoMapper

Common Pitfalls

Pitfall Solution
Mapping from an object or a dynamic Use an explicit cast
Using var with ambiguous types Use strongly typed variables
Missing Profile mappings Always configure profiles
Outdated AutoMapper version Keep packages updated

Real-World API Example

[HttpPost]
public IActionResult CreateUser([FromBody] object model)
{
    var userDto = _mapper.Map<UserDto>(model); // Ambiguous
}

Solution

[HttpPost]
public IActionResult CreateUser([FromBody] User model)
{
    var userDto = _mapper.Map<UserDto>(model); // No ambiguity
}

Best Practices

GitHub Project URL

https://github.com/SardarMudassarAliKhan/AutoMapperwithDependencyInjection

Conclusion

Ambiguous method calls in AutoMapper with dependency injection are a result of compiler confusion over method overloads. The key is to be explicit with types, configure AutoMapper correctly, and avoid loosely typed mappings. With these strategies, you can confidently use AutoMapper in your .NET applications without ambiguity errors.