CB_at_Sw
CB_at_Sw

Reputation: 397

Microsoft.AspNetCore.Http.BadHttpRequestException: Failed to read parameter "xxx" from the request body as JSON

I have a React TypeScript application which makes a call to a C# ASP.NET Core 7 Minimal API.

The call from the React app looks like this:

const resp = await Client.post('https://localhost:7196/institutions', JSON.stringify(doc));

Client is defined as follows:

import axios from 'axios';
import { jsonrepair } from 'jsonrepair';

export class Client {
    static async post(url: string, jsonData: string) {
        const headers = {
            headers: { 'Content-Type': 'application/json' }
        };
        try {
            const response = await axios.post(url, jsonrepair(jsonData), headers );
            return response?.data;
        } catch (e) {
            return e.message;
        }
    }
}

The relevant C# code in my minimal API is as follows:

app.MapPost("/institutions", async ([FromBody]string instJson, InstitutionDb instDb, [FromHeader(Name = "Content-Type")] string contentType) =>
{
    var inst = JsonSerializer.Deserialize<Institution>(instJson);
    if (inst != null)
    {
        instDb.Institutions.Add(inst);
        await instDb.SaveChangesAsync();
        return Results.Created($"/institutions/{inst.Id}", inst);
    }
    return null;
});

However, when executing it - even after verifying that the JSON being passed is legitimate (after being cleaned with the TypeScript jsonrepair utility), I receive the following error:

Microsoft.AspNetCore.Http.BadHttpRequestException: Failed to read parameter "string instJson" from the request body as JSON. ---> System.Text.Json.JsonException: The JSON value could not be converted to System.String. Path: $ | LineNumber: 0 | BytePositionInLine: 1. ---> System.InvalidOperationException: Cannot get the value of a token type 'StartObject' as a string. at System.Text.Json.ThrowHelper.ThrowInvalidOperationException_ExpectedString(JsonTokenType tokenType) at System.Text.Json.Utf8JsonReader.GetString() at System.Text.Json.Serialization.JsonConverter1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value) at System.Text.Json.Serialization.JsonConverter1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state) --- End of inner exception stack trace --- at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& state, Utf8JsonReader& reader, Exception ex) at System.Text.Json.Serialization.JsonConverter1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state) at System.Text.Json.Serialization.JsonConverter1.ReadCoreAsObject(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state) at System.Text.Json.JsonSerializer.ReadCore[TValue](Utf8JsonReader& reader, JsonTypeInfo jsonTypeInfo, ReadStack& state) at System.Text.Json.JsonSerializer.ContinueDeserialize[TValue](ReadBufferState& bufferState, JsonReaderState& jsonReaderState, ReadStack& readStack, JsonTypeInfo jsonTypeInfo) at System.Text.Json.JsonSerializer.ReadFromStreamAsync[TValue](Stream utf8Json, JsonTypeInfo jsonTypeInfo, CancellationToken cancellationToken) at Microsoft.AspNetCore.Http.HttpRequestJsonExtensions.ReadFromJsonAsync(HttpRequest request, Type type, JsonSerializerOptions options, CancellationToken cancellationToken) at Microsoft.AspNetCore.Http.HttpRequestJsonExtensions.ReadFromJsonAsync(HttpRequest request, Type type, JsonSerializerOptions options, CancellationToken cancellationToken) at Microsoft.AspNetCore.Http.RequestDelegateFactory.g__TryReadBodyAsync|90_0(HttpContext httpContext, Type bodyType, String parameterTypeName, String parameterName, Boolean allowEmptyRequestBody, Boolean throwOnBadRequest) --- End of inner exception stack trace --- at Microsoft.AspNetCore.Http.RequestDelegateFactory.Log.InvalidJsonRequestBody(HttpContext httpContext, String parameterTypeName, String parameterName, Exception exception, Boolean shouldThrow) at Microsoft.AspNetCore.Http.RequestDelegateFactory.g__TryReadBodyAsync|90_0(HttpContext httpContext, Type bodyType, String parameterTypeName, String parameterName, Boolean allowEmptyRequestBody, Boolean throwOnBadRequest) at Microsoft.AspNetCore.Http.RequestDelegateFactory.<>c__DisplayClass90_2.<b__2>d.MoveNext() --- End of stack trace from previous location --- at Microsoft.AspNetCore.Routing.EndpointMiddleware.g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger) at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)

The interesting thing is that if I debug and set a breakpoint on (or inside) app.MapPost(), the breakpoint does not get hit.

Why is this happening? Why is the endpoint failing, even with valid JSON and the content-type header being set correctly? Why am I unable to set a breakpoint in my C# code?

Any suggestions? I have searched this error extensively on StackOverflow and elsewhere. Others have reported this error but none of the solutions I've tried have worked for me.

Upvotes: 0

Views: 2595

Answers (1)

Serge
Serge

Reputation: 43931

you sending your data as a json, not as a string, so changed the header

app.MapPost("/institutions", async ([FromBody]Institution inst)

and remove deserialization code

Upvotes: 0

Related Questions