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

Angular传FormData至.NET+MediatR时componentsData/cablesData映射为空

问题描述

Angular应用通过FormData提交数据,包含tePartNumber、customerPN等普通字段,以及多条componentsData、cablesData条目(请求数据如下)。.NET端使用MediatR接收,定义了SaveDrawingDataCommand类,其中包含List<ComponentsDataDto>类型的componentsData和List<CablesDataDto>类型的cablesData,但接收时这两个列表始终为空,其他字段可正常获取。

请求打印数据:

Key: tePartNumber, Value: test

Key: customerPN, Value: test

Key: projectNumber, Value: test

Key: oem, Value: 994f433e-f36b-1410-9006-00a33fe338d1

Key: harnessMaker, Value: e14f433e-f36b-1410-9006-00a33fe338d1

Key: numberOfConnectors, Value: 2

Key: cdPath, Value: [object File]

Key: pdPath, Value: [object File]

Key: excelFilePath, Value: null

Key: imagePath, Value: [object File]

Key: componentsData, Value: {"componentId":"e94f433e-f36b-1410-9006-00a33fe338d1","side":"left"}

Key: componentsData, Value: {"componentId":"e94f433e-f36b-1410-9006-00a33fe338d1","side":"right"}

Key: cablesData, Value: {"componentId":"dd4f433e-f36b-1410-9006-00a33fe338d1"}

.NET端相关代码:
控制器方法:

[HttpPost]
public async Task<ActionResult<RequestResponseMessage>> SaveDrawingData([FromForm] SaveDrawingDataCommand command)
{
    try
    {
        Console.WriteLine("Compoentdata :"+ command.componentsData.Count);
        var response = await Mediator.Send(command);
        return Ok(response);
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "An error occurred while saving the drawing data.");
        return StatusCode(StatusCodes.Status500InternalServerError, ex.Message);
    }
}

SaveDrawingDataCommand类:

public class SaveDrawingDataCommand : IRequest<SaveDrawingDataResponse>
{
    public Guid Id { get; set;}
    public string? tePartNumber { get; set; }
    public string? customerPN { get; set; }
    public string? projectNumber { get; set; }
    public string? oem { get; set; }
    public string? harnessMaker { get; set; }
    public int numberOfConnectors { get; set; }
    public List<ComponentsDataDto>? componentsData { get; set; }
    public List<CablesDataDto>? cablesData { get; set; }
    public IFormFile? cdPath { get; set; }
    public IFormFile? pdPath { get; set; }
    public IFormFile? excelFilePath { get; set; }
    public IFormFile? imagePath { get; set; }
}
原因分析

ASP.NET Core的表单数据绑定机制,无法直接识别多个同名key对应单个JSON对象的格式为List<T>类型。当前请求中componentsData和cablesData是重复key,每个key对应一个独立的JSON对象,默认绑定逻辑不会将这些对象合并为列表。

解决方案

方案1:Angular端将列表序列化为单个JSON字符串提交

修改Angular中FormData的构造逻辑,把整个componentsData和cablesData数组序列化为JSON字符串,作为单个key的值提交:

// 假设componentsData是你的数组变量
formData.append('componentsData', JSON.stringify(componentsData));
// cablesData同理
formData.append('cablesData', JSON.stringify(cablesData));

.NET端无需修改现有SaveDrawingDataCommand类,ASP.NET Core会自动将JSON字符串反序列化为List<ComponentsDataDto>和List<CablesDataDto>。

方案2:Angular端使用索引式表单字段命名

按照ASP.NET Core表单绑定的列表格式要求,使用索引标识每个列表项的属性:

componentsData.forEach((item, index) => {
  formData.append(`componentsData[${index}].componentId`, item.componentId);
  formData.append(`componentsData[${index}].side`, item.side);
});

cablesData.forEach((item, index) => {
  formData.append(`cablesData[${index}].componentId`, item.componentId);
});

这种方式符合默认表单绑定规则,.NET端无需修改代码即可正确映射为列表。

额外检查项

  1. 确保ComponentsDataDto和CablesDataDto的属性名称与JSON字段完全匹配(ASP.NET Core默认大小写不敏感,但建议保持一致避免意外);
  2. 确认Dto类的属性是公开可访问的(public),且包含对应的get/set方法。
验证步骤
  1. 修改Angular端代码后,重新提交请求,打印FormData的key-value,确保列表数据格式符合上述方案要求;
  2. 在.NET控制器中打印command.componentsData.Count,检查是否已正确获取到列表长度;
  3. 调试Handler方法,确认列表中的数据项已正确映射。

内容的提问来源于stack exchange,提问作者Chabba Mohamed Nadir

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 20:57:35