我有一个db模型,我想用多个视图编辑它。我的实际数据库模型比我在这里显示的要大得多。
Db模型: PersonModel
public class PersonModel {
public Int32 Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Description { get; set; }
}
然后我有两个视图, EditPersonName.cshtml 和 EditPersonDescription.cshtml ,使用户能够修改 PersonModel 的不同部分。
查看1: EditPersonName.cshtml
@model EditPersonNameModel
@using (Html.BeginForm()) {
<div class="editor-label">@Html.LabelFor(m => m.FirstName)</div>
<div class="editor-field">@Html.TextBoxFor(m => m.FirstName)</div>
<div class="editor-label">@Html.LabelFor(m => m.LastName)</div>
<div class="editor-field">@Html.TextBoxFor(m => m.LastName)</div>
<input type="submit" value="Save" />
}
查看2: EditPersonDescription.cshtml
@model EditPersonDescriptionModel
@using (Html.BeginForm()) {
<div class="editor-label">@Html.LabelFor(m => m.Description)</div>
<div class="editor-field">@Html.TextBoxFor(m => m.Description)</div>
<input type="submit" value="Save" />
}
我不想将每个视图直接绑定到 PersonModel ,而是希望将它们分别链接到 EditPersonNameModel 和 EditPersonDescriptionModel 。
查看模型1: EditPersonNameModel
public class EditPersonNameModel {
public string FirstName { get; set; }
public string LastName { get; set; }
}
查看模型2: EditPersonDescriptionModel
public class EditPersonDescriptionModel {
public string Description { get; set; }
}
我想还值得一提的是我正在使用EF的 DbContext 模式。
public class PersonDbContext : DbContext {
public DbSet<PersonModel> Persons { get; set; }
}
现在为我的控制器,这是事情开始破裂的地方!
控制器: PersonController
public class PersonController {
private PersonDbContext = new PersonDbContext();
[HttpGet]
public ActionResult EditName(int id) {
// ??? ---- #1 -----
}
[HttpPost]
public ActionResult EditName(EditPersonNameModel model, int id) {
if (ModelState.IsValid) {
// ??? ---- #2 ----- ??? Update FirstName,LastName ONLY
db.SaveChanges();
return RedirectToAction("Index");
}
return View(model);
}
[HttpGet]
public ActionResult EditDescription(int id) {
// ??? ---- #3 -----
}
[HttpPost]
public ActionResult EditDescription(EditPersonDescriptionModel model, int id) {
if (ModelState.IsValid) {
// ??? ---- #4 ----- ??? Update Description ONLY
db.SaveChanges();
return RedirectToAction("Index");
}
return View(model);
}
}
我的问题是我不知道在上面的??? ---- #X -----
区块放什么。显然,#1
和#3
与#2
和#4
非常相似。
有些人建议我使用AutoMapper。这有助于从Db模型到视图模型,但不是相反。
目前,#1
的代码块如下所示:
[HttpGet]
public ActionResult EditName(int id) {
PersonModel person = db.Persons.Find(id);
if (person == null) {
return HttpNotFound();
}
EditPersonNameModel viewModel;
AutoMapper.Mapper.CreateMap<PersonModel, EditPersonNameModel>();
viewModel = AutoMapper.Mapper.Map<PersonModel, EditPersonNameModel>(person);
return View(viewModel);
}
#2
的代码块如下所示:
[HttpPost]
public ActionResult EditName(EditPersonNameModel viewModel, int id) {
if (ModelState.IsValid) {
PersonModel person = db.Persons.Find(id);
if (person == null) {
return HttpNotFound();
}
EditPersonNameModel viewModel;
AutoMapper.Mapper.CreateMap<EditPersonNameModel, PersonModel>();
person = AutoMapper.Mapper.Map<EditPersonNameModel, PersonModel>(viewModel);
db.Entry(person).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(viewModel);
}
上面的 #1
实际上工作正常。 AutoMapper将从较大的Person对象映射到EditPersonName对象。
#2
已被打破。 AutoMapper将从EditPersonNameModel对象映射到一个新的 Person对象,因此db.Entry(person).State = EntityState.Modified
将抛出异常:
ObjectStateManager中已存在具有相同键的对象。 ObjectStateManager无法使用相同的键跟踪多个对象。
我不需要AutoMapper来创建新对象,我需要映射到现有对象。如果只有AutoMapper.Mapper.
更新 <EditPersonNameModel, PersonModel>(viewModel, person)
。
好的,所以这是一个非常长的问题!感谢您的阅读,我非常感谢您的帮助!如果您熟悉AutoMapper并且知道我做错了什么,请告诉我。如果您阅读此代码并了解完全相同的方法,请告诉我们!
谢谢!!!
更新1
我有#2
工作,但我不确定它有多好。
新#2
[HttpPost]
public ActionResult EditName(EditPersonNameModel viewModel, int id) {
if (ModelState.IsValid) {
PersonModel person = db.Persons.Find(id);
if (person == null) {
return HttpNotFound();
}
TryUpdateModel(person);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(viewModel);
}
请注意TryUpdateModel
而不是person
会调用viewModel
。我已经从数据库中获取了person
,所以它已完全填写,带有Id。 TryModelUpdate
方法使用IModelBinder
将当前“mvc请求上下文”中的属性映射到指定对象。由于我的PersonModel
和EditPersonNameModel
使用相同的命名属性,因此可以使用。这真是一个非常糟糕的解决方案,所以如果你知道更好的东西,请告诉我!