使用HttpClient发送Multipart数据调用FromForm接口报400错误求助
问题描述
我有一个接收表单数据的API:
[HttpPost] [Route("sign")] public async Task<IActionResult> SignDocument([FromForm] SignDTO signDTO)
SignDTO定义如下:
public class SignDTO { public IFormFile[] Files { get; set; } public string CertIdentifier { get; set; } public string Certificate { get; set; } public string PhoneNumber { get; set; } public string UserId { get; set; } }
我尝试通过以下代码调用该API:
SignDTO request = new SignDTO(); request.UserId = dto.UserId; request.PhoneNumber = dto.Phone; request.Certificate = certificate.Value; request.CertIdentifier = certificate.Key; HttpClient client = new HttpClient(); client.BaseAddress = new Uri(_signUrl); var multipartContent = new MultipartFormDataContent(); ByteArrayContent fileContent = new ByteArrayContent(file); multipartContent.Add(fileContent, "files", "files"); multipartContent.Add(new StringContent(JsonConvert.SerializeObject(request), Encoding.UTF8, "application/json"), "signDTO"); var response = await client.PostAsync("api/sign/sign", multipartContent);
但请求返回400错误,之前用HttpWebRequest实现过类似功能,不确定当前HttpClient的写法是否正确,请问哪里出错了?
问题分析与解决
核心错误:你把整个
SignDTO序列化为JSON字符串放到signDTO表单字段中,但API用[FromForm]标记,期望的是表单键值对对应DTO的每个属性,而非序列化后的JSON对象。ASP.NET Core无法将这个JSON字符串自动绑定到SignDTO,因此返回400参数错误。正确做法:将
SignDTO中的每个字符串属性单独作为表单字段添加,同时正确处理文件上传(多文件需循环添加)。
修正后的代码示例:
// 提取参数值 var userId = dto.UserId; var phoneNumber = dto.Phone; var certificateVal = certificate.Value; var certIdentifier = certificate.Key; HttpClient client = new HttpClient(); client.BaseAddress = new Uri(_signUrl); var multipartContent = new MultipartFormDataContent(); // 添加文件(多文件的话循环调用Add即可) ByteArrayContent fileContent = new ByteArrayContent(file); // 键名"files"需和DTO的Files属性名一致,框架会自动绑定为数组 multipartContent.Add(fileContent, "files", "actual-filename.ext"); // 逐个添加字符串属性,键名必须和DTO属性名完全匹配(大小写敏感) multipartContent.Add(new StringContent(userId), "UserId"); multipartContent.Add(new StringContent(phoneNumber), "PhoneNumber"); multipartContent.Add(new StringContent(certificateVal), "Certificate"); multipartContent.Add(new StringContent(certIdentifier), "CertIdentifier"); var response = await client.PostAsync("api/sign/sign", multipartContent);
补充说明:
- 表单字段的键名必须和
SignDTO的属性名完全一致,ASP.NET Core的模型绑定才能正确识别。 - 多文件上传时,只需循环调用
multipartContent.Add,每个文件都用"files"作为键名,框架会自动收集为IFormFile[]数组。 - 无需创建
SignDTO对象并序列化,直接将每个字段单独添加到表单即可。
内容的提问来源于stack exchange,提问作者Jamil
相关产品推荐
相关产品推荐

