dotnet / dotnet/aspnetcore

Request.ReadFromJsonAsync does not support quoted charset parameter values

Open
#61,514 2 comments 0 reactions 0 assignees View on GitHub
area-mvc
Dominant language
C#
Stars
38.4k
Forks
10.9k
Avg merge
2d 6h
Merged PRs (30d)
290

Description

### Is there an existing issue for this?

- [x] I have searched the existing issues

### Describe the bug

When a client request contains a quoted charset in the content-type header (like `application/json; charset="utf-8"`), normal model binding works, but reading the JSON body manually with `ReadFromJsonAsync` generates an internal server error from an exception.

### Expected Behavior

`ReadFromJsonAsync` should be symmetrical with model binding and accept a quoted `charset` parameter.

### Steps To Reproduce

Using the following controller
```cs
[ApiController]
public class TestController : ControllerBase
{
[HttpPost("one")]
[Consumes("application/json")]
public int One([FromBody] Model model)
{
return model is not null ? 1 : 0;
}

[HttpPost("two")]
[Consumes("application/json")]
public async Task Two()
{
var model = await Request.ReadFromJsonAsync();
return model is not null ? 2 : 0;
}
}

public class Model
{
public required string Name { get; init; }
}

```

issue this request to both endpoints:
`curl -v -X POST -d '{"name":"a"}' -H 'Content-Type: application/json; charset="utf-8"' https://localhost:…/[one|two]`.

For `one`, there'll be a normal response, for `two`, there is an internal server error. With an unquoted `charset=utf-8`, both requests succeed.

### Exceptions (if any)

```
System.InvalidOperationException: Unable to read the request as JSON because the request content type charset '"utf-8"' is not a known encoding.
---> System.ArgumentException: '"utf-8"' is not a supported encoding name. For information on defining a custom encoding, see the documentation for the Encoding.RegisterProvider method. (Parameter 'name')
at System.Text.EncodingTable.InternalGetCodePageFromName(String name)
at System.Text.EncodingTable.GetCodePageFromName(String name)
at System.Text.Encoding.GetEncoding(String name)
at Microsoft.AspNetCore.Http.HttpRequestJsonExtensions.GetEncodingFromCharset(StringSegment charset)
--- End of inner exception stack trace ---
at Microsoft.AspNetCore.Http.HttpRequestJsonExtensions.GetEncodingFromCharset(StringSegment charset)
at Microsoft.AspNetCore.Http.HttpRequestJsonExtensions.ReadFromJsonAsync[TValue](HttpRequest request, JsonTypeInfo`1 jsonTypeInfo, CancellationToken cancellationToken)
at QuotedCharset.TestController.Two() in …TestController.cs:line 17
at lambda_method6(Closure, Object)
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(ActionContext actionContext, IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
```

### .NET Version

9.0.201

### Anything else?

_No response_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.