It took me a good day to answer a closely related problem - although I'm not sure if this is exactly the same problem, I post it here if others are looking for a solution to the exact same problem.
In my case, I have an abstract base type for several types of presentation types. So, in the main view model, I have a property of an abstract base type:
class View { public AbstractBaseItemView ItemView { get; set; } }
I have several subtypes of AbstractBaseItemView, many of which define their own exclusive properties.
My problem is that the binder model does not look at the type of the object attached to the View.ItemView, but instead only looks at the declared property type, which is AbstractBaseItemView, and decides to bind only the properties defined in the abstract type, ignoring the properties, specific to the specific type of AbstractBaseItemView that is being used.
The work for this is pretty small:
using System.ComponentModel; using System.ComponentModel.DataAnnotations; // ... public class ModelBinder : DefaultModelBinder { // ... override protected ICustomTypeDescriptor GetTypeDescriptor(ControllerContext controllerContext, ModelBindingContext bindingContext) { if (bindingContext.ModelType.IsAbstract && bindingContext.Model != null) { var concreteType = bindingContext.Model.GetType(); if (Nullable.GetUnderlyingType(concreteType) == null) { return new AssociatedMetadataTypeTypeDescriptionProvider(concreteType).GetTypeDescriptor(concreteType); } } return base.GetTypeDescriptor(controllerContext, bindingContext); } // ... }
Although this change seems hacked and very βsystemic,β it seems to work - and as far as I can imagine, it does not pose a significant security risk, since it does not bind to CreateModel () and thus do not allow you publish something and deceive the binding to the model in creating only any object.
It also works only when the declared property type is an abstract type, for example. abstract class or interface.
In the relevant note, it occurs to me that other implementations that I saw here that override CreateModel () will probably only work when publishing completely new objects - and will suffer from the same problem that I encountered when the declared type properties has an abstract type. Thus, you most likely will not be able to edit specific properties of specific types on existing model objects, but only create new ones.
In other words, you probably need to integrate this work environment into your binder in order to also be able to correctly edit the objects that were added to the view model before binding ... Personally, I believe that it is a safer approach, since I control the addition of a specific type - therefore, the controller / action can indirectly indicate a specific type that can be connected by simply filling the property with an empty instance.
I hope this is helpful to others ...