I'm trying to TryParse
a string from API to an Enum
with AutoMapper, and if cannot parse, he should return an "default value".
My model is: Class Expense
public long Id { get; set; }
public string Description { get; set; }
public double Value { get; set; }
public DateTime Date { get; set; }
public Category Categories { get; set; }
My DTO is: Class ExpenseDTO
public long Id { get; set; }
public string Description { get; set; }
public double Value { get; set; }
public DateTime Date { get; set; }
public string Categories { get; set; }
Enum contain:
public enum Category : int {
Others = 0,
Food = 1,
Health = 2,
Home = 3,
Transport = 4,
Education = 5,
Chill = 6,
Unexpected = 7
}
I already tried a resolution that I saw here on Stack OverFlow, which is:
CreateMap<ExpenseDTO, Expense>()
.ForMember(dest => dest.Category,
opt =>
{
object? parsedResult;
opt.MapFrom(src =>
Enum.TryParse(typeof(Category), src.Categories, true, out parsedResult) ? parsedResult : Category.Others);
})
.ReverseMap().ForMember(dest => dest.Category,
opt => opt.MapFrom(src => src.Categories.ToString()));
That resolution still throw an exception when I try to send a category that not exist like "Test".
The API return that error:
Mapping types:
ExpenseDTO -> Expense
Challenge.API.ExpenseDTO -> Challenge.Domain.Expense
Type Map configuration:
ExpenseDTO -> Expense
Challenge.API.ExpenseDTO -> Challenge.Domain.Expense
Someone could help me, please?
If you need something more complicated than a simple src.Field => dest.Field type mapping, you can use a value resolver to plug in that custom logic like so:
public class CategoriesEnumValueResolver : IValueResolver<ExpenseDTO, Expense, Category>
{
public Category Resolve(ExpenseDTO source, Expense destination, Category destMember, ResolutionContext context)
{
if (Enum.TryParse<Category>(source.Categories, out var category))
return category;
return Category.Others;
}
}
You then tell AutoMapper to use that value resolver when you create your map:
CreateMap<ExpenseDTO, Expense>()
.ForMember(m => m.Categories, opt => opt.MapFrom<CategoriesEnumValueResolver>());