简体   繁体   中英

How to fix Automapper Mapping a Join Table to a ViewModel

I'm using AutoMapper 7.0.1 in an ASP CORE 2 project. I'm trying to map a class with a join table. Mapping from the entity to my view model works. When I ReverseMap() the join table is null and does not map back to the entity.

The reason behind it is I use the viewModel to get a list of int values to populate the selected values into a multiselect list.

I've gone through the documentation of AutoMapper but I must be missing something in CreateMap configurations. I've tried using ForMember but was unsuccessful.

I'm also trying to understand the flattening and unflattening process in ReverseMap()

    //Article.cs

    public class Article
    {
        public int ArticleId { get; set; }
        public string Title { get; set; }
        public virtual ICollection<ArticleGroup> ArticleGroups { get; set; } = new List<ArticleGroup>();
    }

    //Group.cs

    public class Group
    {
       public int GroupId { get; set; }
       public string GroupName { get; set; }
       public virtual ICollection<ArticleGroup> ArticleGroups { get; set; } = new List<ArticleGroup>();
    }

    //ArticleGroup.cs

    public class ArticleGroup
    {
       public int ArticleId { get; set; }
       public Article Article { get; set; }
       public int GroupId { get; set; }
       public Group Group { get; set; }
    }

    //ArticleFormView.cs

    public class ArticleFormView
    {
        public int ArticleId { get; set; }
        public string Title { get; set; }
        public virtual List<int> GroupIds { get; set; }
    }

    //Startup.cs
    ...

    AutoMapper.Mapper.Initialize(cfg =>
    {
       cfg.CreateMap<Article, ArticleFormView>()
          .ReverseMap()
       ;

       //Tried this as well removing ReverseMap() from above
       //cfg.CreateMap<ArticleFormView, Article>()
       //    .ForMember(a => a.ArticleGroups, opt =>
       //        opt.MapFrom(src =>
       //            src.GroupIds
       //        )
       //    )
       //;
    });

    ...
//View Component
@model ArticleFormView

<div class="form-group">
    <label asp-for="Title" class="col-xs-1 control-label"></label>
    <div class="col-xs-11">
        <span asp-validation-for="Title" class="text-danger"></span>
        <input asp-for="Title" class="form-control">
    </div>
</div>
<div class="form-group">
    <label asp-for="GroupIds" class="col-xs-1 control-label"></label>
    <div class="col-xs-2">
        <select multiple="multiple" asp-for="GroupIds" asp-items="ViewBag.ListOfGroups" name="GroupIds[]" style="display:none"></select>
    </div>
</div>

How do I configure AutoMapper to from List of int in ViewModel back into List of ArticleGroup in Article entity?

I tried to reproduce your scenario and I ended up with AutoMapperConfigurationException stating that unmapped members were found for GroupIds property of ArticleFormView . Thus, I wrote a map from the domain as well:

Mapper.Initialize(cfg =>
{
    cfg.CreateMap<Article, ArticleFormView>()
        .ForMember(articleFormView => articleFormView.GroupIds, opts =>
            opts.MapFrom(article => article.ArticleGroups.Select(articleGroup => articleGroup.GroupId)));

    cfg.CreateMap<ArticleFormView, Article>()
        .ForMember(article => article.ArticleGroups, opts =>
            opts.MapFrom(articleFormView => articleFormView.GroupIds.Select(id => new ArticleGroup
            {
                // Uncomment these two lines if you need them.
                //Article = new Article { Title = articleFormView.Title, ArticleId = articleFormView.ArticleId },
                //Group = new Group { GroupId = id },

                ArticleId = articleFormView.ArticleId,
                GroupId = id,
            })));
});

Be aware, that by mapping an entity from article to form view you are irreversibly losing data. With the structure of form view you provided there are limitations of what members you can fill out when reversing the mapping process, simply because you have less data to start with. For example, keeping only the group ids, you are losing the group names, so when reversing the mapping you will not know the group name.

ReverseMap() didn't work because AutoMapper will not know automagically how to treat two different collections of different type and name:

  • Article : a collection of ArticleGroup called "ArticleGroups"
  • ArticleFormView : a list of int called "GroupIds"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM