ASP.NET 6表单提交时ViewModel未传入Controller Post方法问题
ASP.NET 6 ViewModel回传为null问题修复
核心根因
共3处问题直接触发模型绑定失败,导致Post方法入参ArtImages vm始终为null:
- 表单必填属性拼写错误:文件上传场景下form标签必须声明
enctype="multipart/form-data",现有代码错写为encrypte="multipart/form-data",浏览器不会按文件上传格式编码提交数据,服务端无法解析请求内容 - 下拉框绑定类型不匹配:
<select>元素仅能提交单个简单类型值(选中option的value属性),现有代码直接将select绑定到复杂实体Artwork,模型绑定器无法将提交的int类型Id映射为完整Artwork实例,触发绑定失败 - 隐含逻辑缺陷:Post方法未做基础模型校验,一旦绑定过程出现空值直接抛出空引用异常,同时文件上传input未显式声明
type="file",部分浏览器下不会渲染为文件选择控件
分步修复方案
1. 修正表单标签属性
将form标签的拼写错误修正,确保文件上传编码格式生效:
<form asp-action="Create" enctype="multipart/form-data" asp-controller="ArtworkImages">
2. 调整ViewModel结构
不要在提交模型中直接绑定完整复杂实体,仅保留需要接收的简单类型字段:
public class ArtImages { public List<IFormFile> Images { get; set; } // 仅接收下拉框提交的作品Id,不直接绑定整个Artwork实体 public int ArtworkId { get; set; } }
建议同时给ArtworkImage实体补充显式外键,避免EF Core隐式外键关联异常:
public class ArtworkImage { public int Id { get; set; } public string ImageURL { get; set; } public int ArtworkId { get; set; } // 显式定义外键 public Artwork Artwork { get; set; } }
3. 修正视图绑定逻辑
调整下拉框绑定目标为ArtworkId,同时给文件上传控件显式指定type属性:
<div class="form-group"> <label asp-for="ArtworkId" class="control-label"></label> <select asp-for="ArtworkId" asp-items="@ViewBag.images" class="form-control"> <option value="0">Select artwork</option> </select> <span asp-validation-for="ArtworkId" class="text-danger"></span> </div> <div class="form-group"> <label asp-for="Images" class="control-label"></label> <input asp-for="Images" type="file" class="form-control" multiple /> <span asp-validation-for="Images" class="text-danger"></span> </div>
4. 修正Post接口逻辑
补充模型校验,通过接收的ArtworkId查询关联实体,不要直接绑定导航属性,同时修正异步方法缺失await的问题:
[HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> Create(ArtImages vm) { // 基础模型校验 if (!ModelState.IsValid || vm.Images == null || vm.Images.Count == 0 || vm.ArtworkId == 0) { // 重新初始化下拉框数据返回表单页 ViewBag.images = new SelectList(_context.Artworks.ToList(), "Id", "Information"); return View(vm); } // 查询关联的作品实体 var targetArtwork = await _context.Artworks.FindAsync(vm.ArtworkId); if (targetArtwork == null) { ModelState.AddModelError("", "选中的作品不存在"); ViewBag.images = new SelectList(_context.Artworks.ToList(), "Id", "Information"); return View(vm); } foreach (var item in vm.Images) { if (item.Length > 0) { string stringFileName = UploadFile(item); var artworkImage = new ArtworkImage { ImageURL = stringFileName, ArtworkId = vm.ArtworkId // 直接赋值外键即可 }; _context.ArtworkImages.Add(artworkImage); } } await _context.SaveChangesAsync(); return RedirectToAction("Index"); }
内容的提问来源于stack exchange,提问作者DaSernet
相关产品推荐
相关产品推荐

