views:

424

answers:

2

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!

A: 

Try doing it this way:

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

You can change the function to meet your requirements.

jonnii
This doesn't seem to work either... everytime I write out my "Published" field... it writes out the date in the same format: MM/DD/YYYY HH:MM:SS PMIt doesn't seem like AutoMapper is affecting that field at all... using either "ConvertUsing" or the custom formatter.
leftend
+2  A: 

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

Jimmy Bogard
Thanks Jimmy, I went with option #2. I've got a few other source objects with this same type of field. Just started with Automapper, and loving it so far.
leftend
Do you have samples of how you did it?
gugulethun