dotnet / dotnet/aspnetcore

Asp.Net Core does not properly handle the error with polymorphic deserialization from STJ when type discriminator is not specified

Open
#54,037 30 comments 2 reactions 0 assignees View on GitHub
area-mvc
Dominant language
C#
Stars
38.4k
Forks
10.9k
Avg merge
2d 10h
Merged PRs (30d)
281

Description

### Description

When type discriminator is not specified in the request, the error is not handled and 500 is returned instead of 400.

Example request 1:
```json
{
"type": "unknown",
"someOtherProperty": "value"
}
```

Example request 2:
```json
{
"someOtherProperty": "value"
}
```

Controller action:

```csharp
[HttpPost("test")]
public void Test(Base request)
{

}
```

Models:

```csharp
[JsonPolymorphic(TypeDiscriminatorPropertyName = "type")]
[JsonDerivedType(typeof(Derived), "derived")]
public abstract record Base
{
}

public record Derived : Base
{
}
```

### Reproduction Steps

1. Create a controller with the action and models from Description
2. Do a call with the example request 1, response is 400

```json
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"errors": {
"$": [
"Read unrecognized type discriminator id 'unknown'. Path: $ | LineNumber: 2 | BytePositionInLine: 21."
],
"request": [
"The request field is required."
]
},
"traceId": "00-a4e0c60070a4c53222d0622acad8d198-e18068d6fe5d5773-00"
}
```

3. Do a call with the example request 2, response is 500
```
System.NotSupportedException: Deserialization of types without a parameterless constructor, a singular parameterized constructor, or a parameterized constructor annotated with 'JsonConstructorAttribute' is not supported.
```

### Expected behavior

Ideally I expect the 400 error that will say clearly that the "type" TypeDiscriminator has to be provided (since the base class is abstract it is clear it cannot be constructed).

At the very least some form of 400 with json that tells that json cannot be deserialized instead of 500 (there was nothing "wrong" with the server, but client provided a bad request which is clearly a 400).

### Actual behavior

A 500 is returned and the exception is not handled by asp.net core (unlike example 1 request)

### Regression?

_No response_

### Known Workarounds

One can probably make class not abstract and do a validation oneself that the "base" class is not supported.

### Configuration

.Net 8
MacOS ARM

### Other information

It is somewhat related to the case when type discriminator is not the first field. If it is not the first - it will be the same error I think, which should also be handled ideally, but this can be fixed in .Net 9 hopefully.

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.