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

如何修复ASP.NET Core Web API子对象创建失败问题?

ASP.NET Core Web API(.NET7)Post请求对象创建失败问题解决

问题概述

在.NET7的ASP.NET Core Web API项目中,BooksController的CreateAsync Post方法无法正常创建Book对象,Swagger返回400验证错误,且不想使用DTO解决该问题。

实体类代码

public class Book
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Author { get; set; }
    public int Count { get; set; }

    // Navigation property
    public BookDetail BookDetail { get; set; }
}

public class BookDetail
{
    public int Id { get; set; }
    public string Description { get; set; }

    // Foreign key
    public int BookId { get; set; }
    // navigation properties
    public Book Book { get; set; }
}

控制器相关代码

[HttpPost("Create")]
public async Task<ActionResult<Book>> CreateAsync(Book book)
{
    if (book == null)
    {
        return BadRequest();
    }

    _db.Books.Add(book);

    await _db.SaveChangesAsync();

    return CreatedAtRoute(nameof(GetByIdAsync), new { id = book.Id }, book);
}

[HttpGet("{id:int}")]
public async Task<ActionResult<Book>> GetByIdAsync(int id)
{
    var book = await _db.Books.FindAsync(id);

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

    return Ok(book);
}

Swagger返回的错误信息

{
  "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
  "title": "One or more validation errors occurred.",
  "status": 400,
  "traceId": "00-2695d8ae6781a68ca32420345ecf40a1-9851e26a3bcb27f2-00",
  "errors": {
    "book": [
      "The book field is required."
    ],
    "$.bookDetail.book": [
      "The JSON value could not be converted to BookShopApp.Models.Book. Path: $.bookDetail.book | LineNumber: 9 | BytePositionInLine: 20."
    ]
  }
}

测试用的JSON输入

变体1

{
  "id": 0,
  "title": "string",
  "author": "string",
  "count": 0,
  "bookDetail": {
    "id": 0,
    "description": "string",
    "bookId": 0,
    "book": "string"
  }
}

变体2

{
  "title": "Book Title",
  "author": "Author Name",
  "count": 3,
  "bookDetail": {
    "description": "Book Description"
  }
}

已尝试的配置(未解决问题)

// in Program.cs
builder.Services
    .AddControllers()
    .AddJsonOptions(x => x.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles);

解决方案

1. 修改实体类的可空导航属性

由于.NET7默认启用Nullable参考类型,BookDetail中的Book导航属性被标记为不可空,导致模型绑定验证失败。将其改为可空类型:

public class BookDetail
{
    public int Id { get; set; }
    public string Description { get; set; }

    public int BookId { get; set; }
    // 将导航属性改为可空
    public Book? Book { get; set; }
}

2. 明确控制器参数的绑定来源

在CreateAsync方法的参数上添加[FromBody]特性,确保模型绑定从请求体获取JSON数据:

[HttpPost("Create")]
public async Task<ActionResult<Book>> CreateAsync([FromBody] Book book)
{
    // 原有逻辑不变
}

3. 调整JSON输入格式

创建对象时无需传递BookDetail中的Book(导航属性)和BookId(外键由EF Core自动关联生成),使用以下正确的JSON格式:

{
  "title": "Book Title",
  "author": "Author Name",
  "count": 3,
  "bookDetail": {
    "description": "Book Description"
  }
}

4. 配置EF Core的实体关系(可选)

在DbContext的OnModelCreating方法中明确配置一对一关系,确保EF Core正确处理外键关联:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<BookDetail>()
        .HasOne(bd => bd.Book)
        .WithOne(b => b.BookDetail)
        .HasForeignKey<BookDetail>(bd => bd.BookId);
}

完成以上步骤后,重新运行项目,即可正常通过Post请求创建Book对象。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 11:23:18