始终对使用局部视图动态添加的字段触发验证
Validation always fired for fields dynamically added with partial view
使用主视图和局部视图通过 ModelViews 动态添加字段。问题是 ModelState.isValid 总是 returns 下降,因为部分视图中有 2 个字段未通过验证。这些字段并非强制性的,因此我已将其设为可为空,但这些字段仍在验证中。如何克服这种情况?
代码:
查看主要内容:
@model ViewModel.EnquiryVM
@using (Html.BeginForm("Create", "Enquiries", FormMethod.Post))
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.EnquiryNumber, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-3">
@Html.EditorFor(model => model.EnquiryNumber, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.EnquiryNumber, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.ClientID, "Client", htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-3">
@Html.DropDownListFor(u => u.ClientID, (IEnumerable<SelectListItem>)Model.Clients, "--Select--")
@Html.ValidationMessageFor(model => model.ClientID, "", new { @class = "text-danger" })
</div>
</div>
<div id="LineItems">
<div id="editorRowsLineitems">
@foreach (var item in Model.LineItems)
{
@Html.Partial("_CreateEnquiryItem", item)
}
</div>
@Html.ActionLink("Add Items", "CreateLineItem", null, new { id = "addItem", @class = "button" });
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
<script type="text/javascript">
$(function () {
$('#addItem').on('click', function () {
$.ajax({
url: '@Url.Action("CreateLineItem")',
cache: false,
success: function (html) {
$("#editorRowsLineitems").append(html);
$('form').data('validator', null);
$.validator.unobtrusive.parse($('form'));
}
});
return false;
});
$('#editorRowsLineitems').on('click', '.deleteRow', function () {
$(this).closest('.editorRow').remove();
});
$('form').data('validator', null);
$.validator.unobtrusive.parse($('form'));
});
</script>
}
局部视图:
@model ViewModels.EnquiryLineItemVM
<div class="editorRow">
@using (Html.BeginCollectionItem("LineItems"))
{
<table class="table">
<tr>
<td>
@Html.EditorFor(model => model.ItemDesc)
</td>
<td>
@Html.EditorFor(model => model.Quantity)
</td>
<td>
@Html.DropDownListFor(model => model.ManufacturerId, Model.ManufacturerList, "--Please Select--")
</td>
<td>
<a href="#" class="deleteRow">Delete</a>
</td>
</tr>
</table>
}
视图模型:
public class EnquiryVM
{
public int ID { get; set; }
[Required]
public string EnquiryNumber { get; set; }
public int ClientID { get; set; }
public IEnumerable<SelectListItem> Clients { get; set; }
public int ItemID { get; set; }
public List<EnquiryLineItem> LineItems { get; set; }
}
public class EnquiryLineItemVM
{
public int? EnquiryID { get; set; } //nullable but still validation fires
[Required]
public string ItemDesc { get; set; }
public int Quantity { get; set; }
public int? ManufacturerId { get; set; } // this too fires
public IEnumerable<SelectListItem> ManufacturerList { get; set; }
}
控制器操作方法
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create( EnquiryVM enquiryVM)
{
var errors = ModelState.Keys.Where(k => ModelState[k].Errors.Count > 0).Select(k => new { propertyName = k, errorMessage = ModelState[k].Errors[0].ErrorMessage });// for error debugging shows Validation errors for EnquiryID and ManufacturerID
var enquiry = new Enquiry();
enquiry.EnquiryNumber = enquiryVM.EnquiryNumber;
enquiry.ClosingDate = enquiryVM.ClosingDate;
enquiry.RFQSentDate = enquiryVM.RFQSentDate;
enquiry.ClientID = enquiryVM.ClientID;
enquiry.DivisionID = enquiryVM.DivisionID;
enquiry.EnquiryLineItems = enquiryVM.LineItems;
if (ModelState.IsValid)
{
db.Enquiries.Add(enquiry);
enquiryVM.ID = enquiry.ID;
foreach (var item in enquiry.EnquiryLineItems)
{
if (enquiryVM.ID != null)
{
item.EnquiryID = (int)enquiryVM.ID;
}
db.EnquiryLineItems.Add(item);
}
db.SaveChanges();
return RedirectToAction("Index");
}
var viewModel = GetAllCategories();
return View(viewModel);
}
无法解决这个问题。谢谢你的时间。
ManufacturerID
和 EnquiryID
是 Model 中使用的 FK 关系,但我使用的是对这些字段可为空的 ViewModels。
EnquiryVM
的 LineItems
属性 是 typeof List<EnquiryLineItem>
但您为该系列显示的模型是 EnquiryLineItemVM
,而不是 EnquiryLineItem
.
我假设 EnquiryLineItem
是您的数据模型,并且基于图像中的 ModelState
错误,EnquiryId
和 ManufacturerId
在该数据中均未标记为可为空型号。
更改您的 EnquiryVM
以使用您的 EnquiryLineItemVM
视图模型
public class EnquiryVM
{
public int ID { get; set; }
[Required]
public string EnquiryNumber { get; set; }
....
public List<EnquiryLineItemVM> LineItems { get; set; } // change
}
public class EnquiryLineItemVM
{
....
}
使用主视图和局部视图通过 ModelViews 动态添加字段。问题是 ModelState.isValid 总是 returns 下降,因为部分视图中有 2 个字段未通过验证。这些字段并非强制性的,因此我已将其设为可为空,但这些字段仍在验证中。如何克服这种情况?
代码: 查看主要内容:
@model ViewModel.EnquiryVM
@using (Html.BeginForm("Create", "Enquiries", FormMethod.Post))
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.EnquiryNumber, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-3">
@Html.EditorFor(model => model.EnquiryNumber, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.EnquiryNumber, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.ClientID, "Client", htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-3">
@Html.DropDownListFor(u => u.ClientID, (IEnumerable<SelectListItem>)Model.Clients, "--Select--")
@Html.ValidationMessageFor(model => model.ClientID, "", new { @class = "text-danger" })
</div>
</div>
<div id="LineItems">
<div id="editorRowsLineitems">
@foreach (var item in Model.LineItems)
{
@Html.Partial("_CreateEnquiryItem", item)
}
</div>
@Html.ActionLink("Add Items", "CreateLineItem", null, new { id = "addItem", @class = "button" });
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
<script type="text/javascript">
$(function () {
$('#addItem').on('click', function () {
$.ajax({
url: '@Url.Action("CreateLineItem")',
cache: false,
success: function (html) {
$("#editorRowsLineitems").append(html);
$('form').data('validator', null);
$.validator.unobtrusive.parse($('form'));
}
});
return false;
});
$('#editorRowsLineitems').on('click', '.deleteRow', function () {
$(this).closest('.editorRow').remove();
});
$('form').data('validator', null);
$.validator.unobtrusive.parse($('form'));
});
</script>
}
局部视图:
@model ViewModels.EnquiryLineItemVM
<div class="editorRow">
@using (Html.BeginCollectionItem("LineItems"))
{
<table class="table">
<tr>
<td>
@Html.EditorFor(model => model.ItemDesc)
</td>
<td>
@Html.EditorFor(model => model.Quantity)
</td>
<td>
@Html.DropDownListFor(model => model.ManufacturerId, Model.ManufacturerList, "--Please Select--")
</td>
<td>
<a href="#" class="deleteRow">Delete</a>
</td>
</tr>
</table>
}
视图模型:
public class EnquiryVM
{
public int ID { get; set; }
[Required]
public string EnquiryNumber { get; set; }
public int ClientID { get; set; }
public IEnumerable<SelectListItem> Clients { get; set; }
public int ItemID { get; set; }
public List<EnquiryLineItem> LineItems { get; set; }
}
public class EnquiryLineItemVM
{
public int? EnquiryID { get; set; } //nullable but still validation fires
[Required]
public string ItemDesc { get; set; }
public int Quantity { get; set; }
public int? ManufacturerId { get; set; } // this too fires
public IEnumerable<SelectListItem> ManufacturerList { get; set; }
}
控制器操作方法
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create( EnquiryVM enquiryVM)
{
var errors = ModelState.Keys.Where(k => ModelState[k].Errors.Count > 0).Select(k => new { propertyName = k, errorMessage = ModelState[k].Errors[0].ErrorMessage });// for error debugging shows Validation errors for EnquiryID and ManufacturerID
var enquiry = new Enquiry();
enquiry.EnquiryNumber = enquiryVM.EnquiryNumber;
enquiry.ClosingDate = enquiryVM.ClosingDate;
enquiry.RFQSentDate = enquiryVM.RFQSentDate;
enquiry.ClientID = enquiryVM.ClientID;
enquiry.DivisionID = enquiryVM.DivisionID;
enquiry.EnquiryLineItems = enquiryVM.LineItems;
if (ModelState.IsValid)
{
db.Enquiries.Add(enquiry);
enquiryVM.ID = enquiry.ID;
foreach (var item in enquiry.EnquiryLineItems)
{
if (enquiryVM.ID != null)
{
item.EnquiryID = (int)enquiryVM.ID;
}
db.EnquiryLineItems.Add(item);
}
db.SaveChanges();
return RedirectToAction("Index");
}
var viewModel = GetAllCategories();
return View(viewModel);
}
无法解决这个问题。谢谢你的时间。
ManufacturerID
和 EnquiryID
是 Model 中使用的 FK 关系,但我使用的是对这些字段可为空的 ViewModels。
EnquiryVM
的 LineItems
属性 是 typeof List<EnquiryLineItem>
但您为该系列显示的模型是 EnquiryLineItemVM
,而不是 EnquiryLineItem
.
我假设 EnquiryLineItem
是您的数据模型,并且基于图像中的 ModelState
错误,EnquiryId
和 ManufacturerId
在该数据中均未标记为可为空型号。
更改您的 EnquiryVM
以使用您的 EnquiryLineItemVM
视图模型
public class EnquiryVM
{
public int ID { get; set; }
[Required]
public string EnquiryNumber { get; set; }
....
public List<EnquiryLineItemVM> LineItems { get; set; } // change
}
public class EnquiryLineItemVM
{
....
}