I am trying to map using AutoMapper.
Source object is C# object
public class Source
{
public string comment { get; set; }
public string Subject { get; set; }
public Account Account{ get; set; }
}
public class Account
{
public string FirstName{ get; set; }
public string LastName{ get; set; }
}
My destination is a CRM entity named crm_destination which has fields like comment , Subject but it also has a LookUp field account of type Account.
But I don't know how to map LookUp field.
Following is my Automapper
AutoMapper.Mapper.CreateMap<Source, Destinaetion>()
.ForMember(dest => dest.comment, opt => opt.MapFrom(src => src.comment))
.ForMember(dest => dest.account, opt => opt.MapFrom(src => src.account));
.ForMember(dest => dest.account, opt => opt.MapFrom(src => src.account)) is throwing error of type mismatch..
basically my problem is I don't know how to map LookUp field where CRM entity is destination.
You need to use a custom resolver in AutoMapper. In your custom resolver you'll need to query CRM to get the ID of the account record in that matches your Account object and return an EntityReference to this object.
Lookups are stored as EntityReferences in CRM. So you'll need to convert your account to an EntityReference.
I have never used AutOMapper, but what Nicknow suggests makes sense. Just call the ToEntityReference() method on Entity.
I solved it. Lookup creates a relationship. my lookp created a relationship name cxrm_account_cxrm_source_account
so instead of .ForMember(dest => dest.account, opt => opt.MapFrom(src => src.account))
I did
.ForMember(dest => dest.cxrm_account_cxrm_source_account, opt => opt.MapFrom(src => src.Account))
now it is working
Related
I'm using automapper with CQRS pattern. Below is my class which takes input from .net core API. The API takes collection as input and I'm sending collection in my Mediatr Command object. In Mediatr command, I'm mapping source collection to destination collection and while doing mapping, I'm getting following exception:
AutoMapper.AutoMapperMappingException
HResult=0x80131500
Message=Error mapping types.
Inner Exception 1:
AutoMapperMappingException: Missing type map configuration or unsupported mapping.
I'm using follwing code for mapping:
var insertData = _mapper.Map<List<Source>, List<Destination>>(request.Data.ToList());
In my class, I have following:
public class Source: ICustomMapping
{
public int? Prop1 { get; set; }
public string Prop2 { get; set; }
public void CreateMappings(Profile configuration)
{
configuration.CreateMap<Destination, Source>()
.ForMember(dto => dto.Prop1 , opt => opt.MapFrom(p => p.Prop1 ))
.ForMember(dto => dto.Prop2, opt => opt.MapFrom(p => p.Prop2))
;
}
}
This mapping works flawlessly when I have single object in both ways (forward and reverse). Now I need to pass collection of object for processing and save destination collection data in to database.
After looking in to the documentation I realize that I do not have the reverse mapping.
public void CreateMappings(Profile configuration)
{
configuration.CreateMap<Destination, Source>()
.ForMember(dto => dto.Prop1 , opt => opt.MapFrom(p => p.Prop1 ))
.ForMember(dto => dto.Prop2, opt => opt.MapFrom(p => p.Prop2))
.ReverseMap();
}
The ReverseMap() I was missing.
Thanks
I am using AutoMapper 6.2.2 to map a composite object (made up of two objects) into one, and it isn't working.
Source/destination types
Source type: a composite object (using suggestion from https://github.com/AutoMapper/AutoMapper/issues/389)
public class JoinedJob
{
public JobInfo job { get; set; }
public LocationInfo loc { get; set; }
}
Destination type:
public class JobDetailsModel
{
public int JobID { get; set; }
public string JobType { get; set; }
}
For testing purposes, I am using this very simple destination class, ignoring the source loc fields completely for now.
Mapping configuration
CreateMap<JoinedJob, JobDetailsModel>()
.ForMember(dest => dest.JobID, opt => opt.MapFrom(src => src.job.JobID))
.ForMember(dest => dest.JobType, opt => opt.MapFrom(src => src.job.JTName));
Expected behavior
I expect the JoinedJob object to get properly mapped to the JobDetailsModel object.
Actual behavior
This doesn't work at all when using ProjectTo<>. The objects I got back had null and zero values.
Steps to reproduce
So I tested a single instance:
var testDetail = _mapper.Map<JoinedJob, JobDetailsModel>(testJob);
and this exception is thrown:
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.
JoinedJob -> JobDetailsModel (Destination member list)
NDSWebAPI.Modules.Core.BusinessLogic.JobRetrieval+JoinedJob -> NDSWebAPI.Models.Core.JobDetailsModel (Destination member list)
Unmapped properties:
JobID
JobType
It's as if AutoMapper doesn't recognize the .ForMember mappings I defined?
Should this work? I have no problems at all with mapping single objects (e.g. mapping JobInfo to JobDetailsModel works). The problem is introduced with the composite object.
I am using AutoMapper.
My source object is simple class
public class Source
{
public string FirstName { get; set; }
public string type{ get; set; }
}
My destination is a MS Dynamics CRM Entity ( I have generated the model using CrmSvctil) which contains an option set named type.
Following is my mapping
AutoMapper.Mapper.CreateMap<Source, Destination>()
.ForMember(dest => dest.type, opt => opt.MapFrom(src => src.type));
I am getting error is type mismatch
Basically my problem is
I don't know how to map string to an Option set value using AutoMapper
OptionSets are stored as OptionSetValues that have a Value Property of type Int, not Strings, hence your type mismatch error.
If your type is an actual int, you just need to parse it:
AutoMapper.Mapper.CreateMap<Source, Destination>()
.ForMember(dest => dest.type, opt => opt.MapFrom(src => new OptionSetValue(int.parse(src.type))));
But if it's the actual text value for the option set, you'll need to lookup the text values using the OptionSetMetaData:
public OptionMetadataCollection GetOptionSetMetadata(IOrganizationService service, string entityLogicalName, string attributeName)
{
var attributeRequest = new RetrieveAttributeRequest
{
EntityLogicalName = entityLogicalName,
LogicalName = attributeName,
RetrieveAsIfPublished = true
};
var response = (RetrieveAttributeResponse)service.Execute(attributeRequest);
return ((EnumAttributeMetadata)response.AttributeMetadata).OptionSet.Options;
}
var data = GetOptionSetMetadata(service, "ENTITYNAME", "ATTRIBUTENAME");
AutoMapper.Mapper.CreateMap<Source, Destination>()
.ForMember(dest => dest.type, opt => opt.MapFrom(src => new OptionSetValue(optionList.First(o => o.Label.UserLocalizedLabel.Label == src.type))));
I have my classes defined as below
Source {
public List<Driver> UnreportedDrivers { get; set; } // count 1
public List<Driver> LendingLossDrivers { get; set; } // count 2
public List<Driver> OtherDrivers { get; set; } // count 1
}
Destination {
public List<Driver> Drivers { get; set; } // expected count = 4 after mapping
}
I have to map from source to destination.
I have to merge all the collections from source and map them to Destination.
I have defined my mapping as below. But this piece of code doesn't help me out.
Instead of merging all the collections, it only maps the last one (UnreportedDrivers) overriding the top ones.
AutoMapper.Mapper.CreateMap<ServiceModel.MacReconciliationResponse, MacProcessContext>()
.ForMember(destination => destination.Drivers, source => source.MapFrom(s => s.OtherDrivers))
.ForMember(destination => destination.Drivers, source => source.MapFrom(s => s.LendingLossDrivers))
.ForMember(destination => destination.Drivers, source => source.MapFrom(s => s.UnreportedDrivers));
Please help me in this scenario.
Thanks in advance.
I would simply .Concat each list you'd like to map in one .ForMember call:
Mapper.CreateMap<Source, Destination>()
.ForMember(dest => dest.Drivers, opt => opt.MapFrom(src => src.LendingLossDrivers
.Concat(src.OtherDrivers)
.Concat(src.UnreportedDrivers)));
Can AutoMapper map shared properties?
Entity
public class Entity
{
public static string SomeProperty {get; set;}
...
...
...
}
View Model
public class ViewModel
{
public string SomeProperty {get; set;}
...
...
...
}
Although I have not used AutoMapper yet, I see no reason why you would not be able to achieve what you are looking for. Based on the project's documentation on Projection, you can write a projector:
Mapper.CreateMap<Entity, ViewModel>()
.ForMember(dest => dest.SomeProperty, opt => opt.MapFrom(src => src.SomeProperty));
// Perform mapping
ViewModel form = Mapper.Map<Entity, ViewModel>(entity);
You should use a code like this:
Mapper.CreateMap<Entity, ViewModel>()
.ForMember(
dest => dest.SomeProperty,
opt => opt.MapFrom(src => Entity.SomeProperty));