我目前正处于习惯于MVC的过程中,来自ASP.Net。
到目前为止,我已经找到了实现我想做的事情的方法,但是有了这个,我得到了一个"这不是最简单的方法"时刻。
情境: 我正在将引用应用程序迁移到具有现有数据库的MVC,因此我的模型类是自动生成的。我为每个需要向用户显示数据的控制器动作创建了一个viewmodel类。
编辑报价viewmodel如下所示:
public class QuoteEdit_ViewModel
{
public SelectList DelLocations { get; set; }
public int QuoteID { get; set; }
public string QuoteNo { get; set; }
public string EnquiryNo { get; set; }
public string SalesPerson { get; set; }
public string Exceptions { get; set; }
public string CreatedBy { get; set; }
public string ModifiedBy { get; set; }
[Required]
[Display(Name = "Equipment Overview")]
public string EquipmentOverview { get; set; }
public DateTime Created { get; set; }
public DateTime Modified { get; set; }
[Required]
public int? Validity { get; set; }
[Required]
[Display(Name = "Minimum Delivery Weeks")]
public int? DeliveryMin { get; set; }
[Required]
[Display(Name = "Maximum Delivery Weeks")]
public int? DeliveryMax { get; set; }
[Required]
[Display(Name = "Delivery Location")]
public int? DelLocationID { get; set; }
public List<Constants.QPT> PackTypes { get; set; }
public List<Constants.QE> Equipments { get; set; }
public List<Constants.QEEx> Extras { get; set; }
}
底部的列表包含设备线等,它们是数据库中的连接表。
目前我可以对此进行编辑并将数据发布回数据库,并且运行正常。
看起来很乱的部分如下,特别是if:
之后的部分 public ActionResult Save(QuoteEdit_ViewModel VM)
{
Quote a = DAL.DB.Quotes.Where(x => x.QuoteID == VM.QuoteID).Single();
TryUpdateModel(a);
if (ModelState.IsValid)
{
DAL.DB.SaveChanges();
return RedirectToAction("Dashboard", "Home");
}
VM.DelLocations = DAL.GetDeliveryLocationDropdown();
var QData = DAL.GetQuoteEditVM(VM.QuoteID);
VM.QuoteNo = QData.QuoteNo;
VM.EnquiryNo = QData.EnquiryNo;
VM.SalesPerson = QData.SalesPerson;
VM.PackTypes = QData.PackTypes;
VM.Equipments = QData.Equipments;
VM.Extras = QData.Extras;
VM.Created = QData.Created;
VM.CreatedBy = QData.CreatedBy;
VM.Modified = QData.Modified;
VM.ModifiedBy = QData.ModifiedBy;
return View("Edit", VM);
}
目前我需要重新加载整个viewmodel并重新填充未在视图中绑定的任何字段,因为它们的值在POST期间丢失。
我在其他帖子中读过你可以使用hiddenfor,但是这也可以用于列表吗?
这也是解决这个问题的正确方法,还是我完全忽略了MVC的观点?
答案 0 :(得分:0)
请勿使用HiddenFor
。你正在寻找正确的方法。我要做的唯一改变是将您的公共代码分解为GET和POST操作都可以使用的另一种方法。
private void PopulateQuoteEditViewModel(QuoteEdit_ViewModel model)
{
mode.DelLocations = DAL.GetDeliveryLocationDropdown();
var QData = DAL.GetQuoteEditVM(model.QuoteID);
model.QuoteNo = QData.QuoteNo;
model.EnquiryNo = QData.EnquiryNo;
model.SalesPerson = QData.SalesPerson;
model.PackTypes = QData.PackTypes;
model.Equipments = QData.Equipments;
model.Extras = QData.Extras;
model.Created = QData.Created;
model.CreatedBy = QData.CreatedBy;
model.Modified = QData.Modified;
model.ModifiedBy = QData.ModifiedBy;
}
然后:
public ActionResult QuoteEdit()
{
var model = new QuoteEdit_ViewModel();
PopulateQuoteEditViewModel(model);
return View(model);
}
[HttpPost]
public ActionResult QuoteEdit(QuoteEdit_ViewModel model)
{
if (ModelState.IsValid)
{
...
}
PopulateQuoteEditViewModel(model);
return View(model);
}
其他评论
请勿使用TryUpdateModel
。它并不意味着像你在这里一样使用。正确的方法是映射视图模型中的已发布值。您可以手动执行此操作,也可以使用AutoMapper之类的库。无论哪种方式,你都不希望在你正在做的事情的基础上,根据原始发布的数据不断覆盖数据库实体上的任何内容。
您永远不应发布您正在编辑的实体的ID,而应依赖于通过路由参数从URL获取它。如果将URL更改为其他ID,您实际上是在编辑其他内容,并且可以添加对象级权限等,以控制谁可以编辑内容。但是,可以操纵发布的ID,如果您不小心(因为您不在这里),那么用户可以篡改ID以弄乱他们可能不应该编辑的对象。