title: Custom model binding, model state, and data annotations
body: <p>I have a few questions regarding custom model binding, model state, and data annotations.</p>
  
  <p>1) Is it redundant to do validation in the custom model binder if I have data annotations on my model, because that's what I thought the point of data annotations were.</p>
  
  <p>2) Why is my controller treating the model state as valid even when it's not, mainly I make the Name property null or too short.</p>
  
  <p>3) Is it ok to think of custom model binders as constructor methods, because that's what they remind me of.</p>
  
  <p>First here is my model.</p>
  
  <pre><code>public class Projects
  {     
      [Key]
      [Required]
      public Guid ProjectGuid { get; set; }
  
      [Required]
      public string AccountName { get; set; }
  
      [Required(ErrorMessage = "Project name required")]
      [StringLength(128, ErrorMessage = "Project name cannot exceed 128 characters")]
      [MinLength(3, ErrorMessage = "Project name must be at least 3 characters")]
      public string Name { get; set; }
  
      [Required]
      public long TotalTime { get; set; }
  }
  </code></pre>
  
  <p>Then I'm using a custom model binder to bind some properties of the model. Please don't mind that it's quick and dirty just trying to get it functioning and then refactoring it.</p>
  
  <pre><code>public class ProjectModelBinder : IModelBinder
  {
       public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
      {
          if (controllerContext == null)
          {
              throw new ArgumentNullException("controllerContext");
          }
          if (bindingContext == null)
          {
              throw new ArgumentNullException("bindingContext");
          }
          var p = new Project();
          p.ProjectGuid = System.Guid.NewGuid();
          p.AccountName = controllerContext.HttpContext.User.Identity.Name;
          p.Name = controllerContext.HttpContext.Request.Form.Get("Name");
          p.TotalTime = 0;
  
          //
          // Is this redundant because of the data annotations?!?!
          //
          if (p.AccountName == null)
              bindingContext.ModelState.AddModelError("Name", "Name is required");
  
          if (p.AccountName.Length &lt; 3)
              bindingContext.ModelState.AddModelError("Name", "Minimum length is 3 characters");
  
          if (p.AccountName.Length &gt; 128)
              bindingContext.ModelState.AddModelError("Name", "Maximum length is 128 characters");
  
          return p;
      }
  }
  </code></pre>
  
  <p>Now my controller action.</p>
  
  <pre><code>    [HttpPost]
      public ActionResult CreateProject([ModelBinder(typeof(ProjectModelBinder))]Project project)
      {
          //
          // For some reason the model state comes back as valid even when I force an error
          //
          if (!ModelState.IsValid)
              return Content(Boolean.FalseString);
  
          //_projectRepository.CreateProject(project);
  
          return Content(Boolean.TrueString);
  
      }
  </code></pre>
  
  <p><strong>EDIT</strong></p>
  
  <p>I Found some code on another stackoverflow question but I'm not sure at which point I would inject the following values into this <a href="https://stackoverflow.com/questions/2030059/dataannotation-validations-and-custom-modelbinder">possible solution.</a></p>
  
  <p>What I want to inject when a new object is created:</p>
  
  <pre><code>        var p = new Project();
          p.ProjectGuid = System.Guid.NewGuid();
          p.AccountName = controllerContext.HttpContext.User.Identity.Name;
          p.Name = controllerContext.HttpContext.Request.Form.Get("Name");
          p.TotalTime = 0;
  </code></pre>
  
  <p>How do I get the above code into what's below (Possible solution):</p>
  
  <pre><code>    public class ProjectModelBinder : DefaultModelBinder
      {
          public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
          {
              if (bindingContext.ModelType == typeof(Project))
              {
                  ModelBindingContext newBindingContext = new ModelBindingContext()
                  {
  
                      ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(
                          () =&gt; new Project(), // construct a Project object,
                          typeof(Project)         // using the Project metadata
                      ),
                      ModelState = bindingContext.ModelState,
                      ValueProvider = bindingContext.ValueProvider
  
                  };
  
                  // call the default model binder this new binding context
                  return base.BindModel(controllerContext, newBindingContext);
              }
              else
              {
                  return base.BindModel(controllerContext, bindingContext);
              }
          }
  
      }
  
  }
  </code></pre>