ASP.NET MVC 2 client-side validation rules not being created

asp.net-mvc, asp.net-mvc-2, asp.net-mvc-2-validation, validation

Solution

About five seconds after I posted the question, I realized something: My view didn't have `ValidationMessage` placeholders anywhere. I added `<%= Html.ValidationMessageFor(model => model.Item.Name) %>` and lo and behold, MVC added validation rules for `Item.Name` to the JS block at the bottom of the page.

It turns out that MVC does not emit client-side validation rules for a field unless you actually do one of the following:

- Call `Html.ValidationMessage()` for the property.

- Call `Html.Validate()` for the property. (This one won't output error messages)

- Render the controls using `Html.EditorForModel()`. (source)

Doing any of these tells MVC, "This property of my viewmodel is editable by the user, so you should be validating it." Just using the HTML helper to stick a textbox on the page -- even if you're using the new strongly-typed helpers -- isn't enough.

Problem

MVC isn't generating the client-side validation rules for my viewmodel. The HTML just contains this: ``` <script type="text/javascript"> //<![CDATA[ if (!window.mvcClientValidationMetadata) { window.mvcClientValidationMetadata = []; } window.mvcClientValidationMetadata.push({"Fields":[],"FormId":"form0","ReplaceValidationSummary":false}); //]]> </script> ``` Note that `Fields[]` is empty! My view is strongly-typed and uses the new strongly-typed HTML helpers (`TextBoxFor()`, etc). View Model / Domain Model ``` public class ItemFormViewModel { public Item Item { get; set; } [Required] [StringLength(100)] public string Whatever { get; set; } // for demo } [MetadataType(typeof(ItemMetadata))] public class Item { public string Name { get; set; } public string SKU { get; set; } public int QuantityRequired { get; set; } // etc. } public class ItemMetadata { [Required] [StringLength(100)] public string Name { get; set; } [Required] [StringLength(50)] public string SKU { get; set; } [Range(0, Int32.MaxValue)] public int QuantityRequired { get; set; } // etc. } ``` (I know I'm using a domain model as my / as part of my view model, which isn't a good practice, but disregard that for now.) View ``` <%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<ItemFormViewModel>" %> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2>Editing item: <%= Html.Encode(Model.Item.Name) %></h2> <% Html.EnableClientValidation(); %> <%= Html.ValidationSummary("Could not save the item.") %> <% using (Html.BeginForm()) { %> <%= Html.TextBoxFor(model => model.Item.Name) %> <%= Html.TextBoxFor(model => model.Item.SKU) %> <%= Html.TextBoxFor(model => model.Item.QuantityRequired) %> <%= Html.HiddenFor(model => model.Item.ItemID) %> <%= Html.TextBox("Whatever", Model.Whatever) %> <input type="submit" value="Save" /> <% } %> </asp:Content> ``` I included the `Whatever` property on the view model because I suspected that MVC wasn't recursively inspecting the sub-properties of `ItemFormViewModel.Item`, but even that isn't being validated? I've even tried delving into the MVC framework source code but have come up empty. What could be going on?

Original source

Related problems