dotnet http_error ai_generated true

BadHttpRequestException: Failed to read parameter from the request body as JSON.

ID: dotnet/minimal-api-binding

Also available as: JSON · Markdown
89%Fix Rate
90%Confidence
80Evidence
2023-01-01First Seen

Version Compatibility

VersionStatusIntroducedDeprecatedNotes
8 active

Root Cause

Minimal API endpoints in ASP.NET Core automatically bind complex types from the request body using System.Text.Json. This exception occurs when the request body is missing, malformed, has incorrect Content-Type, or when the JSON structure does not match the expected parameter type. Common causes include sending form data instead of JSON, missing required properties when using required keyword or [Required] attributes, or enum/type mismatches. Fix by ensuring the request Content-Type is application/json and the body structure matches the expected type.

generic

Workarounds

  1. 92% success Ensure the request sends application/json Content-Type with a matching JSON body
    The most common cause is a missing or incorrect Content-Type header. Verify the client sends Content-Type: application/json and the body is valid JSON matching the parameter type. For testing: curl -X POST https://localhost:5001/api/items -H "Content-Type: application/json" -d '{"name": "test", "price": 9.99}'. When using HttpClient: content = new StringContent(json, Encoding.UTF8, "application/json"). Form-encoded data will not bind to JSON parameters
  2. 87% success Configure JsonSerializerOptions to handle common mismatches like camelCase and enums
    Configure the JSON serializer to be more lenient with common mismatches: builder.Services.ConfigureHttpJsonOptions(options => { options.SerializerOptions.PropertyNameCaseInsensitive = true; options.SerializerOptions.Converters.Add(new JsonStringEnumConverter()); options.SerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull; }); PropertyNameCaseInsensitive handles PascalCase vs camelCase mismatches, and JsonStringEnumConverter allows string enum values instead of requiring integers
  3. 84% success Use a custom binding approach with JsonDocument for flexible body handling
    When the request body structure varies or needs validation before binding, accept the raw body and parse manually: app.MapPost("/api/items", async (HttpRequest request) => { using var doc = await JsonDocument.ParseAsync(request.Body); var root = doc.RootElement; if (!root.TryGetProperty("name", out var name)) return Results.BadRequest("name is required"); var item = new Item { Name = name.GetString()! }; return Results.Ok(item); }); This gives complete control over parsing and error messages. For simpler cases, use the JsonElement type as parameter for partial flexibility

Dead Ends

Common approaches that don't work:

  1. Adding [FromBody] attribute explicitly to the parameter assuming it changes binding behavior 85% fail

    In Minimal APIs, complex types are already bound from the body by default. Adding [FromBody] explicitly does not change the binding source or fix deserialization errors. The issue is in the JSON payload structure or Content-Type header, not in how the parameter is annotated. This wastes debugging time on the wrong layer

  2. Making all properties nullable to avoid required property binding failures 75% fail

    Making all properties nullable suppresses the binding error but pushes null-handling responsibility throughout the entire codebase. Every consumer of the model must now check for null on every field, and invalid requests that should be rejected with 400 are silently accepted with null data, leading to NullReferenceExceptions deeper in the application logic

  3. Switching from Minimal API to MVC controllers to get better model binding 80% fail

    MVC controllers use the same System.Text.Json deserialization pipeline and will produce equivalent errors for malformed JSON. The migration adds significant complexity (controller classes, routing attributes, dependency injection changes) without addressing the root cause, which is a mismatch between the client request and the server's expected model

Error Chain

Leads to:
Preceded by:
Frequently confused with: