88

Is there a way to do this? We have a SummaryDto that maps from three different types, and when we create a map for each type, props that are not mapped are throwing an error. There are about 35 attributes on the summary dto. To use Ignore() option on each one is just too much trouble. Is there a global ignore? Something like

CreateMap<Source,Target>()
   .IgnoreAllUnmapped();
abatishchev
  • 98,240
  • 88
  • 296
  • 433
epitka
  • 17,275
  • 20
  • 88
  • 141
  • 7
    This seems like a good thing to do, however, even though there are 35 properties on your DTO, if you are using `AutoMapper.Mapper.AssertConfigurationIsValid();` then it is possible you will forget to map a property in the future and it could lead to problems. I would use with **caution**. – CodeMonkeyKing Nov 09 '11 at 20:21
  • 19
    As of version 5.0+, you can use: `.ForAllOtherMembers(m => m.Ignore())`. See example [here](http://stackoverflow.com/a/39110565/264672) – Shay Feb 19 '17 at 03:58
  • 1
    In this case I would just write a custom mapper. Automapper is only useful if you have lots of columns that are all the same name and type (or able to have types mapped consistently between types). If you're only interested in a few columns out of many then AutoMapper isn't the best solution. – matao Sep 27 '19 at 00:30
  • The solution for AutoMapper 11 is https://stackoverflow.com/questions/72367321/automapper-map-a-few-and-ignore-the-rest/73333328#73333328 – Michael Freidgeim Jan 06 '23 at 18:33

5 Answers5

146

This is working for me:

public static class MappingExpressionExtensions
{
    public static IMappingExpression<TSource, TDest> IgnoreAllUnmapped<TSource, TDest>(this IMappingExpression<TSource, TDest> expression)
    {
        expression.ForAllMembers(opt => opt.Ignore());
        return expression;
    }
}

Because ForAllMembers returns void, calling ForAllMembers(o => o.Ignore()) without this extension method wouldn't work. We want to keep the mapping expression available to enable the subsequent mappings:

CreateMap<Source, Destination>()
            .IgnoreAllUnmapped()
            .ForMember(d => d.Text, o => o.MapFrom(s => s.Name))
            .ForMember(d => d.Value, o => o.MapFrom(s => s.Id));
TheCloudlessSky
  • 18,608
  • 15
  • 75
  • 116
CodeMonkeyKing
  • 4,556
  • 1
  • 32
  • 34
  • 2
    This is removing and ignoring the conventional mappings. Is there a way to keep the conventional mappings? – Joao Leme Apr 20 '13 at 17:11
  • 2
    @JoaoLeme I think you need to decide what you are trying to accomplish. Ignoring all members should be used rarely. I'm not sure how AutoMapper could make the determination of how to keep the what you've called as "conventional mappings" but exclude the unmapped. I think you are better off explicitly stating in your mapping either which members you need to handle -or- use the IgnoreAllUnmapped extension and then specify that you only want the explicitly defined members to be mapped. Perhaps an example of what you need to accomplish could illustrate why you are asking this particular question. – CodeMonkeyKing Apr 20 '13 at 18:56
  • 2
    @JoaoLeme you might also check out this answer - [AutoMapper IgnoreTheRest](http://stackoverflow.com/questions/954480/automapper-ignore-the-rest/6474397#6474397) - that was pointed out by Edward Brey in his answer to this question. – CodeMonkeyKing Apr 20 '13 at 19:01
  • I'm mapping a model with over 100 properties to my domain model that requires just a few. The names match, so I would rather not have to write ".ForMember(d => d.MyProperty, o => o.MapFrom(s => s.MyProperty))" since AutoMapper does that by default. IgnoreTheRest does exactly that, but it is not working when returning IQueryable. – Joao Leme Apr 20 '13 at 19:20
  • 1
    @JoaoLeme just my opinion on this, but if you domain model just requires a few of the 100 properties, then I would just take the hit of having a few repetitive lines versus introducing an edge case extension method. – CodeMonkeyKing Apr 20 '13 at 19:26
  • 26
    This does not work starting 5.0.0. You need to FINISH with `ForAllOtherMembers(opt => opt.Ignore());` and do not use `ForAllMembers` – jsgoupil Sep 21 '17 at 18:12
  • 3
    @jsgoupil AutoMapper 11 has deprecated ForAllOtherMembers :( – thepirat000 Aug 23 '22 at 21:05
  • 3
    The only option in Automapper 11 is to explicitly list all fields, so the profile becomes cluttered with 100+ lines of useless code. This is retarded. The developers of Automapper do not want to support efficiency. – Wouter Sep 13 '22 at 13:59
33

I struggled with this one for quite a while too, or at least a problem similar to this. I had a class with a lot of properties on it (about 30) and I only wanted to map about 4 of them. It seems crazy to add 26 ignore statements (especially when it means that future changes to the class will mean having to update them!)

I finally found that I could tell AutoMapper to ignore everything, and then explicitly add the ones that I did want.

// Create a map, store a reference to it in a local variable
var map = CreateMap<Source,Target>();

// Ignore all members
map.ForAllMembers(opt => opt.Ignore());

// Add mapping for P1
map.ForMember(dest => dest.P1, opt => opt.MapFrom( src => src.P1));

// Add other mappings...
map.ForMember(dest => dest.P2, opt => opt.MapFrom( src => src.P2));
map.ForMember(dest => dest.P3, opt => opt.MapFrom( src => src.P3));
map.ForMember(dest => dest.P4, opt => opt.MapFrom( src => src.P4));

You'd be forgiven for thinking that you could just do this (but don't because it wont compile):

// This won't compile
CreateMap<Source,Target>()
   .ForAllMembers(opt => opt.Ignore())
   .ForMember(dest => dest.P1, opt => opt.MapFrom( src => src.P1));

The reason why this doesn't work is that the ForAllMembers() method doesn't support the fluent style of chaining (at least in the current version 2.0).

The good news is that the non-chaining version does indeed work. The one caveat of course is that you need to explicitly tell AutoMapper which members to map. I haven't yet found an easy way to have it both ways so that you can still use the implied mappings and ignore the broken ones.

Nicholas Green
  • 612
  • 8
  • 10
  • You don't necessarily need to store the `map` in a variable like that. AutoMapper updates the existing mapping if you create it more than once (yes, probably not very intuitive, but that's how it works). So in your example you could call `CreateMap...Ignore()` and then `CreateMap...ForMember()... ForMember() ...` without any problems. I'm not sure why Jimmy decided not to return the mapping expression from `ForAllMembers`, as that would've allowed chaining normally. – julealgon Aug 05 '15 at 21:05
  • 1
    you can also use ForAllOtherMembers at the end and chain it. – maracuja-juice Jun 12 '18 at 13:58
  • @maracuja-juice no, you can't! ForAllMembers will ignore the fields that you've already mapped – Tsagana Nokhaeva Dec 06 '18 at 10:59
  • @JerrySmith Isn't that what is wanted to achieve with it? 1. Configure the fields you want to map/customize 2. Ignore everything else with ForAllOtherMembers – maracuja-juice Dec 10 '18 at 14:07
  • @maracuja-juice this won't work the way you describe it – Tsagana Nokhaeva Dec 11 '18 at 10:52
  • Doesn't work on AutoMapper 11 – thepirat000 Aug 23 '22 at 22:12
5

To avoid having to explicitly specify the mapped properties, you can use IgnoreAllNonExisting. It ignores any destination properties that don't have mapped source properties.

Community
  • 1
  • 1
Edward Brey
  • 40,302
  • 20
  • 199
  • 253
3

Extension method which allows fluent syntax for the ForAllMembers method:

public static IMappingExpression<TSource, TDestination> IgnoreAllMembers<TSource, TDestination>(
    this IMappingExpression<TSource, TDestination> expression
    )
{
    expression.ForAllMembers(opt => opt.Ignore());
    return expression;
}

Usage:

The call to IgnoreAllMembers must be before the call to ForMember.

        CreateMap<LocationRevision, Dto.LocationAddressMap>()
            .IgnoreAllMembers()
            .ForMember(m => m.LocationId, opt => opt.MapFrom(src => src.Id))
            ;
Casey Plummer
  • 2,629
  • 23
  • 20
2

Try to use .ConvertUsing() in your case, e.g.

CreateMap<Source,Target>()
 .ConvertUsing(converter=> new Target(){
P1 = converter.P1,
....
});

So, you can describe all properties what you want to have in your object, other will be ignored.

sth
  • 222,467
  • 53
  • 283
  • 367
Vladimir Dorokhov
  • 3,784
  • 2
  • 23
  • 26
  • 1
    this doesn't work, all the other fields aren't ignored they are just filled with default values – Para Feb 09 '11 at 15:25
  • Since I am instantiating a new object (Target) I want the ignored properties to have their default value, so that's fine. – DownChapel Mar 08 '11 at 12:04