Aaron Aaron - 11 months ago 94
C# Question

Calculate datetime difference in automapper mapping (UseValue)

I have situation where I need to know difference between two dates in days. I wanna do this in

mapper conf

The problem is I dont know is this possible and how?

Here is example code:

CreateMap<Post, ManagePostViewModel>()
.ForMember(d => d.ActiveInDays, conf => conf.UseValue((DateTime.UtcNow - (conf.CreatedAt)).TotalDays));

I tested this syntax in static values and it works. If I use
it dosn't, gives following error:

'IMemberConfigurationExpression' does not contain definition for 'CreatedAt' and no extension method 'CreatedAt' accepting a first argument of type 'IMemberConfigurationExpression' could be found (are you missing a using directive or an assembly reference?)

i have defined

Answer Source

The first problem is a typo: you typed conf.CreatedAt. conf is not your ViewModel, that's the IMemberConfigurationExpression object that allows you to create mapping expression.

The second problem is that UseValue is used to calculate a value only once, hence it doesn't provide access to the ViewModel. You need to use MapFrom to calculate a value for each individual ViewModel.

The final problem is that Automapper isn't supposed to work like that. It should map one property to another, not generate new values. The best place to calculate a duration is the target ViewModel. This will make changing and testing the duration calculation code a lot easier.

In the current scenario, you should map CreatedAt to a similar property in your ViewModel and add a read-only property that returns DateTime.UtcNow - CreatedAt).TotalDays. Using C# 6 syntax this would be a simple

public double ActiveInDays => (DateTime.UtcNow - conf.CreatedAt).TotalDays;

Perhaps a better option would be to return the TimeStamp itself and specify a formatting string in your data binding

public double ActiveDuration => DateTime.UtcNow - conf.CreatedAt;

This will allow you to display date fractions as hours, minutes etc.

If you have to perform the calculation while mapping, you should try:

.ForMember(model => model.ActiveInDays, 
          conf => conf.MapFrom(
                 model => (DateTime.UtcNow - model.CreatedAt).TotalDays

I think it's obvious that using a read-only property is a lot cleaner.


If the intent is to show full days, the Days property should be used instead of TotalDays.