【问题标题】:ASP .NET Core (Net 6) POST Read Array from Form DataASP .NET Core (Net 6) POST 从表单数据读取数组
【发布时间】:2022-01-18 08:01:39
【问题描述】:

我正在编写一个简单的 API,其中包括一个 POST 方法,用于将新记录插入到几个数据库表中。数据来自表单数据。

其中一项是包含几个字段的集合。

我正在使用 Swagger 进行测试,当我发布表单数据时,收集字段为空白。

控制器 - 发布端点

[HttpPost("addboardmember")]
        public IActionResult PostBoardMember([FromForm] MemberForm memberData)
        {
            try
            {
                _memberRepository.PostBoardMember(memberData);
                
                var newMember = _memberRepository.GetMembers().SingleOrDefault(m => m.SSN == memberData.SSN);
                var newMemberId = newMember.Member_ID;

                var boardArray = memberData.BoardForms;


                return Ok();
               //return Ok() is temporary, will return 201 with appropriate data
            }

            catch (Exception ex)
            {
                return BadRequest("Couldn't Save record??" + ex.InnerException.ToString());
            }
            
        }

MemberForm 类(缩写以突出显示主要字段和我正在努力填充的字段:BoardForms

public class MemberForm
    {
        [Required, NotNull]
        public string LastName { get; set; }
        
        [Required, NotNull]
        public string FirstName { get; set; }
       
        [Required, NotNull]
        public string SSN {get; set;}

       


        public virtual ICollection<BoardForm> BoardForms { get; set; }
    }
}

BoardForm 类:

public class BoardForm
    {
        public int Board_ID { get; set; }

        public int StartYear { get; set; }

        public int EndYear { get; set; }
    }

当我使用 Swagger 测试 Post API 端点时,BoardForms 字段的计数为零。

大摇大摆的输入。

我将有额外的业务逻辑来根据 BoardForm 数组中的每条记录创建记录。

我不知道我应该如何访问设置为 ICollection 的表单数据中发送的数组。

浏览器开发者工具负载:

上面显示的有效负载屏幕截图中的所有元素都映射到它们的正确元素,我可以看到除“BoardForms”数组之外的值。

【问题讨论】:

  • 问:您是否在 MSVS 调试器或 Chrome/Edge 开发工具中查看过实际的 HTTP 级请求/响应?当您“保存”表单时,您的“发布”处理程序究竟接收了哪些(如果有)数据?问:您是否查看过 SSMS(或等效的)以查看哪些数据正在保存到数据库中?
  • 我正在接收所有其他字段的数据,并且我验证了我的 API 可以将这些数据写入数据库表。在包含的屏幕截图中,电子邮件字段显示输入的数据。我的大部分字段目前都是选项,所以我将它们留空。当我从浏览器开发人员工具中添加一个屏幕截图时,它显示了正在发送的有效负载。我可以访问除 BoardForms 字段之外的所有字段。当我在 API 运行时查看 Visual Studio 的值时,我看到 BoardForms 的计数为 0。

标签: asp.net-core


【解决方案1】:
  • 您使用了错误的属性并且您的请求格式不正确。
    • 当您希望 ASP.NET 绑定作为application/x-www-form-urlencodedmultipart/form-data 发布的HTML &lt;form&gt; 数据时,请使用[FromForm]
      • 您不能将 [FromForm] 用于 JSON 数据。
    • 使用[FromBody] 让ASP.NET 使用一些已配置的Content-Type 特定绑定器来填充对象。
      • ASP.NET Core 默认支持application/json,不知道还支持哪些其他类型(例如XML、DataContract等)但它是可扩展的,因为您还可以支持gRPC,例如.
      • 可能不应该&lt;form&gt; content-types(multipart/form-dataapplication/x-www-form-urlencoded)用于任何“Web API”,因为它们是特定于 HTML 的 &lt;form&gt;并且不适合描述结构化数据(例如任意数据列表或键控集合),而 ASP.NET 确实支持将 &lt;form&gt; / FormData 绑定到不适合 JSON 文档的对象。
        • 如果您使用multipart/form-data 允许从客户端库和无头客户端(以及人工操作的网络浏览器)上传二进制文件,那么我建议您重新设计您的网络-service 接受二进制文件上传作为单独的PUT/POST 请求,并且不在同一个请求中将 DTO 与二进制数据结合起来。
          • 虽然 ASP.NET Core 可以将对象绑定到 JSON (application/json) IFormFile 来自其他multipart/form-data 请求部分,此功能不是内置的,也不是交钥匙的:您需要编写自己的模型绑定器来处理这种情况- 我认为这不值得付出努力。 YMMV。

所以改变这个:

[HttpPost("addboardmember")]
public IActionResult PostBoardMember([FromForm] MemberForm memberData)
{
}

到这里:

[HttpPost("addboardmember")]
public IActionResult PostBoardMember([FromBody] MemberForm memberData)
{
}

您可能希望确保您的Controller 类已应用[ApiController]

【讨论】:

  • 我相信我将数据作为多部分/表单数据发送。所有其他字段都按 API 中的预期填充。是因为 BoardForms 字段是作为 JSON 对象发送的吗?
  • @Tom 您不能在multipart/form-data 请求正文中包含内联 JSON,除非专门配置自定义模型绑定器来处理它。如果这是您所描述的“API”,您为什么不始终如一地使用 JSON?
  • @Dai:我相信你一针见血。我喜欢像 ASP.Net 这样的框架“抽象”掉了很多低级的“垃圾”......但我讨厌这意味着许多开发人员从未真正理解 HTTP 响应数据可以格式化的不同方式,或者关于如何格式化的详细信息“绑定”确实有效……而且在使用它们时可能会遇到许多潜在的“陷阱”。
  • @paulsm4 等到你遇到我关于 WebForms 的论战...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-11
  • 2022-11-15
  • 2019-09-27
  • 1970-01-01
  • 1970-01-01
  • 2023-01-30
  • 1970-01-01
相关资源
最近更新 更多