POST to Web API action with IEnumerable<Interface> type parameter
asp.net, asp.net-mvc, asp.net-web-api, c#, dotnet-httpclient
Solution
I figured out how to do it without a custom model binder. Posting the answer in case anyone else has this issue...
Client:
// Create list of messages that will be sent
IEnumerable<IMessageApiEntity> messages = new List<IMessageApiEntity>();
// Add messages to the list here.
// They are all different types that implement the IMessageApiEntity interface.
// Create http client
HttpClient client = new HttpClient {BaseAddress = new Uri(ConfigurationManager.AppSettings["WebApiUrl"])};
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// Post to web api (this is the part that changed)
JsonMediaTypeFormatter json = new JsonMediaTypeFormatter
{
SerializerSettings =
{
TypeNameHandling = TypeNameHandling.All
}
};
HttpResponseMessage response = client.PostAsync("Communications/Messages", messages, json).Result;
// Read results
IEnumerable<ApiResponse<IMessageApiEntity>> results = response.Content.ReadAsAsync<IEnumerable<ApiResponse<IMessageApiEntity>>>().Result;
Add to `Register` method in WebApiConfig.cs:
config.Formatters.JsonFormatter.SerializerSettings.TypeNameHandling = TypeNameHandling.Auto;
The key is to send the type as part of the json and turn on automatic type name handling, so that web API can figure out what type it is.
Problem
I am trying to post to a Web API method from a client, as follows: ``` // Create list of messages that will be sent IEnumerable<IMessageApiEntity> messages = new List<IMessageApiEntity>(); // Add messages to the list here. // They are all different types that implement the IMessageApiEntity interface. // Create http client HttpClient client = new HttpClient {BaseAddress = new Uri(ConfigurationManager.AppSettings["WebApiUrl"])}; client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); // Post to web api HttpResponseMessage response = client.PostAsJsonAsync("Communications/Messages", messages).Result; // Read results IEnumerable<ApiResponse<IMessageApiEntity>> results = response.Content.ReadAsAsync<IEnumerable<ApiResponse<IMessageApiEntity>>>().Result; ``` My Web API controller action looks like this: ``` public HttpResponseMessage Post([FromBody]IEnumerable<IMessageApiEntity> messages) { // Do stuff } ``` The problem I am having is that `messages` is always empty (but not null) when coming into the web API controller action. I have verified in the debugger that the `messages` object on the client side does have items in it right before being posted. I suspect it might have something to do with the interface type not being converted to a concrete type when trying to pass the objects, but I don't know how to go about making it work. How can I achieve this?