Razor Pages中PaginatedList表单提交报ArgumentNullException如何解决
问题解决步骤
根因说明
PaginatedList<T>是自定义分页包装类,无公共无参构造函数,ASP.NET Core 模型绑定系统无法直接实例化该类型,因此无法直接作为绑定属性或接口接收参数,这是你加[BindProperty]后报错的核心原因。- Post请求默认不会自动填充
CustomersDisplayList属性,你直接将空的该属性传入TryValidateModel自然触发空引用异常。 - 视图中循环渲染时索引写死为
[0],且手动修改了输入框的name属性,破坏了模型绑定的命名规则,导致后端无法接收到行内编辑的列表数据。
修复步骤
1. 后端调整绑定属性
在ManCatergoryModel中新增专门用于接收提交数据的集合属性,不要直接使用PaginatedList做绑定:
// 新增用于接收提交数据的绑定属性 [BindProperty] public List<CompanyDataListing> SubmitItems { get; set; } // 抽离公共加载列表的方法,避免Get和Post逻辑重复 private async Task LoadCustomersDataAsync(string sortOrder, string currentFilter, int pageIndex) { CurrentSort = sortOrder; NameSort = String.IsNullOrEmpty(sortOrder) ? "CompanyName" : ""; DateSort = sortOrder == "Keywords" ? "date_desc" : "Date"; CurrentFilter = currentFilter; IQueryable<CompanyDataListing> CompData = from s in _context.CompanyDataList where s.GoogleCategory == null select s; switch (sortOrder) { case "name_desc": CompData = CompData.OrderByDescending(s => s.CompanyName); break; case "Date": CompData = CompData.OrderBy(s => s.Keywords); break; case "GoogleCategory": CompData = CompData.OrderByDescending(s => s.GoogleCategory); break; default: CompData = CompData.OrderBy(s => s.CompanyName); break; } CustomersDisplayList = await PaginatedList<CompanyDataListing>.CreateAsync( CompData.AsNoTracking(), pageIndex, PageSize); }
2. 调整OnGet和OnPost逻辑
public async Task OnGetAsync(string sortOrder, string currentFilter, string searchString, int? pageIndex) { if (searchString != null) { pageIndex = 1; } else { searchString = currentFilter; } await LoadCustomersDataAsync(sortOrder, searchString, pageIndex ?? 1); } public async Task<IActionResult> OnPostAsync(string currentSort, string currentFilter, int pageIndex) { if (!TryValidateModel(SubmitItems)) { // 验证失败需重新加载列表数据,否则页面渲染会报错 await LoadCustomersDataAsync(currentSort, currentFilter, pageIndex); return Page(); } // 批量更新逻辑 foreach (var item in SubmitItems.Where(x=>!string.IsNullOrWhiteSpace(x.GoogleCategory))) { var dbEntity = await _context.CompanyDataList.FindAsync(item.Id); if (dbEntity != null) { dbEntity.GoogleCategory = item.GoogleCategory; } } await _context.SaveChangesAsync(); // 保存成功后重定向到Get页,避免重复提交 return RedirectToPage("./ManCatergory", new { sortOrder = currentSort, currentFilter = currentFilter, pageIndex = pageIndex }); }
3. 调整Razor视图代码
- 将
foreach循环改为带索引的for循环 - 删除手动设置的
name属性,让TagHelper自动生成符合绑定规则的名称 - 新增隐藏域存储排序、筛选、页码参数,避免Post后参数丢失
@using (Html.BeginForm(FormMethod.Post, new { enctype = "multipart/form-data" })) { @Html.AntiForgeryToken() <!-- 新增隐藏域存储查询参数 --> <input type="hidden" asp-for="CurrentSort" name="currentSort" /> <input type="hidden" asp-for="CurrentFilter" name="currentFilter" /> <input type="hidden" name="pageIndex" value="@Model.CustomersDisplayList.PageIndex" /> <table class="table"> <thead> <tr> <th> <a asp-page="./ManCatergory" asp-route-sortOrder="@Model.NameSort" asp-route-currentFilter="@Model.CurrentFilter"> @Html.DisplayNameFor(model => model.CustomersDisplayList[0].CompanyName) </a> </th> <th> @Html.DisplayNameFor(model => model.CustomersDisplayList[0].Keywords) </th> <th> <a asp-page="./ManCatergory" asp-route-sortOrder="@Model.DateSort" asp-route-currentFilter="@Model.CurrentFilter"> @Html.DisplayNameFor(model => model.CustomersDisplayList[0].GoogleCategory) </a> </th> <th></th> </tr> </thead> <tbody> <!-- 改为for循环带索引 --> @for (int i = 0; i < Model.CustomersDisplayList.Count; i++) { var item = Model.CustomersDisplayList[i]; <tr> <td> <!-- 绑定到SubmitItems对应索引的Id --> <input type="hidden" asp-for="SubmitItems[i].Id" /> @Html.DisplayFor(modelItem => item.CompanyName) </td> <td> @Html.DisplayFor(modelItem => item.Keywords) </td> <td> <!-- 删除手动设置的name属性,绑定到SubmitItems对应索引的GoogleCategory --> <input asp-for="SubmitItems[i].GoogleCategory" placeholder="Input your keyword" class="form-control GoogleCategory" /> <span asp-validation-for="SubmitItems[i].GoogleCategory" class="text-danger"></span> </td> <td> <a asp-page="./Edit" asp-route-id="@item.Id">Edit</a> | <a asp-page="./Details" asp-route-id="@item.Id">Details</a> | <a asp-page="./Delete" asp-route-id="@item.Id">Delete</a> </td> </tr> } </tbody> </table> <div asp-validation-summary="All"> <span>Please correct the following errors</span> </div> <div class="form-group"> <div class="col-md-offset-2 col-md-10"> <input type="submit" value="Save" class="btn btn-primary" /> </div> </div> }
内容的提问来源于stack exchange,提问作者Trevor
相关产品推荐
相关产品推荐

