Ignore mapping one property with Automapper
Asked Answered
A

10

386

I'm using Automapper and I have the following scenario: Class OrderModel has 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?

Annecorinne answered 14/2, 2011 at 0:22 Comment(4)
Automapper doesn't work that way. Its only concerned about properties on the destination object. The src can contain 100 extra properties -- Automapper only maps the dest properties. There must be something else causing the mapping exception. Can you post some code of what is not working?Sisco
It does what you ask automatically. Post some code to clarifyHohenstaufen
Have a look at the following posts, these might help you #4457019 #4053079Attempt
@Patrick AutoMapper does some tricks with analyzing method/property names. It is possible that there is a property on the source that is being unintentionally mapped even if there isn't an exact match on the destination. This is why there is a ForSourceMember(...Ignore()) to prevent this when it occurs.Preoccupy
G
673

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

Gerhardt answered 14/2, 2011 at 1:39 Comment(7)
Also, CreateMap<Foo, Bar>().ForSourceMember(x => x.Blarg, opt => opt.Ignore()); might be usefulPhillipp
@Phillipp Don't you mean: CreateMap<SourceType, DestType> (MemberList.Source).ForSourceMember(x => x.MySourceProperty, opt => opt.DoNotValidate()) ?Abbieabbot
Ignore has been replaced with DoNotValidate in ForSourceMember: github.com/AutoMapper/AutoMapper/blob/master/docs/…Fanaticism
@Fanaticism @Abbieabbot - I started to update this re: your comment, but it looks like the syntax change only affects the projection case (where the source property needs to be ignored). The OP's request is to ignore a destination property, so, Ignore() remains the correct syntax. This is because the syntax change for Ignore was made on the ISourceMemberConfigurationExpression interface but not on the disjoint IMemberConfigurationExpression`3 interface.Gerhardt
@Phillipp what are the differences between ForSourceMember() and ForMember()?Andromada
@Andromada ForMember() is actually "ForDestinationMember()"Knecht
Pay attention if you use ForMember or ForSourceMember. To make it work, you need to use ForMember, and there is still the option Ignore().Firer
M
283

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.

Mader answered 29/5, 2013 at 8:23 Comment(6)
I know this goes beyond the initial question but I really like this answer, its clean, very easy to read and instantly understand plus easy to reuseBibbie
Regarding params: You could return an array of selectors from inside a single lambda, then map over each selector with foreach or Select() Perhaps not less messy-looking, though.Beore
thanks @Steve Rukuts, for anyone who is looking for extension method to ignore source members you can use this public static IMappingExpression<TSource, TDestination> IgnoreSourceValidation<TSource, TDestination>( this IMappingExpression<TSource, TDestination> map, Expression<Func<TSource, object>> selector) { map.ForSourceMember(selector, config => config.DoNotValidate()); return map; }Wield
How does it work for ReverseMap? ReverseMap().ForPath(...Throwaway
I think I'd prefer to name it IgnoreMember(), but great extension!Jillene
Seems like Ignore() does not work (I am getting destination field overwritten with default value if such field is missing in source) if I map collection to collection, not entity to entity.Pauperize
H
99

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());
Hulse answered 16/4, 2012 at 19:12 Comment(7)
Does automapper have a ForSourceMember extension?Bluefarb
I do this currently, but it would be ideal to NOT have to create all these Ignore... :/Abisha
do you know if there's a way to ignore when actually doing the mapping and not when creating the map?Undertone
FYI: merged from #4053079Freckly
For the scenario given in the question, this should be the accepted answer. The current accepted answer ignores mapping of properties in the destination object. This question is asking about ignoring mappings in the source object.Accursed
for anyone who is looking for extension method public static IMappingExpression<TSource, TDestination> IgnoreSourceValidation<TSource, TDestination>( this IMappingExpression<TSource, TDestination> map, Expression<Func<TSource, object>> selector) { map.ForSourceMember(selector, config => config.DoNotValidate()); return map; }Wield
Ignore() is not present on ForSourceMember() extension. as @JasonDias says, it should be DoNotValidate(). At least in latest version of automapper.Leghorn
A
34

In Automapper 12, there's an Ignore attribute : "Ignore this member for configuration validation and skip during mapping." [Old] 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.

Ablate answered 23/9, 2011 at 8:38 Comment(6)
The ignore attribute leaks auto-mapper through your application though.Mirza
AutoMapper is one thing which I don't mind leaking all over the place. ;)Catbird
You can always consider deriving IgnoreMapAttribute.Bookrack
This is a good way to ignore a base property that is inherited across many objects. Saves from having to ignore it in every mapping config.Casie
IgnoreMap was Removed. docs.automapper.org/en/latest/…Allegiance
And it's back with IgnoreAblate
D
31

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/

Donelu answered 13/2, 2013 at 15:30 Comment(4)
FYI: merged from #4053079Freckly
This doesn't work when injecting IMapper. Mapper.GetAllTypeMaps doesn't exist in the latest version of AutoMapper. Additionally, when I setup my maps in an AutoMapper.Profile and then subsequently injected IMapper, I got this exception "Mapper not initialized. Call Initialize with appropriate configuration. If you are trying to use mapper instances through a container or otherwise, make sure you do not have any calls to the static Mapper.Map methods, and if you're using ProjectTo or UseAsDataSource extension methods, make sure you pass in the appropriate IConfigurationProvider instance."Trevortrevorr
I just get 'Mapper' does not contain a definition for 'GetAllTypeMaps' [DSSTools] ..Sixtieth
@Sixtieth Use Mapper.Configuration.GetAllTypeMaps() sourceOrsini
N
30

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.

Nightmare answered 15/6, 2015 at 3:49 Comment(2)
THIS is what I came looking for, so useful when only modifying a subset of domain object properties from a much simpler DTO.Bluestocking
This is the answer kids, make that official so newbies won't be confusedBullis
Z
3

It is also possible to ignore globally properties like this :

  1. Using the AddGlobalIgnore(string propertyNameStartingWith) method in the mapper configuration to ignore properties with name starting with a specified string.
  2. Using the ShouldMapProperty to provide a predicate and conditionally selecting which properties to map. ShouldMapField and ShouldMapMethod 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
});
Zweig answered 29/9, 2021 at 15:3 Comment(0)
A
2

Could use IgnoreAttribute on the property which needs to be ignored

Alleged answered 28/10, 2019 at 15:48 Comment(1)
Its [IgnoreMap] from IgnoreMapAttributeCradlesong
H
1

you can use attribute: [IgnoreMap] or mapper profile:

CreateMap<TollgateEto, UpdateTollgateModel>()
  .ForMember(x => x.QLX3_ID, opt => opt.Ignore());
Hysterectomize answered 26/10, 2023 at 4:19 Comment(0)
S
-5

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;
Stanford answered 15/12, 2015 at 14:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.