Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WebApi POST works without [FromBody]?

I have this controller action :

 [HttpPost]
 [ActionName("aaa")]
 public HttpResponseMessage aaa(Z z) //notice  - no [FromBody]
 {
    return Request.CreateResponse(HttpStatusCode.OK, 1);  
 }

Where Z is :

public class Z
 {
   public string a { get; set; }
 }

But when I post via fiddler :

POST http://localhost:11485/api/profiles/aaa HTTP/1.1
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Host: localhost:11485
Content-Length: 3
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8,he;q=0.6
Cache-Control: no-cache
Connection: keep-alive

a=1

I can actually see it is working :

enter image description here

Question:

If so , how does it working without the [FromBody] attribute ? and do I still need /not write this attribute ?

Also , what is the scenario where not writing this attribute - will cause problems ?

like image 335
Royi Namir Avatar asked Nov 22 '14 09:11

Royi Namir


People also ask

What is the use of FromBody in Web API?

Using [FromBody] When a parameter has [FromBody], Web API uses the Content-Type header to select a formatter. In this example, the content type is "application/json" and the request body is a raw JSON string (not a JSON object).

Where is the FromBody attribute applied?

The [FromBody] attribute can be applied on only one primitive parameter of an action method. It cannot be applied to multiple primitive parameters of the same action method.

What is difference between FromQuery and FromBody?

[FromQuery] - Gets values from the query string. [FromRoute] - Gets values from route data. [FromForm] - Gets values from posted form fields. [FromBody] - Gets values from the request body.


1 Answers

Binding is different for MVC and Web API. By default, ASP.NET Web API binds complex types from the request message body and simple types from URI, query string, etc. Since you specified Z, which is a class (complex type), it populates the action method parameter from body without you having to specify [FromBody]. On the other hand, if your request is http://localhost:11485/api/profiles/aaa?z=1 without a body, it will NOT bind to your complex parameter automatically. In that case, you will need to specify [FromUri] like this: public HttpResponseMessage aaa([FromUri]Z z).

On the other hand, say your action method is public HttpResponseMessage aaa(string a). We now have string, which is a simple type. In this case, http://localhost:11485/api/profiles/aaa?a=1 without a message body will let Web API bind the parameter correctly without you having to specify [FromUri]. Now, if you want to bind from body in this case, you will need to specify public HttpResponseMessage aaa([FromBody]string a). Of course, for this body must be =1, for application/x-www-form-urlencoded, without the key name of a.

Bottom line - your parameter (simple type or complex type) determines how Web API binds. To make it work differently from the default behavior, you need to tell via FromUri or FromBody.

PS. Whatever I mentioned above holds good purely for the good old ASP.NET Web API (including 2). In ASP.NET 5.0 a.k.a ASP.NET vNext or ASP.NET MVC 6.0, MVC and Web API have been unified. In order for it to bind a complex type from body, you must specify [FromBody].

like image 82
Badri Avatar answered Oct 22 '22 04:10

Badri