PaginatedList onpostasync - ArgumentNullException:值不能为 null。 (参数'model')在paginnatelist上提交时

PaginatedList onpostasync - ArgumentNullException: Value cannot be null. (Parameter 'model') when submitting on paginnatelist

嗨,也许有人能给我指出正确的方向。

我使用 ms 站点上的示例创建了一个分页列表页面。 https://docs.microsoft.com/en-us/aspnet/core/data/ef-rp/sort-filter-page?view=aspnetcore-5.0

稍作修改。我用输入框替换了一个项目,因为我想编辑列表并进行批量保存,而不是打开新页面上的每个项目进行编辑。 但是当它点击提交按钮时我得到了错误。

ArgumentNullException:值不能为空。 (参数'model') Microsoft.AspNetCore.Mvc.RazorPages.PageModel.TryValidateModel(对象模型,字符串名称)

如果我绑定 属性

 [BindProperty(SupportsGet = true)]
public PaginatedList<CompanyDataListing> CustomersDisplayList { get; set; } 

我得到跟随错误

ArgumentException: 类型 'BizFinder.PaginatedList`1[BizFinder.Data.CompanyDataListing]' 没有默认构造函数(参数 'type')

甚至分页列表也不会呈现。

我的 sumbit 代码如下。

        public PaginatedList<CompanyDataListing> CustomersDisplayList { get; set; } 

     public async Task<IActionResult> OnPostAsync()
        {
            if (!TryValidateModel(CustomersDisplayList, nameof(CustomersDisplayList)))
            {
                return Page();
            }
                foreach (var item in CustomersDisplayList)
            {
                if (item.GoogleCategory != "")
                {
                    string cat = item.GoogleCategory;
                }

            }  


            return Page();
        }

我的html如下。

@using (Html.BeginForm(FormMethod.Post,
new { enctype = "multipart/form-data" }))
{
    @Html.AntiForgeryToken()
<table class="table">
    <thead>
        <tr>
            <th>
                  <a asp-page="./Index" 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="./Index" asp-route-sortOrder="@Model.DateSort"
                   asp-route-currentFilter="@Model.CurrentFilter">
                   @Html.DisplayNameFor(model => model.CustomersDisplayList[0].GoogleCategory)
                </a>
            </th>
            <th></th>
        </tr>
    </thead>
    <tbody>
        @foreach (var item in Model.CustomersDisplayList)
        {
            <tr>
                <td>
                     <input type="hidden" asp-for="CustomersDisplayList[0].Id" />
       
                    @Html.DisplayFor(modelItem => item.CompanyName)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.Keywords)
                </td>
                <td>
                    @*@Html.DisplayFor(modelItem => item.GoogleCategory)*@

                        <input asp-for="CustomersDisplayList[0].GoogleCategory"  name="Category1"   placeholder="Input your keyword" class="form-control GoogleCategory"  autofocus="autofocus" />
                <span asp-validation-for="CustomersDisplayList[0].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>

        @* @Html.ValidationSummary(true, "", new { @class = "text-danger" })*@
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Save" class="btn btn-primary" />
            </div>
        </div>
}

完整的代码库是

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using BizFinder.Data;
using BizFinder.ViewModels;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
//https://docs.microsoft.com/en-us/aspnet/core/data/ef-rp/sort-filter-page?view=aspnetcore-5.0
namespace BizFinder.Pages.Admin
{
    public class ManCatergoryModel : PageModel
    {
        private readonly ApplicationDbContext _context;
        private readonly IConfiguration Configuration;
        private readonly IAuthorizationService _authorizationService;
        public int PageSize { get; set; } = 10;

        // private readonly SchoolContext _context;
        public ManCatergoryModel(ApplicationDbContext context, IConfiguration configuration)
        {
            _context = context;
            Configuration = configuration;
        }

        public string NameSort { get; set; }
        public string DateSort { get; set; }
        public string CurrentFilter { get; set; }
        public string CurrentSort { get; set; }

        //   public IList<CompanyDataListing> CustomersDisplayList { get; set; }
   //  [BindProperty(SupportsGet = true)]
        public PaginatedList<CompanyDataListing> CustomersDisplayList { get; set; } 

        public async Task OnGetAsync(string sortOrder,
            string currentFilter, string searchString, int? pageIndex)
        {
            CurrentSort = sortOrder;
            NameSort = String.IsNullOrEmpty(sortOrder) ? "CompanyName" : "";
            DateSort = sortOrder == "Keywords" ? "date_desc" : "Date";
            if (searchString != null)
            {
                pageIndex = 1;
            }
            else
            {
                searchString = currentFilter;
            }

            CurrentFilter = searchString;

            // using System;


            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;
            }

            // var pageSize = Configuration.GetValue("PageSize", 4);
            CustomersDisplayList = await PaginatedList<CompanyDataListing>.CreateAsync(
                CompData.AsNoTracking(), pageIndex ?? 1, PageSize);

        }


        public async Task<IActionResult> OnPostAsync(PaginatedList<CompanyDataListing> Datalist)
        {


          //  List < CompanyDataListing >  mm = CustomersDisplayList.ToList();

            foreach (var item in Datalist)
            {
                string str = item.GoogleCategory;
            }

            return Page();
        }
    }
}

您正在 OnPost 处理程序中引用 CustomerDisplayList,但它尚未初始化,因此出现异常。您在 OnGet 处理程序中对其进行了初始化,但仅针对 GET 请求执行。如果你想使用 POST 请求,你还需要在其中初始化 CustomerDisplayList

就其价值而言,您链接到的示例在整个周期中使用 GET 请求。这通常对分页和过滤结果更有意义。这样,条件将作为查询字符串值或路由数据在 URL 中传递,这意味着您可以为 filtered/paged 结果添加书签。您不需要为 GET 请求呈现防伪令牌。

首先要知道教程中的分页是后台分页。点击下一页时,每次都会重新请求数据,所以如果要批量提交,只能提交当前页数据。

如果你想批量提交当前页面的数据,那么你可以修改你的代码如下。

页面模型:

public class IndexModel : PageModel
{
    private readonly PageListRazorContext _context;
    private readonly IConfiguration Configuration;

    
    public IndexModel(PageListRazorContext context, IConfiguration configuration)
    {
        _context = context;
        Configuration = configuration;
    }
    public string NameSort { get; set; }
    public string KeywordsSort { get; set; }
    public string CurrentSort { get; set; }
    public PaginatedList<CompanyDataListing> CompanyDataListing { get;set; }

    public async Task OnGetAsync(string sortOrder,int? pageIndex)
    {
        NameSort = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
        KeywordsSort = sortOrder == "Keywords" ? "keywords_desc" : "Keywords";
      
        IQueryable<CompanyDataListing> company = from s in _context.CompanyDataListing
                                                    select s;
        switch (sortOrder)
        {
            case "name_desc":
                company = company.OrderByDescending(s => s.CompanyName);
                break;
            case "Keywords":
                company = company.OrderBy(s => s.Keywords);
                break;
            case "keywords_desc":
                company = company.OrderByDescending(s => s.Keywords);
                break;
            default:
                company = company.OrderBy(s => s.CompanyName);
                break;
        }
        var pageSize = Configuration.GetValue("PageSize", 4);
      
        CompanyDataListing = await PaginatedList<CompanyDataListing>.CreateAsync(
            company.AsNoTracking(), pageIndex ?? 1, pageSize);
    }
    public IActionResult OnPost(List<CompanyDataListing> Datalist)
    {

        //....

        return RedirectToPage("./Index");
    }
}

页数:

<form method="post">
<table class="table">
    <thead>
        <tr>
            <th>
                <a asp-page="./Index" asp-route-sortOrder="@Model.NameSort">
                    @Html.DisplayNameFor(model => model.CompanyDataListing[0].CompanyName)
                </a>
            </th>
            <th>
                <a asp-page="./Index" asp-route-sortOrder="@Model.KeywordsSort">
                    @Html.DisplayNameFor(model => model.CompanyDataListing[0].Keywords)
                </a>
            </th>
            <th>
                @Html.DisplayNameFor(model => model.CompanyDataListing[0].GoogleCategory)
            </th>

            <th></th>
        </tr>
    </thead>
    <tbody>
        @foreach (var item in Model.CompanyDataListing)
        {
            <tr>
                <td>
                    <input type="hidden" asp-for="@item.CompanyName" name="Datalist[@i].CompanyName" />
                    @Html.DisplayFor(modelItem => item.CompanyName)
                </td>
                <td>
                    <input type="hidden" asp-for="@item.Keywords" name="Datalist[@i].Keywords" />
                    @Html.DisplayFor(modelItem => item.Keywords)
                </td>
                <td>
                    <input asp-for="@item.GoogleCategory" name="Datalist[@i].GoogleCategory" placeholder="Input your keyword" class="form-control GoogleCategory" autofocus="autofocus" />
                    <span asp-validation-for="@item.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>
               @{i++;}
            </tr>
           
        }
    </tbody>
</table>
<div class="form-group">
    <div class="col-md-offset-2 col-md-10">
        <input type="submit" value="Save" class="btn btn-primary" />
    </div>
</div>
@{
    var prevDisabled = !Model.CompanyDataListing.HasPreviousPage ? "disabled" : "";
    var nextDisabled = !Model.CompanyDataListing.HasNextPage ? "disabled" : "";
}

<a asp-page="./Index"
   asp-route-sortOrder="@Model.CurrentSort"
   asp-route-pageIndex="@(Model.CompanyDataListing.PageIndex - 1)"
   class="btn btn-primary @prevDisabled">
    Previous
</a>
<a asp-page="./Index"
   asp-route-sortOrder="@Model.CurrentSort"
   asp-route-pageIndex="@(Model.CompanyDataListing.PageIndex + 1)"
   class="btn btn-primary @nextDisabled">
    Next
</a>
</form>

测试结果: