-1

I just followed this guide to install and set up AutoMapper, and I think I got it correctly set up. But when I try to map from IEnumerable<ProductCategory> to IEnumerable<ViewModelProductCategory>, like this:

var categories = _context.ProductCategories.Include(e => e.Children).ToList();
var topLevelCategories = categories.Where(e => e.ParentId == null);
var VMCategory = _mapper
    .Map<IEnumerable<ProductCategory>, 
        IEnumerable<ViewModelProductCategory>>(topLevelCategories);
return View(VMCategory);

(Thank you to @Anton Gorbunov, for pointing out that I had my objects swapped!)

... my view complains about receiving the wrong model. I'm pretty sure it's because of the children categories not being mapped to a sub-list, so in the view, item.Children is not properly set up as a viewmodel.

How can I map a list of lists?

This is my Index-view:

@model IEnumerable<MyStore.Models.ViewModels.ViewModelProductCategory>
<ul>
    @Html.Partial("_CategoryRecursive", Model)
</ul>

... and this is _CategoryRecursive.cshtml:

@model IEnumerable<MyStore.Models.ViewModels.ViewModelProductCategory>
<ul style="list-style:none;padding-left:0px;">
   @if (Model != null)
    {
        foreach (var item in Model)
        {
            <li style="margin:8px 0px 0px 0px;">
                <ul>
                    @Html.Partial("_CategoryRecursive.cshtml", item.Children)
                </ul>
            </li>
        }
    }
</ul>

Mapping profile:

public class MappingProfile : Profile
{
    public MappingProfile()
    {
        CreateMap<ProductCategory, ViewModelProductCategory>();
        CreateMap<ViewModelProductCategory, ProductCategory>();
        CreateMap<Product, ViewModelProduct>();
        CreateMap<ViewModelProduct, Product>();
    }
}

Entity model:

public class ProductCategory
{
    public int Id { get; set; }
    public int SortOrder { get; set; }
    public string Title { get; set; }

    [ForeignKey(nameof(ParentCategory))]
    public int? ParentId { get; set; }

    public ProductCategory ParentCategory { get; set; } //nav.prop to parent
    public ICollection<ProductCategory> Children { get; set; } //nav. prop to children

    public List<ProductInCategory> ProductInCategory { get; set; }
}

Viewmodel:

public class ViewModelProductCategory
{
    public int Id { get; set; }
    public int? ParentId { get; set; }
    public string Title { get; set; }
    public int SortOrder { get; set; }

    public string ProductCountInfo
    {
        get
        {
            return Products != null && Products.Any() ? Products.Count().ToString() : "0";
        }
    }

    public ProductCategory ParentCategory { get; set; } // Nav.prop. to parent
    public IEnumerable<ProductCategory> Children { get; set; } // Nav.prop. to children

    public List<ViewModelProduct> Products { get; set; } // Products in this category
    public List<ViewModelProduct> OrphanProducts { get; set; } // Products with no references in ProductInCategory
}
Stian
  • 1,522
  • 2
  • 22
  • 52

1 Answers1

1

Problem here:

var VMCategory = _mapper.Map<IEnumerable<ViewModelProductCategory>, IEnumerable<ProductCategory>>(topLevelCategories);

you should change code to

var VMCategory = _mapper.Map<IEnumerable<ProductCategory>, IEnumerable<ViewModelProductCategory>>(topLevelCategories);

Description: TDestination = Map<TSource,TDestination>(TSource sourceObject), but you swapped the types TSource and TDestination inside brackets <,>

Anton Gorbunov
  • 1,414
  • 3
  • 16
  • 24
  • Thank you! Now I got one step further, but am faced with another error. Please see updated OP. – Stian Jan 12 '18 at 18:29
  • 1
    A problem in Children property of viewModel. Now you use collection `IEnumerable`, but I see in configuration, that it must be `ViewModelProductCategory`, or you should create map rule like `CreateMap()`. Same problem you will get with property `ParentCategory` – Anton Gorbunov Jan 12 '18 at 19:18