MVC,映射器将 ViewModel 传递给 CreateView 的问题

Posted

技术标签:

【中文标题】MVC,映射器将 ViewModel 传递给 CreateView 的问题【英文标题】:MVC, problem with Mapper passing ViewModel to CreateView 【发布时间】:2020-10-21 20:45:50 【问题描述】:

我需要一些帮助。我正在使用我是初学者的 ASP.NET MVC。

我正在编写一个包含一个数据库和 3 个表的应用程序(2 个表仅用于父子下拉列表,第三个用于保存下拉列表中的数据并填写其他表单)。

我正在使用带有 SQL 的实体框架将我的数据库连接到 ASP.NET MVC,并使用来自数据库的自动生成模型。

我手动为所有三个表及其字段创建 ViewModel,我需要将所有数据传递给 1 个视图(创建视图)

这是我在 Home 控制器中遇到错误的代码。

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(CountryStateContactsViewModel csvm)

    if (!ModelState.IsValid)
    
        return View(csvm);
    

    // Error happens here
    Contact contactModel = Mapper.Map<CountryStateContactsViewModel, Contact>(csvm); 
    db.Contacts.Add(contactModel);
    db.SaveChanges();

    return RedirectToAction("Index");

这是我得到的错误:

非静态字段、方法或属性'Mapper.Map(CountryStateContactsViewModel)需要对象引用

【问题讨论】:

你能显示你的映射器配置文件吗? 是的,当然,但我不确定你的意思是什么:( 你在使用 Automapper? 是的,是的。我该如何解决这个问题? 您是否对 AutoMapper 进行过任何配置?如果有,请出示。 【参考方案1】:

为了使用 AutoMapper,首先你应该在你的类之间创建映射。

public class ContactProfile 
    public AutoMapperProfile() 
        CreateMap<CountryStateContactsViewModel,Contact>();
    


public class AutoMapperConfiguration 
    public static void Initialize() 
        Mapper.Initialize(cfg = > 
            cfg.AddProfile(new ContactProfile());
        );
    

最后在您的 Global.asax 中:

AutoMapperConfiguration.Initialize()

【讨论】:

我应该把这些类 ContactProfile 和 AutoMapperConfiguration 放在哪里 视情况而定。例如,您可以将其放在启动项目中的任何文件夹中。 所以我只是在启动时创建新文件夹,创建类并将两个类都放入其中? 是的。这是正确的。别忘了你应该在你的 Globa;.asax 文件中引入 AutoMapperConfiguration。 我收到错误 Mapper does not contain a definition for initialize at Mapper.Initialize【参考方案2】:

根据 OP cmets 没有 AutoMapper 配置,没有它 AutoMapper 无法解析映射。

定义一个接口来抽象映射方法:

public interface IMappingService

    TDest Map<TSrc, TDest>(TSrc source) where TDest : class;

    TDest Map<TSrc, TDest>(TSrc source, TDest dest) where TDest : class;

实现接口:

public class MappingService : IMappingService

    private MapperConfiguration mapperConfiguration;
    private IMapper mapper;

    public MappingService()
    
        mapperConfiguration = new MapperConfiguration(cfg =>
        
            // Define here your mapping profiles... 
            cfg.AddProfile<ViewModelToDomainMappingProfile>();
            cfg.AddProfile<DomainToViewModelMappingProfile>();
        );
        
        // You may not want to assert that your config is valid, and that's ok.
        mapperConfiguration.AssertConfigurationIsValid();
        mapper = mapperConfiguration.CreateMapper();
    

    public TDest Map<TSrc, TDest>(TSrc source) where TDest : class
    
        return mapper.Map<TSrc, TDest>(source);
    

    public TDest Map<TSrc, TDest>(TSrc source, TDest dest) where TDest : class
    
        return mapper.Map(source, dest);
    

现在您必须定义您的个人资料(示例):

public class ViewModelToDomainProfile: Profile

    public ViewModelToDomainProfile()
    
        CreateMap<CountryStateContactsViewModel, Contact>();
    



public class DomainToViewModelProfile: Profile

    public DomainToViewModelProfile()
    
        CreateMap<CountryStateContactsViewModel, Contact>();
    

最后,在控制器中注入 IMappingService:

private readonly IMappingService _mappingService;

public HomeController(IMappingService mappingService) 
    _mappingService = mappingService;

然后像这样使用它:

_mappingService.Map<CountryStateContactsViewModel, Contact>(viewModel);

我喜欢这个解决方案,因为它很好地封装了所有内容。

编辑:@Arsalan Valoojerdi 比我快。但是,这种方式有两种不同的方法。

注意:不要忘记在 IoC 容器(例如 Ninject)上定义对 IMappingService 的依赖。

【讨论】:

在此行执行时出错 cfg.AddProfile(); cfg.AddProfile(); @SvenNenadić 有什么错误?您是否同时实现了 ViewModelToDomainMappingProfile 和 DomainToViewModelMappingProfile 两个类? 找不到类型或命名空间名称 ViewModelToDomainMappingProfile DomainToViewModelMappingProfile 相同 @SvenNenadić 实现类并导入它们

以上是关于MVC,映射器将 ViewModel 传递给 CreateView 的问题的主要内容,如果未能解决你的问题,请参考以下文章

将创建的对象实例传递给映射器

配置注解映射器和适配器。

域对象和数据映射器应如何在使用 MVC 的身份验证系统的服务类中交互

非注解的处理器映射器和适配器

MyBatis映射器--多参数传递方式

Spring MVC 复习笔记02