How do I post form data with fetch api? How do I post form data with fetch api? ajax ajax

How do I post form data with fetch api?


To quote MDN on FormData (emphasis mine):

The FormData interface provides a way to easily construct a set of key/value pairs representing form fields and their values, which can then be easily sent using the XMLHttpRequest.send() method. It uses the same format a form would use if the encoding type were set to "multipart/form-data".

So when using FormData you are locking yourself into multipart/form-data. There is no way to send a FormData object as the body and not sending data in the multipart/form-data format.

If you want to send the data as application/x-www-form-urlencoded you will either have to specify the body as an URL-encoded string, or pass a URLSearchParams object. The latter unfortunately cannot be directly initialized from a form element. If you don’t want to iterate through your form elements yourself (which you could do using HTMLFormElement.elements), you could also create a URLSearchParams object from a FormData object:

const data = new URLSearchParams();for (const pair of new FormData(formElement)) {    data.append(pair[0], pair[1]);}fetch(url, {    method: 'post',    body: data,}).then(…);

Note that you do not need to specify a Content-Type header yourself.


As noted by monk-time in the comments, you can also create URLSearchParams and pass the FormData object directly, instead of appending the values in a loop:

const data = new URLSearchParams(new FormData(formElement));

This still has some experimental support in browsers though, so make sure to test this properly before you use it.


Client

Do not set the content-type header.

// Build formData object.let formData = new FormData();formData.append('name', 'John');formData.append('password', 'John123');fetch("api/SampleData",    {        body: formData,        method: "post"    });

Server

Use the FromForm attribute to specify that binding source is form data.

[Route("api/[controller]")]public class SampleDataController : Controller{    [HttpPost]    public IActionResult Create([FromForm]UserDto dto)    {        return Ok();    }}public class UserDto{    public string Name { get; set; }    public string Password { get; set; }}


You can set body to an instance of URLSearchParams with query string passed as argument

fetch("/path/to/server", {  method:"POST", body:new URLSearchParams("email=test@example.com&password=pw")})

document.forms[0].onsubmit = async(e) => {  e.preventDefault();  const params = new URLSearchParams([...new FormData(e.target).entries()]);  // fetch("/path/to/server", {method:"POST", body:params})  const response = await new Response(params).text();  console.log(response);}
<form>  <input name="email" value="test@example.com">  <input name="password" value="pw">  <input type="submit"></form>