title: Unobtrusively Validating Complex View Models with Fluent Validation - MVC3
body: <p>I am trying to figure out why my <code>FluentValidation</code> is not unobtrusively validating some of my View Model properties.</p>
  
  <p>I installed, via NuGet, the FluentValidation package for MVC3:</p>
  
  <pre><code>  Install-Package FluentValidation.MVC3
  </code></pre>
  
  <p><strong>Results:</strong></p>
  
  <pre><code>&lt;package id="FluentValidation" version="5.0.0.1" targetFramework="net45" /&gt;
  &lt;package id="FluentValidation.MVC3" version="5.0.0.1" targetFramework="net45" /&gt;
  </code></pre>
  
  <p>The properties that are not being validated are some members of a <em>Guitar</em> class object, declared in my View model. The Guitar.ProductionYear property is getting the unobtrusive validation code but the other 2 properties of the Guitar object are not.</p>
  
  <pre><code>public Guitar Guitar1 { get; set; }
  public Guitar Guitar2 { get; set; }
  public Guitar Guitar3 { get; set; }
  </code></pre>
  
  <p>I read the FluentValidation docs, and now specifically about the <a href="http://fluentvalidation.codeplex.com/discussions/452754" rel="nofollow">limitations regarding FluentValidation's client-side validation of lists</a> but this is not a list so I am hoping someone can see  what's wrong and/or offer some suggestions. </p>
  
  <p>I also tried using a custom <em>Guitar</em> object validator but still get the same results</p>
  
  <p><strong>Observations</strong>
  
  <li>Client-side validation is being generated and fires for properties FirstName,LasteName,Phone and Email</li><br />
  <li>I did notice that ModelState is not valid for these objects when they are not filled in by the user but I don't know why the client-side validation is not being generated and subsequently firing.</li><br /></p>
  
  <p><li>The generated form HTML for the <em>Guitar</em> objects are missing the unobtrusive validation attributes. The other properties like FirstName, LastName, Email and Phone are validating fine</li></p>
  
  <p><strong>Example</strong></p>
  
  <pre><code>    &lt;!-- Unobtrusive JS generated--&gt;
          &lt;input type="text" value="" name="FirstName" id="FirstName" data-val-required="'First Name' must not be empty." data-val="true" class="input-validation-error"&gt;
          &lt;div class="messageBottom"&gt; 
                  &lt;span data-valmsg-replace="true" data-valmsg-for="FirstName" class="field-validation-error"&gt;&lt;span for="FirstName" generated="true" class=""&gt;'First Name' must not be empty.&lt;/span&gt;
     &lt;/span&gt;
   &lt;/div&gt;
  
      &lt;!-- Unobtrusive JS Partially generated for Guitar object--&gt;
     &lt;input type="text" value="" name="Guitar.Make" id="Guitar_Make" placeholder="Make"&gt;
          &lt;div class="messageBottom"&gt;
          &lt;span data-valmsg-replace="true" data-valmsg-for="Guitar1.Make" class="field-validation-valid"&gt;&lt;/span&gt;
          &lt;/div&gt;
  
          &lt;input type="text" value="" name="Guitar1.Model" id="Guitar1_Model" placeholder="Model"&gt;
          &lt;div class="messageBottom"&gt;
              &lt;span data-valmsg-replace="true" data-valmsg-for="Guitar1.Model" class="field-validation-valid"&gt;&lt;/span&gt;
          &lt;/div&gt;
  
          &lt;input type="text" value="" name="Guitar1.ProductionYear" id="Guitar1_ProductionYear" data-val-number="The field ProductionYear must be a number." data-val="true" placeholder="Production Year" class="valid"&gt;
          &lt;div class="messageBottom"&gt;
          &lt;span data-valmsg-replace="true" data-valmsg-for="Guitar1.ProductionYear" class="field-validation-valid"&gt;
          &lt;/span&gt;
          &lt;/div&gt;
  </code></pre>
  
  <p>Thanks</p>
  
  <p><strong>Global.asax.cs</strong></p>
  
  <pre><code>FluentValidationModelValidatorProvider.Configure();
  </code></pre>
  
  <p><strong>The View Model</strong></p>
  
  <pre><code>[FluentValidation.Attributes.Validator(typeof(CustomerViewModelValidator))]
  public class CustomerViewModel
  {
      [Display(Name = "First Name")]
      public string FirstName { get; set; }
  
      [Display(Name = "Last Name")]
      public string LastName { get; set; }
  
      [Display(Name = "Phone")]
      public string Phone { get; set; }
  
      [Display(Name = "Email")]
      public string EmailAddress { get; set; }
  
      [Display(Name = "Guitar 1")]
      public Guitar Guitar1 { get; set; }
  
      [Display(Name = "Guitar 2")]
      public Guitar Guitar2 { get; set; }
  
      [Display(Name = "Guitar 3")]
      public Guitar Guitar3 { get; set; }
  }
  </code></pre>
  
  <p><strong>The Custom Guitar Object Validator</strong></p>
  
  <pre><code>public class GuitarValidator : AbstractValidator&lt;Guitar&gt;
  {
      public GuitarValidator()
      {
          RuleFor(x =&gt; x.Make).NotEmpty();
          RuleFor(x =&gt; x.Model).NotEmpty();
          RuleFor(x =&gt; x.ProductionYear).NotEmpty();
      }
  }
  </code></pre>
  
  <p><strong>The View Model Validator</strong></p>
  
  <pre><code>public class CustomerViewModelValidator : AbstractValidator&lt;CustomerViewModel&gt;
  {
      public CustomerViewModelValidator()
      {
          RuleFor(x =&gt; x.FirstName).NotNull();
          RuleFor(x =&gt; x.LastName).NotNull();
          RuleFor(x =&gt; x.Phone).NotNull();
          RuleFor(x =&gt; x.EmailAddress).NotNull();
  
          //1st Guitar Object is Required
          RuleFor(x =&gt; x.Guitar).SetValidator(new GuitarValidator());
  
  
  
      }
  }
  </code></pre>
  
  <p><strong>The View</strong></p>
  
  <pre><code>&lt;!-- Guitar Object #1 --&gt;
       &lt;div id="cosponsorsTemplate_1"&gt;
              &lt;div class="formColumn1"&gt;@Html.LabelFor(x=&gt;x.Guitar1)&lt;/div&gt;
              &lt;div class="formColumn2"&gt;@Html.TextBoxFor(x =&gt; x.Guitar1.Make, new { Placeholder = "Make" })
                  &lt;div class="messageBottom"&gt;@Html.ValidationMessageFor(x =&gt; x.Guitar1.Make)&lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="formColumn3"&gt;@Html.TextBoxFor(x =&gt; x.Guitar1.Model, new { Placeholder = "Model" })
                  &lt;div class="messageBottom"&gt;@Html.ValidationMessageFor(x =&gt; x.Guitar1.Model)&lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="formColumn4"&gt;@Html.TextBoxFor(x =&gt;x.Guitar1.ProductionYear, new { Placeholder = "Production Year" })
                  &lt;div class="messageBottom"&gt;@Html.ValidationMessageFor(x =&gt; x.Guitar1.ProductionYear)&lt;/div&gt;
                  &lt;a class="icon delete" data-delete-id="1"&gt;Delete&lt;/a&gt;
              &lt;/div&gt;
          &lt;/div&gt;
  
     &lt;!-- Guitar Object #2 --&gt;
          &lt;div id="cosponsorsTemplate_2"&gt;
              &lt;div class="formColumn1"&gt;@Html.LabelFor(x=&gt;x.Guitar2)&lt;/div&gt;
              &lt;div class="formColumn2"&gt;@Html.TextBoxFor(x =&gt; x.Guitar2.Make, new { Placeholder = "Make" })
                  &lt;div class="messageBottom"&gt;@Html.ValidationMessageFor(x =&gt; x.Guitar2.Make)&lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="formColumn3"&gt;@Html.TextBoxFor(x =&gt; x.Guitar2.Model, new { Placeholder = "Model" })
                  &lt;div class="messageBottom"&gt;@Html.ValidationMessageFor(x =&gt; x.Guitar2.Model)&lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="formColumn4"&gt;@Html.TextBoxFor(x =&gt; x.Guitar2.ProductionYear, new { Placeholder = "Production Year" })
                  &lt;div class="messageBottom"&gt;@Html.ValidationMessageFor(x =&gt; x.Guitar2.ProductionYear)&lt;/div&gt;
                  &lt;a class="icon delete" data-delete-id="2"&gt;Delete&lt;/a&gt;
              &lt;/div&gt;
          &lt;/div&gt;
  
      &lt;!-- Guitar Object #3 --&gt;
          &lt;div id="cosponsorsTemplate_3"&gt;
              &lt;div class="formColumn1"&gt;@Html.LabelFor(x=&gt;x.Guitar3)&lt;/div&gt;
              &lt;div class="formColumn2"&gt;@Html.TextBoxFor(x =&gt; x.Guitar3.Make, new { Placeholder = "Make" })
                  &lt;div class="messageBottom"&gt;@Html.ValidationMessageFor(x =&gt; x.Guitar3.Make)&lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="formColumn3"&gt;@Html.TextBoxFor(x =&gt; x.Guitar3.Model, new { Placeholder = "Model" })
                  &lt;div class="messageBottom"&gt;@Html.ValidationMessageFor(x =&gt; x.Guitar3.Model)&lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="formColumn4"&gt;@Html.TextBoxFor(x =&gt; x.Guitar3.ProductionYear, new { Placeholder = "Production Year" })
                  &lt;div class="messageBottom"&gt;@Html.ValidationMessageFor(x =&gt; x.Guitar3.ProductionYear)&lt;/div&gt;
                  &lt;a class="icon delete" data-delete-id="3"&gt;Delete&lt;/a&gt;
              &lt;/div&gt;
          &lt;/div&gt;
  </code></pre>