ron
ron

Reputation: 625

Ajax.BeginForm and validation

Client side validation is not working for me in Ajax.BeginForm

This is my code:

<div id="report">
    <div id="projectReport">
        <div >
            @{
                Html.EnableClientValidation();
            }

            @using (Ajax.BeginForm("AnalyticsDates", new AjaxOptions
                {
                    InsertionMode = InsertionMode.Replace,
                    UpdateTargetId = "reportContent"
                }))
            {
                @Html.LabelFor(m => m.StartDate)
                @Html.TextBoxFor(m => m.StartDate, new { id = "start" })
                @Html.ValidationMessageFor(model => model.StartDate)
                @Html.LabelFor(m => m.EndDate)
                @Html.TextBoxFor(m => m.EndDate, new { id = "end" })
                @Html.ValidationMessageFor(model => model.EndDate)
                <input id="btnsearch" type="submit" [email protected] class="iconHeader"/>
            }
        </div>
    </div>
    <div id="reportContent">
    </div>
</div>

And I enabled validation in the web.config page:

<add key="ClientValidationEnabled" value="true" />   
<add key="UnobtrusiveJavaScriptEnabled" value="true" />

and added js files as well

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>

second issue related to the first one, my action is

[HttpPost]
        [Authorize(Roles = "XXXReport")]
        public async Task<ActionResult> AnalyticsDates(ReportRequestVM reportRequestVM)
        {
            if (!ModelState.IsValid)
            {
                return View("**MainReports**", reportRequestVM);
            }

            // fill reportRequestVM with data
            return View("**PartialReport**", reportRequestVM);


        }

If the model is valid I return a partial view and the page looks fine , otherwise I return the main view , with the form , but in this the page renders it self twice. the question is, in case the client validation fails,how to return the main form with the validation errors ?

Any help would be appreciated, 10x Rony

Upvotes: 10

Views: 26121

Answers (2)

ron
ron

Reputation: 625

I figured it out... you should have partial view on the result and on the query.

and on failure you should return "http bad request" and use the following to set the validation on the search partial view.

this is how it should look:

        @using (Ajax.BeginForm("CloudAnalyticsDates", new AjaxOptions
            {
                InsertionMode = InsertionMode.Replace,
                UpdateTargetId = "reportContent",
                OnFailure = "OnCloudAnalyticsFailure",
                OnBegin = "ValidateForm",


            }))
        {
            @Html.LabelFor(m => m.StartDate)
            @Html.TextBoxFor(m => m.StartDate, new { id = "start" })
            @Html.ValidationMessageFor(model => model.StartDate)
            @Html.LabelFor(m => m.EndDate)
            @Html.TextBoxFor(m => m.EndDate, new { id = "end" })
            @Html.ValidationMessageFor(model => model.EndDate)
            <input id="btnsearch" type="submit" [email protected] class="iconHeader"/>
        }
    </div>
</div>

<script type="text/javascript">
    $(document).ready(function () {
        $("#datePicker").kendoDatePicker();
        $("#start").kendoDatePicker().data("kendoDatePicker");
        $("#end").kendoDatePicker().data("kendoDatePicker");
    });


    function OnCloudAnalyticsFailure(parameters) {

        $('#projectReport').html(parameters.responseText);
        $('#reportContent').empty();
        CleanValidationError('form');
    }



</script>

and on the server it should look like:

[HttpPost]

    public async Task<ActionResult> CloudAnalyticsDates(ReportRequestVM reportRequestVM)
    {
        if (!ModelState.IsValid)
        {
            Response.StatusCode = (int)HttpStatusCode.BadRequest;
            return PartialView("_ReportQuery", reportRequestVM);
        }


        reportRequestVM.BomTotals = await CommonRequestsHelper.GetBomTotalAnalytics(bomTotalRequest);
        return PartialView("_ProjectReport", reportRequestVM);
    }

Upvotes: 6

JTMon
JTMon

Reputation: 3199

When your modelstate is invalid and you return the view with the model containing the errors, the response sent by the server has an http status of 200 indicating that the request succeeded. In this case, the ajax form does what you instructed it to do which is to insert the returned response into division repostContent (you can verify that by checking that the second rendering of the page is done inside that div). As to how to get an ajax submit form to act the same as normal form submission as far as displaying validation messages, I have not found a simple straight forward method (maybe someone can point one out here :) for us). I solved this by:

  1. Having the form in a partial view rendered into a div (formDiv) of the main view.
  2. Having a "OnFailure" specified on the ajax form that inserts the response text into the div that contained the original form (formDiv)
  3. Override OnActionExecuted (since I have a main controller that all my other ones inherit from this is done in only one place) to check if a request IsAjax and ModelState is invalid, I change the response status to 4xx. This causes the "OnFailure" to get fired replacing the original form with the one returned inside the If(!ModelState.Isvalid) branch.

Upvotes: 3

Related Questions