asp.net-core-webapijson-deserializationhttpcontent

How to retrieve JSON data from HttpContent


I'm buildin a console Web API to communicate with a localhost server, hosting computer games and highscores for them. Every time I run my code, I get this charming error:

fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1] An unhandled exception has occurred while executing the request.

System.NotSupportedException: Deserialization of types without a parameterless constructor, a singular parameterized constructor, or a parameterized constructor annotated with 'JsonConstructorAttribute' is not supported. Type 'System.Net.Http.HttpContent'. Path: $ | LineNumber: 0 | BytePositionInLine: 1.

This is the method I'm using to post to the database. Note that this method is not in the console application. It is in the ASP.NET Core MvC application opening a web browser and listening for HTTP requests (which can come from the console application).


[HttpPost]
public ActionResult CreateHighscore(HttpContent requestContent)
{
    string jasonHs = requestContent.ReadAsStringAsync().Result;
    HighscoreDto highscoreDto = JsonConvert.DeserializeObject<HighscoreDto>(jasonHs);

    var highscore = new Highscore()
    {
        Player = highscoreDto.Player,
        DayAchieved = highscoreDto.DayAchieved,
        Score = highscoreDto.Score,
        GameId = highscoreDto.GameId
    };

    context.Highscores.Add(highscore);
    context.SaveChanges();
    return NoContent();
}

I'm sending POST requests in a pure C# console application, with information gathered from user input, but the result is exactly the same when using Postman for post requests - the above NotSupportedException.

private static void AddHighscore(Highscore highscore)
{
    var jasonHighscore = JsonConvert.SerializeObject(highscore);
    Uri uri = new Uri($"{httpClient.BaseAddress}highscores");
    HttpContent requestContent = new StringContent(jasonHighscore, Encoding.UTF8, "application/json");

    var response = httpClient.PostAsync(uri, requestContent);
    if (response.IsCompletedSuccessfully)
    {
        OutputManager.ShowMessageToUser("Highscore Created");
    }
    else
    {
        OutputManager.ShowMessageToUser("Something went wrong");
    }
}

I'm new to all this HTTP requests stuff, so if you spot some glaring errors in my code, that would be appreciated. Though, the most important question is, what am I missing, and how can I read from the HttpContent object, to be able to create a Highscore object to send to the database?

It seems to be the string jasonHs... line that is the problem, since the app crashed in exactly the same way, when I commented out the rest of the ActionResult method.


Solution

  • Based on your code, we can find that you make a HTTP Post request with a json string data (serialized from a Highscore object) from your console client to Web API backend.

    And in your action method, you create an instance of Highscore manually based on received data, so why not make your action accept a Highscore type parameter, like below. Then the model binding system would help bind data to action parameter(s) automatically.

    [HttpPost]
    public ActionResult CreateHighscore([FromBody]Highscore highscore)
    {
        //...