Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Posting a collection of subclasses

I have a requirement for users to edit a list of quotes for a lead, the quotes can be different types such as:

  • QuoteForProductTypeA
  • QuoteForProductTypeB

All quote types share a common base class, such as QuoteBase.

I have my quotes displaying fine on the front end, and appear to post back the correct data too.

However, on the server it doesn't obviously doesn't know which subclass to use, so just uses the base class.

I think i need some kind of custom model binder for WebApi to check for a hidden field such as ModelType which contains the type of the object in the collection, the model binder then creates a new object of this type and binds the properties from my posted values to this object.

However, i am stuck at this point with very little documentation / blogs on how to do this.

I have checked the source code for WebApi to see if i can extend a default model binder, but any defaults are sealed classes.

I can only implement IModelBinder by the looks of it, i can create the correct model type by looking for a value called ModelType, but then i'm not sure how to fill the rest of the values in my subclasses, if there was a default model binder i was inheriting from i would just call the base classes bind method.

like image 532
Paul Hinett Avatar asked Oct 12 '12 12:10

Paul Hinett


1 Answers

If your post collection comes from request body, it won't go through model binder. Web API will use formatter to deserialize the content.

If you just want to support json, it's quite easy. Just add following code to your web api config:

config.Formatters.JsonFormatter.SerializerSettings.TypeNameHandling = Newtonsoft.Json.TypeNameHandling.Auto;

The setting will let json.net to save type name in the payload if the runtime type is different with the declare type. When you post it back, json.net will deserialize the payload to the type you specified in the payload.

A sample payload looks like:

{"$type":"MvcApplication2.Models.Car, MvcApplication2","SeatCount":10,"WheelCount":4,"Model":0,"Brand":null}]
like image 61
Hongye Sun Avatar answered Sep 28 '22 06:09

Hongye Sun