You need to enable JavaScript to run this app. Razor Pages中PaginatedList表单提交报ArgumentNullException如何解决
优惠活动
大模型
产品
解决方案
定价
更多

Razor Pages中PaginatedList表单提交报ArgumentNullException如何解决

问题解决步骤

根因说明

  1. PaginatedList<T>是自定义分页包装类,无公共无参构造函数,ASP.NET Core 模型绑定系统无法直接实例化该类型,因此无法直接作为绑定属性或接口接收参数,这是你加[BindProperty]后报错的核心原因。
  2. Post请求默认不会自动填充CustomersDisplayList属性,你直接将空的该属性传入TryValidateModel自然触发空引用异常。
  3. 视图中循环渲染时索引写死为[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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.13 02:21:04