ASP.NET Core 6集成测试:FromBody正常,FromForm绑定DTO值为NULL
为什么ASP.NET Core 6接口从FromBody改FromForm后,集成测试的DTO值为null?
我用WebApplicationFactory给C# ASP.NET Core 6 Web API写集成测试,测试带FromBody的POST方法时代码正常运行,DTO字段能正确填充:
// 测试代码 var DTO = // 填充Dto数据 var payload = JsonConvert.SerializeObject(DTO); var content = new StringContent(payload, Encoding.UTF8, "application/json"); var response1 = await _client.PostAsync("/api/Main/Function1", content);
对应的接口:
[HttpPost("Function1")] public async Task<IActionResult> Function1([FromBody] DTO values) { // 业务逻辑 }
但把接口的FromBody改成FromForm后,测试代码里的DTO值变成null了,修改后的测试代码和接口如下:
// 修改后的测试代码 var DTO = // 填充Dto数据 var payload = JsonConvert.SerializeObject(DTO); var content = new StringContent(payload, Encoding.UTF8, "application/x-www-url-formencoded"); var response1 = await _client.PostAsync("/api/Main/Function1", content);
对应的接口:
[HttpPost("Function1")] public async Task<IActionResult> Function1([FromForm] DTO values) { // 业务逻辑 }
错误原因
你犯的核心错误是用JSON序列化的字符串来模拟表单数据。application/x-www-url-formencoded格式要求数据是key=value&key2=value2这样的键值对结构,而非JSON字符串。ASP.NET Core的模型绑定器无法将JSON字符串解析为[FromForm]标记的DTO对象,因此会返回null。
正确的测试代码
要测试[FromForm]标记的接口,需用FormUrlEncodedContent构建符合表单格式的请求内容,将DTO属性转换为键值对集合:
手动构建键值对(适合属性少的DTO)
var DTO = // 填充Dto数据 var formData = new Dictionary<string, string> { ["Property1"] = DTO.Property1, ["Property2"] = DTO.Property2.ToString(), // 依次添加DTO的所有属性 }; var content = new FormUrlEncodedContent(formData); var response1 = await _client.PostAsync("/api/Main/Function1", content);
反射自动生成键值对(适合属性多的DTO)
var DTO = // 填充Dto数据 var formData = new Dictionary<string, string>(); foreach (var prop in typeof(DTO).GetProperties()) { var value = prop.GetValue(DTO)?.ToString(); if (value != null) { formData[prop.Name] = value; } } var content = new FormUrlEncodedContent(formData); var response1 = await _client.PostAsync("/api/Main/Function1", content);
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

