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

JS Ajax调用WebAPI删除接口传User ID报400错误排查

问题定位

400错误的核心是三层代码的参数传递逻辑完全不匹配,另外还有拼写错误会阻断后续流程,不存在gRPC通信层面的问题,具体错误点如下:

  • 前端Ajax逻辑错误:直接把jQuery对象$Id_user拼接到URL中,实际拼接的是[object Object]字符串,根本没有拿到输入框内的用户ID值;同时后端标记了从请求体读JSON参数,但Ajax既没传请求体,也没指定JSON内容类型,后端无法解析入参。
  • WebAPI参数绑定冲突:路由模板定义了{Id_user}路径占位符,却给参数加了[FromBody]特性要求从请求体读取,ASP.NET Core无法同时从两个位置绑定同一个参数,直接触发模型验证失败。
  • gRPC代码拼写错误:查询到的用户对象变量名是data,非空判断时误写为date,就算参数正常传递,代码也会因变量不存在编译失败。
修正代码

1. gRPC服务层修正

public override async Task<Empty> Delete(UserFilter requestData, ServerCallContext context)
{
    // 修正变量名拼写错误,保持前后一致
    var data = await _context.Users_5.FindAsync(requestData.UserID);
    
    if(data == null)
    {
        // gRPC服务推荐抛出RpcException而非普通Exception,方便客户端识别错误类型
        throw new RpcException(new Status(StatusCode.NotFound, "User Not Found"));
    }
    _context.Users_5.Remove(data);
    await _context.SaveChangesAsync();
    return new Empty();
}

2. WebAPI接口层修正

两种实现方案二选一即可,优先选路径传参的写法,符合RESTful接口规范:

方案A:路径传参(推荐)

// 路由占位符名和参数名对齐,去掉[FromBody]特性,从路径读取ID
[HttpDelete("{userId}")]
public async Task<ActionResult<Empty>> DeleteUser(int userId)
{
    _logger.Log(LogLevel.Information, "Request Received for AuthController::Delete");
    
    // 组装gRPC调用需要的请求对象
    var grpcRequest = new UserFilter { UserID = userId };
    var results = await _userClient.DeleteAsync(grpcRequest);

    _logger.Log(LogLevel.Information, "Sending Response from AuthController::Delete");
    return Ok(results);
}

方案B:请求体传参

如果要保留从请求体读参的逻辑,就删除路由模板里的ID占位符,避免绑定冲突:

[HttpDelete]
public async Task<ActionResult<Empty>> DeleteUser([FromBody] UserFilter request)
{
    _logger.Log(LogLevel.Information, "Request Received for AuthController::Delete");
    
    if(request == null || request.UserID <= 0)
    {
        return BadRequest("Invalid user ID");
    }
    var results = await _userClient.DeleteAsync(request);

    _logger.Log(LogLevel.Information, "Sending Response from AuthController::Delete");
    return Ok(results);
}

3. 前端Ajax修正

对应上面选的接口方案调整,以下为对应方案A(路径传参)的代码:

const $users_A = $('#users_A');
const $userIdInput = $('#Id_user'); // 变量名和DOM元素做区分,避免混淆

// 用on替代已废弃的delegate写法
$users_A.on('click', '.remove', function () {
    const $li = $(this).closest('li');
    // 读取输入框的实际值,不要直接拼接jQuery对象
    const userId = $userIdInput.val().trim();
    if(!userId) {
        alert('请输入要删除的用户ID');
        return;
    }

    $.ajax({
        url: uri_7 + userId, // 拼接真实的用户ID
        type: 'DELETE',
        success: function() {
            $li.fadeOut(300, function () {
                $(this).remove();
            });
        },
        error: function (xhr, textStatus, errorThrown) {
            console.log('XHR:' + JSON.stringify(xhr) + '\nTextStatus:' + textStatus + '\nErrorThrown:' + errorThrown);
        }
    });
});

如果选方案B(请求体传参),Ajax部分需要调整为:

$.ajax({
    url: uri_7,
    type: 'DELETE',
    contentType: 'application/json', // 声明请求体为JSON格式
    data: JSON.stringify({ UserID: userId }), // 序列化JSON参数放到请求体
    // 成功、失败回调逻辑和上面一致
})

内容的提问来源于stack exchange,提问作者José Leal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 22:45:37