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

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序列化逻辑:

  1. 当给axios设置Content-Type: application/json请求头时,axios会自动对传入的data参数执行一次JSON序列化操作
  2. 代码里在传参前手动调用了一次JSON.stringify(id),等于提前把字符串类型的用户ID做了第一次序列化:比如原始ID是abc,第一次序列化后得到字符串值"abc"(带前后双引号)
  3. 之后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",
    })
}

如果要遵循更通用的接口设计规范,避免原始值绑定的兼容问题,建议把接口入参包装为对象格式:

  1. 前端调整传参:
await axios.post(url, { userId: id }, {
    headers: {
        "Content-Type": "application/json"
    }
});
  1. 后端新增入参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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 07:18:23