dotnet / dotnet/aspnetcore

ASP.NET core inconsistent model binding from form-data and json when trying to bind to an IEnumerable<T>

Open
#54,520 0 comments 1 reaction 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

### Is there an existing issue for this?

- [X] I have searched the existing issues

### Describe the bug

Model binding from form-data seems to work differently than model binding from json.

### Expected Behavior

_No response_

### Steps To Reproduce

Create a simple Web API with controllers. Also have Nullable enabled in the csproj.
Create the following controller and model:
```c#
[ApiController]
[Route("[controller]")]
public class ApiController : ControllerBase
{
[HttpPost("[action]")]
public IActionResult PostFormData([FromForm] PostRequest request) =>
Ok(string.Join(",", request.Values ?? [""]));

[HttpPost("[action]")]
public IActionResult PostJson(PostRequest request) =>
Ok(string.Join(",", request.Values ?? [""]));
}

public record PostRequest
{
public IEnumerable Values { get; set; } = [];
}
```

Note that the `Values` property has a default value in the `PostRequest` record.

When calling the `PostJson` method on the controller, the model is bound as expected (screenshot from Postman):
![image](https://github.com/dotnet/aspnetcore/assets/25548778/587d0bb0-a9df-445a-8853-2510516953f9)

When calling the `PostFormData` method, though, the application returns an error:
![image](https://github.com/dotnet/aspnetcore/assets/25548778/0004f776-b874-4f03-974b-1dbfa47da7c5)

The error is:
```
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"errors": {},
"traceId": "00-3ea96923dfbfea72ba0c067b226b3985-0d099b1cc0b1cb3d-00"
}
```

I might be missing something, but there seems to be other strange behavior on the `PostFormData` method, i.e. when the model is bound from form-data:
- Removing the default value of `[]` (i.e. leaving it null), will not raise an error and the model property is bound as expected.
- When the default value is a collection with number of elements that is equal or greater than the elements passed in the form-data (e.g. default value of `["x", "x", "x"]`), then an error is not raised but the bound collection retains the default value (`["x", "x", "x"]`) and not the one passed in the form-data.
- Changing the `Values` property type to one of `string[]`, `List`, `ICollection` seems to prevent the app from raising the error.

### Exceptions (if any)

_No response_

### .NET Version

8.0.200

### 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.