I am using Automapper 6.2.2.0, and trying to map from an entity object to a DTO, with different property names.
I am getting the following error:
Unmapped members were found. Review the types and members below. Add a
custom mapping expression, ignore, add a custom resolver, or modify
the source/destination type For no matching constructor, add a no-arg
ctor, add optional arguments, or map all of the constructor parameters
CompanyInfo -> OwnerDto (Destination member list) Db.CompanyInfo ->
TransferObjects.OwnerDto (Destination member list)
Unmapped properties: Name
My mapping looks like this:
cfg.CreateMap<CompanyInfo, OwnerDto>().ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.CompanyName));
My OwnerDto class:
public class OwnerDto
{
public int Id { get; set; }
public string Name { get; set; }
}
And my CompanyInfo Class:
public class CompanyInfo
{
public int Id { get; set; }
public string CompanyName { get; set; }
}
My mapping:
var results = Mapper.Map<List<CompanyInfo>,List <OwnerDto>>(data);
Any suggestions on what I am missing?
Initializer:
public static class AutomapperMaps {
Mapper.Initialize(cfg => {
cfg.CreateMap<User, UserDto>().ReverseMap();
cfg.CreateMap<CompanyInfo, OwnerDto>().ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.CompanyName));
// There are more mappings like the user one above. Those are all working fine.
}
}
Related
I'm using an Automapper and I need to map a List of objects into a nested object. I have these objects:
public abstract class FooSrcBase
{
}
public class FooSrc : FooSrcBase
{
public bool Prop { get; set; }
}
public class FooDest
{
public bool Prop { get; set; }
}
public class FooDestGroup
{
public FooDest FooDest { get; set; }
}
public class Dest
{
public FooDestGroup FooDestGroup { get; set; }
}
I have IEnumerable<FooSrc> which contains FooSrc objects (there are many implementations and only one object per each type may exist in the source) and I need to map it into Dest object. I need this because of mapping into the view models for front end.
When I register mapping like this:
CreateMap<IEnumerable<FooSrc>, Dest>().ForPath(dest => dest.FooDestGroup.FooDest, opt => opt.MapFrom(src => src.FirstOrDefault(x => x.GetType() == typeof(FooSrc))));
CreateMap<FooSrc, FooDest>();
When I map empty list, a problem occurs in Dest object - FooDestGroup is an instance of object, which has a property FooDest with null value.
How it would be possible to make Dest property FooDestGroup map to null, if I provide empty list as a source?
Firstly, your abstract FooSrc class will need a different name (conflicts with your concrete class name FooSrc)
How about modifying the constructor on Dest to avoid the nesting issue?
Automapper is capable of mapping to the constructor parameter automatically, but if you need more advanced behaviour you can refer to https://docs.automapper.org/en/stable/Construction.html
Something like this should work:
public class Dest
{
public FooGroup FooGroup { get; set; }
public Dest(FooDest fooDest)
{
FooGroup = new FooGroup { FooDest = fooDest };
}
}
[..]
Mapper.CreateMap<FooSrc, Dest>();
Mapper.Map<List<Dest>>(listOfFooSrc);
This fixed my problem:
CreateMap<IEnumerable<FooSrcBase>, Dest>()
.ForMember(dest => dest.FooDestGroup, opt => opt.MapFrom(src => src.FirstOrDefault(x => x.GetType() == typeof(FooSrc))));
CreateMap<FooSrc, FooDestGroup>()
.ForMember(dest => dest.FooDest, opt => opt.MapFrom(src => src));
CreateMap<FooSrc, FooDest>();
I'm using ASP.NET Core and Automapper 6.1.0 ,
I have two types that look like this
public class ExampleDTO
{
public Guid Id { get; set; }
public ProviderDTO Provider { get; set; }
}
public class Example
{
public Guid Id { get; set; }
public Guid Provider { get; set; }
}
ProviderDTO class (which is irelevant in this case)
public class ProviderDTO
{
public Guid Id { get; set; }
public string Name { get; set; }
}
AutoMapper configuration looks like this:
CreateMap<Example, ExampleDTO>().ForMember(x => x.Provider, opt => opt.Ignore());
CreateMap<ExampleDTO, Example>().ForMember(dest => dest.Provider,
opt => opt.MapFrom(src => src.Provider.Id));
When I map from Example to ExampleDTO, I want to pass the value for ProviderDTO type.
I tried something like this.
_mapper.Map<ExampleDTO>(example, opt => opt.AfterMap((src, dest) => dest.Provider = myProvider));
I get this
'object' does not contain a defenition for 'Provider' and no extension method
Is this achievable? If yes, what am I doing wrong?
With the AutoMapper, you may need to provide both the source and destination type, such as:
_mapper.Map<Example, ExampleDTO>(example, opt => {
opt.AfterMap((src, dest) => dest.Provider = myProvider))
});
I need to map an int property from a list of objects to a List<int>.
Here is what my class structure looks like:
I have a parent class:
public class Parent
{
...
public List<Location> Locations { get; set; }
}
Location class:
public class Location
{
public int LocationId { get; set; }
public string Name { get; set; }
}
Destination class for mapping:
public class Destination
{
...
public List<int> Locations { get; set; }
}
Here is the code I am trying to use to accomplish the mapping between List<Location> to List<int>:
CreateMap<Parent, Destination>()
.ForMember(d => d.Locations, o => o.MapFrom(s => s.Locations.Select(l => l.LocationId)))
This isn't working. I get the following error:
AutoMapper.AutoMapperMappingException: Unable to create a map expression from Location.LocationId
(System.Collections.Generic.IEnumerable`1[System.Int32]) to Destination.Locations (System.Collections.Generic.List`1[System.Int32])
Any idea what I'm not doing right?
You need to alter your AutoMapper configuration to map between Location and int then it takes care of the rest for you:
cfg.CreateMap<Location, int>().ConvertUsing(source => source.LocationId);
cfg.CreateMap<Parent, Destination>().ForMember(dest => dest.Locations, opts => opts.MapFrom(src => src.Locations));
See this Gist for working example.
As the exception says:
AutoMapper.AutoMapperMappingException: Unable to create a map expression from Location.LocationId (System.Collections.Generic.IEnumerable1[System.Int32]) to Destination.Locations (System.Collections.Generic.List1[System.Int32])
I believe that this happens because you are attempting to map an IEnumerable to a List.
You either add a ToList() to the map expression after the Select. (not recommended)
Or declare the Locations property as an IEnumerable<int> in your Destination class.
I have two classes that looks as follows:
public class Rule
{
public int Id { get; set; }
public RuleGroup RuleGroup { get; set; }
}
public class RuleGroup
{
public int Id { get; set; }
public List<Rule> RuleList { get; set; }
}
A RuleGroup has a list of rules. My AutoMapper settings are as follows:
Mapper.CreateMap<RuleRecord, FirstSolar.Mes.Core.Entities.Recipe.Rule>()
.ForMember(destination => destination.RuleGroup, source => source.Ignore())
.ForMember(destination => destination.Id, source => source.MapFrom(item => item.RuleId));
Mapper.CreateMap<IList<RuleRecord>, IList<FirstSolar.Mes.Core.Entities.Recipe.Rule>>();
Mapper.CreateMap<RuleGroupRecord, FirstSolar.Mes.Core.Entities.Recipe.RuleGroup>()
.ForMember(destination => destination.Id, source => source.MapFrom(item => item.RuleGroupId));
Mapper.CreateMap<IList<RuleGroupRecord>, IList<FirstSolar.Mes.Core.Entities.Recipe.RuleGroup>>();
When I attempt to map a RuleGroupRecord (LinqToSQL object) to RuleGroup (DTO), AutoMapper says I need to add a mapping for RuleGroup.RuleList. I'm wondering why because I defined how to map a single RuleRecord and a List.
If I have to, how would I do it?
Simply add (I hope I got the syntax right, but you should see what I'm hinting at):
.ForMember(destination => destination.RuleList, source => source.MapFrom(item => item.Rules));
to the second mapping. While you handled the general mapping for RuleRecord to Rule in the first mapping, you didn't tell automapper to map the specific property RuleGroup.RuleList.
I have a simple model like this one:
public class Order{
public int Id { get; set; }
... ...
public IList<OrderLine> OrderLines { get; set; }
}
public class OrderLine{
public int Id { get; set; }
public Order ParentOrder { get; set; }
... ...
}
What I do with Automapper is this:
Mapper.CreateMap<Order, OrderDto>();
Mapper.CreateMap<OrderLine, OrderLineDto>();
Mapper.AssertConfigurationIsValid();
It throw an exception that says:
"The property OrderLineDtos in OrderDto is not mapped, add custom mapping ..."
As we use a custom syntax in our Domain and in our DomainDto, how I can specify that the collection OrderLineDtos in OrderDto corresponds to OrderLines in Order?
Thank you
It works in this way:
Mapper.CreateMap<Order, OrderDto>()
.ForMember(dest => dest.OrderLineDtos, opt => opt.MapFrom(src => src.OrderLines));
Mapper.CreateMap<OrderLine, OrderLineDto>()
.ForMember(dest => dest.ParentOrderDto, opt => opt.MapFrom(src => src.ParentOrder));
Mapper.AssertConfigurationIsValid();
Nested collections work, as long as the names match up. In your DTOs, you have the name of your collection as "OrderLineDtos", but in the Order object, it's just "OrderLines". If you remove the "Dtos" part of the OrderLineDtos and ParentOrderDto property names, it should all match up.