1

Code Context

In my application I am appending partial view in my main view on a button click which is in main view.Partial view contain cancel button which remove the partial view from main view on its click. My submit button is in main view which submit data from both the views ,main and partial .Data annotation on my partial view is not working.

Any help would be appreciated.

My parent model(StudentDetails) is as follows

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
using PartialViewDemo.Models;

namespace PartialViewDemo.Models
{
   public class StudentDetails
     {
    [Required(ErrorMessage ="Required")]
    public string FirstName { get; set; }
    [Required(ErrorMessage = "Required")]
    public string LastName { get; set; }
    [Required(ErrorMessage = "Required")]
    public string StudentId { get; set; }
    [Required(ErrorMessage = "Required")]
    public int Age { get; set; }
    [Required(ErrorMessage = "Required")]
    public string Email { get; set; }

    public IList<PartialAddress1> addressList { get; set; }
    }

}

Child Model(PartialAddress1) is as follows

 public class PartialAddress1
{
    [Required(ErrorMessage ="Required")]
    public string AddressType { get; set; }
    [Required(ErrorMessage ="Required")]
     public string Address { get; set; }
    public Guid UniqueID { get; set; }

    public PartialAddress1()
    {
        UniqueID = Guid.NewGuid();
    }

}

Controller

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using PartialViewDemo.Models;

namespace PartialViewDemo.Controllers
{
   public class StudentController : Controller
{
    StudentDetails student = new StudentDetails();
    PartialAddress1 address1 = new PartialAddress1();
    Services service = new Services();
    // GET: Student
    public ActionResult Index()
    {
        List<StudentDetails> listt = new List<StudentDetails>();
        listt = service.GetRecords();
        if (listt.Count < 1)
        {
            ViewData.Model = listt;
            return View(ViewData.Model);
        }
        ViewData.Model = listt;
        //ViewBag.Personrecords = records;
        return View();
    }

    public ActionResult StudentDetails()
    {
        return View();
    }

    [HttpPost]
    public ActionResult StudentDetails(StudentDetails details)
    {

            student.FirstName = details.FirstName;
            student.LastName = details.LastName;
            student.StudentId = details.StudentId;
            student.Age = details.Age;
            student.Email = details.Email;
            student.addressList = details.addressList;

            service.AddStudent(student);


            return RedirectToAction("Index");

    }

    public  PartialViewResult ShowPartialView()
    {
        PartialAddress1 address1 = new PartialAddress1();
        return PartialView("PartialView", address1);
    }


}

}

Main View(StudentDetails)

@model PartialViewDemo.Models.StudentDetails

@{
   ViewBag.Title = "StudentDetails";
 }
   <head>
  <script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.js"></script>


<script type="text/javascript">
    function deleteAddress(Id) {
        Id.remove();
    }


    $(function () {
        $("#btnClick").click(function () {
            $.post("/Student/ShowPartialView",

                function (response) {
                    $('#view').append(response);

                }
             );
        });
       return false;
    });

    $(function () {
        $('#submit').click(function () {
            alert('calling');
            if ($(this).valid()) {
                var $form = $('#@Model.');
                $("form").data("unobtrusiveValidation", null);
                $("form").data("validator", null);
                $.validator.unobtrusive.parse($("form"));
            }

        });
    });


</script>

</head>

  <h2>StudentDetails</h2>



   @using (Html.BeginForm(null, null, FormMethod.Post, new { id = "signupform"     }))
 {
   @Html.AntiForgeryToken()

<div class="form-horizontal" >
    <h4>StudentDetails</h4>
    <hr />
    @Html.ValidationSummary(true, "", new { @class = "text-danger" })
    <div class="form-group">
        @Html.LabelFor(model => model.FirstName, htmlAttributes: new {     @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.FirstName, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.FirstName, "", new {  @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.LastName, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.LastName, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.LastName, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.StudentId, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.StudentId, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.StudentId, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.Age, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.Age, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.Age, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.Email, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.Email, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.Email, "", new { @class = "text-danger" })
        </div>
    </div>


    <div>Add Address :<input type="button" value="Add" id="btnClick" />   </div>/////button to add partial view

    <div id="view">

    </div>


    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">

            <input  type="submit" value="Submit" class="btn btn-default" id="submit"  />//////button that submits form (main and child view)

        </div>
    </div>
  </div>
}

    @*<div>
        @Html.ActionLink("Back to List", "Index")
    </div>*@



    @section Scripts {
                    @Scripts.Render("~/bundles/jqueryval")
                  }

My child view (PartialView.cshtml)

@model PartialViewDemo.Models.PartialAddress1
@using HtmlHelpers.BeginCollectionItem

<head>
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.js"></script>


</head>


@using (Html.BeginCollectionItem("addressList"))
{
    @Html.ValidationSummary(true)

    @Html.AntiForgeryToken()

    <div class="form-horizontal" id="@Model.UniqueID" >

        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(model => model.AddressType, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.AddressType, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.AddressType, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Address, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Address, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Address, "", new { @class = "text-danger" })
            </div>
        </div>




        <div><input type="button" value="Cancel" id="cancel" name="Cancel" onclick="deleteAddress(document.getElementById('@Model.UniqueID'));" /></div>
    </div>
}



@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

when I am submitting the form only main view data annotations are working .How to make partial view data annotations work properly.

Tripti
  • 19
  • 2
  • You need to reparse the validation when you add the content (see the 6th code snippet in the dupe - i.e. after `$('#view').append(response);`). And delete your `$('#submit').click(function () {` script - that does not make any sense. –  Jan 28 '17 at 22:24

1 Answers1

0

If I understood right, problem is model dataBinder can't find propertyes of list of objects "PartialAddress1", and as result your details.addressList;is null in action method

StudentDetails(StudentDetails details)

Bacause addressList is an IList<PartialAddress1>

you should use in your view inputs with followind names: For 1st object of "PartialAddress1":

<input name="[0].AddressType " type="text" value="" />
<input name="[0].Address " type="text" value="" />

For second:

<input name="[1].AddressType " type="text" value="" />
<input name="[1].Address " type="text" value="" />

In that case modelBinder could find these properties. And in your partial view you can do this like that:

using (Html.BeginForm())
{
    for (int i = 0; i < 2; i++)
    {
        <fieldset>
            <legend>object  @(i + 1)</legend>
            <div><label>AddressType:</label>
                @Html.Editor("[" + i + "].AddressType")
            </div>
            <div><label>Address:</label>
                @Html.Editor("[" + i + "].Address")
            </div>
        </fieldset>
    }

}