You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

.NET Core 2 Web API含外键的POST请求实现方法咨询

实现带外键的.NET Core 2 Web API POST请求

看起来你已经搭好了实体模型和POST方法的基础框架,接下来我们一步步完善这个带外键关联的POST请求实现:

1. 给实体添加显式外键属性

你的Balance模型目前只有导航属性CoinUser,没有对应的外键字段——EF Core虽然会自动生成隐式外键,但直接通过API传递完整的Coin/User对象既冗余又不安全。我们先给实体补充显式外键:

public class Balance { 
    public int Id { get; set; } 
    public string Title { get; set; } 
    public decimal Amount { get; set; } 
    public string Storage { get; set; } 
    // 添加显式外键字段,明确关联关系
    public int CoinId { get; set; } 
    public int UserId { get; set; } 
    // 保留原有导航属性
    public Coin Coin { get; set; } 
    public User User { get; set; } 
} 

这样EF Core的映射逻辑会更清晰,也方便我们在API请求中直接传递外键ID。

2. 创建专用的数据传输对象(DTO)

不要直接用实体类Balance作为API的请求参数,这会暴露不必要的字段(比如Id),还容易引发过度提交的风险。我们创建一个仅用于接收创建请求的DTO:

public class BalanceCreateDto
{
    [Required]
    public string Title { get; set; } 
    [Required]
    [Range(0.01, double.MaxValue)]
    public decimal Amount { get; set; } 
    public string Storage { get; set; } 
    [Required]
    public int CoinId { get; set; } 
    // 注意:UserId从当前登录用户获取,不需要从请求体传递
}

3. 完善POST方法的业务逻辑

现在更新你的PostNew方法,处理DTO验证、外键有效性检查,最终创建并保存实体:

[HttpPost] 
public async Task<IActionResult> PostNew([FromBody] BalanceCreateDto balanceDto) 
{
    // 先验证请求模型的合法性
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }

    // 获取当前登录用户(补全你原有的逻辑)
    var currentUser = await _userManager.FindByNameAsync(User.Identity.Name);
    if (currentUser == null)
    {
        return Unauthorized();
    }

    // 验证CoinId对应的币种是否存在,避免无效关联
    var targetCoin = await _context.Coins.FindAsync(balanceDto.CoinId);
    if (targetCoin == null)
    {
        return BadRequest($"不存在ID为{balanceDto.CoinId}的币种");
    }

    // 构建Balance实体
    var newBalance = new Balance
    {
        Title = balanceDto.Title,
        Amount = balanceDto.Amount,
        Storage = balanceDto.Storage,
        CoinId = balanceDto.CoinId,
        UserId = currentUser.Id
        // 无需手动赋值导航属性,EF Core会通过外键自动关联
    };

    // 写入数据库
    _context.Balances.Add(newBalance);
    await _context.SaveChangesAsync();

    // 返回符合REST规范的201响应,附带新资源的访问链接
    return CreatedAtAction(nameof(GetBalanceById), new { id = newBalance.Id }, newBalance);
}

// 配套的单条Balance查询方法(用于CreatedAtAction生成链接)
public async Task<ActionResult<Balance>> GetBalanceById(int id)
{
    var balance = await _context.Balances.Include(b => b.Coin).FirstOrDefaultAsync(b => b.Id == id);
    if (balance == null)
    {
        return NotFound();
    }
    return balance;
}

4. 测试请求示例

你可以用Postman或curl发送如下JSON格式的请求体(记得设置Content-Type: application/json,并确保用户已通过身份验证):

{
    "title": "我的比特币钱包",
    "amount": 0.35,
    "storage": "硬件钱包",
    "coinId": 1
}

关键要点总结

  • 始终用DTO接收API请求,避免直接暴露实体类的内部结构
  • 显式定义外键字段,让EF Core的关联逻辑更透明,也简化API参数传递
  • 必须验证外键对应的实体是否存在,防止创建无效的关联数据
  • CreatedAtAction返回符合REST规范的响应,帮助客户端快速定位新创建的资源

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

火山引擎 最新活动