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

ASP.NET Core JsonPatch中ModelState始终有效问题求助

问题描述

我正在使用ASP.NET Core的JsonPatch Document构建API,控制器中的Patch方法如下:

[HttpPatch("{id:int}")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<ActionResult> Patch(int id, [FromBody] JsonPatchDocument<ClientDto> clientPatch)
{
    Client? client = await _clientRepository.GetClientAsync(id);

    if (client != null)
    {
        ClientDto clientDto = _mapper.Map<ClientDto>(client);

        clientPatch.ApplyTo(clientDto, ModelState);

        if(ModelState.IsValid)
        {
            _mapper.Map(clientDto, client);
            await _clientRepository.UpdateClientAsync(client);

            return NoContent();
        }

        return BadRequest();
    }

    return NotFound();
}

对应的DTO定义:

public record ClientDto
{
    public int? Id { get; set; }

    [Required]
    [StringLength(50, MinimumLength = 1)]
    public required string Name { get; set; }
}

我原本以为发送如下PATCH请求会触发Model验证失败,返回400响应:

[
  {
    "path": "/name",
    "op": "replace",
    "value": "Changed"
  }
]

但实际测试时,ModelState始终显示有效,请问哪里操作有误?


解决方法

问题出在JsonPatchDocument.ApplyTo方法的行为上:

  • 该方法仅会捕获JsonPatch操作本身的错误(比如路径不存在、操作类型无效等),不会自动验证DTO上标注的数据注解(如[Required]、[StringLength])。
  • 你测试的请求是合法的替换操作,所以ModelState不会被标记为无效。

要触发DTO的属性验证,需要在ApplyTo之后手动验证clientDto,并将验证结果合并到ModelState中。修改后的代码如下:

[HttpPatch("{id:int}")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<ActionResult> Patch(int id, [FromBody] JsonPatchDocument<ClientDto> clientPatch)
{
    Client? client = await _clientRepository.GetClientAsync(id);

    if (client != null)
    {
        ClientDto clientDto = _mapper.Map<ClientDto>(client);

        clientPatch.ApplyTo(clientDto, ModelState);

        // 新增:手动验证DTO的属性规则
        if (!TryValidateModel(clientDto))
        {
            return BadRequest(ModelState);
        }

        if(ModelState.IsValid)
        {
            _mapper.Map(clientDto, client);
            await _clientRepository.UpdateClientAsync(client);

            return NoContent();
        }

        return BadRequest();
    }

    return NotFound();
}

现在如果发送违反DTO验证规则的请求(比如将value设为空字符串),TryValidateModel会触发数据注解验证,将错误写入ModelState,最终返回400响应。


内容的提问来源于stack exchange,提问作者Andy Clark

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 20:28:08