JavaScript Fetch With .NET Core WebAPI: Fetch Method Examples For Auto Binding

(Auto)Binding: The Struggle Is Real

For additional details and sample code read my article at CodeProject.com:
GitHub – raddevus/BindApi: Sample code for article for using auto-bind in dotnet webapi and JavaScript Fetch[^]

If you use JavaScript Fetch API to make requests to a .NET Core WebAPI and expect Model Binding and Parameter Binding to just-work, you may run into some problems as I have.  Yesterday, I was trying to get a call to the simplest WebAPI method to work and it kept failing.

Here’s the method I was trying to hit using JS Fetch:

public ActionResult RegisterUser(string uuid)
I tried all manner of Fetch calls to get it working.  Anyways, it annoyed me enough that I decided to write up an article that maps a number of exact Fetch calls to WebAPI methods so I can never forget how it is done for every type ([FromBody], [FromQuery], [FromForm], etc.)

FromQuery

I’ll start out with the first one I got working.

FromQuery WebAPI Defined This Way

I defined the WebAPI method in the following way:

[HttpPost] publicActionResultRegisterUser([FromQuery] string uuid)

JavaScript Fetch Call For FromQuery

I then defined my JS Fetch call like the following:

fetch(`${baseUrl}User/RegisterUser?uuid=${currentUuid}`,{
method:'POST',
})
.then(response => response.json())
.then(data => console.log(data));

The important parts to recognize is that we are adding the string named uuid (exact same name as the WebAPI parameter) to the queryString.

FromForm WebAPI Method

[HttpPost] publicActionResultRegisterUser([FromForm] string uuid)

JavaScript Fetch Call For FromForm

// 1. Create the FormData object
var fd = new FormData();
// 2. Append the name/value pair(s) for values you want to send
fd.append("uuid", currentUuid);
fetch(`${baseUrl}User/RegisterUser`,{
      method:'POST',
     body:fd,   // add the FormData object to the body data which will be posted
})
.then(response => response.json())
.then(data => console.log(data));

FromBody WebAPI Method

I decided to see what would happen if I change the method Parameter to [FromBody] but not make the change to the JavaScript from the previous example (FromForm).

415 Error

When I did that and posted I got a 415 error (unsupported media type).

I gave up on that idea and then defined the WebAPI method with FromBody also.

FromBody WebAPI Method: The Big Issue

I know defined the WebAPI method like the following:

public ActionResult RegisterUser([FromBody] string uuid)

Spoiler Alert:  Here’s The Explanation

But as you’ll see, it is not possible to post to this method with a uuid as a string value.   That’s because, as we will discover, the WebAPI method is expecting to parse an object that contains a member named uuid.

JavaScript Fetch Call For FromBody

Second Try

I then tried the following set up for the data that I wanted to send:

varpostdata= {"uuid":currentUuid};
fetch(`${baseUrl}User/RegisterUser`,{
        method:'POST',
       body:JSON.stringify(postdata), 
       headers: {
             "Content-Type":"application/json",
        },
  })
  .then(response => response.json())
 .then(data => console.log(data));

Notice that I have now added the header object to the fetch object.  The header object allows us to send the Content-Type header to let the receiving application know that we are posting JSON.

500 Error

When I posted, I received a 500 error but that was because I was attempting to use the value on the server side even though it hadn’t been supplied.

Nothing Works With WebAPI FromBody & String Parameter

The point is that the .NET Core auto-binding never works with any string you post to the method.

That’s because the auto-binding is expecting an object which contians a string named uuid.

You’d have to re-define the WebAPI method like the following:

[HttpPost] public ActionResult RegisterUser2([FromBody] Id uuid)
You’d then have to create the Id class like the following:
public class Id{
     public string uuid{get;set;}
}
Next, you’d have to create your Fetch to look like the following:
fetch(`/User/RegisterUser2`,{
     method: 'POST',
     body:
          "{\"uuid\":\"test-this-value-10987\"}",
      headers: {
           'Content-type':'application/json; charset=UTF-8',
       },
})
.then(response => response.json())
.then(data => console.log(data));

WebAPI Demands An Object

The WebAPI knows that a JSON object is coming in the body.  You can’t get away from that, because the body is defined between the two { } curly brackets and that defines an object.

You can also create your postdata object (create an actual JavaScript object that contains the expected name (uuid) / value and then call stringify to post like the following:

var postdata = {uuid:"my-id-value-12345"};

fetch(`/User/RegisterUser2`,{
      method: 'POST',
      body:
      JSON.stringify(postdata),
        headers: {
           'Content-type':'application/json; charset=UTF-8',
       },
})
.then(response => response.json())
.then(data => console.log(data));

FromHeader WebAPI Method: This One Seems Odd, But Works

Define the method like the following:

public ActionResult RegisterUser( [FromHeader] string uuid)

FromHeader JavaScript Fetch API

fetch(`/User/RegisterUser`,{
    method: 'POST',
     headers:{ "content-type":"UTF-8",
             "uuid":"1234-4578-838298"},
})
.then(response => response.json())
.then(data => console.log(data));

It works.  It’s a lot easier than the FromBody one.  But I’m not sure why we’d pass the value in the headers like this.  It seems a bit odd.  But, it means you can auto-bind values in the headers to your WebAPI methods and that is interesting.

There are a couple of other methods which are new to .NET Core 8.x (FromServices, FromKeyedServices) so I will not cover them for now.

Hope this helps someone who is stuck on that crazy [FromBody] one.  It is quite tricky.

Leave a Reply