Open
Description
Is there an existing issue for this?
- I have searched the existing issues
Is your feature request related to a problem? Please describe the problem.
The error response for a deserialization error in a Minimal API app is very verbose and difficult to parse. Here's an example:
HTTP/1.1 400 Bad Request
Content-Type: application/problem+json
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
"title": "Microsoft.AspNetCore.Http.BadHttpRequestException",
"status": 400,
"detail": "Failed to read parameter \"WeatherForecast body\" from the request body as JSON.",
"exception": {
"details": "Microsoft.AspNetCore.Http.BadHttpRequestException: Failed to read parameter \"WeatherForecast body\" from the request body as JSON.\n ---> System.Text.Json.JsonException: The JSON value could not be converted to System.String. Path: $.summary | LineNumber: 3 | BytePositionInLine: 17.\n ---> System.InvalidOperationException: Cannot get the value of a token type 'Number' as a string.\n at System.Text.Json.ThrowHelper.ThrowInvalidOperationException_ExpectedString(JsonTokenType tokenType)\n at System.Text.Json.Utf8JsonReader.GetString()\n at System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1.ReadJsonAndSetMember(Object obj, ReadStack& state, Utf8JsonReader& reader)\n at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)\n at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value, Boolean& isPopulatedValue)\n at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, T& value, JsonSerializerOptions options, ReadStack& state)\n --- End of inner exception stack trace ---\n at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& state, Utf8JsonReader& reader, Exception ex)\n at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, T& value, JsonSerializerOptions options, ReadStack& state)\n at System.Text.Json.Serialization.Metadata.JsonTypeInfo`1.ContinueDeserialize(ReadBufferState& bufferState, JsonReaderState& jsonReaderState, ReadStack& readStack, T& value)\n at System.Text.Json.Serialization.Metadata.JsonTypeInfo`1.DeserializeAsync(Stream utf8Json, CancellationToken cancellationToken)\n at System.Text.Json.Serialization.Metadata.JsonTypeInfo`1.DeserializeAsObjectAsync(Stream utf8Json, CancellationToken cancellationToken)\n at Microsoft.AspNetCore.Http.HttpRequestJsonExtensions.ReadFromJsonAsync(HttpRequest request, JsonTypeInfo jsonTypeInfo, CancellationToken cancellationToken)\n at Microsoft.AspNetCore.Http.HttpRequestJsonExtensions.ReadFromJsonAsync(HttpRequest request, JsonTypeInfo jsonTypeInfo, CancellationToken cancellationToken)\n at Microsoft.AspNetCore.Http.RequestDelegateFactory.<HandleRequestBodyAndCompileRequestDelegateForJson>g__TryReadBodyAsync|102_0(HttpContext httpContext, Type bodyType, String parameterTypeName, String parameterName, Boolean allowEmptyRequestBody, Boolean throwOnBadRequest, JsonTypeInfo jsonTypeInfo)\n --- End of inner exception stack trace ---\n at Microsoft.AspNetCore.Http.RequestDelegateFactory.Log.InvalidJsonRequestBody(HttpContext httpContext, String parameterTypeName, String parameterName, Exception exception, Boolean shouldThrow)\n at Microsoft.AspNetCore.Http.RequestDelegateFactory.<HandleRequestBodyAndCompileRequestDelegateForJson>g__TryReadBodyAsync|102_0(HttpContext httpContext, Type bodyType, String parameterTypeName, String parameterName, Boolean allowEmptyRequestBody, Boolean throwOnBadRequest, JsonTypeInfo jsonTypeInfo)\n at Microsoft.AspNetCore.Http.RequestDelegateFactory.<>c__DisplayClass102_2.<<HandleRequestBodyAndCompileRequestDelegateForJson>b__2>d.MoveNext()\n--- End of stack trace from previous location ---\n at Microsoft.AspNetCore.Diagnostics.StatusCodePagesMiddleware.Invoke(HttpContext context)\n at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)\n at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)\n at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)",
"headers": {
"Accept": [
"application/json"
],
"Connection": [
"close"
],
"Host": [
"localhost:5280"
],
"User-Agent": [
"vscode-restclient"
],
"Accept-Encoding": [
"gzip, deflate"
],
"Content-Type": [
"application/json"
],
"Content-Length": [
"71"
]
},
"path": "/forecast/",
"endpoint": "HTTP: POST /forecast",
"routeValues": {}
},
"traceId": "00-0ee0c4d5c4664bcba04e8368d7cb98bc-85d7d92bfdd90048-00"
}
Contrast this with the error response for the same scenario with a controller-based app:
HTTP/1.1 400 Bad Request
Content-Type: application/problem+json; charset=utf-8
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"errors": {
"body": [
"The body field is required."
],
"$.summary": [
"The JSON value could not be converted to System.String. Path: $.summary | LineNumber: 3 | BytePositionInLine: 17."
]
},
"traceId": "00-d3c338ac09225363af3fd502ee551533-db5efa0694a6a7ca-00"
}
Describe the solution you'd like
Error responses for deserialization errors in Minimal APIs should have concise and clear error responses that are at least as good as the error responses from controller-based apps.
Additional context
A project that illustrates the difference between deserialization errors from a Minimal API app vs a controller-based app is in the deser-error-handling
directory of my dotnet10-issue-repros repo.