1

I am currently working on an ASP.NET Core MVC project and I am facing a problem with binding collections from IFormCollection to a JSON array.

Currently I have a web application that passes data from an IFormCollection through to other Web API microservices.

So, my form collection might look something like this pseudocode:

People[0].Name="Jon Skeet"&People[1].Name="SLaks"

When it is posted to my MVC controller as an IFormCollection, it pretty much looks the same, where the keys are "People[0].Name", "People[1].Name" and the values are "Jon Skeet" and "SLaks".

This is problematic because when I eventually serialize to JSON, instead of getting this:

{ People: [ { Name: "Jon Skeet" }, { Name: "SLaks"} ] }

I get this instead:

{ "People[0].Name": "Jon Skeet", "People[1].Name": "SLaks" }

Which does not bind to [FromBody]IEnumerable<Person> People when I post from my MVC controller to my microservice's controller for obvious reasons.

So, my question is, how can I get my IFormCollection to serialize to JSON in such a way that indexed collections serialize properly to a JSON array? Is there some kind of custom converter or something else I need to implement in order to make it work?

Please note that my MVC controller must take an IFormCollection because it acts as a catch-all controller that routes to the proper microservice based on the Request URL.

Brian Driscoll
  • 19,373
  • 3
  • 46
  • 65
  • You didn't post how you are serializing, but I'd assume it's something like `JsonConvert.SerializeObject(People)`? – Camilo Terevinto May 02 '18 at 20:52
  • Yes, I’m using JsonConvert.SerializeObject on the IFormCollection. – Brian Driscoll May 02 '18 at 20:57
  • It looks like you want to populate a `JToken` hierarchy with a set of paths and values. There's nothing built in to Json.NET for that so you will need to parse the path yourself. [how to set the value of a json path using json.net](https://stackoverflow.com/q/17455052) has a partial answer that doesn't handle arrays. [Set JSON attribute by path](https://stackoverflow.com/q/33828942) and [JSON.net - Write into JSON / JObject using path string](https://stackoverflow.com/q/31929433) only work if the intermediate containers already exist. – dbc May 02 '18 at 20:59
  • Is the parameter type `IFormCollection` in your action method where the form is originally posted to? If so, have you tried change this type to `IEnumerable`? – Brad May 03 '18 at 02:55
  • Yes, it’s an IFormCollection. I cannot change the type because the controller action is a catch-all that passes the request payload on to a microservice, so it handles many different data shapes. – Brian Driscoll May 03 '18 at 12:11
  • Is it possible to change it to extract just the People data from the `IFormCollection` for sending to the microservice as the correct type? – Brad May 03 '18 at 12:25
  • Here’s the thing: the MVC controller action doesn’t know what kind of data it’s getting. It is effectively acting as a router for underlying UI microservices in a composite application. The only solution that I can think of that works is posting form data rather than JSON to the underlying microservices, but that won’t work in all cases. – Brian Driscoll May 03 '18 at 12:28

0 Answers0