How to use inheritance and polymorphism when passing a JSON to an MVC C # Controller?

1

I have an MVC method that receives a client class as a parameter:

      public async Task<ActionResult> Cadastrar(cliente model)
      {
      }

It turns out that this class has two children, a class called a person. and another class called a company that also inherits from a client.

I would like to know if it is possible (and how) I do to pass a JSON generic for this method? being both a PERSON and a COMPANY object. A polymorphism indeed.

I have tried to pass object person or company and it did not work. but if I put person or company in place of client and step the JSON I get usually the data.

    
asked by anonymous 12.04.2017 / 01:13

1 answer

0

Basically, using a Model Binder written by you and a bit of 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;
    }
}

In event Application_Start of your Global.asax.cs , register your Model Binder :

protected void Application_Start()
{
    ModelBinders.Binders.Add(typeof(Cliente), new ClienteModelBinder());
}

In form or in JSON, you need to pass a Tipo field so that Model Binder knows what is being passed:

@Html.Hidden("Tipo", Model.GetType())

Or:

{ 'Tipo': 'Pessoa' }

Or, you can test something else. For example, if the passed value has defined a CPF or CNPJ, or a name or business name, it does not need a Tipo field in form or 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;
}
    
12.04.2017 / 02:43