skip to Main Content

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 }

2

Answers


  1. Chosen as BEST ANSWER

    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!


  2. 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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search