传递对象角度的FormData Item数组

Posted

技术标签:

【中文标题】传递对象角度的FormData Item数组【英文标题】:Pass FormData Item array of object angular 【发布时间】:2022-01-11 10:45:04 【问题描述】:

如何将 FormData 传递给 api,其中包含对象数组?

我正在尝试这样

这是请求的负载 如何在 .net core c# Api 中获取所有包含其他数据的项目?

public class BackgroundCheckParam

    public Guid EmpId  get; set; 
    public List<BackgroundChecksResults> Items  get; set; 
    public IFormFile ResultPdf  get; set; 
    public IFormFile DisclosurePdf  get; set; 
    public DateTime CompleteDate  get; set; 


public class BackgroundChecksResults

    public string Type  get; set; 
    public string Result  get; set; 



   public ResponseResult AddBackgroundCheck([FromForm] BackgroundCheckParam data)
    

    

其他都很好,除了物品,我什么都收到了。项目始终为 0。

【问题讨论】:

使用 Angular 的 HttpClient。警告:它会强制你使用 RxJS,它的学习曲线非常陡峭。 已经使用 Angular 的 HttpClient 来创建上面的有效载荷。只需要 c# 帮助我如何以列表的形式访问项目。 它不起作用,因为您正在混合 JSON 和 &lt;form&gt; 数据。这不是 ASP.NET Core 的错。您需要更改 Angular/TypeScript 以使用 ASP.NET 的 List FormData 名称值,而不是 JSON。 这意味着我们不能在 FormData 中传递这样的项目? 没错。要么只使用 JSON,要么只使用 URLSearchParams (application/x-www-form-urlencoded) 主体。 【参考方案1】:

它不起作用,因为您正在混合 JSON 和传统的 &lt;form&gt; 数据

一些背景信息: 在没有脚本或 AJAX 的“普通”html 中,&lt;form&gt; 可以POST 提交为application/x-www-form-urlencodedmultipart/form-dataapplication/x-www-form-urlencoded 是每个键+值对的几乎人类可读的文本表示。例如key1=value1&amp;key2=value2multipart/form-data 是二进制编码。从&lt;input type="file"&gt; 发布文件时,您需要使用此选项。 对于 javascript 发起的 HTTP 请求(使用 fetchXMLHttpRequest),通常将数据以 JSON (application/json) 形式发布,而不是使用两种 &lt;form&gt; 编码中的任何一种。 Angular 的HttpClient 在内部使用fetch如果&lt;form&gt; 也可以用于提交JSON,而不需要任何脚本,那就太好了;它没有,哦,好吧。

具体而言,您的Items 是一个List&lt;...&gt;,当它应该作为多个表单项发送时,它被表示为单个表单项中的 JSON 数组,每个值一个。

解决方案是以与 ASP.NET 的表单模型绑定语法兼容的方式表示 Items

具体来说,每个离散值都有自己的表单名称,每个列表元素都由从 0 开始的增量索引引用。

在您的情况下,Items 的键/名称将类似于:

Items[0].Type   = "Background"
Items[0].Result = "Pass" 
Items[1].Type   = "Foreground"
Items[1].Result = "Fail" 
Items[2].Type   = "Middleground"
Items[2].Result = "Compromise" 
请注意,ASP.NET(所有版本)始终要求集合索引器从 0 开始,并且索引之间没有间隙,否则 List&lt;&gt; 属性将为 null 或为空,并且不会出现任何警告或错误(很烦人)。

所以你应该有这样的东西:

// * Use `URLSearchParams` for `application/x-www-form-urlencoded`.
// * Use `FormData` for `multipart/form-data`.

const resultPdfFile = inputElement1.files[0];
const disclosurePdf = inputElement2.files[0];

const formValues = new FormData();
formValues.append( "EmpId"        , "fckgw-rhqq2-yxrkt-8tg6w-2b7q8" );
formValues.append( "ResultPdf"    , resultPdfFile );
formValues.append( "DisclosurePdf", disclosurePdf );
formValues.append( "CompleteDate" , "2021-12-01" );

for( let i = 0; i < items.length; i++ ) 
    
    const keyPrefix = "Items[" + i.toString() + "].";
    formValues.append( keyPrefix + "Type"  , items[i].type   ); // e.g. "Items[0].Type"
    formValues.append( keyPrefix + "Result", items[i].result );


await postRequest( formValues );

替代快速修复解决方法“解决方案”

在您的 ASP.NET 代码中,忽略您的 BackgroundCheckParam data 操作参数的 Items 成员和来自 Request.Form 的 JSON 解码 Items

public ResponseResult AddBackgroundCheck([FromForm] BackgroundCheckParam data)

    IReadOnlyList<BackgroundChecksResults> items;
    
        String formList = this.Request.Form["Items"];

        items = JsonConvert.DeserializeObject< List<BackgroundChecksResults> >( formList );
    

【讨论】:

以上是关于传递对象角度的FormData Item数组的主要内容,如果未能解决你的问题,请参考以下文章

如何以角度将预先生成的数组传递给模板中的组件?

检查角度数组对象是否具有指定值

FormData如何向后端传递数组

如何在调用WebService方法时,传递对象数组参数

怎么通过ajax一起传递formData和另一个对象数据

使用axios请求数据,post请求出错。因为axios传递的请求参数是json格式,而后端接口要求是formData