Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AutoMapper Custom Type Converter not working

I am using Troy Goode's PagedList to provide paging information in my WebApi. His package returns an IPagedList that implements IEnumerable but also contains custom properties such as IsLastPage, PageNumber, PageCount, etc.

When you try to return this class from a WebApi controller method (such as the GET), the Enumerable is serialized, but the custom properties are not. So, I thought I would use AutoMapper and write a custom type converter to convert to a class such as this:

public class PagedViewModel<T>
{
    public int FirstItemOnPage { get; set; }
    public bool HasNextPage { get; set; }
    public bool HasPreviousPage { get; set; }
    public bool IsFirstPage { get; set; }
    public bool IsLastPage { get; set; }
    public int LastItemOnPage { get; set; }
    public int PageCount { get; set; }
    public int PageNumber { get; set; }
    public int PageSize { get; set; }
    public int TotalItemCount { get; set; }
    public IEnumerable<T> rows { get; set; }
}

Since I move the Enumerable into a distinct property, the serialization handles it perfectly. So, I sat down and wrote a custom type converter like this:

public class PagedListTypeConverter<T> : ITypeConverter<IPagedList<T>, PagedViewModel<T>>
{
    public PagedViewModel<T> Convert(ResolutionContext context)
    {
        var source = (IPagedList<T>)context.SourceValue;
        return new PagedViewModel<T>()
        {
            FirstItemOnPage = source.FirstItemOnPage,
            HasNextPage = source.HasNextPage,
            HasPreviousPage = source.HasPreviousPage,
            IsFirstPage = source.IsFirstPage,
            IsLastPage = source.IsLastPage,
            LastItemOnPage = source.LastItemOnPage,
            PageCount = source.PageCount,
            PageNumber = source.PageNumber,
            PageSize = source.PageSize,
            TotalItemCount = source.TotalItemCount,
            rows = source
        };
    }
}

And then set it up in my configuration like this:

Mapper.CreateMap<IPagedList<Department>, PagedViewModel<Department>>().ConvertUsing(new PagedListTypeConverter<Department>());

But, when I try to call it like this:

var x = Mapper.Map<IPagedList<Department>, PagedViewModel<Department>>(departments);

I get this error:

Missing type map configuration or unsupported mapping.

Mapping types: IPagedList1 -> PagedViewModel1 PagedList.IPagedList1[[Provision.DomainObjects.Department, Provision.DomainObjects, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]] -> Provision.DomainObjects.PagedViewModel1[[Provision.DomainObjects.Department, Provision.DomainObjects, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]

Destination path: PagedViewModel`1

Source value: PagedList.StaticPagedList`1[Provision.DomainObjects.Department]

How can I make this work?

like image 578
Brian McCord Avatar asked Sep 18 '12 03:09

Brian McCord


People also ask

Can AutoMapper map collections?

AutoMapper supports polymorphic arrays and collections, such that derived source/destination types are used if found.

What is AutoMapper good for?

AutoMapper in C# is a library used to map data from one object to another. It acts as a mapper between two objects and transforms one object type into another. It converts the input object of one type to the output object of another type until the latter type follows or maintains the conventions of AutoMapper.

What is AutoMapper ResolutionContext?

The ResolutionContext contains all of the contextual information for the current resolution operation, such as source type, destination type, source value and so on.


1 Answers

After pulling my hair out, I finally figured this one out. There isn't anything at all wrong with the code. It turned out to be a threading issue where the configured mappings were getting cleared out. The code above is the proper way to do what I wanted. I am leaving this here so that I can point another question to it for others who need to do the same thing.

like image 107
Brian McCord Avatar answered Sep 22 '22 16:09

Brian McCord