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

ASP.NET Core MVC表单上传图片至Web API时参数传递失败问题

问题原因

你的API接口用[FromForm]接收表单数据(包含文件),但MVC端调用时用了PostAsJsonAsync发送JSON格式请求,两者完全不兼容:

  1. [FromForm]期望请求是multipart/form-data或application/x-www-form-urlencoded格式,JSON请求无法被解析为表单对象。
  2. IFormFile类型不能通过JSON序列化传递,必须通过multipart/form-data格式上传。
解决方案

1. 修正MVC的AddStudent方法

移除不必要的ModelState.Remove("Pic"),确保文件能正确绑定到student.Pic,同时补全RedirectToAction的return语句:

[HttpPost]
public async Task<IActionResult> AddStudent(Student student)
{
    ModelState.Remove("PicUrl"); // 保留这个,因为API会生成PicUrl

    if (ModelState.IsValid)
    {
        var response = await webApiExecuter.InvokePostWithFormData<Student>("student", student, student.Pic);

        if (response != null)
        {
            return RedirectToAction(nameof(Index)); // 补上return,否则不会跳转
        }

        return View(student);
    }

    return View(student);
}

2. 新增支持表单+文件的API调用方法

替换原来的InvokePost,改用MultipartFormDataContent构建符合API要求的请求:

public async Task<T?> InvokePostWithFormData<T>(string relativeUrl, Student student, IFormFile? pic)
{
    var httpClient = httpClientFactory.CreateClient(name);
    using var content = new MultipartFormDataContent();

    // 逐个添加Student的属性到表单数据
    content.Add(new StringContent(student.Id.ToString()), "Id");
    content.Add(new StringContent(student.Name ?? string.Empty), "Name");
    if (student.Age.HasValue)
        content.Add(new StringContent(student.Age.Value.ToString()), "Age");
    content.Add(new StringContent(student.Gender ?? string.Empty), "Gender");
    if (student.RollNumber.HasValue)
        content.Add(new StringContent(student.RollNumber.Value.ToString()), "RollNumber");
    content.Add(new StringContent(student.Standard ?? string.Empty), "Standard");
    if (student.Section.HasValue)
        content.Add(new StringContent(student.Section.Value.ToString()), "Section");
    if (student.Birthday.HasValue)
        content.Add(new StringContent(student.Birthday.Value.ToString("o")), "Birthday");
    content.Add(new StringContent(student.BloodGroup ?? string.Empty), "BloodGroup");

    // 添加文件到表单
    if (pic != null && pic.Length > 0)
    {
        var fileStreamContent = new StreamContent(pic.OpenReadStream());
        fileStreamContent.Headers.ContentType = new MediaTypeHeaderValue(pic.ContentType);
        content.Add(fileStreamContent, "Pic", pic.FileName);
    }

    var res = await httpClient.PostAsync(relativeUrl, content);
    res.EnsureSuccessStatusCode();

    return await res.Content.ReadFromJsonAsync<T>();
}

3. 验证视图绑定

确保视图中的文件上传控件正确绑定到Pic属性:

<input type="file" asp-for="Pic" accept=".jpg" />
关键说明
  • 必须用MultipartFormDataContent构建包含文件的表单请求,才能匹配API的[FromForm]接收规则。
  • 日期类型按ISO格式(ToString("o"))传递,避免跨系统解析错误。
  • 提前确认HttpClient的BaseAddress已正确配置为你的Web API地址。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 23:26:13