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

.NET Web API接收Angular multipart-formdata参数为null问题

Angular表单提交至.NET Core Web API时,SampleDTO字段全为null的解决方法

问题描述

使用Angular表单提交请求至.NET Core Web API时,SampleDTO的Name字段和File字段均接收为null,相关代码如下:

.NET Core API代码

[HttpPost("file")]
public ActionResult<string> Upload([FromForm]SampleDTO dto)
{
    try
    {
        var folderName = Path.Combine("wwwroot", "Images/products");
        var pathToSave = Path.Combine(Directory.GetCurrentDirectory(), folderName);
        if (dto.File != null && dto.File?.Length > 0)
        {
            var fileName = ContentDispositionHeaderValue.Parse(dto.File.ContentDisposition)
            .FileName.Trim('"');
            var fullPath = Path.Combine(pathToSave, fileName);
            var dbPath = Path.Combine(folderName, fileName);
            using (var stream = new FileStream(fullPath, FileMode.Create))
            {
                dto.File.CopyTo(stream);
                return Ok(dto.File.FileName+" ");
            }
        }
        return BadRequest();
    }
    catch (System.Exception)
    {
        return BadRequest();
    }
}

DTO代码

public class SampleDTO
{
    [Required]
    public string Name { get; set; }
    [Required]
    public IFormFile File { get; set; }
}

Angular接口定义

export interface ISample
{
    name:string;
    file:File;
}

Angular服务方法

createSample(data:any)
{
    return this.http.post("https://localhost:7169/api/product/file",data);
}

Angular组件提交方法

onSubmit(data:any)
{
    console.log(data as ISample);
    this.productService.createSample(data as ISample).subscribe(res=>console.log(res));
}

Angular组件文件赋值方法

onChange(event:any)
{
    this.file = event.target.files[0] as File;
    this.testForm.patchValue(
        {
            file:this.file
        }); 
}

Angular HTML代码

<form [formGroup]="this.testForm">
    <input type="text" name="name" id="name" formControlName="name">
    <input type="file" name="file" id="file" (change)="onChange($event)">
    <button (click)="this.onSubmit(this.testForm.value)">Submit</button>
</form>

解决方法

1. 改用FormData构建请求数据

上传文件必须使用multipart/form-data格式,不能直接传递JSON对象。修改Angular组件的提交方法:

onSubmit(data: any) {
    const formData = new FormData();
    // 键名必须与.NET DTO的属性名完全匹配(区分大小写)
    formData.append('Name', data.name);
    formData.append('File', data.file);
    
    this.productService.createSample(formData).subscribe(res => console.log(res));
}

2. 确保服务请求头正确

Angular的HttpClient在发送FormData时会自动设置Content-Type: multipart/form-data,无需手动添加。如果之前手动设置过JSON相关请求头,需要移除:

createSample(data: FormData) {
    return this.http.post("https://localhost:7169/api/product/file", data);
}

3. 严格匹配属性大小写

.NET模型绑定区分大小写,FormData的键名必须和DTO的属性名一致(如Name而非name),否则无法完成绑定。

4. 优化文件控件的处理(可选)

可以直接从DOM获取文件对象,避免表单patchValue的潜在问题:

onSubmit() {
    const name = this.testForm.get('name')?.value;
    const fileInput = document.getElementById('file') as HTMLInputElement;
    const file = fileInput.files?.[0];
    
    if (file) {
        const formData = new FormData();
        formData.append('Name', name);
        formData.append('File', file);
        this.productService.createSample(formData).subscribe(res => console.log(res));
    }
}

原因说明

.NET API使用[FromForm]标记,要求请求数据为multipart/form-data格式,但原Angular代码直接传递JSON对象,导致API无法解析请求内容,最终DTO字段全部为null。改用FormData后,请求格式与API要求匹配,模型绑定即可正常完成。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 13:40:33