You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 00:15:27