Just following all the examples in ChatGTP and Google but my first use of javascript fetch with POST always returns 400. (I have a fetch using GET which works fine so I don't understand why POST fails.)
Here is the Fetch javascript code:
async function FetchPost() {
let data = { a: 1, b: 2 };
let json = JSON.stringify(data);
try {
const response = await fetch('/FetchDemo?handler=Fetch',
{
method: 'POST',
// adding mode, cache and credentials did not help
mode: 'cors',
cache: 'no-cache',
credentials: 'same-origin',
headers: { 'Content-Type': 'application/json' },
body: json
});
if (response.ok) {
data = await response.json();
} else {
throw new exception(response.statusText);
}
} catch (error) {
data = 'Error fetching data:' + error;
}
return data;
}
Here is the OnGet (which works) and the OnPost method but it is never executed. The Network log in the browser shows the 400 status.
public class FetchDemoModel : PageModel {
public void OnGet() {
}
// This always works
public IActionResult OnGetFetch(string action, string identity) {
string data = "";
switch(action.ToLower()) {
case "find":
break;
default:
data = "action=" + action + ", identity=" + identity;
break;
}
return new JsonResult(data);
}
// This code is never executed
public IActionResult OnPostFetch() {
string data = "";
return new JsonResult(data);
}
}
For completeness and comparison here is the javascript fetch GET which works.
async function FetchGet(action, identity) {
let data = null;
try {
let url = '/FetchDemo?handler=Fetch&action=' + action + "&identity=" + identity;
const response = await fetch(url,
{
method: 'GET',
});
if (response.ok) {
data = await response.json();
} else {
throw new exception(response.statusText);
}
} catch (error) {
data = 'Error fetching data:' + error;
}
return data;
}
I have checked all the issues which ChatGPT says may cause a 400 error to no avail. Can you help diagnose this?
The POST request is missing the required request verification token:
In short, you can either switch off request verification for the PageModel class by adding an IgnoreAntiforgeryToken
attribute to it:
[IgnoreAntiforgeryToken(Order = 10001)]
public class FetchDemoModel : PageModel
{
....
Or you can generate a hidden field using the Html.AntiForgeryToken
helper in the view file and include it in the request headers:
var token = document.querySelector('input[name="__RequestVerificationToken"]').value;
fetch(..., {
method: "post",
headers: {
"RequestVerificationToken": token
},
body: { foo: "bar" }
}).then(() => {
...
});