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

启用可空引用类型时非可空属性导致Action方法未执行

问题现象

启用Version 0或Version 1对应的代码配置时,在Swagger-UI中保持所有文本框为空点击Execute按钮会触发错误,经排查ContactsController中的Get方法体始终未被调用。切换为其余版本配置时,Get方法可正常执行。
错误截图
复现代码如下:

public class Contact
{
    public string Name { get; set; }                    // Version 0
    public string Name { get; set; } = null!;           // Version 1
    // public string Name { get; set; } = String.Empty; // Version 2
    // public string? Name { get; set; }                // Version 3
    // public string? Name { get; set; } = String.Empty;// Version 4
    public int Age { get; set; }
}

[ApiController]
[Route("api/[controller]/[action]")]
public class ContactsController : ControllerBase
{
    [HttpGet]
    public ActionResult Get([FromQuery] Contact c)
    {
        if (c.Name is null)
            return Ok("Name is null");

        if (c.Name == String.Empty)
            return Ok("Name is empty");

        return Ok("End reached");
    }
}
产生原因

该问题是ASP.NET Core模型验证默认规则和C#可空引用类型(NRT)特性联动导致的:

  • 项目开启可空引用类型检查后,所有未标注?的引用类型属性,会被框架自动判定为非空必填字段,要求请求必须传入对应有效值,否则会在模型绑定阶段直接返回400参数错误,不会进入控制器方法逻辑。
  • Version 0和Version 1中的Name属性均为未加?的string类型,其中Version 1的=null!写法仅用于绕过编译器的空引用警告,不会改变框架对字段必填性的判定。
  • Swagger空表单提交时,请求Query参数中没有携带Name字段值,模型绑定阶段直接判定必填字段缺失,触发自动校验拦截,因此Get方法永远不会执行。
  • 其余版本可正常运行的原因:
    • Version 2为Name设置了空字符串默认值,模型绑定未获取到传入值时会直接使用默认值填充,不会触发校验失败
    • Version 3、Version 4的Name带?标记,被框架识别为可空字段,请求未传值也不会触发验证拦截

如果需要保留Version 0/1的属性写法,同时让接口正常处理空参数请求,可以在服务配置中关闭非空引用类型的隐式必填校验:

builder.Services.AddControllers(options =>
{
    options.SuppressImplicitRequiredAttributeForNonNullableReferenceTypes = true;
});

内容的提问来源于stack exchange,提问作者Display Name

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 06:18:09