Corstiaan
Corstiaan

Reputation: 1114

Asp.net core 2.0 POST endpoint works without json payload, but fails (400 Bad request) with a json payload

I have the following endpoint in my asp.net core 2.0 app:

[HttpPost("postself")]
public IActionResult post([FromBody]JObject email)
{
    try
    {
        var service = new EmailService();
        var emailHtml = service.GenerateEmail(email.ToString(), false);
        return Json(new { Email = emailHtml });
    }
    catch
    {
        return Json(new { Email = "error" });
    }
}

When calling the API like so:

curl -X POST \
  http://myapp/api/v1/emails/postself \
  -H 'cache-control: no-cache' \
  -H 'content-type: application/json' \
  -H 'postman-token: 85c9bbe7-2112-0746-5f41-8dc01b52ab59'

The endpoint gets hit and returns at return Jason(new { Email = "error" }); so that works. It returns error because the JObject is null but still this is expected behavior.

However, when calling the API like so (with JSON payload):

curl -X POST \
  http://myapp/api/v1/emails/postself \
  -H 'cache-control: no-cache' \
  -H 'content-type: application/json' \
  -H 'postman-token: a80c85de-8939-01d8-4a5d-c2108bf1491d' \
  -d '{
  "body": [
    {
      "image": {
        "url": "mailing_logo_slice.png",
        "alt": "This is my logo"
      }
    }
  ]
}'

...my app returns 400 Bad request.

Also, the requests work in development, but only returns 400 in production.

Any ideas?

=========

Updated code:

[HttpPost("postself")]
public IActionResult PostSameDomain([FromBody]string email)
{
    try
    {
        var service = new EmailGenerationService();
        var emailHtml = service.GenerateEmailFromJson(email, false);
        return Json(new { Email = emailHtml });
    }
    catch
    {
        return Json(new { Email = "error" });
    }
}

[HttpPost("test")]
        public IActionResult PostSameDomain([FromBody]EmailViewModel email)
        {
            try
            {
                var service = new EmailGenerationService();
                var emailHtml = service.GenerateEmailFromJson(email.Raw, false);
                return Json(new { Email = emailHtml });
            }
            catch
            {
                return Json(new { Email = "error" });
            }
        }

Upvotes: 1

Views: 716

Answers (3)

Corstiaan
Corstiaan

Reputation: 1114

For anyone else stumbling onto this issue, this was the root of the problem.

Thanks to everybody for thinking along with my issue.

Upvotes: 0

Marc LaFleur
Marc LaFleur

Reputation: 33132

I believe your problem here is that you're passing in an JSON Array and attempting to deserialize it into a singular JObject.

Possible fixes:

  1. Pass in a single JSON object:

    curl -X POST \
      http://myapp/api/v1/emails/postself \
      -H 'cache-control: no-cache' \
      -H 'content-type: application/json' \
      -H 'postman-token: a80c85de-8939-01d8-4a5d-c2108bf1491d' \
      -d '{
      "body": {
          "image": {
            "url": "mailing_logo_slice.png",
            "alt": "This is my logo"
          }
        }
    }'
    
  2. Switch to JArray instead of JObject:

    [HttpPost("postself")]
    public IActionResult post([FromBody]JArray email)
    {
        try
        {
            var service = new EmailService();
            var emailHtml = service.GenerateEmail(email.ToString(), false);
            return Json(new { Email = emailHtml });
        }
        catch
        {
            return Json(new { Email = "error" });
        }
    }
    
  3. Take in the data as a string and deserialize it within. This would allow you to test if you've received an array or a single object and then deserialize to a JObject or JArray as needed (this would be my personal recommendation for what its worth).

Upvotes: 2

Ricardo Peres
Ricardo Peres

Reputation: 14555

JObject is specific to Newtonsoft.Json and will not work. Please specify a POCO class that contains url and alt properties.

Upvotes: 2

Related Questions