In ASP.NET 5, MVC and Web API have been merged into a single framework called MVC 6. If you are deep into Web API and MVC in the previous versions of ASP.NET, like me, it will take some time to get used to how binding works in MVC 6. Especially, if you are more into Web API in the recent past than MVC, like me, you will actually feel sad to see that the things you are so used to with Web API are all gone and it is different now : (.
As the name indicates, MVC 6 is actually MVC, when it comes to binding. Well, it is MVC with Web API stuff bolted on, perhaps.
Let’s see some examples now.
| Action Method | Request Message | Binding Result |
| public void Post(string name) |
POST http://localhost:10725/api/values?name=23 HTTP/1.1 Content-Type: application/x-www-form-urlencoded Host: localhost:10725 Content-Length: 7 name=34 |
name is set to 23, since query string wins over form data. |
| public void Post([FromForm]string name) |
POST http://localhost:10725/api/values?name=23 HTTP/1.1 Content-Type: application/x-www-form-urlencoded Host: localhost:10725 Content-Length: 7 name=34 |
name is set to 34, since you are specifically asking for it through [FromForm]. |
| public void Post(string name) |
POST http://localhost:10725/api/values HTTP/1.1 Content-Type: application/x-www-form-urlencoded Host: localhost:10725 Content-Length: 7 name=34 |
name is set to 34. Despite being simple type, name is set from body by default, because the body is form data (one of MVC’s favorites). |
| public void Post([FromBody]string name) |
POST http://localhost:10725/api/values HTTP/1.1 Content-Type: application/x-www-form-urlencoded Host: localhost:10725 Content-Length: 7 name=34 |
name is null, because for formatting body, we have only JSON and XML formatters. |
| public void Post([FromBody]string name) |
POST http://localhost:10725/api/values?name=20 HTTP/1.1 Content-Type: application/json Host: localhost:10725 Content-Length: 17 {“name” : “john”} |
Error, because JSON.NET is not happy with the JSON provided, which is for a complex type. |
| public void Post([FromBody]string name) |
POST http://localhost:10725/api/values?name=20 HTTP/1.1 Content-Type: application/json Host: localhost:10725 Content-Length: 6 “john” |
name is set to john, since we specifically ask for binding from body. |
|
public void Post(Person p)
public class Person |
POST http://localhost:10725/api/values?name=20 HTTP/1.1 Content-Type: application/json Host: localhost:10725 Content-Length: 30 {“Name” : “John”, “Age” : 24 } |
p.Name is set to 20 from query string. Despite being complex type, Person is being bound from query string, even though body with JSON is available. |
| public void Post(Person p) |
POST http://localhost:10725/api/values HTTP/1.1 Content-Type: application/json Host: localhost:10725 Content-Length: 30 {“Name” : “John”, “Age” : 24 } |
p is not null but p.Name is null and p.Age is 0. Despite being complex type, body is not used for binding. |
| public void Post(Person p) |
POST http://localhost:10725/api/values?name=b&age=2 HTTP/1.1 Content-Type: application/json Host: localhost:10725 Content-Length: 30 {“Name” : “John”, “Age” : 24 } |
p.Name is set to b and p.Age is set to 2 from query string. Again, despite being complex type, Person is being bound from query string even if body is present. Query string rules! |
| public void Post([FromBody]Person p) |
POST http://localhost:10725/api/values?name=b&age=2 HTTP/1.1 Content-Type: application/json Host: localhost:10725 Content-Length: 30 {“Name” : “John”, “Age” : 24 } |
p.Name and p.Age are set to John and 24 from JSON. At last, Web API 2 like behavior but we need to ask for body to be used for binding using FromBody. |
| public void Post([FromBody]Person p, Person q) |
POST http://localhost:10725/api/values?name=b&age=2 HTTP/1.1 Content-Type: application/json Host: localhost:10725 Content-Length: 30 {“Name” : “John”, “Age” : 24 } |
p is bound from JSON and q is bound from query string. |
| public void Post(Person p) |
POST http://localhost:10725/api/values?name=b&age=2 HTTP/1.1 Content-Type: application/x-www-form-urlencoded Host: localhost:10725 Content-Length: 16 name=john&age=24 |
p.Name is set to b and p.Age is set to 2. Again, query string rules! |
| public void Post(Person p) |
POST http://localhost:10725/api/values HTTP/1.1 Content-Type: application/x-www-form-urlencoded Host: localhost:10725 Content-Length: 16 name=john&age=24 |
p.Name is set to john and p.Age is set to 24. This is similar to Web API in that complex type is bound from body. In fact, this is only a coincidence. As far MVC is concerned, it is doing MVC binding using the form data. |
| public void Post([FromBody]Person p) |
POST http://localhost:10725/api/values HTTP/1.1 Content-Type: application/x-www-form-urlencoded Host: localhost:10725 Content-Length: 16 name=john&age=24 |
p is null, because form data cannot be bound using the formatters available: JSON and XML. We are specifically asking for body but MVC 6 cannot read form data using the formatters. |
| public void Post([FromForm]Person p) |
POST http://localhost:10725/api/values HTTP/1.1 Content-Type: application/x-www-form-urlencoded Host: localhost:10725 Content-Length: 16 name=john&age=24 |
p.Name is set to john and p.Age is set to 24. MVC 6 is happy because now we are asking the body to be treated as form data. |
| public void Post(List<Person> p) |
POST http://localhost:10725/api/values HTTP/1.1 Content-Type: application/x-www-form-urlencoded Host: localhost:10725 Content-Length: 52 p[0].name=john&p[0].age=24&p[1].name=joe&p[1].age=28 |
p(0).Name is john p(0).Age is 24 p(1).Name is joe p(1).Age is 28 MVC all over the place! |
| public void Post(List<string> p) |
POST http://localhost:10725/api/values HTTP/1.1 Content-Type: application/x-www-form-urlencoded Host: localhost:10725 Content-Length: 7 p=1&p=2 |
p(0) = 1 p(1) = 2 |
| public void Post(List<string> p) |
POST http://localhost:10725/api/values?p=20&p=30 HTTP/1.1 Content-Type: application/x-www-form-urlencoded Host: localhost:10725 Content-Length: 7 p=1&p=2 |
p(0) = 20 p(1) = 30 |
awesome thank you
I like your example-based approach, great!
This is the best illustration I’ve ever seen.
Thank you so much.
Great stuff! Thank you
This was very very helpful and a clear presentation. Thank you
Thank you for the list, this does seem completely backwards though! All I want to do is post JSON data back to a controller and get those values.
– I dont want to use query parameters (this isnt a right fit for POST data)
– I dont want to have to create a model solely to accept this data (a waste of time / effort)
– I’d rather not have to convert my JSON data into form-like data just to send it back
ARGH!
This is great information
Very useful. Save me much time, good job.
Thank you for this article.
Thank you! It solved my problem to use web api 2 with POST data.
Very helpful. Thank you.