Files
PowderCoatingLogix/AUTOMAPPER_DI_FIX.md
2026-04-23 21:38:24 -04:00

4.1 KiB

AutoMapper Configuration Error - FIXED

🐛 Issue Found

Error: AutoMapper dependency injection not working properly - IMapper interface couldn't be resolved.

Root Cause: The mapper instance was registered, but the IMapper interface wasn't explicitly registered, causing dependency injection failures in controllers.

Fix Applied

Updated both Program.cs files (Web and API) to properly register the IMapper interface.

Before (Incorrect):

// Configure AutoMapper
var mapperConfig = new MapperConfiguration(mc =>
{
    mc.AddProfile<CustomerProfile>();
    mc.AddProfile<JobProfile>();
});
builder.Services.AddSingleton(mapperConfig.CreateMapper());

Problem: This only registered the concrete Mapper type, not the IMapper interface that controllers depend on.

After (Correct):

// Configure AutoMapper
var mapperConfig = new MapperConfiguration(mc =>
{
    mc.AddProfile<CustomerProfile>();
    mc.AddProfile<JobProfile>();
});
IMapper mapper = mapperConfig.CreateMapper();
builder.Services.AddSingleton(mapper);
builder.Services.AddSingleton<IMapper>(mapper);

Solution:

  1. Create the mapper instance and store it in a variable
  2. Register the instance directly
  3. Explicitly register it as IMapper interface

This ensures that when controllers request IMapper via dependency injection, the service provider can resolve it.

📝 Why This Matters

Controllers and services use dependency injection like this:

public class CustomersController : Controller
{
    private readonly IMapper _mapper;  // ← Needs IMapper interface
    
    public CustomersController(IMapper mapper)
    {
        _mapper = mapper;
    }
}

Without the explicit IMapper registration, the DI container can't resolve this dependency, causing runtime errors:

InvalidOperationException: Unable to resolve service for type 'AutoMapper.IMapper'

🎯 Files Modified

  1. src/PowderCoating.Web/Program.cs - Lines 52-58
  2. src/PowderCoating.Api/Program.cs - Lines 76-82

🧪 Testing the Fix

In Controllers:

public class CustomersController : Controller
{
    private readonly IMapper _mapper;

    public CustomersController(IMapper mapper)
    {
        _mapper = mapper;  // ✅ Now works!
    }

    public async Task<IActionResult> Index()
    {
        var customers = await _unitOfWork.Customers.GetAllAsync();
        var dtos = _mapper.Map<List<CustomerDto>>(customers); // ✅ Works!
        return View(dtos);
    }
}

In API Controllers:

[ApiController]
[Route("api/[controller]")]
public class CustomersController : ControllerBase
{
    private readonly IMapper _mapper;

    public CustomersController(IMapper mapper)
    {
        _mapper = mapper;  // ✅ Now works!
    }

    [HttpGet]
    public async Task<ActionResult<List<CustomerDto>>> GetAll()
    {
        var customers = await _unitOfWork.Customers.GetAllAsync();
        return Ok(_mapper.Map<List<CustomerDto>>(customers)); // ✅ Works!
    }
}

💡 Alternative Approach (For Reference)

If you were using AutoMapper.Extensions.Microsoft.DependencyInjection, you could do:

builder.Services.AddAutoMapper(typeof(CustomerProfile).Assembly);

But since we're using AutoMapper 16.0 without the Extensions package, we need the manual configuration shown above.

Verification

After this fix, you should be able to:

  1. Inject IMapper into any controller or service
  2. Use _mapper.Map<TDestination>(source) without errors
  3. Run the application without DI resolution errors

🚀 Build and Run

# Clean and rebuild
dotnet clean
dotnet build

# Expected: Build succeeded. 0 Warning(s) 0 Error(s)

# Run the application
cd src/PowderCoating.Web
dotnet run

# Should start without errors

📋 Summary

What was wrong: Mapper instance created but IMapper interface not registered

What we fixed: Explicitly registered both the instance and the IMapper interface

Result: Dependency injection now works correctly in all controllers and services


AutoMapper configuration is now correct and ready to use!