Basically using a Model Binder written by you and a little Reflection:
public class ClienteModelBinder : DefaultModelBinder
{
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
{
var tipoString = bindingContext.ValueProvider.GetValue(bindingContext.ModelName + ".Tipo");
var tipo = Type.GetType(
(string)tipoString.ConvertTo(typeof(string)),
true
);
var model = Activator.CreateInstance(type);
bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, tipo);
return model;
}
}
At the event Application_Start
of your Global.asax.cs
, register your Model Binder:
protected void Application_Start()
{
ModelBinders.Binders.Add(typeof(Cliente), new ClienteModelBinder());
}
In the form
or in JSON, you will need to pass a field Tipo
so that the Model Binder know what is being passed:
@Html.Hidden("Tipo", Model.GetType())
Or:
{ 'Tipo': 'Pessoa' }
Or you can test something else. For example, if the value passed has defined a CPF or CNPJ, or even a name or a social reason, then it does not need a field Tipo
in the form
or in the JSON:
var cpf = bindingContext.ValueProvider.GetValue(bindingContext.ModelName + ".Cpf");
if (cpf != null)
{
/* É Pessoa Física */
var model = Activator.CreateInstance(typeof(Pessoa));
bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, typeof(Pessoa));
return model;
}
thanks, testing here now
– Paulo