I'm facing a strange bug, where .NET Core 2.1 API seems to ignore a JSON body on certain cases.
- I advised many other questions (e.g this one, which itself references others), but couldn't resolve my problem.
I have something like the following API method:
[Route("api/v1/accounting")]
public class AccountingController
{                                            sometimes it's null
                                                       ||
    [HttpPost("invoice/{invoiceId}/send")]             ||
    public async Task<int?> SendInvoice(               \/
         [FromRoute] int invoiceId, [FromBody] JObject body
    ) 
    {
        // ...                                                                   
    }
}
And the relevant configuration is:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
     services
       .AddMvcCore()
       .AddJsonOptions(options =>
        {
           options.SerializerSettings.Converters.Add(new TestJsonConverter());
        })
       .AddJsonFormatters()
       .AddApiExplorer();
     
     // ...
}
Where TestJsonConverter is a simple converter I created for testing why things doesn't work as they should, and it's simple as that:
public class TestJsonConverter : JsonConverter
{
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var token = JToken.Load(reader);
        return token;
    }
    public override bool CanRead
    {
        get { return true; }
    }
    public override bool CanConvert(Type objectType)
    {
        return true;
    }
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException("Unnecessary (would be neccesary if used for serialization)");
    }
}
Calling the api method using Postman works, meaning it goes through the JSON converter's CanConvert, CanRead, ReadJson, and then routed to SendInvoice with body containing the parsed json.
However, calling the api method using HttpWebRequest (From a .NET Framework 4, if that matters) only goes through CanConvert, then routes to SendInvoice with body being null.
The request body is just a simple json, something like:
{
    "customerId": 1234,
    "externalId": 5678
}
When I read the body directly, I get the expected value on both cases:
using (var reader = new StreamReader(context.Request.Body))
{
   var requestBody = await reader.ReadToEndAsync(); // works
   var parsed = JObject.Parse(requestBody);
}
I don't see any meaningful difference between the two kinds of requests - to the left is Postman's request, to the right is the HttpWebRequest:
To be sure, the Content-Type header is set to application/json. Also, FWIW, the HttpWebRequest body is set as follows:
using(var requestStream = httpWebRequest.GetRequestStream())
{
    JsonSerializer.Serialize(payload, requestStream);
}
And called with:
var response = (HttpWebResponse)request.GetResponse();   
Question
Why does body is null when used with HttpWebRequest? Why does the JSON converter read methods are skipped in such cases?

