WebApi and AngularJS: Mapping parameter objects

Looks like the parameter behavior between MVC and WebApi is slightly different, mainly because WebApi can only get one parameter from the Body which forces us to use request models.

I am working with Angular resources and I have found certain problems to connect to Web API services due to the different way of thinking or structuring the data. Let’s see some workarounds:

Sending an array of objects

If you try to send an Array, in AngularJS you may assign the Body by forming it into parameters with something like this (just because it’s the usual way we add them):

myResource.post({ myItems: myItems })

Which results in a JSON like this:

{myItems: [{"Id": 0, "Name": "Blah"}, {"Id": 1, "Name": "Bleh"}]}

And this is how your Controller signature looks like:

public async Task<HttpResponseMessage> Post([FromBody]IEnumerable<ItemModel> MyItems)

That won’t work as the WebApi Controller is expecting just one parameter and such parameter to come directly, no struct, no “key”, this is the way it expects it to arrive:

[{"Id": 0, "Name": "Pepe"}, {"Id": 1, "Name": "John"}]

Solution

To send an array of items in AngularJS you must send the array directly:

    myResource.post(myItems);

Sending more than one parameter

But sometimes we really need to send more than just one object or one array of objects:

// AngularJS Resource
myResource.post({ user: user, product: product });

Which would form a JSON like this:

{User: {Id: 9, Name: "Jake"}, Product: {Id: 1, Name: "ProdName", Desc: "Prod desc"}}

It won’t work, it may be able to parse the first object, User, but won’t parse the second.

Solution

In such case, the best solution is to build a RequestModel in the .Net service, that is just one object in essence, and can have more subobjects inside of it:

public class MyControllerPostModel
        {
            public IUser User { get; set; }
            public IProduct Product{ get; set; }
        }

public async Task<HttpResponseMessage> Post([FromBody]MyControllerPostModel model) 
{ ... }

Leave a Reply

Your email address will not be published. Required fields are marked *