使用IHttpClientFactory调用Post API遇验证错误(.NET Core 8+WPF)求助
错误原因分析
- ASP.NET Core对简单类型参数(比如string)的默认绑定规则是:优先从URL查询字符串或表单数据里读取值,但你的WPF客户端是把数据序列成JSON放在请求体里发送的,两者不匹配,导致API找不到
name和districtname的参数值,触发必填字段验证失败。 - 顺带提一句:你的WPF代码里重复调用了
PostAsync,会发两次请求,属于冗余代码,得清理掉。
解决方案
方案1:用模型类接收请求体(推荐)
这种方式符合REST API设计规范,后续维护扩展也更方便。
步骤1:在API项目里定义请求模型
public class SalePersonRequest { [Required(AllowEmptyStrings = false)] public string Name { get; set; } [Required(AllowEmptyStrings = false)] public string Districtname { get; set; } }
步骤2:修改API的Action方法
[HttpPost("InsertSalePerson")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task<IActionResult> InsertSalePerson([FromBody] SalePersonRequest request) { try { await _districtRepo.InsertSalePerson(request.Name, request.Districtname); return Ok(); } catch(Exception ex) { return BadRequest(ex.Message); } }
关键是加
[FromBody]特性,明确告诉框架从JSON请求体里绑定模型数据。
步骤3:清理WPF里的冗余代码
public async override void Execute(object? parameter) { string localHost = "https://localhost:7235/api/SalePerson/InsertSalePerson"; var person = new DistrictAndSalePerson { name = _showDistrictViewModel.SalepersonToAdd, districtname = _showDistrictViewModel.SelectedDistrictTest }; var httpClient = _httpClientFactory.CreateClient(); var todoItemJson = new StringContent( JsonSerializer.Serialize(person), Encoding.UTF8, "application/json"); // 删掉重复的PostAsync调用 using var httpResponse = await httpClient.PostAsync(localHost, todoItemJson); var result = await httpResponse.Content.ReadAsStringAsync(); }
方案2:修改参数绑定来源(不推荐,仅适用于简单场景)
如果不想定义模型类,也可以调整参数的绑定方式,但ASP.NET Core不支持多个[FromBody]参数,只能用动态类型接收后手动解析,还得自己做验证,扩展性很差,不推荐生产环境用。
示例代码:
[HttpPost("InsertSalePerson")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task<IActionResult> InsertSalePerson([FromBody] dynamic request) { string name = request.name; string districtname = request.districtname; // 手动验证必填字段 if(string.IsNullOrEmpty(name) || string.IsNullOrEmpty(districtname)) { return BadRequest("name和districtname为必填字段"); } try { await _districtRepo.InsertSalePerson(name, districtname); return Ok(); } catch(Exception ex) { return BadRequest(ex.Message); } }
额外建议
在WPF发送请求前,可以先验证一下_showDistrictViewModel.SalepersonToAdd和_showDistrictViewModel.SelectedDistrictTest是不是空字符串,提前拦截无效请求:
if(string.IsNullOrEmpty(_showDistrictViewModel.SalepersonToAdd) || string.IsNullOrEmpty(_showDistrictViewModel.SelectedDistrictTest)) { // 这里可以提示用户输入必填信息 return; }
内容的提问来源于stack exchange,提问作者Doraemon
相关产品推荐
相关产品推荐

