Ignore mapping one property with Automapper
I'm using Automapper and I have the following scenario: Class OrderModel has开发者_如何学JAVA a property called 'ProductName' that isn't in the database. So when I try to do the mapping with:
Mapper.CreateMap<OrderModel, Orders>();
It generates an exception :
"The following 1 properties on Project.ViewModels.OrderModel are not mapped: 'ProductName'
I've read at AutoMapper's Wiki for Projections the opposite case (the extra attribute is on the destination, not in the source which is actually my case )
How can I avoid automapper to make the mapping of this property?
From Jimmy Bogard: CreateMap<Foo, Bar>().ForMember(x => x.Blarg, opt => opt.Ignore());
It's in one of the comments at his blog.
UPDATE(from Jamie's comment Jan 4 '19 at 11:11:)
Ignore has been replaced with DoNotValidate in ForSourceMember: https://github.com/AutoMapper/AutoMapper/blob/master/docs/8.0-Upgrade-Guide.md
I'm perhaps a bit of a perfectionist; I don't really like the ForMember(..., x => x.Ignore())
syntax. It's a little thing, but it matters to me. I wrote this extension method to make it a bit nicer:
public static IMappingExpression<TSource, TDestination> Ignore<TSource, TDestination>(
this IMappingExpression<TSource, TDestination> map,
Expression<Func<TDestination, object>> selector)
{
map.ForMember(selector, config => config.Ignore());
return map;
}
It can be used like so:
Mapper.CreateMap<JsonRecord, DatabaseRecord>()
.Ignore(record => record.Field)
.Ignore(record => record.AnotherField)
.Ignore(record => record.Etc);
You could also rewrite it to work with params
, but I don't like the look of a method with loads of lambdas.
You can do this:
conf.CreateMap<SourceType, DestinationType>()
.ForSourceMember(x => x.SourceProperty, y => y.Ignore());
Or, in latest version of Automapper, you simply want to tell Automapper to not validate the field
conf.CreateMap<SourceType, DestinationType>()
.ForSourceMember(x => x.SourceProperty, y => y.DoNotValidate());
There is now (AutoMapper 2.0) an IgnoreMap
attribute, which I'm going to use rather than the fluent syntax which is a bit heavy IMHO.
Just for anyone trying to do this automatically, you can use that extension method to ignore non existing properties on the destination type :
public static IMappingExpression<TSource, TDestination> IgnoreAllNonExisting<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
{
var sourceType = typeof(TSource);
var destinationType = typeof(TDestination);
var existingMaps = Mapper.GetAllTypeMaps().First(x => x.SourceType.Equals(sourceType)
&& x.DestinationType.Equals(destinationType));
foreach (var property in existingMaps.GetUnmappedPropertyNames())
{
expression.ForMember(property, opt => opt.Ignore());
}
return expression;
}
to be used as follow :
Mapper.CreateMap<SourceType, DestinationType>().IgnoreAllNonExisting();
thanks to Can Gencer for the tip :)
source : http://cangencer.wordpress.com/2011/06/08/auto-ignore-non-existing-properties-with-automapper/
When mapping a view model back to a domain model, it can be much cleaner to simply validate the source member list rather than the destination member list
Mapper.CreateMap<OrderModel, Orders>(MemberList.Source);
Now my mapping validation doesn't fail, requiring another Ignore()
, every time I add a property to my domain class.
Could use IgnoreAttribute on the property which needs to be ignored
It is also possible to ignore globally properties like this :
- Using the
AddGlobalIgnore(string propertyNameStartingWith)
method in the mapper configuration to ignore properties with name starting with a specified string. - Using the
ShouldMapProperty
to provide a predicate and conditionally selecting which properties to map.ShouldMapField
andShouldMapMethod
properties are also available.
Usage :
public class MappingProfile : Profile
{
public MappingProfile()
{
// other configs...
AddGlobalIgnore("foo")); // this will ignore properties with name starting with "foo"
ShouldMapProperty = p => p.Name != "bar"; // this will ignore properties with name "bar"
}
}
Or :
var config = new MapperConfiguration(cfg => {
// other configs...
cfg.AddGlobalIgnore("foo"); // way 1
cfg.ShouldMapProperty = p => p.Name != "bar"; // way 2
});
Hello All Please Use this it's working fine... for auto mapper use multiple .ForMember in C#
if (promotionCode.Any())
{
Mapper.Reset();
Mapper.CreateMap<PromotionCode, PromotionCodeEntity>().ForMember(d => d.serverTime, o => o.MapFrom(s => s.promotionCodeId == null ? "date" : String.Format("{0:dd/MM/yyyy h:mm:ss tt}", DateTime.UtcNow.AddHours(7.0))))
.ForMember(d => d.day, p => p.MapFrom(s => s.code != "" ? LeftTime(Convert.ToInt32(s.quantity), Convert.ToString(s.expiryDate), Convert.ToString(DateTime.UtcNow.AddHours(7.0))) : "Day"))
.ForMember(d => d.subCategoryname, o => o.MapFrom(s => s.subCategoryId == 0 ? "" : Convert.ToString(subCategory.Where(z => z.subCategoryId.Equals(s.subCategoryId)).FirstOrDefault().subCategoryName)))
.ForMember(d => d.optionalCategoryName, o => o.MapFrom(s => s.optCategoryId == 0 ? "" : Convert.ToString(optionalCategory.Where(z => z.optCategoryId.Equals(s.optCategoryId)).FirstOrDefault().optCategoryName)))
.ForMember(d => d.logoImg, o => o.MapFrom(s => s.vendorId == 0 ? "" : Convert.ToString(vendorImg.Where(z => z.vendorId.Equals(s.vendorId)).FirstOrDefault().logoImg)))
.ForMember(d => d.expiryDate, o => o.MapFrom(s => s.expiryDate == null ? "" : String.Format("{0:dd/MM/yyyy h:mm:ss tt}", s.expiryDate)));
var userPromotionModel = Mapper.Map<List<PromotionCode>, List<PromotionCodeEntity>>(promotionCode);
return userPromotionModel;
}
return null;
精彩评论