【问题标题】:Automapper missing type map configuration or unsupported mapping - ErrorAutomapper 缺少类型映射配置或不支持的映射 - 错误
【发布时间】:2013-01-18 15:07:22
【问题描述】:

实体模型

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);
    }
}

错误

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

目标路径: 类别_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());
    }
}

【问题讨论】:

  • 还要仔细检查你在不同的命名空间中是否有相同的类名。所以你有可能正在初始化不同的对象并映射和映射不同的对象
  • @Iman 这正是我今天的问题,很好地隐藏在大量映射中。

标签: asp.net-mvc automapper


【解决方案1】:

您在哪里指定了映射代码(CreateMap)?参考:Where do I configure AutoMapper?

如果您使用的是静态 Mapper 方法,则每个 AppDomain 只应进行一次配置。这意味着放置配置代码的最佳位置是在应用程序启动中,例如 ASP.NET 应用程序的 Global.asax 文件。

如果在调用 Map 方法之前没有注册配置,你会收到Missing type map configuration or unsupported mapping.

【讨论】:

  • 是的,你必须注册你的类 Mapper.CreateMap();
【解决方案2】:

在您的班级AutoMapper 个人资料中,您需要为您的实体和视图模型创建一个地图。

ViewModel 到域模型的映射:

这通常在AutoMapper/DomainToViewModelMappingProfile

Configure()中,添加一行

Mapper.CreateMap<YourEntityViewModel, YourEntity>();

域模型到 ViewModel 映射:

ViewModelToDomainMappingProfile,添加:

Mapper.CreateMap<YourEntity, YourEntityViewModel>();

Gist example

【讨论】:

  • 谢谢 :) 我一直在睡觉,并认为它只是双向工作,并没有真正意识到订购很重要。 Profile.CreateMap()
  • @Kiksen Mapper.CreateMap&lt;YourEntityViewModel, YourEntity&gt;().ReverseMap(); .ReverseMap() 将使其双向工作,您甚至不必担心这种情况下的顺序。
【解决方案3】:

注意到异常中的Categoies_7314E98C41152985A4218174DDDF658046BC82AB0ED9E1F0440514D79052F84D 类了吗?那是一个实体框架代理。我建议您处理您的 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 知道它必须映射什么(除了自动)?
  • 您需要配置映射。对于那些您想要自定义映射规则的人,请编写这些规则。
  • 谢谢。我完全跳过了关于自动映射器如何......不知何故的部分。
  • 它是正确的,实际上我们必须为 Get 和 Post 的 Edit 方法创建 Map,用于 Get Its: Domain Model To ViewModel Mappings 和 Post Its: ViewModel To Domain Model映射,检查this,希望对某人有所帮助。
【解决方案4】:

我试图将一个 IEnumerable 映射到一个对象。这就是我得到这个错误的方式。也许有帮助。

【讨论】:

    【解决方案5】:

    我这样做是为了消除错误:

    Mapper.CreateMap<FacebookUser, ProspectModel>();
    prospect = Mapper.Map(prospectFromDb, prospect);
    

    【讨论】:

      【解决方案6】:

      我在 .Net Core 中遇到了同样的问题。因为我的基础 dto 类(我将它作为 automapper 程序集的启动类型)在不同的项目中。 Automapper 尝试在基类项目中搜索配置文件。但我的 dto 在不同的项目中。我移动了我的基类。并且问题解决了。这可能对某些人有所帮助。

      【讨论】:

        【解决方案7】:

        我找到了解决办法,谢谢大家的回复。

        category = (Categoies)AutoMapper.Mapper.Map(viewModel, category, typeof(CategoriesViewModel), typeof(Categoies));
        

        但是,我已经不知道原因了。完全看不懂。

        【讨论】:

        • 找到问题的原因了吗?
        • 可能是“类别”的错字
        【解决方案8】:

        检查您的 Global.asax.cs 文件并确保该行存在

         AutoMapperConfig.Configure();
        

        【讨论】:

          【解决方案9】:

          就我而言,我创建了地图,但缺少 ReverseMap 功能。添加它消除了错误。

                private static void RegisterServices(ContainerBuilder bldr)
                {
                   var config = new MapperConfiguration(cfg =>
                   {
                      cfg.AddProfile(new CampMappingProfile());
                   });
                   ...
                 }
          
          
                public CampMappingProfile()
                {
                   CreateMap<Talk, TalkModel>().ReverseMap();
                   ...
                }
          

          【讨论】:

            【解决方案10】:

            到目前为止,我知道这是一个相当老的问题,但我发现正确的解决方案是我没有声明程序集属性。

            我的代码是:

            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();
                }
                ...
            }
            

            【讨论】:

              【解决方案11】:

              从 AutoMapper v.3 更新到 v.5 后,我们遇到了同样的错误。

              最终我们发现目标类具有 IDictionary 类型的属性,并且在同一类型的配置文件映射是有效的。

              有下一个可能的解决方案:

              1. 更新到更高版本。在 v.6 中,该错误消失了。
              2. 或者忽略映射中的那个道具。
              3. 或者使用方法Mapper.Map&lt;IFooDto&gt;(foo) instead of Mapper.Map(foo, fooDto).

              我们的个人资料就像使用界面作为目的地:

              public class FooProfile : Profile
              {
                  public FooProfile()
                  {
                      CreateMap<Foo, IFooDto>()
                          .ConstructUsing(foo => new FooDto());
                  }
              }
              

              另外我应该提一下,在从 v.3 更新到更高版本的过程中,与旧版本相比,我们遇到了许多错误和差异,以及对我们有什么帮助:

              • 每次检查下一个版本可能会修复该错误;
              • 仔细检查现有的映射配置。它可能有旧的隐藏错误,例如在没有设置器的情况下映射到属性或现有的重复映射等。可能是旧版本允许这样做,而新版本则不允许。

              【讨论】:

                【解决方案12】:

                将 Automapper 升级到版本 6.2.2。它帮助了我

                【讨论】:

                  【解决方案13】:

                  我创建了一个新的 AutomapperProfile 类。它扩展了 Profile。我们的解决方案中有 100 多个项目。许多项目都有一个 AutomapperProfile 类,但这个对现有项目来说是新的。但是,我确实找到了必须为我们解决此问题的方法。有一个绑定项目。在初始化中有这段代码:

                  var mappingConfig = new List<Action<IConfiguration>>();
                  
                  // Initialize the Automapper Configuration for all Known Assemblies
                  mappingConfig.AddRange( new List<Action<IConfiguration>>
                  {
                     ConfigureProfilesInAssemblyOfType<Application.Administration.AutomapperProfile>,
                     //...
                  

                  我必须添加 ConfigureProfilesInAssemblyOfTypeMyNewNamespace.AutomapperProfile>

                  请注意,ConfigureProfilesInAssemblyOfType 如下所示:

                      private static void ConfigureProfilesInAssemblyOfType<T>( IConfiguration configuration )
                      {
                          var log = LogProvider.Get( typeof (AutomapperConfiguration) );
                  
                          // The Automapper Profile Type
                          var automapperProfileType = typeof (Profile);
                  
                          // The Assembly containing the type
                          var assembly = typeof (T).Assembly;
                          log.Debug( "Scanning " + assembly.FullName );
                  
                          // Configure any Profile classes found in the assembly containing the type.
                          assembly.GetTypes()
                              .Where( automapperProfileType.IsAssignableFrom ).ToList()
                              .ForEach( x =>
                              {
                                  log.Debug( "Adding Profile '" + x.FullName + "'" );
                                  configuration.AddProfile( Activator.CreateInstance( x ) as Profile );
                              } );
                      }
                  

                  最好的问候, -杰夫

                  【讨论】:

                    猜你喜欢
                    • 2019-03-01
                    • 2017-04-16
                    • 2015-09-22
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2018-11-15
                    • 2015-05-07
                    • 1970-01-01
                    相关资源
                    最近更新 更多