【问题标题】:MVC, problem with Mapper passing ViewModel to CreateViewMVC,映射器将 ViewModel 传递给 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 进行过任何配置?如果有,请出示。

标签: asp.net-mvc entity-framework asp.net-mvc-4 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ć 实现类并导入它们
猜你喜欢
  • 1970-01-01
  • 2013-08-17
  • 2012-05-13
  • 2015-01-30
  • 1970-01-01
  • 1970-01-01
  • 2017-07-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多