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

开发用户收藏商品功能遇400错误:Invalid user ID format求助

收藏商品功能触发"Invalid user ID format"错误排查

问题描述

开发商城用户收藏商品功能,需求支持:用户可收藏多个商品,一个商品可被多个用户收藏。但Postman测试请求时,触发代码中第三个if条件,返回400 Bad Request错误,提示“Invalid user ID format”。尽管User实体的Id为int类型,调试发现userString的值为"saymon",且用户已登录。

相关代码

实体类代码

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
    [ForeignKey("UserId")]
    public User User { get; set; }
    public int UserId { get; set; }
}

public class User
{
    public int Id { get; set; }
    public string UserName { get; set; }
    public byte[] PasswordHash { get; set; }
    public byte[] PasswordSalt { get; set; }
    public List<Product> Products { get; set; }
    public List<Product> LikedProducts { get; set; } = new List<Product>();
}

控制器端点代码

[HttpPost("add-to-favorites/{productId}")]
public async Task<ActionResult> AddToFavorites(int productId)
{
    var userString = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
    var product = await _productRepository.GetProductById(productId);

    if (product == null)
    {
        return NotFound();
    }

    if (product.UserId.ToString() == userString)
    {
        return BadRequest("You cannot like your own product.");
    }

    if (!int.TryParse(userString, out int id))
    {
        return BadRequest("Invalid user ID format.");
    }

    var user = await _userRepository.GetUser(id);
    user.LikedProducts.Add(product);
    await _context.SaveChangesAsync();
    return Ok();
}

错误原因

  1. Claim值错误:ClaimTypes.NameIdentifier对应的Claim存储的是用户名("saymon"),而非用户的int类型ID,导致int.TryParse解析失败,触发格式错误提示。
  2. 逻辑判断无效:product.UserId.ToString() == userString的比较逻辑完全错误——一边是商品所属用户的ID字符串,一边是当前登录用户的用户名,两者永远不可能相等,这个判断毫无意义。
  3. 多对多关系设计缺陷:当前实体中User.LikedProducts的设计是一对多关联,不符合“一个商品可被多个用户收藏”的需求,会导致一个商品只能被单个用户收藏。

解决建议

1. 修正Claim获取逻辑

确保用户登录时,将用户的int类型ID存入ClaimTypes.NameIdentifier(或使用自定义Claim类型):

  • 如果使用JWT认证,在生成Token时添加正确的Claim:
    var claims = new List<Claim>
    {
        new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
        new Claim(ClaimTypes.Name, user.UserName)
    };
    
  • 后续从Claim中获取的就是用户ID的字符串形式,能正常解析为int。

2. 修复用户判断逻辑

拿到解析后的用户ID后,直接和product.UserId做int类型比较,无需转字符串:

var userString = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
if (string.IsNullOrEmpty(userString))
{
    return Unauthorized(); // 未正确获取用户信息,返回未授权
}

if (!int.TryParse(userString, out int userId))
{
    return BadRequest("Invalid user ID format.");
}

var product = await _productRepository.GetProductById(productId);
if (product == null)
{
    return NotFound();
}

if (product.UserId == userId)
{
    return BadRequest("You cannot like your own product.");
}

3. 修正多对多关系设计

使用EF Core的多对多配置,创建中间表来维护用户和收藏商品的关联:

  • 在DbContext的OnModelCreating方法中添加配置:
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<User>()
            .HasMany(u => u.LikedProducts)
            .WithMany() // 如果需要反向导航,可在Product中添加List<User> LikedByUsers,此处改为.WithMany(p => p.LikedByUsers)
            .UsingEntity(j => j.ToTable("UserLikedProducts"));
    }
    

这样就能实现一个用户收藏多个商品、一个商品被多个用户收藏的需求。

内容的提问来源于stack exchange,提问作者szymix1322

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 00:35:41