[FromForm] with Custom Property Names Fails to Bind in .NET 8 Minimal API, Works in MVC Controllers
- 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
When using .NET 8 Minimal API, form data binding with customized property names via `[FromForm(Name = "some name")]` and `[JsonPropertyName("some name")]` fails to deserialize the request object, resulting in null. However, the same configuration works correctly in .NET 8 when using MVC controllers.
### Expected Behavior
The form data should be correctly deserialized into the request object in a Minimal API project when using customized property names, just like it does in a traditional MVC controller project.
### Steps To Reproduce
A minimalistic project reproducing the issue is provided below:
`Minimal API Project`
```c#
app.MapPost("/submit", ([FromForm] UserInput input, HttpContext context) =>
{
return Results.Ok(new { Message = "Form received", input });
})
.WithName("SubmitForm")
.WithOpenApi()
.DisableAntiforgery();
public class UserInput
{
[JsonPropertyName("first_name")]
[FromForm(Name = "first_name")]
public string FirstName { get; set; }
[JsonPropertyName("last_name")]
[FromForm(Name = "last_name")]
public string LastName { get; set; }
}
```


`Controller API Project`
```c#
using Microsoft.AspNetCore.Mvc;
using System.Text.Json.Serialization;
namespace WebAPI.Controllers;
[Route("api/[controller]")]
[ApiController]
public class SubmitController : ControllerBase
{
[HttpPost]
public IActionResult Post([FromForm] UserInput input)
{
return Ok(new { Message = "Form received", input });
}
}
public class UserInput
{
[JsonPropertyName("first_name")]
[FromForm(Name = "first_name")]
public string FirstName { get; set; }
[JsonPropertyName("last_name")]
[FromForm(Name = "last_name")]
public string LastName { get; set; }
}
```


### Exceptions (if any)
_No response_
### .NET Version
8.0.403
### Anything else?
`dotnet --info`
**.NET SDK:**
- Version: 8.0.403
- Commit: c64aa40a71
- Workload version: 8.0.400-manifests.e99c892e
- MSBuild version: 17.11.9+a69bbaaf5
**Runtime Environment:**
- OS Name: Windows
- OS Version: 10.0.19045
- OS Platform: Windows
- RID: win-x64
- Base Path: C:\Program Files\dotnet\sdk\8.0.403\
**.NET workloads installed:**
Configured to use loose manifests when installing new manifests.
- [aspire]
- Installation Source: VS 17.11.35327.3
- Manifest Version: 8.1.0/8.0.100
- Manifest Path: C:\Program Files\dotnet\sdk-manifests\8.0.100\microsoft.net.sdk.aspire\8.1.0\WorkloadManifest.json
- Install Type: FileBased
**Host:**
- Version: 8.0.10
- Architecture: x64
- Commit: 81cabf2857
**.NET SDKs installed:**
- 8.0.403 [C:\Program Files\dotnet\sdk]
**.NET runtimes installed:**
- Microsoft.AspNetCore.App 6.0.35 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
- Microsoft.AspNetCore.App 7.0.20 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
- Microsoft.AspNetCore.App 8.0.10 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
- Microsoft.NETCore.App 6.0.35 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
- Microsoft.NETCore.App 7.0.20 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
- Microsoft.NETCore.App 8.0.10 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
- Microsoft.WindowsDesktop.App 6.0.35 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
- Microsoft.WindowsDesktop.App 7.0.20 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
- Microsoft.WindowsDesktop.App 8.0.10 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
**Other architectures found:**
- x86 [C:\Program Files (x86)\dotnet] registered at [HKLM\SOFTWARE\dotnet\Setup\InstalledVersions\x86\InstallLocation]
**Environment variables:**
- Not set
**global.json file:**
- Not found
**Learn more:**
- https://aka.ms/dotnet/info
Contributor guide
Research direction
Start with the provided Minimal API reproduction at app.MapPost("/submit", ...) and the UserInput properties using [FromForm] and [JsonPropertyName]. Run the reproduction and compare its form binding with the controller project; done means customized first_name and last_name values bind correctly in Minimal API requests as they do in MVC.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100