3

I have the below viewmodel which is same as domain model (but includes some extra properties).

public class ProductViewModel
{
    public string Name { get; set; }
    public string ShortDescription { get; set; }
    public string FullDescription { get; set; }
    public string AdminComment { get; set; }
}

From above, I am only using some of the properties in my view page.

While I am using Automapper to map my existing model, all my viewmodel fields to getting mapped to the domainmodel fields.

Mapper.Map(productViewModel, product);

Due to the above mapping all the unused viewmodel fields (by default unused viewmodel fields have NULL values) are mapped to the domain model. It is replacing my existing database data with NULL values.

Is there any way to exclude NULL and default property values from mapping?

Notes:

  • I came across Using Automapper to update an existing Entity POCO
  • If we use hidden fields for the excluded properties the above issue will be fixed because the viewmodel will carry the data using the hidden fields. But I am not preferring it!
  • I tried the below code which is not working:

    Mapper.CreateMap<ProductViewModel, Product>()
          .ForAllMembers(opt =>
               opt.Condition(srs => (!srs.IsSourceValueNull || IsDefaultValue(srs.SourceValue, srs.SourceType))));
    

Edit:

After I tried Automapper skip null values with custom resolver (Thanks abatishchev). I have used the resolver but getting error Missing type map configuration or unsupported mapping

My code snippet:

...
public System.DateTime CreatedOnUtc { get; set; }
public System.DateTime UpdatedOnUtc { get; set; }
public virtual ICollection<BackInStockSubscription> BackInStockSubscriptions { get; set; }
public virtual ICollection<OrderItem> OrderItems { get; set; }

While the resolver accessing the BackInStockSubscriptions in the above code, I am getting the error.

Any clues?

Community
  • 1
  • 1
Rajasekar Sa
  • 65
  • 11
  • Have you tried a resolver from http://stackoverflow.com/questions/20021633/automapper-skip-null-values-with-custom-resolver? – abatishchev Jan 27 '15 at 18:37
  • I tried it but getting the error **Missing type map configuration or unsupported mapping.** The resolver finished accessing all the domain model properties and start accessing the below virtual mappings in that. By the time of accessing "BackInStockSubscriptions" the abovee issue is happening.
    `public System.DateTime CreatedOnUtc { get; set; } public System.DateTime UpdatedOnUtc { get; set; } public virtual ICollection BackInStockSubscriptions { get; set; } public virtual ICollection OrderItems { get; set; }` Do i need to do anything more?
    – Rajasekar Sa Jan 27 '15 at 19:40
  • Can you put this inside your question? It's hard to read code form a comment. – abatishchev Jan 27 '15 at 21:16
  • Hi abatishchev, I have edited my question. Plz check now. – Rajasekar Sa Jan 28 '15 at 16:37

2 Answers2

8

Don't use AutoMapper to map back into your domain model. It's more complicated, there are too many edge cases and it just doesn't provide the same ROI as mapping read models.

I wrote the tool and I never, ever do this. You have collections, lazy loaded entities, fetching, merging, loading, so many things that can go wrong.

Just. Don't. Do it.

Jimmy Bogard
  • 26,045
  • 5
  • 74
  • 69
  • 2
    Then how we can update the viewmodel data back to db? By mapping property by property? (Since I am having 25 properties its very lengthy process rite?) Note: As I know many users are using automapper to map viewmodel data to domain model. What is the best practice for these kind of scenarios? – Rajasekar Sa Jan 28 '15 at 20:00
  • I don't really know, honestly. The systems I build are task-oriented systems, not "giant page of editable fields". It's only a handful of fields, usually with validation and side effects where I wouldn't want to just splat data from one to the other. I've heard of people using conditions and resolvers etc. but it's just not something I ever do. – Jimmy Bogard Jan 28 '15 at 20:41
  • 2
    Thanks Jimmy. But in my above case can u suggest me any solution? – Rajasekar Sa Jan 28 '15 at 20:59
1

I have fixed the issue by adding the ICollection properties to ignore list in AutoMapper.

Fixed code:

Mapper.CreateMap<ProductViewModel, Product>()
        .ForMember(dest => dest.BackInStockSubscriptions, mo => mo.Ignore())
        .ForMember(dest => dest.OrderItems, mo => mo.Ignore())            
        .ForAllMembers(c => c.IgnoreIfSourceIsNull()); //To checking NULL
Rajasekar Sa
  • 65
  • 11