在ViewModel上进行表单验证
我有一个窗体,它有一个ViewModel类。 我已经在窗体的字段上设置了[必需的]验证。 表单仍然提交,即使它提交 - 在提交之前 - 显示在特定字段上设置的ErrorMessage。
StockReceipt模型本身没有验证,但只有ViewModel。 我在这里看到了这个问题,并得知验证模型是可选的。
我想知道为什么当输入无效时表单仍然提交?
这是我的View和ViewModel代码:
视图:
@using (Html.BeginForm("SaveSettings", "StockReceipt", FormMethod.Post,
    new { id = "StockReceiptForm", enctype = "multipart/form-data" }))
{
    <fieldset>
        <div>
            @* @Html.ValidationSummary(false)*@
            <legend>Stock-Receipt Details</legend>
            @*@if (User.IsInRole(Constants.Super))
                {*@
            <div style="display: none;">
                Delivery Note Ref
            </div>
            <div style="display: none;">
                @Html.TextBoxFor(model => model.StockReceiptID, new { @Class = "k-textbox" })
            </div>
            <div class="editor-label">
                Supplier
            </div>
            <div class="editor-field">
                @Html.Kendo().DropDownListFor(model => model.SupplierID).BindTo(Model.SuppliersList).DataTextField("Name").DataValueField("SupplierID").OptionLabel("Select")
                @Html.ValidationMessageFor(model => model.SupplierID)
            </div>
            <div class="editor-label">
                Material
            </div>
            <div class="editor-field">
                @Html.Kendo().DropDownListFor(model => model.MaterialID).BindTo(Model.MaterialsList).DataTextField("Name").DataValueField("MaterialID").OptionLabel("Select")
                @Html.ValidationMessageFor(model => model.MaterialID)
            </div>
            <div class="editor-label">
                Qty
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(model => model.Quantity, new { @Class = "k-textbox" })
                @Html.ValidationMessageFor(model => model.Quantity)
            </div>
            <div class="editor-label">
                Of which reserved
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(model => model.QuantityReserved, new { @Class = "k-textbox" })
            </div>
            <div class="editor-label">
                Units
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(model => model.NumberOfUnits, new { @Class = "k-textbox" })
                @(Html.Kendo().DropDownListFor(model => model.StockUnitsEnum).Name("StockUnitsEnum")
              .BindTo(Enum.GetValues(typeof(StockUnitsEnum))
                  .Cast<StockUnitsEnum>()
                  .Select(p => new SelectListItem
                  {
                      Text = p.ToString(),
                      Value = ((int)p).ToString(CultureInfo.InvariantCulture)
                  })
                  .ToList())
                )
                @Html.ValidationMessageFor(model => model.NumberOfUnits)
            </div>
            <div class="editor-label">
                Batch Reference:
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(model => model.BatchReference, new { @Class = "k-textbox" })
                @Html.ValidationMessageFor(model => model.BatchReference)
            </div>
            <div class="editor-label">
                Slab Width
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(model => model.SlabWidth, new { @Class = "k-textbox" }) x @Html.TextBoxFor(model => model.SlabHeight, new { @Class = "k-textbox" })
            </div>
            <div class="editor-label">
                Include Transport:
            </div>
            <div class="editor-field">
                @Html.CheckBoxFor(model => model.IncludeTransport)
            </div>
            <div class="editor-label">
                Notes
            </div>
            <div class="editor-field">
                @Html.TextAreaFor(model => model.Notes, new { @Class = "k-textbox" })
            </div>
            <div class="clear">
                Totals
            </div>
            <div class="editor-label">
                Unit Cost
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(model => model.UnitCost, new { @Class = "k-textbox" })
                @Html.ValidationMessageFor(model => model.UnitCost)
            </div>
            <div class="editor-label">
                Units
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(model => model.NumberOfUnits, new { @Class = "k-textbox" })
                @Html.ValidationMessageFor(model => model.NumberOfUnits)
            </div>
            <div class="editor-label">
                Slab Cost
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(model => model.SlabCost, new { @Class = "k-textbox" })
                @Html.ValidationMessageFor(model => model.SlabCost)
            </div>
            <div class="editor-label">
                Location
            </div>
            <div class="editor-field">
                @Html.Kendo().DropDownListFor(model => model.LocationID).BindTo(Model.LocationsList).DataTextField("Name").DataValueField("LocationID").OptionLabel("Select")
            </div>
            <div class="editor-label">
                Purchase-Order Ref.
            </div>
            <div class="editor-field">
                @Html.Kendo().DropDownListFor(model => model.PurchaseOrderID).BindTo(Model.PurchaseOrdersList).DataTextField("PONumber").DataValueField("PurchaseOrderID").OptionLabel("Select")
                @Html.ValidationMessageFor(model => model.PurchaseOrdersList)
            </div>
            <div class="editor-label">
                Invoice Ref.
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(model => model.InvoicNo, new { @Class = "k-textbox" })
                @Html.ValidationMessageFor(model => model.InvoicNo)
            </div>
            <br />
            <div class="editor-label">
            </div>
            <div class="editor-field">
                <input type="submit" value="Save" class="k-button" />
            </div>
        </div>
    </fieldset>
}
视图模型:
public class StockReceiptViewModel
{
    public int StockReceiptID { get; set; }
    [Required(ErrorMessage = "Required")]
    public int SupplierID { get; set; }
    [Required(ErrorMessage = "Required")]
    public int MaterialID { get; set; }
    [Required(ErrorMessage = "Required")]
    public DateTime? ReceiptDate { get; set; }
    [Required(ErrorMessage = "Required")]
    public int Quantity { get; set; }
    public int? QuantityReserved { get; set; }
    [Required(ErrorMessage = "Required")]
    public decimal? SlabWidth { get; set; }
    [Required(ErrorMessage = "Required")]
    public decimal? SlabHeight { get; set; }
    [Required(ErrorMessage = "Required")]
    public int SizeUnits { get; set; }
    [Required(ErrorMessage = "Required")]
    public StockUnitsEnum StockUnitsEnum
    {
        get {return (StockUnitsEnum)SizeUnits;}
        set {SizeUnits = (int)value;}
    }
    [Required(ErrorMessage = "Required")]
    public string BatchReference { get; set; }
    [Required(ErrorMessage = "Required")]
    [DataType(DataType.Currency)]
    public decimal? UnitCost { get; set; }
    [Required(ErrorMessage = "Required")]
    public int? NumberOfUnits { get; set; }
    [Required(ErrorMessage = "Required.")]
    public int PurchaseOrderID { get; set; }
    [Required(ErrorMessage = "Required")]
    public string InvoicNo { get; set; }
    [Required(ErrorMessage = "Required")]
    public decimal SlabCost { get; set; }
    public bool IncludeTransport { get; set; }
    [Required(ErrorMessage = "Required.")]
    public int LocationID { get; set; }
    public int? EnteredBy { get; set; }
    public DateTime OnSystemFrom { get; set; }
    public string Notes { get; set; }
    public List<SupplierViewModel> SuppliersList { get; set; }
    public List<MaterialViewModel> MaterialsList { get; set; }
    public List<LocationsViewModel> LocationsList { get; set; }
    public List<PurchaseOrderViewModel>  PurchaseOrdersList { get; set; }
    public int LastModifiedBy { get; set; }
    public DateTime LastModifiedDate { get; set; }
    public int LiveQuantity { get; set; }
}
Controller方法也具有ModelState.Isvalid检查。
如果可以的话请帮忙。
非常感谢。
您需要将jquery.unobtrusive和jquery.validate文件添加到您的视图。 将此添加到您的BundleConfig.cs中:
bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
                        "~/Scripts/jquery.unobtrusive*",
                        "~/Scripts/jquery.validate*"));
然后在你的_Layout视图或视图中渲染它,你需要验证:
@Scripts.Render("~/bundles/jqueryval")
如果你正在使用默认的MVC模板,你应该已经有了这个包。 只要确保你在视图中有参考。 您可以使用Mozzila中的Firebug等Web开发工具加载js文件,或者在Chrome中按F12键,然后在NET选项卡中查看加载的脚本。
我已经通过确保提交表单的方法解决了这个问题,如果ModelState.IsValid为false,则返回viewmodel到页面(视图)。
这提供了返回的viewModel实际上与提交的相同:
   [HttpPost]
    public ActionResult SaveSettings(StockReceiptViewModel stockReceiptVm)
    {
        try
        {
            if (ModelState.IsValid)
            {
                var stockReceipt = new StockReceipt();
                if (stockReceiptVm.StockReceiptID != 0)
                {
                        MapViewModelToModel(stockReceiptVm, stockReceipt);
                        stockReceipt.LastModifiedBy = UserHelper.GetCurrentUserIDByEmail();
                        stockReceipt.LastModifiedDate = DateTime.Now;
                        //update
                        _stockReceiptRepository.UpdateStockReceipt(stockReceipt, stockReceiptVm.StockReceiptID);                        
                }
                else
                {
                        MapViewModelToModel(stockReceiptVm, stockReceipt);
                        stockReceipt.EnteredBy = UserHelper.GetCurrentUserIDByEmail();
                        stockReceipt.OnSystemFrom = Utilities.RemoveTimeFromDate(DateTime.Now);
                            //save new
                        _stockReceiptRepository.InsertStockReceipt(stockReceipt);
                    }
                    return RedirectToAction("Index", "StockReceiptsGrid");                    
            }
            SetupViewDropdownLists(stockReceiptVm);
            return View("Index", stockReceiptVm);
        }
        catch (Exception exc)
        {
            ErrorHelper.WriteToEventLog(exc);
            return RedirectToAction("Index", "Error");
        }
    }
上一篇: Forms Validation on the ViewModel
下一篇: DropDownListFor Unobtrusive Validation Required Not getting correct attributes
