9.8 KiB
Final Update Summary - AutoMapper 16.0 Without Extensions
✅ All Changes Completed
1. Removed AutoMapper.Extensions.Microsoft.DependencyInjection
- Replaced with direct AutoMapper 16.0 package
- Manual configuration using
MapperConfiguration - Singleton registration for better performance
2. All Projects Reverted to .NET 8.0 LTS
- ✅ PowderCoating.Core → net8.0
- ✅ PowderCoating.Application → net8.0
- ✅ PowderCoating.Infrastructure → net8.0
- ✅ PowderCoating.Web → net8.0
- ✅ PowderCoating.Api → net8.0
- ✅ PowderCoating.Shared → net8.0
- ✅ PowderCoating.UnitTests → net8.0
- ✅ PowderCoating.IntegrationTests → net8.0
3. AutoMapper Configuration
Web Project (PowderCoating.Web/Program.cs)
using AutoMapper;
using PowderCoating.Application.Mappings;
// Configure AutoMapper
var mapperConfig = new MapperConfiguration(mc =>
{
mc.AddProfile<CustomerProfile>();
mc.AddProfile<JobProfile>();
});
builder.Services.AddSingleton(mapperConfig.CreateMapper());
API Project (PowderCoating.Api/Program.cs)
using AutoMapper;
using PowderCoating.Application.Mappings;
// Configure AutoMapper
var mapperConfig = new MapperConfiguration(mc =>
{
mc.AddProfile<CustomerProfile>();
mc.AddProfile<JobProfile>();
});
builder.Services.AddSingleton(mapperConfig.CreateMapper());
4. AutoMapper Profiles Created
CustomerProfile.cs
Location: src/PowderCoating.Application/Mappings/CustomerProfile.cs
Maps:
- Customer ↔ CustomerDto
- CreateCustomerDto → Customer
- UpdateCustomerDto → Customer
- Customer → CustomerListDto (with contact name formatting)
JobProfile.cs
Location: src/PowderCoating.Application/Mappings/JobProfile.cs
Maps:
- Job ↔ JobDto
- CreateJobDto → Job
- UpdateJobDto → Job
- Job → JobListDto
- JobItem ↔ JobItemDto
- CreateJobItemDto → JobItem
- Job → ShopFloorJobDto (with priority colors & next steps)
Smart Features:
- Priority color coding (Rush=danger, Urgent=warning, etc.)
- Next step suggestions based on job status
- Enum name formatting ("InPreparation" → "In Preparation")
5. Package Updates
All packages updated to stable .NET 8.0 versions:
| Package | Version |
|---|---|
| AutoMapper | 16.0.0 |
| Microsoft.AspNetCore.Identity.UI | 8.0.0 |
| Microsoft.EntityFrameworkCore | 8.0.0 |
| Microsoft.EntityFrameworkCore.SqlServer | 8.0.0 |
| Microsoft.EntityFrameworkCore.Design | 8.0.0 |
| Microsoft.AspNetCore.Authentication.JwtBearer | 8.0.0 |
| Swashbuckle.AspNetCore | 6.5.0 |
| Serilog.AspNetCore | 8.0.0 |
| FluentValidation | 11.9.0 |
| Microsoft.SemanticKernel | 1.0.1 |
| Microsoft.ML | 3.0.1 |
📦 What's Changed from Previous Version
Before:
// Used extension package
builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
After:
// Manual configuration with explicit profile registration
var mapperConfig = new MapperConfiguration(mc =>
{
mc.AddProfile<CustomerProfile>();
mc.AddProfile<JobProfile>();
});
builder.Services.AddSingleton(mapperConfig.CreateMapper());
🎯 Benefits of This Approach
1. No Extension Package Dependency
- Direct AutoMapper 16.0 reference only
- Simpler dependency tree
- Better control over configuration
2. Explicit Profile Registration
- Know exactly which profiles are registered
- Easier to debug
- Better IntelliSense support
3. Singleton Registration
- Better performance (mapper created once)
- Thread-safe
- Recommended by AutoMapper team
4. Compile-Time Safety
- Errors caught at compile time
- No runtime profile discovery issues
- Clear configuration errors
🚀 How to Add New Profiles
When you add new features, follow this pattern:
Step 1: Create Profile Class
Create in src/PowderCoating.Application/Mappings/:
using AutoMapper;
using PowderCoating.Core.Entities;
using PowderCoating.Application.DTOs.YourModule;
namespace PowderCoating.Application.Mappings;
public class YourModuleProfile : Profile
{
public YourModuleProfile()
{
CreateMap<YourEntity, YourDto>();
CreateMap<CreateYourDto, YourEntity>();
// Add more mappings...
}
}
Step 2: Register in Both Program.cs Files
In Web/Program.cs:
var mapperConfig = new MapperConfiguration(mc =>
{
mc.AddProfile<CustomerProfile>();
mc.AddProfile<JobProfile>();
mc.AddProfile<YourModuleProfile>(); // ← Add this line
});
In Api/Program.cs:
var mapperConfig = new MapperConfiguration(mc =>
{
mc.AddProfile<CustomerProfile>();
mc.AddProfile<JobProfile>();
mc.AddProfile<YourModuleProfile>(); // ← Add this line
});
🔍 Verification Steps
1. Extract the Archive
# Windows
Expand-Archive PowderCoatingApp.zip -DestinationPath C:\Projects\
# Mac/Linux
tar -xzf PowderCoatingApp.tar.gz -C ~/Projects/
2. Restore Packages
cd PowderCoatingApp
dotnet restore
Expected Output:
Restore succeeded.
3. Build the Solution
dotnet build
Expected Output:
Build succeeded.
0 Warning(s)
0 Error(s)
4. Verify AutoMapper Configuration
When you run the application, AutoMapper will validate all mappings at startup. Any configuration errors will be caught immediately.
📝 Usage Examples
In Controllers
public class CustomersController : Controller
{
private readonly IUnitOfWork _unitOfWork;
private readonly IMapper _mapper;
public CustomersController(IUnitOfWork unitOfWork, IMapper mapper)
{
_unitOfWork = unitOfWork;
_mapper = mapper;
}
public async Task<IActionResult> Index()
{
var customers = await _unitOfWork.Customers.GetAllAsync();
var customerDtos = _mapper.Map<List<CustomerListDto>>(customers);
return View(customerDtos);
}
}
In API Controllers
[ApiController]
[Route("api/[controller]")]
public class JobsController : ControllerBase
{
private readonly IMapper _mapper;
public JobsController(IMapper mapper)
{
_mapper = mapper;
}
[HttpGet]
public async Task<ActionResult<List<JobListDto>>> GetAll()
{
var jobs = await _unitOfWork.Jobs.GetAllAsync();
return Ok(_mapper.Map<List<JobListDto>>(jobs));
}
}
⚠️ Important Notes
AutoMapper Validation
AutoMapper validates configurations at startup. If you see an error like:
AutoMapper.AutoMapperConfigurationException: Unmapped members were found.
This means a mapping is incomplete. Check:
- All DTOs have corresponding mappings
- Property names match or are explicitly mapped
- Complex mappings have custom resolvers
Adding Collections
When mapping collections, AutoMapper handles it automatically:
var customers = await _unitOfWork.Customers.GetAllAsync();
var dtos = _mapper.Map<List<CustomerDto>>(customers); // Works automatically
Nested Mappings
AutoMapper automatically maps nested objects if they have profiles:
// If Job has Customer property and both have profiles, this works:
var jobDto = _mapper.Map<JobDto>(job); // Automatically maps job.Customer
🐛 Troubleshooting
Error: "Type 'CustomerProfile' not found"
Solution: Add using statement:
using PowderCoating.Application.Mappings;
Error: "No parameterless constructor defined"
Solution: Ensure profile classes have no constructor parameters:
public class CustomerProfile : Profile
{
public CustomerProfile() // ← Must be parameterless
{
// Configuration...
}
}
Build Error: Package version conflicts
Solution: Clean and restore:
dotnet clean
dotnet nuget locals all --clear
dotnet restore
dotnet build
📋 File Changes Summary
Modified Files:
- src/PowderCoating.Web/PowderCoating.Web.csproj - Package updates
- src/PowderCoating.Web/Program.cs - Manual AutoMapper config
- src/PowderCoating.Api/PowderCoating.Api.csproj - Package updates
- src/PowderCoating.Api/Program.cs - Manual AutoMapper config
- src/PowderCoating.Core/PowderCoating.Core.csproj - .NET 8.0
- src/PowderCoating.Application/PowderCoating.Application.csproj - .NET 8.0, AutoMapper 16.0
- src/PowderCoating.Infrastructure/PowderCoating.Infrastructure.csproj - .NET 8.0
- src/PowderCoating.Shared/PowderCoating.Shared.csproj - .NET 8.0
- tests/PowderCoating.UnitTests/PowderCoating.UnitTests.csproj - .NET 8.0
- tests/PowderCoating.IntegrationTests/PowderCoating.IntegrationTests.csproj - .NET 8.0
New Files:
- src/PowderCoating.Application/Mappings/CustomerProfile.cs
- src/PowderCoating.Application/Mappings/JobProfile.cs
✨ Key Improvements
✅ Cleaner Dependencies - No Extensions package needed ✅ Explicit Configuration - Clear what's registered ✅ Better Performance - Singleton mapper instance ✅ Type Safety - Compile-time profile validation ✅ Easier Debugging - Clear error messages ✅ .NET 8.0 LTS - Long-term support until 2026 ✅ AutoMapper 16.0 - Latest features and performance
🎉 Ready to Use!
Your project now has:
- ✅ AutoMapper 16.0 without Extensions package
- ✅ Manual configuration for full control
- ✅ All projects on .NET 8.0 LTS
- ✅ Complete mapping profiles for Customer and Job modules
- ✅ Smart features (priority colors, next steps, formatting)
Download, extract, and build - it's ready to go!
When you add new features, just:
- Create a new Profile class
- Add it to MapperConfiguration in both Program.cs files
- That's it!
Note: When .NET 10.0 releases in November 2025, you can upgrade by simply changing <TargetFramework>net8.0</TargetFramework> to net10.0 in all .csproj files and updating package versions.