Question

I'm trying to add a formatter to my Automapper configuration to style all DateTime? fields. I've tried adding my formatter globally:

Mapper.AddFormatter<DateStringFormatter>();

And on the specific mapping itself:

Mapper.CreateMap<Post, PostViewModel>()
            .ForMember(dto => dto.Published, opt => opt.AddFormatter<DateStringFormatter>());

But neither seems to work - it always outputs the date in the normal format. For reference, here is the ViewModel I'm using, and the rest of the configuration:

public class DateStringFormatter : BaseFormatter<DateTime?>
{
    protected override string FormatValueCore(DateTime? value)
    {
        return value.Value.ToString("d");
    }
}

public abstract class BaseFormatter<T> : IValueFormatter
{
    public string FormatValue(ResolutionContext context)
    {
        if (context.SourceValue == null)
            return null;

        if (!(context.SourceValue is T))
            return context.SourceValue == null ? String.Empty : context.SourceValue.ToString();

        return FormatValueCore((T)context.SourceValue);
    }

    protected abstract string FormatValueCore(T value);
}

PostViewModel:

public int PostID { get; set; }
    public int BlogID { get; set; }
    public string UniqueUrl { get; set; }
    public string Title { get; set; }
    public string Body { get; set; }
    public string BodyShort { get; set; }
    public string ViewCount { get; set; }
    public DateTime CreatedOn { get; set; }

    private DateTime? published;
    public DateTime? Published
    {
        get
        {
            return (published.HasValue) ? published.Value : CreatedOn;
        }
        set
        {
            published = value;
        }
    }

What am I doing wrong?

Thanks!

Was it helpful?

Solution

Formatters are only applied when the destination member type is of type "string". Since "Published" is of type "DateTime?", the formatter never gets applied. You have a few options here:

  • Add a Published property to the Post object, with the behavior laid out above
  • Create a custom resolver for the Published property, which first resolves the DateTime? value from the property logic, then change the destination member type to string on Published. First, the resolver will execute. Next, the formatter takes the result of the custom resolver, and finally, the resulting value is set on Published
  • Do all of your custom Type -> String formatting in the View, with things like an HtmlHelper

We usually go for 1), unless the value displayed is truly only for this view, then we go for option 2).

OTHER TIPS

Try doing it this way:

Mapper.CreateMap<DateTime?, string>().ConvertUsing(d => d.Value.ToString("d"));

You can change the function to meet your requirements.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top