Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 507
ron Avatar asked May 19 '13 14:05

ron


People also ask

What is the difference between Ajax BeginForm and HTML BeginForm?

BeginForm() will create a form on the page that submits its values to the server as a synchronous HTTP request, refreshing the entire page in the process. Ajax. BeginForm() creates a form that submits its values using an asynchronous ajax request.

What is Ajax BeginForm in MVC?

Ajax. BeginForm is the extension method of the ASP.NET MVC Ajax helper class, which is used to submit form data to the server without whole page postback. To work Ajax. BeginForm functionality properly, we need to add the reference of jquery.


2 Answers

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);
    }
like image 130
ron Avatar answered Oct 21 '22 10:10

ron


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.
like image 36
JTMon Avatar answered Oct 21 '22 08:10

JTMon