Asp.net mvc AutoMapper展平用于查看记录,但不用于创建/更新?
我有一个与地址模型有一对一关系的公司模型。我正在使用视图模型进行创建、详细信息、编辑和更新操作。我使用AutoMapper从一个模型映射到另一个视图模型,反之亦然 我的视图模型用于包含公开公司地址的属性:Asp.net mvc AutoMapper展平用于查看记录,但不用于创建/更新?,asp.net-mvc,entity-framework,automapper,Asp.net Mvc,Entity Framework,Automapper,我有一个与地址模型有一对一关系的公司模型。我正在使用视图模型进行创建、详细信息、编辑和更新操作。我使用AutoMapper从一个模型映射到另一个视图模型,反之亦然 我的视图模型用于包含公开公司地址的属性: public Address Address { get; set; } 我最近更改了此选项,以抽象地址数据并对地址的某些属性进行验证(有关更多信息,请参阅my…) 在这些更改之后,我的属性如下: public string Address1 { get; set; } public str
public Address Address { get; set; }
我最近更改了此选项,以抽象地址数据并对地址的某些属性进行验证(有关更多信息,请参阅my…)
在这些更改之后,我的属性如下:
public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
// etc...
这弄坏了我的汽车制造商。基于对我另一个问题的回答,我决定使用AutoMapper的扁平化功能。我更改了属性名称,以符合Navigation_propertyProperty的命名约定:
public string AddressAddress1 { get; set; }
public string AddressAddress2 { get; set; }
public string AddressCity { get; set; }
// etc...
我修改了我的视图以使用这些新的属性名称,并且成功了!嗯,有点。如果我查看一家公司的详细信息,我可以看到它的地址。如果我删除一家公司,地址也会被成功删除。但是,在编辑时,会保存我更改的公司属性,但不会保存地址属性。如果我创建了一个新公司,那么它创建时没有地址
因此,似乎AutoMapper正在工作(它能够提取现有公司的地址),但更新没有进入数据库。。。如果我手动将视图模型属性映射到company.Address属性,它可以工作,但我不知道如何使用AutoMapper使其工作
我是否需要改变我在控制器中保存数据的方式,告诉上下文具体更新地址或其他什么
以下是我的控制器的编辑方法供参考:
public ActionResult Edit(int id = 0)
{
Company company = db.Companies
.Include(c => c.Address)
.Where(c => c.CompanyID == id)
.Single();
// Make sure we found something
if (company == null)
return HttpNotFound();
// Use AutoMapper to map model to viewmodel
CompanyViewModel viewModel = Mapper.Map<Company, CompanyViewModel>(company);
return View(viewModel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(CompanyViewModel viewModel)
{
if (ModelState.IsValid)
{
// Find appropriate record in DB
Company company = db.Companies
.Include(c => c.Address)
.Where(c => c.CompanyID == viewModel.CompanyID)
.Single();
// Map viewmodel data to company object
Mapper.Map<CompanyViewModel, Company>(viewModel, company);
// I've also tried the following without success:
// Mapper.Map(viewModel, company);
// company = Mapper.Map<CompanyViewModel, Company>(viewModel, company);
// Save and redirect to company list
db.SaveChanges();
return RedirectToAction("Index");
}
return View(viewModel);
}
公共操作结果编辑(int-id=0)
{
公司=数据库公司
.包括(c=>c.地址)
.其中(c=>c.CompanyID==id)
.Single();
//确保我们找到了什么
如果(公司==null)
返回HttpNotFound();
//使用AutoMapper将模型映射到viewmodel
CompanyViewModel viewModel=Mapper.Map(公司);
返回视图(viewModel);
}
[HttpPost]
[ValidateAntiForgeryToken]
公共操作结果编辑(公司视图模型视图模型)
{
if(ModelState.IsValid)
{
//在数据库中找到合适的记录
公司=数据库公司
.包括(c=>c.地址)
.Where(c=>c.CompanyID==viewModel.CompanyID)
.Single();
//将viewmodel数据映射到公司对象
Mapper.Map(viewModel,公司);
//我还尝试了以下方法,但没有成功:
//Mapper.Map(viewModel,公司);
//company=Mapper.Map(viewModel,company);
//保存并重定向到公司列表
db.SaveChanges();
返回操作(“索引”);
}
返回视图(viewModel);
}
感谢您的帮助。如前所述,我总是可以手动将视图模型映射到要更新/创建的对象(事实上,有些人会认为这通常是写入DB的更好做法),但我很好奇为什么映射只能在一个方向上工作……请告诉我您是否需要更多代码……老实说,我不确定,为什么这在某些场景下不起作用,现在你已经改变了一切,我不想告诉你全部撤销,但在这种情况下,定制地图通常更容易:
AutoMapper.Mapper.CreateMap<Company, CompanyViewModel>()
.ForMember(dest => dest.Address1, opts => opts.MapFrom(src => src.Address.Address1))
.ForMember(dest => dest.Address1, opts => opts.MapFrom(src => src.Address.Address1))
// etc.
.ForMember(dest => dest.Country, opts => opts.MapFrom(src => src.Address.Country));
AutoMapper.Mapper.CreateMap<CompanyViewModel, Company>()
.ForMember(dest => dest.Address, opts => opts.MapFrom(src => new Address
{
Address1 = src.Address1,
Address2 = src.Address2,
// etc.
}));
AutoMapper.Mapper.CreateMap()
.FormMember(dest=>dest.Address1,opts=>opts.MapFrom(src=>src.Address.Address1))
.FormMember(dest=>dest.Address1,opts=>opts.MapFrom(src=>src.Address.Address1))
//等等。
.ForMember(dest=>dest.Country,opts=>opts.MapFrom(src=>src.Address.Country));
AutoMapper.Mapper.CreateMap()
.ForMember(dest=>dest.Address,opts=>opts.MapFrom(src=>newaddress
{
Address1=src.Address1,
Address2=src.Address2,
//等等。
}));
这似乎很多,但您只需要为应用程序指定一次,然后就可以开始了。现在可能对你没有帮助,但将来…我不介意像这样定制地图(实际上可能更喜欢知道地图布局正确,而不是由AutoMapper“神奇地”决定),但我很好奇为什么我的更新不起作用!因此,对我先前问题的评论证实了这是正确的解决方案——显然,扁平化不会自动反向工作。我继续按照这里所示定义了我的地图,这让我1)有了更高的舒适度,事情将被正确地映射,2)摆脱了ViewModel中的时髦属性名称(Address1)。谢谢,+1!