Search code examples
c#asp.net-coreautomapper

Automapper to manually map some fields then handle the rest


I have this automapper:

namespace App.Mappings
{
    public class AutoMapperModelOne : Profile
    {
        public AutoMapperModelOne()
        {
            CreateMap<JToken, ModelOne>()
                .ForMember(dest => dest.id, opt => opt.MapFrom(src => src.SelectToken("application_id")))
                .ForMember(dest => dest.activity_created, opt => opt.MapFrom(src => src.SelectToken("activity_created")))
                .ForMember(dest => dest.source_url, opt => opt.MapFrom(src => src.SelectToken("source_url")))
                .ForMember(dest => dest.is_transferred, opt => opt.MapFrom(src => src.SelectToken("is_transferred")));
        }
    }
}

And I want to be able to automatically map the token values to the model values. But some fields should be ignored and some selected fields have a different token key compared to the model properties.

Something like this:

namespace App.Mappings
{
    public class AutoMapperModelOne : Profile
    {
        public AutoMapperModelOne()
        {
            CreateMap<JToken, RAFApplication>()
            // manually mapping this field to the id
            .ForMember(dest => dest.id, opt => opt.MapFrom(src => src.SelectToken("application_id")))
            // ignoring this field
            .ForMember(dest => dest.actualId, opt => opt.Ignore())
            // mapping specific fields first the mapping all others?
            .ForAllMembers(opt => opt.MapFrom(src => src.SelectToken(opt.DestinationMember.Name)));
        }
    }
}

The second block of code currently does not work and it produces an error thrown by my fluent validator:

enter image description here

What might I be doing wrong here?


Solution

  • the map rules you defined in ForMember would be overrided in that in ForAllMember You could try as below:

    public AutoMapperModelOne()
            {
                CreateMap<JToken, ModelOne>()                           
                    
                    .ForAllMembers(opt =>
                    {
                        opt.MapFrom( src=> opt.DestinationMember.Name=="Id"?src.SelectToken("appid"): src.SelectToken(opt.DestinationMember.Name)) ;
    
                        opt.Condition((src, des, arg3, arg4, resolutionContext) =>
                        {
                            var propname = opt.DestinationMember.Name;
                            if (propname == "Prop1")
                            {                            
                                return false;
                            }
                            return true;
                        });
                        });
    
    
            }
    

    Model class:

     public class ModelOne
        {
            public int Id { get; set; }
    
            public string? Prop1 { get; set; }
    
            public string? Prop2 { get; set; }
            public string? Prop3 { get; set; }
            public string? Prop4 { get; set; }
    
        }
    

    Map

    var obj = new {appid=1,Prop1="val1",Prop2="val2",Prop3="val3",Prop4="val4"};
        var jtoken = JToken.FromObject(obj);
        var targetmodel = mapper.Map<ModelOne>(jtoken);
    

    Result:

    enter image description here