Automapper缺少类型映射配置或不支持的映射 - 错误

131

实体模型

public partial class Categoies
{
    public Categoies()
    {
        this.Posts = new HashSet<Posts>();
    }

    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public Nullable<int> PositionId { get; set; }

    public virtual CategoryPositions CategoryPositions { get; set; }
    public virtual ICollection<Posts> Posts { get; set; }
}

视图模型

public class CategoriesViewModel
{
    public int Id { get; set; }

    [Required(ErrorMessage = "{0} alanı boş bırakılmamalıdır!")]
    [Display(Name = "Kategori Adı")]
    public string Name { get; set; }

    [Display(Name = "Kategori Açıklama")]
    public string Description { get; set; }

    [Display(Name = "Kategori Pozisyon")]
    [Required(ErrorMessage="{0} alanı boş bırakılmamalıdır!")]
    public int PositionId { get; set; }
}

创建地图

Mapper.CreateMap<CategoriesViewModel, Categoies>()
            .ForMember(c => c.CategoryPositions, option => option.Ignore())
            .ForMember(c => c.Posts, option => option.Ignore());

地图

[HttpPost]
public ActionResult _EditCategory(CategoriesViewModel viewModel)
{
    using (NewsCMSEntities entity = new NewsCMSEntities())
    {
        if (ModelState.IsValid)
        {
            try
            {
                category = entity.Categoies.Find(viewModel.Id);
                AutoMapper.Mapper.Map<CategoriesViewModel, Categoies>(viewModel, category);
                //category = AutoMapper.Mapper.Map<CategoriesViewModel, Categoies>(viewModel);
                //AutoMapper.Mapper.Map(viewModel, category);
                entity.SaveChanges();

                // Veritabanı işlemleri başarılı ise yönlendirilecek sayfayı 
                // belirleyip ajax-post-success fonksiyonuna gönder.
                return Json(new { url = Url.Action("Index") });
            }
            catch (Exception ex)
            {

            }
        }

        // Veritabanı işlemleri başarısız ise modeli tekrar gönder.
        ViewBag.Positions = new SelectList(entity.CategoryPositions.ToList(), "Id", "Name");
        return PartialView(viewModel);
    }
}

错误

缺少类型映射配置或不支持的映射。 映射类型: CategoriesViewModel -> Categoies_7314E98C41152985A4218174DDDF658046BC82AB0ED9E1F0440514D79052F84D NewsCMS.Areas.Admin.Models.CategoriesViewModel -> System.Data.Entity.DynamicProxies.Categoies_7314E98C41152985A4218174DDDF658046BC82AB0ED9E1F0440514D79052F84D

目标路径: Categoies_7314E98C41152985A4218174DDDF658046BC82AB0ED9E1F0440514D79052F84D

源值: NewsCMS.Areas.Admin.Models.CategoriesViewModel

我错过了什么?我尝试找到问题,但我看不到。

更新

我在Global.asax中的application_start指定了。

protected void Application_Start()
{
    InitializeAutoMapper.Initialize();
}

初始化类

public static class InitializeAutoMapper
{
    public static void Initialize()
    {
        CreateModelsToViewModels();
        CreateViewModelsToModels();
    }

    private static void CreateModelsToViewModels()
    {
        Mapper.CreateMap<Categoies, CategoriesViewModel>();
    }

    private static void CreateViewModelsToModels()
    {
        Mapper.CreateMap<CategoriesViewModel, Categoies>()
            .ForMember(c => c.CategoryPositions, option => option.Ignore())
            .ForMember(c => c.Posts, option => option.Ignore());
    }
}

2
请注意,如果在不同的名称空间中具有相同的类名,则需要进行仔细检查。这样可能会初始化不同的对象并映射不同的对象。 - Iman
1
@Iman,这正是我今天遇到的问题,在无数的映射中非常难以发现。 - edelwater
16个回答

82
你在哪里指定了映射代码(CreateMap)?参考:我应该在哪里配置AutoMapper?

如果你正在使用静态 Mapper 方法,则每个 AppDomain 只需要进行一次配置。这意味着最好将配置代码放在应用程序启动时,如 ASP.NET 应用程序的 Global.asax 文件中。

如果在调用 Map 方法之前未注册配置,则会收到“缺少类型映射配置或不支持的映射”。


3
是的,您需要注册您的类 Mapper.CreateMap<IDataReader, UserBo>();。 - Nikki

49

在你的类AutoMapper配置文件中,你需要为实体和视图模型创建一个映射。

视图模型到领域模型的映射:

通常位于AutoMapper / DomainToViewModelMappingProfile文件中。

Configure()方法中添加一行代码,例如:

Mapper.CreateMap<YourEntityViewModel, YourEntity>();

领域模型到视图模型的映射:

ViewModelToDomainMappingProfile中添加:

Mapper.CreateMap<YourEntity, YourEntityViewModel>();

Gist示例


2
谢谢 :) 我一直在睡觉,以为它可以双向工作,没有意识到顺序很重要。Profile.CreateMap<TSource,TDestination>() - Kiksen
10
.ReverseMap()可以实现双向映射,而且您甚至不必担心顺序问题。 - Pramil Gawande

26

注意异常中的Categoies_7314E98C41152985A4218174DDDF658046BC82AB0ED9E1F0440514D79052F84D类吗?那是一个Entity Framework代理。我建议您处理EF上下文,以确保所有对象都从数据库中急切地加载,并且不存在这样的代理:

[HttpPost]
public ActionResult _EditCategory(CategoriesViewModel viewModel)
{
    Categoies category = null;
    using (var ctx = new MyentityFrameworkContext())
    {
        category = ctx.Categoies.Find(viewModel.Id);
    }
    AutoMapper.Mapper.Map<CategoriesViewModel, Categoies>(viewModel, category);
    //category = AutoMapper.Mapper.Map<CategoriesViewModel, Categoies>(viewModel, category);
    entity.SaveChanges();
}

如果实体检索是在数据访问层内进行的(这当然是正确的方式),请确保在从DAL返回实例之前处理好EF上下文。


这是自动完成的吗,还是我们需要让Automapper知道它必须映射的内容(除了自动之外的任何内容)? - brumScouse
1
您需要配置映射。对于那些您想要自定义映射规则的内容,请编写这些规则。 - Darin Dimitrov
谢谢。我完全跳过了关于自动映射器如何使用的部分...不知怎么回事。 - brumScouse
正确的做法是,实际上我们需要为编辑方法的Get和Post创建Map。对于Get,它是从领域模型到视图模型的映射;对于Post,它是从视图模型到领域模型的映射。请参考这里,希望能帮助到某些人。 - Shaiju T

21

我试图将一个IEnumerable映射到一个对象。这就是我遇到此错误的原因。也许可以帮到你。


这个注释帮助了我。 - Sarath Baiju

9
我采取这个方法来解决错误:
Mapper.CreateMap<FacebookUser, ProspectModel>();
prospect = Mapper.Map(prospectFromDb, prospect);

8

我在 .Net Core 中遇到了同样的问题。原因是我的基础 dto 类(我在启动时将其作为 automapper 组件的类型)位于不同的项目中。Automapper 尝试在基础类项目中搜索配置文件,但是我的 dto 类在不同的项目中。我将基础 dto 类移动到正确的位置,问题得到解决。这可能对某些人有所帮助。


7
我找到了解决办法,谢谢大家的回复。
category = (Categoies)AutoMapper.Mapper.Map(viewModel, category, typeof(CategoriesViewModel), typeof(Categories));

但是,我已经不知道原因了。我无法完全理解。

你找到问题的原因了吗? - Roi Shabtai
27
也许是那个笔误导致了拼写错误的“Categoies”。 - Joe Phillips

6
请检查您的Global.asax.cs文件,确保这行代码存在。
 AutoMapperConfig.Configure();

6
在我的情况下,我已经创建了地图,但是缺少了ReverseMap函数。添加它就可以消除错误。
      private static void RegisterServices(ContainerBuilder bldr)
      {
         var config = new MapperConfiguration(cfg =>
         {
            cfg.AddProfile(new CampMappingProfile());
         });
         ...
       }


      public CampMappingProfile()
      {
         CreateMap<Talk, TalkModel>().ReverseMap();
         ...
      }

3
我知道这是一个比较旧的问题,但我找到了正确的解决方案,就是我没有声明程序集属性。
我的代码是:
using AutoMapper;
...

namespace [...].Controllers
{
    public class HousingTenureTypesController : LookupController<HousingTenureType, LookupTypeModel>
    {
        Mapper.CreateMap<HousingTenureType, LookupTypeModel>().ReverseMap();
    }
    ...
}

在我的命名空间声明之前添加以下行即可解决此问题:
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(HousingTenureTypesController), "AutoMapperStart")]

完整代码如下:
using AutoMapper;
...

[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(HousingTenureTypesController), "AutoMapperStart")]

namespace [...].Controllers
{
    public class HousingTenureTypesController : LookupController<HousingTenureType, LookupTypeModel>
    {
        Mapper.CreateMap<HousingTenureType, LookupTypeModel>().ReverseMap();
    }
    ...
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接