0

I have a .Net Core 5 console app running on Linux (Debian 10) on an Orange Pi. I am trying to post some JSON to a Web API (also written in .Net Core 5 and hosted on Azure App Service) The API has two HTTPPOST endpoints - one to receive a single object, and a near identical one to receive an array of said object.

When I post a single object to the first endpoint, I receive a 201 Created status code response. But when I post an array of same object, the API returns a 405 response:

StatusCode: 415, ReasonPhrase: 'Unsupported Media Type', Version: 1.1, Content: System.Net.Http.HttpConnectionResponseContent, Headers: {
Server: Microsoft-IIS/10.0 Request-Context: appId= X-Powered-By: ASP.NET Set-Cookie: ARRAffinity=10f4677b6e2472959a213314a4f212e32905ecb3d38e1a47aefbb00645a0d541;Path=/;HttpOnly;Secure;Domain=eball-api.azurewebsites.net Set-Cookie: ARRAffinitySameSite=10f4677b6e2472959a213314a4f212e32905ecb3d38e1a47aefbb00645a0d541;Path=/;HttpOnly;SameSite=None;Secure;Domain=eball-api.azurewebsites.net Date: Sun, 28 Feb 2021 18:58:41 GMT Content-Length: 175
Content-Type: application/problem+json; charset=utf-8 }

This is what my console app looks like:

public partial class ReadingDto
{
    public int? Id { get; set; }
    public DateTime? TimeReceived { get; set; }
    public double? Frequency { get; set; }
    public byte? FrequencyByte { get; set; }
    public byte? Modulation { get; set; }
    public byte? AGC1 { get; set; }
    public byte? AGC2 { get; set; }
    public string RawData { get; set; }
    public bool? IsTest { get; set; }
    public bool IsReported { get; set; }
    public DateTime? TimeReported { get; set; }
}

private async Task PostReadings(List<ReadingDto> readingsDto)
{
    using (var httpClient = new HttpClient())
    {
        httpClient.BaseAddress = "https://somedomain.com/api/";
        string serializedObject = JsonSerializer.Serialize(readingsDto);
        StringContent content = new StringContent(serializedObject);
        using (var response = await httpClient.PostAsync("readings/batch", content))
        {
            Console.Write(response.IsSuccessStatusCode);
        }
    }
}

And this is what the action method looks like in the API's controller:

[Route("api/[controller]")]
[ApiController]
public class ReadingsController : Controller
{
    [HttpPost("batch")]
    public async Task<IActionResult> PostReadings([FromBody] List<ReadingDto> readingsDto)
    {
        List<Reading> readings = _mapper.Map<List<Reading>>(readingsDto);
        _context.Readings.AddRange(readings);
        await _context.SaveChangesAsync();
        return Created("GetReadings", readings);
    }
}

Any ideas? I've searched many forums, and MOST suggest replacing this line:

StringContent content = new StringContent(serializedObject);

with this

StringContent content = new StringContent(serializedObject, Encoding.UTF8, "application/json");

But When I do this, I get this error instead:

StatusCode: 400, ReasonPhrase: 'Bad Request', Version: 1.1, Content: System.Net.Http.HttpConnectionResponseContent, Headers: {
Transfer-Encoding: chunked Server: Microsoft-IIS/10.0
Request-Context: appId= X-Powered-By: ASP.NET Set-Cookie: ARRAffinity=10f4677b6e2472959a213314a4f212e32905ecb3d38e1a47aefbb00645a0d541;Path=/;HttpOnly;Secure;Domain=eball-api.azurewebsites.net Set-Cookie: ARRAffinitySameSite=10f4677b6e2472959a213314a4f212e32905ecb3d38e1a47aefbb00645a0d541;Path=/;HttpOnly;SameSite=None;Secure;Domain=eball-api.azurewebsites.net Date: Sun, 28 Feb 2021 19:07:45 GMT Content-Type: application/problem+json; charset=utf-8 }

Fabricio Rodriguez
  • 3,769
  • 11
  • 48
  • 101
  • Can you add how are you structuring the json array in body – Mocas Feb 28 '21 at 20:52
  • you would need to send as byte content, have a look at this example https://www.paddingleft.com/2018/04/11/HttpClient-PostAsync-GetAsync-Example/ – coder_b Feb 28 '21 at 23:53
  • Did you all use `ReadingCreateDto` when sending the request? But why did you provide the `ReadingDto`. I suspect that the wrong property leading this error. – Karney. Mar 01 '21 at 02:50
  • @Karney. Sorry about that - that was a copy-and-paste mistake when creating this post - I have corrected it. – Fabricio Rodriguez Mar 01 '21 at 13:35
  • After adding `Encoding.UTF8, "application/json"`, I have no error. Whether it is caused by violation of data constraints. – Karney. Mar 02 '21 at 01:52
  • 1
    You should add logging to the API that is receiving the posted request, so that you can troubleshoot this - since you are using Azure, Application Insights would be simplest. As it stands now, this question is essentially asking us to debug your code for you, which is not how Stack Overflow works. – Ian Kemp Mar 03 '21 at 13:41
  • @IanKemp Thanks for the reply Ian. Yes, that is a good suggestion. Unfortunately, i have not been able to work on this all week but tonight I will get a chance. Regarding your comment, that is debatable in my opinion. It's certainly not my expectation for anyone to debug my code. But it's entirely possible that I am making a silly mistake, which someone could've spotted immediately and answered in a few seconds. Believe me I spent two full evenings, working till 1am both nights, before I even thought of posting the question on here. – Fabricio Rodriguez Mar 04 '21 at 14:31

2 Answers2

0

I would avoid the StringContent altogether by using PostAsJsonAsync which is included in the System.Net.Http.Formatting package:

await httpClient.PostAsJsonAsync("url", readingsDto);

Also, I would suggest using IHttpClientFactory to create the HttpClient.

Francesco D.M.
  • 2,129
  • 20
  • 27
0

I managed to figure out the problem. There was a slight difference between the ReadingDto class used by the client and the ReadingDto class used by the API. The data type for the client version is a nullable integer, whereas the API version is a non-nullable integer. So the client was trying to POST a null in the Id field, which the API didn't like.

I apologize for having wasted everyone's time. Unfortunately I cannot work on this project during office hours as I'm at my job then, so I have to work on it after hours (and then only after my son falls asleep (around 10pm))! That's the problem with working late and tired!

Fabricio Rodriguez
  • 3,769
  • 11
  • 48
  • 101