locked
How To Display ModelState Error message in Validationsummary with Jquery AJAX call? RRS feed

  • Question

  • User-1042970710 posted

    If my model have validation errors on wrong input in the MVC form, it should be displayed in ValidationSummary without the web page being refreshed.

    I am not able to render model errors collection inside the ValidationSummary in   success: part of my AJAX call

    Can anyone help me?

    Here is my code:

    View

    @model TendersBI.Models.TendersTechEvalViewModel
    
    <div id="TechEvalScreen">
        <div class="uk-modal-dialog uk-modal-dialog-large" style=" top:100px;">
            <button type="button" class="uk-modal-close uk-close"></button>
            <div class="uk-width-large-1-1" style="width:auto">
    
                @using (Ajax.BeginForm("EditTechEvalInfo", "Evaluation", null, new AjaxOptions()
                {
                    HttpMethod = "Post",
                    InsertionMode = InsertionMode.ReplaceWith,
                    UpdateTargetId = "TechEvalScreen"
    
                }, new { @id = "updateoffer" }))
    
                {
    
                    @Html.AntiForgeryToken()
    
                    <h3 class="heading_a Azer-Regular">إضافة معلومات التقييم الفني للمناقصة</h3>
                    <div class="uk-grid" data-uk-grid-margin>
                        <div class="uk-width-medium-1-1">
                            <div class="uk-form-row">
                                <div class="uk-grid" data-uk-grid-margin>
    
                                    @Html.HiddenFor(model => model.TenderInfoID)
    
                                    <div class="uk-width-medium-1-1">
                                        <label>اسم المنافسة</label>
                                        @Html.EditorFor(model => model.TenderName, new { htmlAttributes = new { @class = "md-input", @readonly = "readonly" } })
                                    </div>
    
                                    <div class="uk-width-medium-1-1">
    
                                    </div>
    
    
                                    <div class="uk-width-medium-1-4">
                                    </div>
                                    <div class="uk-width-medium-1-4">
                                    </div>
                                    <div class="uk-width-medium-1-4">
                                    </div>
                                    <div class="uk-width-medium-1-4">
                                    </div>
    
                                    <div class="uk-width-medium-1-4">
                                        <label>تاريخ تشكيل اللجنة الفنية</label>
                                        @Html.EditorFor(model => model.TechCommitteFormationDate, new { htmlAttributes = new { @class = "md-input", data_uk_datepicker = "{format:'YYYY/MM/DD'}" } })
                                    </div>
                                    <div class="uk-width-medium-1-4">
                                        <label>رئيس اللجنة الفنية</label>
                                        @Html.DropDownListFor(model => model.ManagerID, Model.ManagerList, " الرجاء اختيار رئيس اللجنة ", new { @class = "md-input", @title = "يرجى اختيار من القائمة" })
                                    </div>
                                    <div class="uk-width-medium-1-4">
                                        <label>تاريخ رفع التقرير الفني</label>
                                        @Html.EditorFor(model => model.TechReportDate, new { htmlAttributes = new { @class = "md-input", data_uk_datepicker = "{format:'YYYY/MM/DD'}" } })
                                    </div>
    
                                    <div class="uk-width-medium-1-4">
                                    </div>
    
                                    <div class="uk-width-medium-1-4">
                                    </div>
                                    <div class="uk-width-medium-1-4">
                                    </div>
                                    <div class="uk-width-medium-1-4">
                                    </div>
                                    <div class="uk-width-medium-1-4">
                                    </div>
    
                                    <div class="uk-form-row"></div>
                                    <div class="uk-form-row"></div>
    
    
    
                                    <div class="uk-width-medium-1-1">
                                        <input type="submit" id="addorupdate" name="addedorupdate" class="md-btn" value="حفظ معلومات التقييم الفني" />
                                    </div>
    
                                    <div class="uk-form-row"></div>
                                    <div class="uk-form-row"></div>
                                    <div class="uk-form-row"></div>
    
    
                                    <div class="uk-width-medium-1-4">
    
                                    </div>
                                    <div class="uk-width-medium-1-4">
    
                                    </div>
                                    <div class="uk-width-medium-1-4">
    
                                    </div>
                                    <div class="uk-width-medium-1-4">
    
                                    </div>
    
                                    <div class="uk-form-row"></div>
    
    
                                    <div class="uk-width-medium-1-1">@Html.ValidationSummary(false, "", new { @class = "text-danger" })</div>
                                </div>
                            </div>
                        </div>
                    </div>
                }
            </div>
        </div>
    </div>
    <script>
                $(function () {
                    $("#addorupdate").click(function (e) {
                        e.preventDefault();
                            $.ajax(
                                {
                                    type: "POST",
                                    url: '@Url.Action("EditTechEvalInfo", "Evaluation")',
                                    data: $('#updateoffer').serialize(),               
                                    dataType: 'json',
                                    success: function (data) {
                                        if (data) {
                                            $('#TechEvalScreen').css("visibility", "hidden");
                                           window.location.href = '@Url.Action("Index", "Evaluation")';
                                        }
                                        else {
                                            $summaryUl = $(".text-danger").find("ul");
                                            $summaryUl.empty();
    
                                            $.each(data.errors,
                                                function (a, b) {
                                                    $summaryUl.append($("<li>").text(b));
                                                });
                                        }
                                    },
                                    error: function (xhr, textStatus, errorThrown) {
                                        alert(errorThrown);
                                    }
                                    });
                      
                    });
                });
    </script>
    
    
    
    
    
    
    

    Here is my controller:

     [HttpPost]
            public ActionResult EditTechEvalInfo(TendersTechEvalViewModel model)
            {
                if (ModelState.IsValid)
                {
                    TendersTechEvalModel tender = new TendersTechEvalModel()
                    {
                        TenderInfoID = model.TenderInfoID,
    
                         TechCommitteFormationDate = model.TechCommitteFormationDate,
                         ManagerID = model.ManagerID,
                         TechReportDate=model.TechReportDate
                    };
    
                    var tenderRecord = new TendersBI.BusinessObjects.TenderInfoBO();
                    tenderRecord.UpdateTechEvalInfo(tender);
                    return Json(new { data = true });
                }
    
                model.ManagerList = new TendersBI.BusinessObjects.ManagerBO().GetAll()
                              .Select(i => new SelectListItem()
                              {
                                  Text = i.ManagerName,
                                  Value = i.ManagerID.ToString()
                              }).ToList();
    
                // return PartialView("EditTechEvalInfo", model);
                return Json(new { data = false, issue = model, errors = ModelState.Values.Where(i => i.Errors.Count > 0) });
            }
        }

    Here is my model:

    public class TendersTechEvalViewModel : IValidatableObject
        {
            public int TenderInfoID { get; set; }
            public string TenderName { get; set; }
    
    
            [DisplayFormat(DataFormatString = "{0:yyyy/MM/dd}")]
            [Required(ErrorMessage = "من فضلك أدخل تاريخ تشكيل اللجنة الفنيةض")]
    
            public Nullable<System.DateTime> TechCommitteFormationDate { get; set; }
    
            [Required(ErrorMessage = "يرجى تحديد رئيس اللجنة الفنية")]
            public int ManagerID { get; set; }
            public List<SelectListItem> ManagerList { get; set; }
    
            public List<TendersTechEvalModel> TechEvalList { get; set; }
    
            [DisplayFormat(DataFormatString = "{0:yyyy/MM/dd}")]
            [Required(ErrorMessage = "تاريخ رفع التقرير الفني")]
            public Nullable<System.DateTime> TechReportDate { get; set; }
    
            public double NoOfDays { get; set; }
    
            IEnumerable<ValidationResult> IValidatableObject.Validate(ValidationContext validationContext)
            {
                //DateTime BondOpeningDate = DateTime.ParseExact(TechCommitteFormationDate, "yyyy/mm/dd", CultureInfo.InvariantCulture);
                List<ValidationResult> res = new List<ValidationResult>();
                if (TechReportDate < TechCommitteFormationDate)
                {
                    ValidationResult mss = new ValidationResult("تاريخ رفع التقرير الفني يجب ان لا يكون قبل تاريخ تشكيل اللجنة الفنية");
                    res.Add(mss);
    
                }
    
                return res;
            }
        }

    Friday, January 24, 2020 6:21 PM

All replies

  • User475983607 posted

    There are several issues with the design.  Think about the logic for a moment... if the response data is empty then there is no way to select $(".text-danger").find("ul");

    if (data) {
    	$('#TechEvalScreen').css("visibility", "hidden");
       window.location.href = '@Url.Action("Index", "Evaluation")';
    }
    else {
    	$summaryUl = $(".text-danger").find("ul");
    	$summaryUl.empty();
    
    	$.each(data.errors,
    		function (a, b) {
    			$summaryUl.append($("<li>").text(b));
    		});
    }

    The ValidationSummer helper runs on the server in a View.   If there is a validation error, the AJAX function should update the DOM with a partial view response from the action method.  You must write code in the handler that updates the current page - the DOM.

    You've implemented an AJAX Form and an AJAX function.  The AJAX form is a better options as it is designed to work with the ValidationSummary.  Regardless, use The AJAX Form or the AJAX function not both.

    Back to the AJAX success handler.  The handler does a full page refresh when the AJAX POST is successful.  This is contradictory to your requirement.  You might as well do a full POST since you are refreshing the browser anyway.  This will simplify your code.

    Friday, January 24, 2020 7:06 PM
  • User-1042970710 posted

    Thank you very much  for your suggestions.

    Let me explain you the partial view loads and ask user to EDIT/ADD data what I am trying to achieve  is if there is a error in my model it should keep the model open until the data get fixed by the user. On successful post I am simply calling the refresh page becuase I want to update the grid to reflect the changes made by the user.  This is the only reason I want to refresh.  On Error I want the Model form to keep open Until User fix the errors.  

    Friday, January 24, 2020 8:38 PM
  • User475983607 posted

    jalali

    Thank you very much  for your suggestions.

    Let me explain you the partial view loads and ask user to EDIT/ADD data what I am trying to achieve  is if there is a error in my model it should keep the model open until the data get fixed by the user. On successful post I am simply calling the refresh page becuase I want to update the grid to reflect the changes made by the user.  This is the only reason I want to refresh.  On Error I want the Model form to keep open Until User fix the errors.  

    Your design is overly complex. Render everything the page needs to function, the modal, and data.  The modal inputs will be empty at this point.  I assume you have a list of records the user can edit.  Use Bootstrap recommendation for populating a modal from a button click using data- attributes.  Your edit buttons will have data- attribute that reflect the record.

    https://getbootstrap.com/docs/4.0/components/modal/#varying-modal-content

    The user clicks the edit button, the modal open, the JavaScript (from Bootstrap) will populate the modal form fields.  The user makes edits and clicks the submit button.  The client side validation will catch any validation errors.  If all is good, the form will POST and the response shows an updated grid.  This approach should catch most user entry validation.  If there is a model error on the server then simply return the View along with a little JavaScript to open the modal.  Very simple.

    Friday, January 24, 2020 9:18 PM