React调用.NET接口传用户ID带多余转义字符报500错误问题
问题现象
- 已实现两个管理员操作接口:为用户授予管理员身份、移除用户管理员身份,两个接口均通过用户ID定位目标用户
- 点击前端对应操作按钮时接口返回500错误,排查发现后端接收到的用户ID参数格式不符合预期
- 实际接收到的参数值:
"\"65efe6a5-1384-49f7-8519-8d6789d26baf\"" - 预期正确参数值:
"65efe6a5-1384-49f7-8519-8d6789d26baf"
- 实际接收到的参数值:
- 关联代码如下
后端接口代码:
前端请求代码:[HttpPost("assignAdminClaim")] //[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme, Policy = "IsAdmin")] public async Task<ActionResult> AssignAdminClaim([FromBody] string userId) { var user = await userManager.FindByIdAsync(userId); await userManager.AddClaimAsync(user, new Claim("role", "admin")); return NoContent(); }const assignAdminClaim = async (id: string) => { await adminClaim(`${UrlUsers}/assignAdminClaim`, id) } const adminClaim = async (url: string, id: string) => { await axios.post(url, JSON.stringify(id), { headers: { "Content-Type": "application/json" } }); Swal.fire({ title: "Success", text: "Successfully updated", icon: "success", }) }
问题根因
核心问题出在前端请求的双重JSON序列化逻辑:
- 当给axios设置
Content-Type: application/json请求头时,axios会自动对传入的data参数执行一次JSON序列化操作 - 代码里在传参前手动调用了一次
JSON.stringify(id),等于提前把字符串类型的用户ID做了第一次序列化:比如原始ID是abc,第一次序列化后得到字符串值"abc"(带前后双引号) - 之后axios拿到这个已经序列化过的字符串,会再执行一次JSON序列化,最终发给后端的请求内容就变成了带转义符的
"\"abc\"",后端反序列化后得到的字符串就额外多了前后的双引号,和用户存储的真实ID不匹配,最终触发异常返回500。
另外当前后端代码存在潜在空引用问题:如果userManager.FindByIdAsync根据传入的ID没找到对应用户,会返回null,后续直接调用AddClaimAsync会直接抛出空引用异常,也是500错误的可能诱因。
修复方案
前端修复(核心修复)
去掉手动调用的JSON.stringify,直接把ID值传给axios即可,axios会自动完成正确的单次序列化:
const adminClaim = async (url: string, id: string) => { // 移除JSON.stringify包装,直接传id await axios.post(url, id, { headers: { "Content-Type": "application/json" } }); Swal.fire({ title: "Success", text: "Successfully updated", icon: "success", }) }
如果要遵循更通用的接口设计规范,避免原始值绑定的兼容问题,建议把接口入参包装为对象格式:
- 前端调整传参:
await axios.post(url, { userId: id }, { headers: { "Content-Type": "application/json" } });
- 后端新增入参DTO,调整接口签名,补充空值校验:
// 新增入参类 public class UserIdRequest { public string UserId { get; set; } } [HttpPost("assignAdminClaim")] //[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme, Policy = "IsAdmin")] public async Task<ActionResult> AssignAdminClaim([FromBody] UserIdRequest request) { // 先判空,避免空引用异常 var user = await userManager.FindByIdAsync(request.UserId); if (user == null) { return NotFound("指定用户不存在"); } await userManager.AddClaimAsync(user, new Claim("role", "admin")); return NoContent(); }
注:移除管理员身份的接口存在完全相同的问题,按照相同逻辑修复即可。
内容的提问来源于stack exchange,提问作者Joro
相关产品推荐
相关产品推荐

