ASP.NET Core 5 MVC表单提交报ArgumentNullException(items为空)问题求助
问题根因
- 第一个错误
ArgumentNullException: Value cannot be null. (Parameter 'items')的核心原因:ViewBag仅在单请求生命周期内生效,GET请求赋值的ViewBag在请求结束后就销毁了,POST是独立的新请求,你如果在POST处理逻辑中返回视图前没有重新给ViewBag.users赋值,渲染下拉框时asp-items读取到的是null值,直接抛出空参数异常。 - 补充ViewBag赋值后仍报空引用:是你生成用户列表的逻辑没有做空值兼容,比如
_context.NR_Users查询返回null时直接调用Insert方法就会触发空引用异常。 - 提交后直接返回Create页面、未执行数据库插入:说明
ModelState.IsValid结果为false,代码根本没有进入if(ModelState.IsValid)对应的插入逻辑块,直接走了返回视图的分支,你观测到的"进入代码块后无输出"是误判,实际上代码从未进入该分支。 - 相同逻辑在其他页面正常:另一页面的POST逻辑要么验证通过率100%,成功后直接走重定向不会返回视图;要么POST逻辑中所有返回视图的场景都提前重新赋值了ViewBag,不会触发空值问题。
解决方案
- 抽离公共的下拉列表加载逻辑,统一做空值兼容,避免重复代码:
// 控制器内新增私有方法 private void LoadUserSelectList() { // 做空值兼容,避免查询结果为空时报错 List<string> users = (from c in _context.NR_Users select c.Name).ToList() ?? new List<string>(); users.Insert(0, "Select"); ViewBag.users = users; }
- 所有需要渲染Create页面的位置都调用该方法:GET请求的Create方法、POST请求中所有返回View的分支都要提前调用:
// GET方法示例 public IActionResult Create() { LoadUserSelectList(); return View(); } // POST方法示例 [HttpPost] [ValidateAntiForgeryToken] public IActionResult Create(YourModel typeOne) { // 验证不通过时重新加载下拉列表再返回视图 if (!ModelState.IsValid) { // 调试时可以加这段打印验证错误,定位ModelState不通过的原因 var validationErrors = ModelState.Values .SelectMany(v => v.Errors) .Select(e => e.ErrorMessage) .ToList(); // 打断点查看validationErrors即可知道是哪个字段验证不通过,常见原因:其他必填字段为空、字段格式不符合要求等 LoadUserSelectList(); return View(typeOne); } // 这里写你的数据库插入逻辑 _context.Add(typeOne); _context.SaveChanges(); // 插入成功后用重定向跳转,不要直接返回View,避免重复提交 return RedirectToAction(nameof(Index)); }
- 优化视图层下拉框的写法,做一层空值防护,同时把默认选项移到视图中更灵活:
<div class="form-group col-md-4"> <label class="control-label">Prepared By</label> <select asp-for="Prepared_By" class="form-control" asp-items="@(ViewBag.users != null ? new SelectList(ViewBag.users) : Enumerable.Empty<SelectListItem>())"> <option value="">Select</option> </select> <span asp-validation-for="Prepared_By" class="text-danger"></span> </div>
内容的提问来源于stack exchange,提问作者GrillOwner69420
相关产品推荐
相关产品推荐

