对于使用局部视图动态添加的字段,始终会触发验证

时间:2017-09-19 17:11:21

标签: validation asp.net-mvc-5 asp.net-mvc-viewmodel

使用主视图和局部视图使用ModelViews动态地向其添加字段。问题是ModelState.isValid总是返回fall,因为部分视图中有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>

    }

ViewModels:

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

无法修复此问题。谢谢你的时间。

ManufacturerIDEnquiryID是模型中使用的FK关系,但我使用的ViewModel对于这些字段可以为空。

enter image description here

1 个答案:

答案 0 :(得分:1)

LineItems的{​​{1}}属性类型为EnquiryVM,但您为该集合显示的模型为List<EnquiryLineItem>,而不是EnquiryLineItemVM

我认为EnquiryLineItem是您的数据模型,并且基于图片中的EnquiryLineItem错误,ModelStateEnquiryId在该数据模型中都未标记为可为空。

更改ManufacturerId以使用EnquiryVM视图模型

EnquiryLineItemVM