dotnet / dotnet/aspnetcore

Inconsistencies in parameter binding between Minimal APIs, AoT, and Controllers

Open
#62,095 1 comment 2 reactions 0 assignees View on GitHub
area-minimal NativeAOT
Dominant language
C#
Stars
38.4k
Forks
10.9k
Avg merge
2d 5h
Merged PRs (30d)
276

Description

There are some subtle differences in parameter binding between Minimal APIs, Minimal APIs compiled for AoT, and Controller-based APIs.

In particular, the way nullability and the RequiredAttribute are handled varies, as well as how these are represented in the generated OpenAPI.

I created a project that explores the combinations of nullability and required for both value and ref params:

https://github.com/mikekistler/aspnet-param-binding

I ran tests and summarized the results in the [README.md](https://github.com/mikekistler/aspnet-param-binding/blob/main/README.md). My analysis of these results follows.

### OpenAPI required

- Minimal APIs (AoT or not) set `required: true` if the parameter has the `Required` attribute _or_ if the parameter is not nullable.
- Controllers set `required: true` only if the parameter has the `Required` attribute.

I think Minimal APIs should adopt the behavior of Controllers to make these consistent.

### Handling of omitted param

- Minimal APIs (AoT or not) appear to treat an omitted parameter as having a `null` value, and fail the request if the parameter is either required or non-nullable.
- Controllers appear to treat omitted parameters differently for value vs reference types:
- For value types, an omitted parameter appears to be treated as having the default value for the type
- For reference types, an omitted parameter appears to be treated as having a `null` value, whether or not the type is nullable.

I think Minimal APIs should fail a request where a parameter with the `Required` attribute is omitted, and otherwise set the parameter to its default value.

To achieve full consistency between Minimal APIs and Controllers, Controllers should treat omitted parameters as having their default value -- so the empty string rather than null in the case of a non-nullable string parameter. But this is likely a breaking change so maybe something to avoid.

### Handling of empty param value

- Minimal APIs handle empty values differently for AoT and non-AoT scenarios:
- Minimal APIs without AoT appear to treat an empty value as being an empty string, and fails if it cannot assign an empty string to the param (as in the case of the value param).
- Minimal APIs with AoT appear to treat an empty value as being the default value for the type.
- Controllers appear to treat an empty value as if the parameter's value was "null". As a result, it returns 400 if param is not nullable, or if param is required, and otherwise sets it to null.

I think Minimal APIs without AoT should change to be consistent with AoT and treat an empty value as being the default value for the type.

This does not resolve the inconsistency between Minimal APIs and Controllers, but that's probably not fixable without a breaking change to Controllers.

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.