ASP.NET Core API:Body与Query传参时前导零影响绑定的原因
ASP.NET Core Web API中[FromBody]与[FromQuery]处理带前导零整数的差异
问题场景
我用ASP.NET Core Web API + 本地MS SQL Server开发日历API,接收date、month、year参数返回对应日期的星期信息。相关代码如下:
仓库层代码
public async Task<List<DayParameter>> GetDayByDate(Day RequestParameter) { using (var connection = _context.CreateConnection()) { var days = await connection.QueryAsync<DayParameter>( "sp_getDay", // 存储过程名称 param: new { RequestParameter.date, RequestParameter.month, RequestParameter.year }, commandType: CommandType.StoredProcedure // 指定调用存储过程 ); return days.ToList(); } }
Day类定义
public class Day { public int date { get; set; } public int month { get; set; } public int year { get; set; } }
当参数通过HTTP请求Body传递(默认或加[FromBody])时,传入带前导零的整数(如01、04)会直接返回400验证错误:
{ "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1", "title": "One or more validation errors occurred.", "status": 400, "traceId": "00-d482f86081879283daasa2qpq0314-00", "errors": { "day": [ "The day field is required." ], "$.month": [ "Invalid leading zero before '4'. Path: $.month | LineNumber: 2 | BytePositionInLine: 12." ] } }
但将参数改为从Query传递(加[FromQuery])时,API可正常工作:
[HttpPost] [Route("getdaybydate")] public async Task<IActionResult> GetDayByDate([FromQuery] Day day) { var _list = await this.repo.GetDayByDate(day); if (_list != null) { return Ok(_list); } else { return NotFound(); } }
正常响应示例:
[ { "date": "1 January 2024", "day": "Monday" } ]
差异原因
1. JSON反序列化的严格性
ASP.NET Core默认用System.Text.Json处理[FromBody]的JSON请求体,而JSON规范明确禁止整数带前导零(除了0本身)。System.Text.Json默认遵循这个规范,遇到带前导零的整数会直接抛出反序列化错误,触发400验证失败。
2. Query参数绑定的宽松处理
[FromQuery]使用的是ASP.NET Core的模型绑定系统,查询参数本质是字符串类型,绑定器在将字符串转换为整数时,会自动忽略前导零(比如把"04"转换为整数4),因此不会触发验证错误。
解决方案
方案1:修改JSON序列化配置,允许前导零整数
在Program.cs中配置JSON序列化选项,允许读取带前导零的整数:
builder.Services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowLeadingZero; });
方案2:将字段改为字符串类型,自行处理转换
把Day类的date、month字段改为string类型,接收后再转换为整数,兼容前导零输入:
public class Day { public string date { get; set; } public string month { get; set; } public int year { get; set; } }
在仓库层或Action中手动转换为整数:
int dateInt = int.Parse(day.date); int monthInt = int.Parse(day.month);
方案3:保持使用[FromQuery]
如果参数结构简单,保持用Query传递参数的方式,无需额外配置即可兼容前导零输入。
内容的提问来源于stack exchange,提问作者Abhijeet PS
相关产品推荐
相关产品推荐

