发布时保留未绑定的viewmodel数据

时间:2016-11-22 11:39:50

标签: c# asp.net-mvc entity-framework

我目前正处于习惯于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的观点?

1 个答案:

答案 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);
}

其他评论

  1. 请勿使用TryUpdateModel。它并不意味着像你在这里一样使用。正确的方法是映射视图模型中的已发布值。您可以手动执行此操作,也可以使用AutoMapper之类的库。无论哪种方式,你都不希望在你正在做的事情的基础上,根据原始发布的数据不断覆盖数据库实体上的任何内容。

  2. 您永远不应发布您正在编辑的实体的ID,而应依赖于通过路由参数从URL获取它。如果将URL更改为其他ID,您实际上是在编辑其他内容,并且可以添加对象级权限等,以控制谁可以编辑内容。但是,可以操纵发布的ID,如果您不小心(因为您不在这里),那么用户可以篡改ID以弄乱他们可能不应该编辑的对象。