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
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!
I would avoid the
StringContent
altogether by usingPostAsJsonAsync
which is included in theSystem.Net.Http.Formatting
package:Also, I would suggest using
IHttpClientFactory
to create theHttpClient
.