I have a property in my destination entity with IgnoreMap attribute.
I want to disable only once. I use Automapper list to list mapping.
public class TestDto {
public string Name { get; set; }
public DateTime UpdateDate { get; set; }
}
public class Test {
public string Name { get; set; }
//Normally, I want to ignore this entities all mapping except one method.
[IgnoreMap]
public DateTime UpdateDate { get; set; }
}
class Program {
public void MapMethod(List<TestDto> sourceList)
{
var content = new MapperConfigurationExpression();
content.CreateMap<TestDto,Test>();
var config = new MapperConfiguration(content);
var mapper = config.CreateMapper();
//I do not want to ignore UpdateDate entity in here.
var destinationList = mapper.Map<List<Test>>(sourceList);
}
}
you can try this:
_mapper.Map<DestType>(result, options => options.AfterMap((s, d) => ((DestType) d).Code = null));
Full Example
void Main()
{
IConfigurationProvider conf = new MapperConfiguration(exp => exp.CreateMap<Src, Dest>());
IMapper mapper = new Mapper(conf);
var src = new Src(){
Id =1,
Name= "John Doe"
};
var result = mapper.Map<Dest>(src, options => options.AfterMap((s, d) => ((Dest) d).Name = null));
result.Dump();
var result2 = mapper.Map<List<Dest>>(srcList, options => options.AfterMap((s, d) => ((List<Dest>) d).ForEach(i => i.Name = null)));
result2.Dump();
}
public class Src
{
public int Id {get; set;}
public string Name {get; set;}
}
public class Dest
{
public int Id {get; set;}
public string Name {get; set;}
}
Alternatively
void ConfigureMap(IMappingOperationOptions<Src, Dest> opt)
{
opt.ConfigureMap()
.ForMember(dest => dest.Name, m => m.Ignore());
};
var result3 = mapper.Map<List<Dest>>(srcList, ConfigureMap());
result3.Dump();
Related
I'm trying to map a flat object to a list. The Id gets mapped properly, but the list is always empty. I have used reverse mapping for the ListItem in destination.
What is wrong with this code or missing please?
using AutoMapper;
MapperConfiguration config = new MapperConfiguration(x =>
{
x.CreateMap<Origin, Destination>();
x.CreateMap<Destination, NonListItem>()
.ReverseMap()
.ForPath(d => d.ListItem, o => o.MapFrom(s => new List<ListItem> {
new ListItem
{
ListInt = s.NonListInt,
ListStr = s.NonListStr
}
}));
});
var origin = new Origin();
origin.Id = 12345;
origin.NonListItem.NonListInt = 54321;
origin.NonListItem.NonListStr = "This is a test";
IMapper mapper = new Mapper(config);
var destination = mapper.Map<Destination>(origin);
Console.ReadKey();
//###############################################################+
public class Origin
{
public NonListItem NonListItem { get; set; } = new NonListItem();
public int Id { get; set; }
}
public class NonListItem
{
public int NonListInt { get; set; }
public string? NonListStr { get; set; }
}
public class Destination
{
public int Id { get; set; }
public List<ListItem> ListItem { get; set; } = new List<ListItem>();
}
public class ListItem
{
public int ListInt { get; set; }
public string? ListStr { get; set; }
}
Mapping from Destination to NonListItem is not needed. Just configure the Origin to Destination mapping.
MapperConfiguration config = new MapperConfiguration(x =>
{
x.CreateMap<Origin, Destination>()
.ForMember(dest => dest.ListItem, opt => opt.MapFrom(src => new List<ListItem>
{
new ListItem
{
ListInt = src.NonListItem.NonListInt,
ListStr = src.NonListItem.NonListStr
}
}));
});
Below is the mapper snippet with classes :
Mapper.Initialize(cfg =>
{
cfg.CreateMap<STest, ETest>().ForMember(d => d.customFields[0].stringValue, o => o.MapFrom(s => s.val));
}
);
var result = Mapper.Map<ETest>(JsonDeseriazedSource);
var serialized = JsonConvert.SerializeObject(result, Formatting.Indented);
And these are the source and destination classes to be mapped:
//source class
public class STest
{
public string Id { get; set; }
public string val { get; set; }
}
// destination class
public class ETest
{
public string Id { get; set; }
public Customfield[] customFields { get; set; }
}
public class Customfield
{
public string id { get; set; }
public string fieldName { get; set; }
public string stringValue { get; set; }
}
I need to map stringValue in Customfield object(destination) from val in Stest(source).
Thanks in advance!!
If I understand your question correctly, you can try this:
Mapper.Initialize(cfg =>
{
cfg.CreateMap<STest, Customfield>()
.ForMember(d => d.stringValue, o => o.MapFrom(s => s.val));
cfg.CreateMap<STest[], ETest>()
.ForMember(d => d.customFields, o => o.MapFrom(s => s.Select(Mapper.Map<Customfield>)));
});
var sTests= new[] { new STest { Id = "1", val = "val1" }, new STest { Id = "2", val = "val2" } };
var result = Mapper.Map<ETest>(sTests);
I am trying to map source string to List<T> for member but the value of the mapped member list property is always null.
Here is my code.
//Source model
public class Claims
{
public int Id { get; set; }
public string ClaimType {get; set; }
public string ClaimValue { get; set; } // produce json string [{"Action":"read","Status":"active"}]
}
// Dest model
public class ClaimsDto
{
public int Id { get; set; }
public string ClaimType { get; set; }
public List<ResourceActions> ClaimValues { get; set; }
}
public class ResourceActions
{
public string Action { get; set; }
public string Status { get; set; }
}
CreateMap<ResourceActions, ResourceActions>();
CreateMap<Claims, ClaimsDto>()
.ForMember(dest => dest.ClaimValues,
opt => opt.MapFrom( src=> JsonConvert.DeserializeObject<List<ResourceActions>>(src.ClaimValue)))
.ReverseMap();
Also tried with resolver like this.
.ForMember(dto => dto.ClaimValues, opt => opt.ResolveUsing<CustomResolver,string>(src=>src.ClaimValue ))
The resolver:
public class CustomResolver : IMemberValueResolver<Claims, ClaimsDto, string, List<ResourceActions>>
{
public List<ResourceActions> Resolve(Claims source, ClaimsDto destination, string sourceMember, List<ResourceActions> destinationMember, ResolutionContext context)
{
var data = JsonConvert.DeserializeObject<List<ResourceActions>>(sourceMember);
return context.Mapper.Map<List<ResourceActions>>(data); // not working
return JsonConvert.DeserializeObject<List<ResourceActions>>(sourceMember); // not working
}
}
And the controller
var mapped = _mapper.Map<List<ClaimsDto>>(source); // success without exception but the list property is null.
Other properties are mapped except this string to List<T> property.
I think this profile should solve the issue:
public class MyMapperProfile : Profile
{
public MyMapperProfile()
{
CreateMap<Claims, ClaimsDto>()
.ForMember(dto => dto.ClaimValues, cfg => cfg.MapFrom((claim, _) =>
JsonSerializer.Deserialize<IReadOnlyCollection<ResourceActions>>(claim.ClaimValue)));
}
}
Here is an example:
var config = new MapperConfiguration(cfg => cfg.AddProfile<MyMapperProfile>());
var mapper = config.CreateMapper();
var someClaims = new List<Claims>
{
new Claims { Id = 5, ClaimType = "Foo", ClaimValue = #"[{""Action"":""read"",""Status"":""active""}]" },
new Claims { Id = 7, ClaimType = "Bar", ClaimValue = #"[{""Action"":""create"",""Status"":""disabled""}]" },
};
var result = mapper.Map<List<ClaimsDto>>(someClaims);
foreach (var item in result)
{
Console.WriteLine(JsonSerializer.Serialize(item));
}
public class SourceExamModel
{
public int ExamId { get; set; }
public List<SectionModel> Sections { get; set; }
}
public class DesiationExamModel
{
public in ExamId {get;set;}
public System.Collections.Generic.IEnumerable<SectionModel> DestSections
{
get
{
}
set
{
}
}
What I tried:
var config = new MapperConfiguration(cfg => {
cfg.CreateMap<CrmMapper.SourceExamModel, CrmMapper.DestiationExamModel>()
.ForMember(v => v.Id, opts => opts.MapFrom(src => src.Id))
.ForMember(v => v.DestSections, opts => opts.MapFrom(src => src.SourceSections));
});
IMapper mapper = config.CreateMapper();
var source = new ExamModel();
var dest = mapper.Map<SourceExamModel, CrmMapper.DestiationExamModel>(source);
Can ayone help me how to map list of comple objects o los of complex objects
Assuming half of your example code is simple spelling mistakes, you pretty much have it working.
If the properties on the source and destination are named the same, you don't have to explicitly map them.
Your source in your example doesn't make sense, it needs the correct object and data.
Here's my attempt at a working example you can copy past into a console application.
class Program
{
static void Main(string[] args)
{
var config = new MapperConfiguration(cfg =>
cfg.CreateMap<SourceExamModel, DestinationExamModel>()
.ForMember(dest => dest.DestSections, c => c.MapFrom(src => src.Sections))
);
config.AssertConfigurationIsValid();
var mapper = config.CreateMapper();
var source = new SourceExamModel
{
ExamId = 1,
Sections = new List<SectionModel> { new SectionModel { SectionId = 1 }, new SectionModel { SectionId = 2 } }
};
var destination = mapper.Map<SourceExamModel, DestinationExamModel>(source);
}
}
public class SourceExamModel
{
public int ExamId { get; set; }
public List<SectionModel> Sections { get; set; }
}
public class DestinationExamModel
{
public int ExamId { get; set; }
public List<SectionModel> DestSections { get; set; }
}
public class SectionModel
{
public int SectionId { get; set; }
}
Not sure that I'm wording this the right way so hopefully the example is clear enough.
What I'm trying to do seems pretty basic to me so I'm assuming I'm missing something obvious.
For this example, the two ForMember mappings are trivial and get the job done. The question is for a more complex class, given any intermediate mappings are configured, how do you simply map the property of one object to the entire destination?
I searched for a while now and the closest I came to finding an answer is here but the ConvertUsing syntax doesn't work for me (I'm using Automapper 4.2.1)
Here are the example classes:
public class UserRoleDto
{
public string Name { get; set; }
public string Description { get; set; }
}
public class DbRole
{
public Guid RoleId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
public class DbUserRole
{
public Guid UserId { get; set; }
public DbRole Role { get; set; }
}
And here's my test case with the Automapper config setup (testing in LINQPad, that's what the Dump() is for at the end of the last line)
var dbRole = new DbRole { RoleId = Guid.NewGuid(), Name = "Role Name", Description = "Role Description" };
var dbUserRole = new DbUserRole { UserId = Guid.NewGuid(), Role = dbRole };
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<DbRole, UserRoleDto>();
/* Works but verbose for a class with more than a few props */
cfg.CreateMap<DbUserRole, UserRoleDto>()
.ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.Role.Name))
.ForMember(dest => dest.Description, opt => opt.MapFrom(src => src.Role.Description))
;
});
config.AssertConfigurationIsValid();
var mapper = config.CreateMapper();
var userRoleDto = mapper.Map<UserRoleDto>(dbUserRole).Dump();
How about passing in the sub-object to be mapped? E.g.
cfg.CreateMap<DbRole, UserRoleDto>();
Then, instead of mapping dbUserRole, you would map dbUserRole.Role.
var userRoleDto = mapper.Map<UserRoleDto>(dbUserRole.Role);
Here is another similar example using the following classes:
public class Person
{
public int person_id;
public int age;
public string name;
}
public class Address
{
public int address_id;
public string line1;
public string line2;
public string city;
public string state;
public string country;
public string zip;
}
public class PersonWithAddress
{
public int person_id;
public int age;
public string name;
public InnerAddress address;
}
public class InnerAddress
{
public string city;
public string state;
public string country;
}
With the following test case:
var person = new Person { person_id = 100, age = 30, name = "Fred Flintstone" };
var address = new Address { address_id = 500, line1 = "123 Main St", line2 = "Suite 3", city = "Bedrock", state = "XY", country = "GBR", zip="90210" };
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Person, PersonWithAddress>();
cfg.CreateMap<Address, InnerAddress>();
});
var mapper = config.CreateMapper();
var person_with_address = mapper.Map<Person, PersonWithAddress>(person);
person_with_address.address = new InnerAddress();
mapper.Map<Address, InnerAddress>(address, person_with_address.address);
Regards,
Ross