MVC 4 Validation with a partial view

19,963

If you post the page it will not come back to the dynamically loaded partial view. Try to make a ajax call to /Person/CreatePerson. Your CreatePerson will look similar to

[HttpPost]
    public JsonResult CreatePerson(Person person)
    {
        ViewBag.Id_ProductPackageCategory = new SelectList(db.ProductPackageCategories, "Id_ProductPackageCategory", "Name", person.Id_ProductPackageCategory);

    try
    {
        if (!ModelState.IsValid)
        {
            string messages = string.Join("; ", ModelState.Values
                                .SelectMany(x => x.Errors)
                                .Select(x => x.ErrorMessage));
            throw new Exception("Please correct the following errors: " + Environment.NewLine + messages);
        }

        db.Persons.AddObject(person);
        db.SaveChanges();

        return Json(new { Result = "OK" });
    }
    catch (Exception ex)
    {
        return Json(new { Result = "ERROR", Message = ex.Message });
    }
}                                                                                                    `

The ajax call to /Person/CreatePerson will look similar to

`

$.ajax({
                url: '/Person/CreatePerson',
                type: "POST",
                data: $("#form").serialize(),
                success: function (responce) {
                    alert(responce.Message);
                },
                error: function (xhr, textStatus) {
                    alert(xhr.status + " " + xhr.statusText);
                }
            });

Besides unobtrusive validation will not work easily with dynamic content. check the link unobtrusive validation on dynamically added partial view (not working)

Share:
19,963
Traffy
Author by

Traffy

Code & Sport...

Updated on June 29, 2022

Comments

  • Traffy
    Traffy almost 2 years

    I'm using MVC 4 and Entity Framework to develop a web app. I'm working with partial views which are loaded with javascript. One of them is a create view which includes validation. And that's my problem : the validation. I have a custom validation logic and, for example, if a user enters some numbers into a field such as "Name", it displays an error.

    Here, with the partial views, it redirects me on my partial with the errors displayed but what I wanted to do is to stay on my main view (Index view) and keep my partial view which displays the errors.

    EDIT :

    Here is my partial view :

    @model BuSIMaterial.Models.Person
    
    @using (Html.BeginForm()) {
        @Html.ValidationSummary(true)
        <fieldset>
            <legend>Person</legend>
    
            <div class="editor-label">
                First name : 
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(model => model.FirstName, new { maxlength = 50 })
                @Html.ValidationMessageFor(model => model.FirstName)
            </div>
    
            <div class="editor-label">
                Last name : 
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(model => model.LastName, new { maxlength = 50 })
                @Html.ValidationMessageFor(model => model.LastName)
            </div>
    
            <div class="editor-label">
                National number : 
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(model => model.NumNat, new { maxlength = 11 })
                @Html.ValidationMessageFor(model => model.NumNat)
            </div>
    
            <div class="editor-label">
                Start date : 
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(model => model.StartDate, new {@class = "datepicker", @placeholder="yyyy/mm/dd"})
                @Html.ValidationMessageFor(model => model.StartDate)
            </div>
    
            <div class="editor-label">
                End date : 
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(model => model.EndDate, new { @class = "datepicker", @placeholder = "yyyy/mm/dd" })
                @Html.ValidationMessageFor(model => model.EndDate)
            </div>
    
            <div class="editor-label">
                Distance House - Work (km) : 
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.HouseToWorkKilometers)
                @Html.ValidationMessageFor(model => model.HouseToWorkKilometers)
            </div>
    
            <div class="editor-label">
                Category : 
            </div>
            <div class="editor-field">
                @Html.DropDownList("Id_ProductPackageCategory", "Choose one ...")
                @Html.ValidationMessageFor(model => model.Id_ProductPackageCategory) <a href = "../ProductPackageCategory/Create">Add a new category?</a>
            </div>
    
            <div class="editor-label">
                Upgrade? : 
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.Upgrade)
                @Html.ValidationMessageFor(model => model.Upgrade)
            </div>
    
            <br />
    
            <div class="form-actions">
              <button type="submit" class="btn btn-primary">Create</button>
            </div>
        </fieldset>
    }
    
    
    @section Scripts {
        @Scripts.Render("~/bundles/jqueryval")
        @Scripts.Render("~/bundles/jqueryui")
        @Styles.Render("~/Content/themes/base/css")
    }
    

    In my view Index, I have this :

    <div class="form-actions"><button type="button" id="create" class="btn btn-primary">Create</button> </div>
    <div id ="create_person"></div>
    

    And the way I load my Partial View :

                $("#create").click(function () {
                    var form = $("#create_person").closest("form");
                    form.removeData('validator');
                    form.removeData('unobtrusiveValidation');
                    $.validator.unobtrusive.parse(form);
    
                    $.ajax({
                        url: "/Person/CreateOrUpdate",
                        type: "POST",
                        data: $("#create_person").serialize(),
                        cache: false
                    });
    
    //                var url = '/Person/CreatePerson';
    //                $("#create_person").load(url);
    
                });
    

    The actions :

    [HttpGet]
            public ActionResult CreateOrUpdate()
            {
                ViewBag.Id_ProductPackageCategory = new SelectList(db.ProductPackageCategories, "Id_ProductPackageCategory", "Name");
                return View();
            }
    
    
            [HttpPost]
            public JsonResult CreateOrUpdate(Person person)
            {
                ViewBag.Id_ProductPackageCategory = new SelectList(db.ProductPackageCategories, "Id_ProductPackageCategory", "Name", person.Id_ProductPackageCategory);
    
                try
                {
                    if (!ModelState.IsValid)
                    {
                        string messages = string.Join("; ", ModelState.Values
                                            .SelectMany(x => x.Errors)
                                            .Select(x => x.ErrorMessage));
                        throw new Exception("Please correct the following errors: " + Environment.NewLine + messages);
                    }
    
                    db.Persons.AddObject(person);
                    db.SaveChanges();
    
                    return Json(new { Result = "OK" });
                }
                catch (Exception ex)
                {
                    return Json(new { Result = "ERROR", Message = ex.Message });
                }
            }