I am trying to write a simple API te receive POST requests with a body. When I try to test my method it keeps resulting in a 400 bad request in Postman. I first thought the issue was with deserializing the JSON body. So to be sure I stripped out that logic from the controller, but the request still returned a 400 status code.
So I removed everything from my method except for the method itself, only returning Ok('Hello World');
and still the response was a 400.
What I have left for now is this:
[Route("api/v1/service/")]
public class ServiceController : Controller
{
public ServiceController()
{
}
[HttpGet("get")]
public IActionResult Get()
{
return Ok("GET works fine");
}
[HttpPost("post")]
public IActionResult Post()
{
return Ok("Hello World"); // <-- Keeps returning 400
}
}
The GET method works fine, but when I sent an empty POST call to /api/v1/service/post
in Postman I get a bad request.
I also noticed that when I change the route to something different or random that does not exists it also gets a 400, instead of a 404.
So making a POST call to api/v1/service/this-route-is-not-defined
also results in a bad request.
I keep changing small things in my request form adding/removing ContentType or Accept headers and adjusting my StartUp.cs
. But every POST call I make to .NET seems to result in a 400 status code.
This might be related to the routing in Startup.cs
:
app.UseHsts();
app.UseMvc(routes =>
{
});
app.UseRouting();
This is the request in POST man:
GET:
POST:
The code in the sample was offcourse altered from my original API method, but the idea is the same. I copied the sample to a new file in my project and clicked in Postman on create new request. So headers are the default ones.
First of all, the answers and comments given to this question were all helpfull.
I found the culprit. Apperently there was an option enabled in the Startup.cs
file that puts an anti-forgery token check on all API calls that can modify stuff, like POST, PUT, DELETE. This is not an issue when calling the API from the frontend with a Javascript fetch()
for instance. The token is added to a tag in the document and you can add to the request headers like this:
headers.append('X-XSRF-TOKEN', (document.getElementsByName("__RequestVerificationToken")[0] as any).value)
To be able to make a POST call from Postman for instance you can add this line temporarely above your action.
[IgnoreAntiforgeryToken]
So working example would like this:
[Route("api/v1/service/")]
public class ServiceController : Controller
{
public ServiceController()
{
}
[HttpGet("get")]
public IActionResult Get()
{
return Ok("GET works fine");
}
[IgnoreAntiforgeryToken]
[HttpPost("post")]
public IActionResult Post()
{
return Ok("Hello World"); // <-- Keeps returning 400
}
}
It is important to think about when to use [IgnoreAntiforgeryToken]
and not to use it. On methods that allready expect an API key for instance you can use it in a production environment. But when method is public the anti-forgery token is a way of protecting your method from attackers or people/robots trying to spam your API.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With