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

Asked

Viewed 351 times

3

I have a MVC method that takes a client class as a parameter:

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

Turns out this class has two kids, a class called a person. and another class called company that also inherits from customer.

I wonder if it is possible (and how) I do to pass a JSON generic for this method? can both be an object PERSON as an object COMPANY. A polymorphism all right.

I’ve tried to pass object person or company and it didn’t work. but if I put person or company in the client’s place and pass the JSON I receive normally the data.

1 answer

2


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

Browser other questions tagged

You are not signed in. Login or sign up in order to post.