ASP.NET Core 6.0 Web API 错误状态:400 标题:“发生一个或多个验证错误。” 对于由于外键而导致的 POST 请求

Kil*_*ilo 16 c# sql asp.net-core-webapi asp.net-core-6.0

我一直在开发一个使用 .NET 6.0 和 SQL 的项目,并且遇到了状态:400 标题:“发生一个或多个验证错误”。每当我尝试对治疗表发出 POST 请求时,都会出现错误,如下所示(使用 Swagger)。

400 - Undocumented
Error: response status is 400

Response body
Download
{
  "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
  "title": "One or more validation errors occurred.",
  "status": 400,
  "traceId": "00-471d5fa9b5bd60df0f6dddef0dcd44ad-4ed5f5f29428b83e-00",
  "errors": {
    "TblPet": [
      "The TblPet field is required."
    ],
    "Procedure": [
      "The Procedure field is required."
    ]
  }
}
Response headers
 content-type: application/problem+json; charset=utf-8 
 date: Thu,14 Jul 2022 11:25:42 GMT 
 server: Kestrel 
Run Code Online (Sandbox Code Playgroud)

该项目遵循此 ERD:

在此输入图像描述

该 API 是使用 Visual Studio 2022 构建的,它创建了许多public virtual项目,这些项目很可能是已设置的所有外键的结果。因此,我的 GET 请求将返回指定表的数据以及外键表中的数据,因此我一直[JsonIgnore]在模型中使用数据注释来防止这种情况发生,这是迄今为止的解决方案。

模型Treatments类如下所示:

using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;

namespace api.Models
{
    public partial class TblTreatment
    {
        public int Ownerid { get; set; }
        public string Petname { get; set; } = null!;
        public int Procedureid { get; set; }
        public DateTime Date { get; set; }
        public string? Notes { get; set; }
        public string? Payment { get; set; }
        [JsonIgnore]
        public virtual TblProcedure Procedure { get; set; } = null!;
        [JsonIgnore]
        public virtual TblPet TblPet { get; set; } = null!;
    }
}
Run Code Online (Sandbox Code Playgroud)

使用[JsonIgnore],POST 请求的响应正文如下所示,这是我想要的响应正文。也许删除付款部分是个好主意,因为每个程序已经有预设价格,并且在 POST 请求期间不会更改,因此通过提供 procedureid,API 应自动将价格与程序关联起来。但同样,我不太确定:

{
  "ownerid": 1,
  "petname": "Buster",
  "procedureid": 1,
  "date": "2022-07-14T11:25:31.335Z",
  "notes": "Broken Nose",
  "payment": "24"
}
Run Code Online (Sandbox Code Playgroud)

但是,如果没有它,它看起来像这样,它请求TreatmentsProceduretable 和Petstable 的数据输入,因为它们附加了外键:

{
  "ownerid": 0,
  "petname": "string",
  "procedureid": 0,
  "date": "2022-07-14T11:41:34.382Z",
  "notes": "string",
  "payment": "string",
  "procedure": {
    "procedureid": 0,
    "description": "string",
    "price": 0
  },
  "tblPet": {
    "ownerid": 0,
    "petname": "string",
    "type": "string"
  }
Run Code Online (Sandbox Code Playgroud)

POST对控制器的请求如下Treatments

[HttpPost]
public async Task<ActionResult<List<TblTreatment>>> AddTreatment(TblTreatment treatment)
{
    _context.TblTreatments.Add(treatment);
    await _context.SaveChangesAsync();

    return Ok(await _context.TblTreatments.ToListAsync());
}
Run Code Online (Sandbox Code Playgroud)

这种 POST 请求格式适用于我的其他控制器,但不适用于该Treatments控制器,我不确定为什么。我怀疑该问题可能是由与该Treatments表关联的所有外键引起的,因为错误正在请求外键表的数据输入(我不想输入)。我完全不知道需要改变什么。

对此的任何建议将不胜感激。

Ser*_*rge 38

因为您使用的是 net6,所以所有不需要的属性都应该显式为空。所以你应该尝试这个

        public string? Petname { get; set; } 
        public int? Procedureid { get; set; }
        [JsonIgnore]
        public virtual TblProcedure? Procedure { get; set; } 
        [JsonIgnore]
        public virtual TblPet? TblPet { get; set; }
Run Code Online (Sandbox Code Playgroud)

或者另一种方法是您可以从项目文件中删除可为空的选项

<PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <!--<Nullable>enable</Nullable>-->
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>
Run Code Online (Sandbox Code Playgroud)

或将此行添加到配置(启动或程序)中

services.AddControllers(
options => options.SuppressImplicitRequiredAttributeForNonNullableReferenceTypes = true
Run Code Online (Sandbox Code Playgroud)

  • options.SuppressImplicitRequiredAttributeForNonNullableReferenceTypes 可能是框架内单个最长的布尔属性。这正是我所需要的。从 NET5 升级到 NET6 并在我的项目文件中启用可为空会导致此问题,但直到我开始针对旧 API 端点进行回归测试时,它才被注意到。所以在那一点上我花了很多时间回溯到这一点。感谢你的回答! (2认同)