skip to Main Content

I’m currently writing an ASP.NET Core web service and I want to setup an endpoint receiving JSON data in a string. I don’t want to have it parsed before the endpoint starts.

I’ve defined this endpoint:

[HttpPost]
[Route("pushjson/{channelCode}")]
public async Task<string> PushJson(string channelCode,
    [FromBody]string jsonData)
{
    return await mediator.Send(new PushJsonCommand(channelCode, jsonData));
}

I’m sending a standard request with a JSON object in the body and I get the following error:

Unexpected character encountered while parsing value: {. Path ”, line 1, position 1.

The jsonData field is required.

So it seems that the framework tries to parse the provided data, which is definitely not expected. The following code will decide how to handle and process the JSON data based on the configuration, so a pre-parsing is just a waste of time.

How can I configure this endpoint to tell the framework to only store the body data unprocessed and unparsed into a string and provide it to my method?

Changing the code to receive a JObject lets the code work, but then I do have an unneeded parsing and an unneeded serialization which costs CPU time for nothing.

[HttpPost]
[Route("pushjson/{channelCode}")]
public async Task<string> PushJson(string channelCode,
                                   [FromBody]JObject jsonData)
{
    return await mediator.Send(new PushJsonCommand(channelCode, JsonSerializer.Serialize(jsonData)));
}

2

Answers


  1. Seems ASP.NET automatically parses the body using JsonSerializer, see remarks here:

    Remarks

    By default, ASP.NET Core MVC delegates the responsibility of reading
    the body to an input formatter. In the case of ASP.NET Core Minimal
    APIs, the body is deserialized by JsonSerializer.

    I’d wager that, when you’ve got an [HttpPost] that doesn’t specify the Content Type that it consumes, it’s assumed to be "application/json", try adding this attribute above your endpoint:

    [Consumes("text/plain")]

    Login or Signup to reply.
  2. In ASP.NET Core, the default behavior for [FromBody] is to deserialize the JSON data into a model object. When you pass a string to [FromBody], ASP.NET Core still expects to deserialize it, leading to the error you’re encountering.

    You could manually read the body stream and treat it as a plain string like below:

    [HttpPost]
    [Route("pushjson/{channelCode}")]
    public async Task<string> PushJson(string channelCode)
    {
        using (var reader = new StreamReader(Request.Body))
        {
            string jsonData = await reader.ReadToEndAsync();
            return await mediator.Send(new PushJsonCommand(channelCode, jsonData));
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search