Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C#/.NET POST request keeps returning 400 Bad Request in controller

Tags:

c#

bad-request

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.

Edit

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: enter image description here

POST: enter image description here

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.

like image 725
OCP30pt1c1l1l43-X1z17 Avatar asked Sep 17 '25 15:09

OCP30pt1c1l1l43-X1z17


1 Answers

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.

like image 109
OCP30pt1c1l1l43-X1z17 Avatar answered Sep 19 '25 04:09

OCP30pt1c1l1l43-X1z17