.NET 8中Blazor客户端提交MultipartFormDataContent到Minimal API报400错误
问题描述
我使用.NET 8创建了自动渲染模式项目,在服务端添加了如下端点:
public static void RegisterUserEndpoints(this WebApplication app) { var userGroup = app.MapGroup("/api/users"); userGroup.MapPost("/changepersonalInfo", ([FromForm] string name) => { Results.Ok(name); }).RequireAuthorization(); }
并在Program.cs中注册路由:
app.RegisterUserEndpoints(); app.UseAntiforgery();
计划从客户端组件提交包含图片文件及其他字段的表单,但尝试提交简单字符串"name"时返回400 Bad Request:
var formContent = new MultipartFormDataContent(); formContent.Add(new StringContent("Sample Name"), "name"); var response = await httpClient.PostAsync("/api/users/changepersonalInfo", formContent);
注:使用[FromBody]接收JSON数据时,路由可正常工作。
补充信息:最终API将接收包含图片和其他字段的ViewModel:
userGroup.MapPost("/changepersonalInfo", ([FromForm] UserViewmodel model) => { //save image and other info }).RequireAuthorization();
客户端提交代码示例:
var formContent = new MultipartFormDataContent(); formContent.Add(new StringContent(myProfile!.FirstName!), "firstName"); formContent.Add(new StringContent(myProfile!.LastName!), "lastName"); formContent.Add(new StringContent(myProfile!.PhoneNumber!), "phoneNumber"); // Add the image file if (ImageFile != null) { var imageContent = new ByteArrayContent(ImageBuffer); imageContent.Headers.ContentType = new MediaTypeHeaderValue(ImageFile.ContentType); imageContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data") { Name = "profilePicture", FileName = ImageFile.Name }; formContent.Add(imageContent); } var response = await httpClient.PostAsync("/api/users/changepersonalInfo", formContent);
问题原因及解决方案
返回400 Bad Request的核心原因是缺少Antiforgery令牌。因为你启用了UseAntiforgery(),ASP.NET Core会自动验证POST/PUT/DELETE等请求的Antiforgery令牌,multipart/form-data请求也不例外,未携带令牌会直接被拒绝。
修复步骤
获取并传递Antiforgery令牌
在客户端组件中,通过IAntiforgery服务获取令牌,然后将其添加到表单字段或请求头中:@inject IAntiforgery Antiforgery @code { private async Task SubmitForm() { var tokens = await Antiforgery.GetTokensAsync(HttpContext); var formContent = new MultipartFormDataContent(); // 方式1:将令牌添加到表单字段 formContent.Add(new StringContent(tokens.RequestToken!), "__RequestVerificationToken"); // 方式2:将令牌添加到请求头 // httpClient.DefaultRequestHeaders.Add("RequestVerificationToken", tokens.RequestToken!); // 添加其他表单字段和文件 formContent.Add(new StringContent("Sample Name"), "name"); // ... 图片及其他字段 var response = await httpClient.PostAsync("/api/users/changepersonalInfo", formContent); } }ViewModel字段匹配检查
当使用[FromForm] UserViewmodel model接收数据时,确保ViewModel的属性名称与客户端表单字段名称一致(大小写敏感)。如果需要不同的字段名,可以用[FormName]特性指定映射关系:public class UserViewmodel { [FormName("firstName")] public string FirstName { get; set; } = string.Empty; [FormName("lastName")] public string LastName { get; set; } = string.Empty; [FormName("phoneNumber")] public string PhoneNumber { get; set; } = string.Empty; public IFormFile ProfilePicture { get; set; } = null!; }额外验证项
- 确认请求携带了有效的Authorization凭证(JWT或Cookie),因为端点启用了
RequireAuthorization(),权限验证失败也可能返回400,但当前场景下核心问题还是Antiforgery令牌缺失。 - 无需手动设置
MultipartFormDataContent的Content-Type,它会自动生成正确的类型值。
- 确认请求携带了有效的Authorization凭证(JWT或Cookie),因为端点启用了
内容的提问来源于stack exchange,提问作者Robin Khan
相关产品推荐
相关产品推荐

