0

I have setup a little test project that I hope will explain my problem. I have a parent class that has a property containing all its children of type Child. In the MVC view I list all the children in a table and to have the form post back my children and map them to the parent property automatically I render them like:

@Html.TextBox(string.Format("Children[{0}].ChildName", childIndex), child.ChildName)

In the controller I have marked property ChildName to be required. The problem I have is that jquery unobtrusive validation does not emit any data validation attributes. Everything validates nice on the server but not on the client (obviously because there are no attributes for jquery validation to find on these inputs).

Please have a look at the code:

VIEW

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    <div>
        <form action="@Url.Action("Save")" method="post">
            @Html.TextBox("Name", (string)Model.Name)

            <table>
                <tr><td>Child name</td></tr>
                @{var childIndex = 0;}
                @foreach (var child in (List<GridValidationTest.Controllers.Child>)Model.Children)
                {
                    <tr><td>@Html.TextBox(string.Format("Children[{0}].ChildName", childIndex), child.ChildName)</td></tr>
                    childIndex++;
                }
            </table>

            <br /><button>Submit</button>
        </form>
    </div>
</body>
</html>

CONTROLLER

namespace GridValidationTest.Controllers
{
    public class Parent
    {
        [Required]
        public string Name { get; set; }
        public IList<Child> Children { get; set; }
    }

    public class Child
    {
        [Required]
        public string ChildName { get; set; }
    }

    public class MyController : Controller
    {
        //
        // GET: /My/

        public ActionResult Index()
        {
            var parent = new Parent { Name = "Parent name" };
            parent.Children = new List<Child>
            {
                new Child {ChildName = "First child"},
                new Child {ChildName = "Second child"}
            };
            return View("Index", parent);
        }

        public ActionResult Save(Parent parent)
        {
            return View("Index", parent);
        }

    }
}

The client validation on property Name of Parent class works fine as expected. How should I render the children to have client-side validation to work as I expect?

John
  • 2,043
  • 5
  • 28
  • 49

1 Answers1

1

You need to bind the fields in your view to your model. Instead of using:

@Html.TextBox(string.Format("Children[{0}].ChildName", childIndex), child.ChildName)

Use

@Html.TextBoxFor(model => model.Children[childIndex])
@Html.ValidationMessageFor(model => model.Children[childIndex])

Also make sure you are including the right jquery javascript files on your page. Something like:

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

Also make sure that in your web config you have ClientValidationEnabled and UnobtrusiveJavaScriptEnabled turned on like so:

<appSettings>
    ....
    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />
    ....
</appSettings>
Ben Tidman
  • 2,129
  • 17
  • 30
  • I immediately ran into new problems. I guess I found out pretty quickly why I had not rendered with @Html.TextBoxFor in my original project. Some of my real properties are for example Timespan, I need to format the output in the view like .ToString("hh':'mm"). This doesn't work with TextBoxFor. What is my next step then? (I had to accept your answer since it is the correct solution to the question asked) – John Jan 10 '13 at 14:32
  • Never mind, think I found a good post [here](http://stackoverflow.com/questions/1961114/date-only-from-textboxfor) – John Jan 10 '13 at 14:37