How do I POST a x-www-form-urlencoded request using Fetch?
You have to put together the x-www-form-urlencoded payload yourself, like this:
var details = {
'userName': 'test@gmail.com',
'password': 'Password!',
'grant_type': 'password'
};
var formBody = [];
for (var property in details) {
var encodedKey = encodeURIComponent(property);
var encodedValue = encodeURIComponent(details[property]);
formBody.push(encodedKey + "=" + encodedValue);
}
formBody = formBody.join("&");
fetch('https://example.com/login', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
},
body: formBody
})
Note that if you were using fetch
in a (sufficiently modern) browser, instead of React Native, you could instead create a URLSearchParams
object and use that as the body, since the Fetch Standard states that if the body
is a URLSearchParams
object then it should be serialised as application/x-www-form-urlencoded
. However, you can't do this in React Native because React Native does not implement URLSearchParams
.
POST Request in Body as x-www-form-urlencoded
You are mixing things up. Those parameters grant_type, client_id, client_secret and refresh_token are not HTTP-Headers but the payload that you're sending to the server.
According to the docs (https://developers.google.com/apps-script/reference/url-fetch/url-fetch-app), this should work:
var cisurl = "https://webexapis.com/v1/access_token";
var data = {
'grant_type': 'refresh_token',
'client_id': 'abcdefg',
'client_secret': 'hijklmn',
'refresh_token': 'opqrstuvw'
};
var options = {
'method': 'post',
'payload': data
}
var response = UrlFetchApp.fetch(cisurl,options);
P.S.: Do not share your secrets on stack-overflow
How to post a x-www-form-urlencoded data properly using javascript?
You're building an array of encoded name/value pairs and passing that directly as the body
of the POST. But fetch
doesn't accept an array in that parameter.
The minimal change to your code would be to join the array using &
as the separator:
return fetch(
`${serverAddress}/api/shopProducts`,
{
method: 'POST',
body: formBody.join("&"), // <===== here
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}
). /* etc */
Alternately, use FormData
, as this is exactly what it's for: :-)
getInsideMenu(categoryid,shopid){
var formBody = new FormData();
formBody.set("categoryId", categoryid);
formBody.set("shopId", shopid);
formBody.set("page", "0");
return fetch(
`${serverAddress}/api/shopProducts`,
{
method: 'POST',
body: formBody,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}
).then((res)=>(res.json()));
}
(Depending on your needs, you might use set
or append
. The above uses set
.)
Side note 1:
This line:
).then((res)=>(res.json()));
...doesn't need most of those ()
:
).then(res => res.json());
Side note 2:
Don't forget to check for success; failing to do so is a common pitfall when using fetch
. fetch
doesn't reject on HTTP error (like 404 or 500). If you want to reject on HTTP error, you have to do it yourself:
return fetch(/*...*/)
.then(res => {
if (!res.ok) {
throw new Error(res.status);
}
return res;
})
.then(res => res.json());
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 theXMLHttpRequest.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.
ASP.NET Core Fetch POST FormData() application/x-www-form-urlencoded
Since you are sending data using FormData
the Content-Type
of your request should be application/form-data
. But as you can see in browser network tab there is some strange values between the actual data values
-----WebKitFormBoundarySomeValue
This is a boundary
separating your data entries. And the actual value of Content-Type
header should be application/form-data; boundary=-----WebKitFormBoundarySomeValue
. Since this value is generated randomly by a browser you cannot set it manually and you should just omit Content-Type
header, browser will set it for you.
headers: {
"Accept": "application/json, application/xml, text/plain, text/html, *.*"
//no content-type
}
In your controller code use [FromForm]
attribute to read request data as form data. And you should abandon using Consumes
attribute in this case since you cannot specify correct Content-Type
value because it varies between requests.
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login([FromForm]LoginModel model)
Related Topics
Please Explain the Use of JavaScript Closures in Loops
Trying to Fire the Onload Event on Script Tag
Can (A== 1 && a ==2 && A==3) Ever Evaluate to True
How to Get Node Datum on Mouseover in D3 V6
JavaScript Unit Test Tools for Tdd
JavaScript Global Event Mechanism
Angularjs with Django - Conflicting Template Tags
How to Run Gulp Tasks Sequentially One After the Other
JavaScript Scroll Event for Iphone/Ipad
Declaring Multiple Variables in JavaScript
Promise - How to Force Cancel a Promise
Javascript: Setting Location.Href Versus Location
How to Replace While Loops with a Functional Programming Alternative Without Tail Call Optimization
How to Write a Named Arrow Function in Es2015
Calling an Asynchronous Function Within a for Loop in JavaScript
What Techniques Can Be Used to Define a Class in JavaScript, and What Are Their Trade-Offs
Defining Methods via Prototype VS Using This in the Constructor - Really a Performance Difference