Ignore mapping one property with Automapper

2019-01-15 12:34发布

问题:

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?

回答1:

From Jimmy Bogard: CreateMap<Foo, Bar>().ForMember(x => x.Blarg, opt => opt.Ignore());

It's in one of the comments at his blog.



回答2:

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 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.



回答3:

You can do this:

conf.CreateMap<SourceType, DestinationType>()
   .ForSourceMember(x => x.SourceProperty, y => y.Ignore());


回答4:

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.



回答5:

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/



回答6:

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.



回答7:

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;


回答8:

I appreciated an extension added by Steve Rukuts, so I decided to add one more extension method based on his example. Hope it will help somebody:

    public static IMappingExpression<TSource, TDestination> Map<TSource, TDestination>(
        this IMappingExpression<TSource, TDestination> map,
        Expression<Func<TSource, object>> src,
        Expression<Func<TDestination, object>> dst)
    {
        map.ForMember(dst, opt => opt.MapFrom(src));
        return map;
    }

Usage:

    Mapper.Initialize(cfg => cfg.CreateMap<UserModel, UserDto>()
        .Map(src => src.FirstName + " " + src.LastName, dst => dst.UserName));