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

ASP.NET MVC Razor表单批量文件上传绑定始终为null问题

文件上传字段绑定为null的解决方案

问题场景

我有一个基于订单金额等选项生成所需文档列表的表单,允许终端用户上传对应文件后点击“全部上传”。但将视图模型绑定回Action时,Upload字段始终为null,其他所有字段均正常。

现有Razor页面代码

<form asp-action="UploadQuotes" class="quoteForm" enctype="multipart/form-data" asp-controller="Home" onsubmit="return jQueryAjaxPost(this);">

@for (int i = 0; i < Model.Count; i++)
{                
    <input type="hidden" asp-for="@Model[i].Id"/>

    <li class="list-group-item list-group-item-action itemClass">
        <div class="row">
            <div class="col-3">
                <div class="form-group">
                    <select asp-for="@Model[i].SelectedType" class="form-control custom-select" asp-items="@Model[i].Options"></select>

                    <span asp-validation-for="@Model[i].SelectedType" text-danger" style="color:red;"></span>
                </div>
            </div>
            <div class="col-8 text-center">
                <input class="form-control" asp-for="@Model[i].Upload" type="file" >
            </div>
            <div class="col-1 my-auto">
                @if (Model[i].AllowDelete)
                {
                    <button class="btn ms-0 ps-0" title="Delete" onclick="jQueryAjaxDelete('@Url.Action("DeleteQuote", "Actions", new {id = Model[i].Id })',this)"><i class="fa-solid fa-circle-xmark"></i></button>
                }
            </div>
        </div>
    </li>
}
</form>

现有Controller代码

public async Task<IActionResult> UploadQuotes(List<QuoteVM> vm)
{
    foreach(var quote in vm)
    {
        var quotePlaceholder = await _unitOfWork.quoteRepo
                                                .GetByIdAsync(x => x.Id == quote.Id);

        var file = _baseFactory.ConvertUpload(quote.Upload); //returns tuple with upload as byte[]
        quotePlaceholder.Doc = file.Item4;

        _unitOfWork.quoteRepo.Update(quotePlaceholder);
        await _unitOfWork.SaveAsync();
    }

    return View(vm);
}

解决步骤

1. 修正AJAX提交逻辑

问题核心在于AJAX上传文件不能使用普通的表单序列化,必须通过FormData对象传递,同时禁用jQuery的自动数据处理和 contentType 设置。

修改jQueryAjaxPost函数如下:

function jQueryAjaxPost(form) {
    // 用表单实例构造FormData,自动包含所有表单字段(包括文件)
    var formData = new FormData(form);
    
    $.ajax({
        url: form.action,
        type: form.method,
        data: formData,
        // 禁止jQuery处理数据,避免文件被转成字符串
        processData: false,
        // 禁止设置contentType,让浏览器自动添加正确的multipart/form-data头
        contentType: false,
        success: function (result) {
            // 这里添加上传成功后的处理逻辑,比如提示或页面刷新
            alert("文件上传完成");
        },
        error: function (xhr) {
            alert("上传失败,请重试");
        }
    });
    
    return false; // 阻止表单默认的同步提交
}

2. 确认视图模型字段类型

确保QuoteVM中的Upload属性为IFormFile类型(ASP.NET Core中唯一支持文件上传绑定的类型):

public class QuoteVM
{
    public int Id { get; set; }
    public string SelectedType { get; set; }
    public IEnumerable<SelectListItem> Options { get; set; }
    public bool AllowDelete { get; set; }
    // 必须是IFormFile类型,才能正确接收上传的文件
    public IFormFile Upload { get; set; }
}

3. 验证表单字段命名

Razor循环中asp-for="@Model[i].Upload"会自动生成name="vm[i].Upload"的属性,这符合ASP.NET Core对集合绑定的要求,无需修改。只要AJAX正确传递FormData,绑定就能正常工作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 16:57:17