title: MVC 3 Model Binding a Sub Type (Abstract Class or Interface)
body: <p>Say I have a Product model, the Product model has a property of ProductSubType (abstract) and we have two concrete implementations Shirt and Pants.</p>
  
  <p>Here is the source:</p>
  
  <pre><code> public class Product
   {
      public int Id { get; set; }
  
      [Required]
      public string Name { get; set; }
  
      [Required]
      public decimal? Price { get; set; }
  
      [Required]
      public int? ProductType { get; set; }
  
      public ProductTypeBase SubProduct { get; set; }
  }
  
  public abstract class ProductTypeBase { }
  
  public class Shirt : ProductTypeBase
  {
      [Required]
      public string Color { get; set; }
      public bool HasSleeves { get; set; }
  }
  
  public class Pants : ProductTypeBase
  {
      [Required]
      public string Color { get; set; }
      [Required]
      public string Size { get; set; }
  }
  </code></pre>
  
  <p>In my UI, user has a dropdown, they can select the product type and the input elements are displayed according to the right product type. I have all of this figured out (using an ajax get on dropdown change, return a partial/editor template and re-setup the jquery validation accordingly).</p>
  
  <p>Next I created a custom model binder for ProductTypeBase. </p>
  
  <pre><code> public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
   {
  
          ProductTypeBase subType = null;
  
          var productType = (int)bindingContext.ValueProvider.GetValue("ProductType").ConvertTo(typeof(int));
  
          if (productType == 1)
          {
              var shirt = new Shirt();
  
              shirt.Color = (string)bindingContext.ValueProvider.GetValue("SubProduct.Color").ConvertTo(typeof(string));
              shirt.HasSleeves = (bool)bindingContext.ValueProvider.GetValue("SubProduct.HasSleeves").ConvertTo(typeof(bool));
  
              subType = shirt;
          }
          else if (productType == 2)
          {
              var pants = new Pants();
  
              pants.Size = (string)bindingContext.ValueProvider.GetValue("SubProduct.Size").ConvertTo(typeof(string));
              pants.Color = (string)bindingContext.ValueProvider.GetValue("SubProduct.Color").ConvertTo(typeof(string));
  
              subType = pants;
          }
  
          return subType;
  
      }
  }
  </code></pre>
  
  <p>This binds the values correctly and works for the most part, except I lose the server side validation. So on a hunch that I am doing this incorrectly I did some more searching and came across this answer by Darin Dimitrov:</p>
  
  <p><a href="https://stackoverflow.com/questions/4012217/asp-net-mvc-2-binding-to-abstract-model">ASP.NET MVC 2 - Binding To Abstract Model</a></p>
  
  <p>So I switched the model binder to only override CreateModel, but now it doesn't bind the values.</p>
  
  <pre><code>protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
      {
          ProductTypeBase subType = null;
  
          var productType = (int)bindingContext.ValueProvider.GetValue("ProductType").ConvertTo(typeof(int));
  
          if (productType == 1)
          {
              subType = new Shirt();
          }
          else if (productType == 2)
          {
              subType = new Pants();
          }
  
          return subType;
      }
  </code></pre>
  
  <p>Stepping though the MVC 3 src, it seems like in BindProperties, the GetFilteredModelProperties returns an empty result, and I think is because bindingcontext model is set to ProductTypeBase which doesn't have any properties. </p>
  
  <p>Can anyone spot what I am doing wrong? This doesn't seem like it should be this difficult. I am sure I am missing something simple...I have another alternative in mind of instead of having a SubProduct property in the Product model to just have separate properties for Shirt and Pants. These are just View/Form models so I think that would work, but would like to get the current approach working if anything to understand what is going on...</p>
  
  <p>Thanks for any help!</p>
  
  <h1>Update:</h1>
  
  <p>I didn't make it clear, but the custom model binder I added, inherits from the DefaultModelBinder</p>
  
  <h1>Answer</h1>
  
  <p>Setting ModelMetadata and Model was the missing piece. Thanks Manas!</p>
  
  <pre><code>protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
          {
              if (modelType.Equals(typeof(ProductTypeBase))) {
                  Type instantiationType = null;
  
                  var productType = (int)bindingContext.ValueProvider.GetValue("ProductType").ConvertTo(typeof(int));
  
                  if (productType == 1) {
                      instantiationType = typeof(Shirt);
                  }
                  else if (productType == 2) {
                      instantiationType = typeof(Pants);
                  }
  
                  var obj = Activator.CreateInstance(instantiationType);
                  bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, instantiationType);
                  bindingContext.ModelMetadata.Model = obj;
                  return obj;
              }
  
              return base.CreateModel(controllerContext, bindingContext, modelType);
  
          }
  </code></pre>