title: Custom DataAnnotation Binding Wrong Value
body: <p>I have a C# app with a custom <code>RequiredIf</code> DataAnnotation implementation as follows:</p>
  
  <pre><code>public class RequiredIf : RequiredAttribute {
      private String PropertyName { get; set; }
      private Object DesiredValue { get; set; }
  
      public RequiredIf (String property_name, Object desired_value) {
          PropertyName = property_name;
          DesiredValue = desired_value;
      }
  
      protected override ValidationResult IsValid (object value, ValidationContext context) {
          Object instance = context.ObjectInstance;
          Type type = instance.GetType();
          Object prop = type.GetProperty(PropertyName);
          Object property_value = type.GetProperty(PropertyName).GetValue(instance, null);
          if ( property_value.ToString() == DesiredValue.ToString() ) {
              ValidationResult result = base.IsValid(value, context);
              return result;
          }
  
  
          return ValidationResult.Success;
      }
  }
  </code></pre>
  
  <p>This appears to work in nearly every case.</p>
  
  <p>I have a ViewModel that I am trying to validate. The ViewModel has a child class. The basic implementation is:</p>
  
  <pre><code>public class ViewModel {
      .........
      public class ChildObject {
          [RequiredIf("FieldToCheck", false)]    // note that it's only required if the value is FALSE!
          DateTime? ConditionalField { get; set; }  // could be NULL
          Boolean FieldToCheck { get; set; }
      }
      ..........
  }
  </code></pre>
  
  <p>When I submit the form with <code>FieldToCheck</code> set to true, my ViewModel validation still fails on this <code>RequiredIf</code>. I can view the value in the ViewModel variable in the controller and verify that it is <code>true</code>. However, I can set a breakpoint in the DataAnnotation's <code>IsValid</code> method and see in the debugger that the <code>FieldToCheck</code> is <em>false</em> - NOT what I submitted!</p>
  
  <p>Is the Model Binder binding wrong? If so, why? And why is the bound value <em>incorrect</em> in the validator, but <em>correct</em> in the controller?</p>
  
  <p>This is causing my ViewModel validation to fail <em>whenever</em> that DateTime field is left blank (NULL gets submitted). But if that Boolean is false, I don't even <em>show</em> the DateTime field in my form -- I don't <em>want</em> the user to submit anything in that field.</p>
  
  <p>EDIT: This seems to happen <em>only with Booleans</em>, but it happens consistently regardless of where the Boolean/ConditionalField are created.</p>
  
  <p>Does the Model Binder not bind Boolean members prior to validation?</p>
  
  <p>EDIT2:</p>
  
  <p>In the view, I have a standard form that I use to post the data:</p>
  
  <pre><code>@Model ViewModel
  
  @using ( Html.BeginForm("Create", "Controller", FormMethod.Post ) {
  
      .........
  
      @Html.DropDownListFor(m =&gt; m.FieldToCheck, Model.FieldToCheckList)
  
      .........
  
      &lt;button type="submit"&gt;Submit&lt;/button&gt;
  
  }
  </code></pre>
  
  <p>The Controller:</p>
  
  <pre><code>public class Controller : Controller {
  
      [HttpPost]
      public ActionResult Create (ViewModel view_model) {
          // I set a breakpoint here, and if I submit FieldToCheck = true, the debugger shows that FieldToCheck is, indeed, true.
          if ( ModelState.IsValid ) {
              // save to db
              return View();
          }
          return View();
     }
  }
  </code></pre>
  
  <p>I have a method that initializes fields in the ViewModel before rendering the form, and in it, I set <code>FieldToCheckList</code> as follows:</p>
  
  <pre><code>view_model.FieldToCheckList = new List&lt;SelectListItem&gt; {
      new SelectListItem { Text = "Yes", Value = Boolean.TrueString },
      new SelectListItem { Text = "No", Value = Boolean.FalseString }
  }
  </code></pre>
  
  <p>So I am using a <code>select</code> to populate the value. However, I have tried multiple other form elements (including statically setting a <code>HiddenFor</code> to true) and it still results in the same problem. If I set a breakpoint in the <code>IsValid</code> method in the <code>RequiredIf</code> validator, all of my boolean values are false, regardless of submitted data. If I set a breakpoint in the <code>Create</code> method in <code>Controller</code>, my boolean values are set correctly.</p>
  
  <p>I have also tested both <code>Boolean</code> and <code>bool</code> data types. It doesn't seem to affect anything.</p>
  
  <p>EDIT4:</p>
  
  <p>I didn't actually figure out the <em>cause</em> of the problem or a real solution, but I did find a workaround.</p>
  
  <p>So, apparently the issue occurs when I do <code>RequiredIf(AnyBooleanValue, AnythingButTrue)</code>. If the <code>DesiredValue</code> is set to <em>anything</em> except <code>true</code>, the Model Binder sets <em>all</em> boolean values in the ViewModel to the default value - <code>false</code> - regardless of what is submitted. I have tried multiple things - <code>RequiredIf(FieldToCheck, "False")</code>, <code>RequiredIf(FieldToCheck, !true)</code>, etc. None work. But if I do <code>RequiredIf(FieldToCheck, true)</code>, the values get bound correctly!</p>
  
  <p>So the workaround is to add a new field:</p>
  
  <pre><code>public class ViewModel {
      public Boolean FieldToCheck { get; set; }
      public Boolean IsConditionalFieldRequired { get; set; }
      [RequiredIf("IsConditionalFieldRequired",true)]
      public string ConditionalField { get; set; }
  }
  </code></pre>
  
  <p>In the view, I have <code>IsConditionalFieldRequired</code> as a hidden field, and whenever <code>FieldToCheck</code> is changed, I use jQuery to set <code>IsConditionalFieldRequired</code> to the inverse of <code>FieldToCheck</code>.</p>
  
  <p>(I added this as an edit instead of an answer because I don't think it's a true solution, just a viable workaround. Obviously it's not the most eloquent way to get things done.)</p>