Asp.Net Core 5 POST请求无法同时获取路由与Body参数如何解决?
问题原因
第一次报错的根源
你给Model的string类型Token属性加了[FromBody]时,ASP.NET Core会尝试将整个请求正文直接反序列化为string类型,但你传递的是JSON对象{"token":"ABC"},不是纯字符串文本,所以反序列化失败,抛出类型转换错误。如果此时请求体直接传纯字符串"ABC"(不加外层JSON结构),其实可以正常拿到Token和路由的UserId,但这种传参方式不符合常规JSON接口的使用习惯。
第二次UserId为null的根源
你给整个Model参数加了[FromBody]后,ASP.NET Core会完全从请求正文反序列化整个Model对象,会直接忽略路由、查询字符串等其他来源的值,你的JSON参数里没有传userId,所以UserId自然为null。
解决方案
方案1:拆分Action参数(最推荐)
直接将不同来源的参数拆分声明,符合ASP.NET Core默认绑定规则,逻辑清晰:
// 定义Body参数对应的DTO public class ConfirmEmailRequest { public string Token { get; set; } } [HttpPost("users/{userId:int}/confirm-email")] public async Task<IActionResult> ConfirmEmail([FromRoute] int userId, [FromBody] ConfirmEmailRequest request) { // userId 从路由取值,request.Token 从请求Body取值 }
请求体还是保持你原来的{"token":"ABC"}即可,无需修改前端请求逻辑。
方案2:保留单个Model参数,调整属性结构
如果你一定要把所有参数都封装在同一个Model类里,可以将Body对应的属性修改为嵌套类,适配你传递的JSON结构:
public class ConfirmEmailModel { [FromRoute] public int? UserId { get; set; } [FromBody] public ConfirmEmailRequest Payload { get; set; } public class ConfirmEmailRequest { public string Token { get; set; } } } // Action参数不要加[FromBody] [HttpPost("users/{userId:int}/confirm-email")] public async Task<IActionResult> ConfirmEmail(ConfirmEmailModel model) { // model.UserId 来自路由,model.Payload.Token 来自请求Body }
内容的提问来源于stack exchange,提问作者Miguel Moura
相关产品推荐
相关产品推荐

