19

I have quite a bit of entities and so far, I've been doing stuff like

Mapper.CreateMap<Employee, EmployeeDetailsDTO>()
    .ForSourceMember(mem => mem.NewsPosts, opt => opt.Ignore());

I want to tell AutoMapper to simply ignore missing properties in the destination object without having to specify each of them. So far, I haven't found a way to do so with my multiple SO and Google searches. Anyone has a solution? I'm ready to do some sort of loop or anything, as long as it can be written once and that it will scale with model / dto changes or added properties.

Pluc
  • 2,909
  • 1
  • 22
  • 36

3 Answers3

11

When are you getting the error? Is it when you call AssertConfigurationIsValid ?

If yes, then simply dont call this method

You dont have to call this method, consider the following mapping which works:

public class Foo1
{
    public string Field1 { get; set; }
}
public class Foo2
{
    public string Field1 { get; set; }
    public string Field2 { get; set; }
}

Mapper.CreateMap<Foo1, Foo2>();
var foo1 = new Foo1() {Field1 = "field1"};
var foo2 = new Foo2();
Mapper.Map(foo1, foo2);//maps correctly, no Exception

You may want to call AssertConfigurationIsValid for other mappings to ensure they are correct so instead what you need to do is organize your mappings into Profiles:

public class MyMappedClassesProfile: Profile
{
    protected override void Configure()
    {
        CreateMap<Foo1, Foo2>();
        //nb, make sure you call this.CreateMap and NOT Mapper.CreateMap
        //I made this mistake when migrating 'static' mappings to a Profile.    
    }
}

Mapper.AddProfile<MyMappedClassesProfile>();

and then if you decide you want to check the validity of the mapping (case by case basis in your situation) then call

Mapper.AssertConfigurationIsValid(typeof(MyMappedClassesProfile).FullName);

important in your case and/or any case where you dont call AssertConfigurationIsValid you should use something like AutoFixture and a Unit Test to ensure your mapping is working. (which is the intent of AssertConfigurationIsValid)

wal
  • 17,409
  • 8
  • 74
  • 109
  • It is when I call AssertConfigurationIsValid, but I would have perefered to keep it in my unit testing. Right now it's in the Global.asax but would eventually move in the unit testing (It's a ASP.NET MVC application). So basically you are telling me that I should avoid using the AssertConfigurationIsValid and write my own unit testing for my DAL? – Pluc Nov 13 '12 at 13:50
  • I'm not telling you to do that in *every* case... in places where the mapping is straightforward then continue to use AssertConfigurationIsValid. In places where it becomes problematic because you know better do not use it. You should however organize your mappings into Profiles (classes which extend `AutoMapper.Profile`) as this sort-of reduces the static nature of the mappings config and the call to `AssertConfigurationIsValid ` which would then apply to every Mapper.Map declaration you've made. – wal Nov 13 '12 at 13:54
  • Every entity will have missing properties because I'm mapping EF POCOs to DTOs. The DTOs will never contain other DTOs but rather keep the IDs (one-one / one-many relation) or call the appropriate repository in charge of the requried entity (with his ID as a parameter). Some are only a single missing property, but they all have at least one. I'm not sure if using Profiles will bring me much as the mappings are only configured once (since it's a web application) when the web server starts. I also only using AutoMapper for Model=>DTO. Unless I start using it for ViewModels, I dont see the need. – Pluc Nov 13 '12 at 14:11
  • i see your point. you should perhaps approach the process of defining the `Ignore` methods as a quasi-unit test (assuming you dont want to remove the call to AssertConfigurationIsValid) - do that or otherwise, and to answer your original question about getting AutoMapper to ignore unmapped properties, remove this call. – wal Nov 13 '12 at 14:18
7

Suggested in wal's answer "don't call AssertConfigurationIsValid()" is not safe, as it will hide potential errors in mappings.
It's better to explicitly ignore mapping between classes, for which you are sure that all needed properties already mapped correctly. You can use extensions created in AutoMapper: "Ignore the rest"? answer:

var config = new MapperConfiguration(cfg =>
{
    cfg.CreateMap<Src, Dest>();
     cfg.IgnoreUnmapped<Src, Dest>();  // Ignores unmapped properties on specific map
});

The overload without parameters cfg.IgnoreUnmapped(this IProfileExpression profile) ignores unmapped properties on all maps and not recommended, because it also hides any potential problems for all classes.

Michael Freidgeim
  • 26,542
  • 16
  • 152
  • 170
0

If I have many classes with many properties to ignore, I don't want to have exception when call AssertConfigurationIsValid(), but prefer to report it in a log and just review are all unmapped properties missed intentionally. Because method to do validation is not exposed by AutoMapper, I catch AssertConfigurationIsValid and return error message as string.

    public string ValidateUnmappedConfiguration(IMapper mapper)
    {
        try
        {
            mapper.ConfigurationProvider.AssertConfigurationIsValid();
        }
        catch (AutoMapperConfigurationException e)
        {
              return e.Message;
        }
        return "";
    }

I am calling the ValidateUnmappedConfiguration method from unit test

   [TestMethod]
    public void LogUmmappedConfiguration()
    {
        var mapper = new MapperConfiguration((cfg =>
        {
            cfg.AddProfile(new AutoMapperProfile());
        })).CreateMapper();
        var msg=ValidateUnmappedConfiguration(mapper) ;
        if (!msg.IsNullOrBlank())
        {
            TestContext.WriteString("Please review the list of unmapped fields and check that it is intentional: \n"+msg);
        }
    }
Michael Freidgeim
  • 26,542
  • 16
  • 152
  • 170