简体   繁体   English

Razor 页面中具有多个搜索字段的分页列表

[英]Paginated List with Multiple Search Fields in Razor Pages

I'm creating a Razor Page application in which my clients need to search on multiple fields at once, however, when I create the multiple search fields the search itself works well but the pagination on the paginated list breaks, losing the search terms on the second page and reverting to it's default pagination order.我正在创建一个 Razor 页面应用程序,我的客户需要在其中一次搜索多个字段,但是,当我创建多个搜索字段时,搜索本身运行良好,但分页列表上的分页中断,丢失了搜索词第二页并恢复到它的默认分页顺序。 Is there a different list type that I should implement, or is there a way to conditionally prioritize which search field the paginated list uses to maintain it's pagination order and to not lose the search?是否有我应该实现的不同列表类型,或者有没有办法有条件地优先考虑分页列表使用哪个搜索字段来维护其分页顺序并且不会丢失搜索? As a newcomer to development I will provide most of the code in the code behind, as I am still unclear as to how the pieces all fit together when it comes to pagination, sorting and filtering in Razor Pages.作为开发新手,我将在后面的代码中提供大部分代码,因为在 Razor 页面中的分页、排序和过滤方面,我仍然不清楚这些部分是如何组合在一起的。

Everything was working perfectly when I had a search set up that allowed the client to search on one field at a time and the problem arose when I made the changes to allow for a multiple concurrent search.当我设置了允许客户端一次搜索一个字段的搜索设置时,一切都运行良好,当我进行更改以允许多个并发搜索时,问题就出现了。

This is the Code Behind:这是背后的代码:

 private readonly PFDTrustContext _context;

    public IndexModel(PFDTrustContext context)
    {
        _context = context;
    }

    public PaginatedList<Client> Clients { get; set; }

    // sorting
    public string AcctNumberSort { get; set; }
    public string FirstNameSort { get; set; }
    public string LastNameSort { get; set; }
    public string SSNSort { get; set; }
    public string CurrentSort { get; set; }

    // filtering
    public string FilterLN { get; set; }
    public string FilterFN { get; set; }
    public string FilterSSN { get; set; }
    public string FilterAcctNum { get; set; }
    public string CurrentFilter { get; set; }


    public async Task OnGetAsync(string sortOrder, string searchStringLN, string searchStringFN, string searchStringSSN, string searchStringAcctNum, string filterLN, string filterFN, string filterSSN, string filterAcctNum, string currentFilter, int? pageIndex)
    {
        CurrentSort = sortOrder;

        // Sorting
        LastNameSort = string.IsNullOrEmpty(sortOrder) ? "lastName_desc" : "";
        FirstNameSort = sortOrder == "firstName" ? "firstName_desc" : "firstName";
        AcctNumberSort = sortOrder == "acctNumber" ? "acctNumber_desc" : "acctNumber";
        SSNSort = sortOrder == "SSN" ? "SSN_desc" : "SSN";

        // Paging
        if (searchStringLN != null)
        {
            pageIndex = 1;
        }
        else
        {
            searchStringLN = filterLN;
        }

        if (searchStringFN != null)
        {
            pageIndex = 1;
        }
        else
        {
            searchStringFN = filterFN;
        }

        if (searchStringSSN != null)
        {
            pageIndex = 1;
        }
        else
        {
            searchStringSSN = filterSSN;
        }

        if (searchStringAcctNum != null)
        {
            pageIndex = 1;
        }
        else
        {
            searchStringAcctNum = filterAcctNum;
        }

        // Searching/Filtering
        FilterLN = searchStringLN;
        FilterFN = searchStringFN;
        FilterSSN = searchStringSSN;
        FilterAcctNum = searchStringAcctNum;

        if (!string.IsNullOrEmpty(FilterLN))
        {
            CurrentFilter = FilterLN;
        }
        else if (!string.IsNullOrEmpty(FilterSSN))
        {
            CurrentFilter = FilterSSN;
        }
        else if (!string.IsNullOrEmpty(FilterAcctNum))
        {
            CurrentFilter = FilterAcctNum;
        }
        else
        {
            CurrentFilter = FilterFN;
        }


        // Sorting
        IQueryable<Client> clients = from c in _context.Clients
                                     select c;

        // Searching
        if (!string.IsNullOrEmpty(searchStringLN))
        {
            clients = clients.Where(c => c.LastName.ToUpper().Contains(searchStringLN.ToUpper()));
        }
        if (!string.IsNullOrEmpty(searchStringFN))
        {
            clients = clients.Where(c => c.FirstName.ToUpper().Contains(searchStringFN.ToUpper()));
        }
        if (!string.IsNullOrEmpty(searchStringSSN))
        {
            clients = clients.Where(c => c.SSN.ToString().Contains(searchStringSSN));
        }
        if (!string.IsNullOrEmpty(searchStringAcctNum))
        {
            clients = clients.Where(c => c.AcctNumber.ToString().Contains(searchStringAcctNum));
        }

        // Sorting
        switch (sortOrder)
        {
            case "lastName_desc":
                clients = clients.OrderByDescending(c => c.LastName);
                break;
            case "acctNumber":
                clients = clients.OrderBy(c => c.AcctNumber);
                break;
            case "acctNumber_desc":
                clients = clients.OrderByDescending(c => c.AcctNumber);
                break;
            case "firstName_desc":
                clients = clients.OrderByDescending(c => c.FirstName);
                break;
            case "firstName":
                clients = clients.OrderBy(c => c.FirstName);
                break;
            case "SSN":
                clients = clients.OrderBy(c => c.SSN);
                break;
            case "SSN_desc":
                clients = clients.OrderByDescending(c => c.SSN);
                break;
            default:
                clients = clients.OrderBy(c => c.LastName);
                break;
        }

        // Pagination
        int pageSize = 12;

        Clients = await PaginatedList<Client>.CreateAsync(
            clients.AsNoTracking(), pageIndex ?? 1, pageSize);
    }

This is the Razor Page:这是 Razor 页面:

 <table class="table">
     <thead>
         <tr>
             <th>
                 @Html.DisplayNameFor(model => model.Clients[0].ClientId)
             </th>
             <th>
                 <a asp-page="./Index" asp-route-sortOrder="@Model.AcctNumberSort"
               asp-route-currentFilter="@Model.FilterAcctNum">
                     @Html.DisplayNameFor(model => model.Clients[0].AcctNumber)
                 </a>
             </th>
             <th>
                 <a asp-page="./Index" asp-route-sortOrder="@Model.FirstNameSort"
               asp-route-currentFilter="@Model.FilterFN">
                     @Html.DisplayNameFor(model => model.Clients[0].FirstName)
                 </a>
             </th>
             <th>
                 <a asp-page="./Index" asp-route-sortOrder="@Model.LastNameSort"
               asp-route-currentFilter="@Model.FilterLN">
                @Html.DisplayNameFor(model => model.Clients[0].LastName)
                 </a>
             </th>
             <th>
                 @Html.DisplayNameFor(model => model.Clients[0].MdlInit)
             </th>
             <th>
                 <a asp-page="./Index" asp-route-sortOrder="@Model.SSNSort"
               asp-route-currentFilter="@Model.FilterSSN">
                     @Html.DisplayNameFor(model => model.Clients[0].SSN)
                 </a>
             </th>
             <th>
                 @Html.DisplayNameFor(model => model.Clients[0].DOB)
             </th>
             <th>
                 @Html.DisplayNameFor(model => model.Clients[0].InitialEntryDate)
             </th>
             <th></th>
         </tr>
     </thead>
     <tbody>
         @foreach (var item in Model.Clients)
         {
         <tr>
             <td>
                 @Html.DisplayFor(modelItem => item.ClientId)
             </td>
             <td>
                 @Html.DisplayFor(modelItem => item.AcctNumber)
             </td>
             <td>
                 @Html.DisplayFor(modelItem => item.FirstName)
             </td>
             <td>
                 @Html.DisplayFor(modelItem => item.LastName)
             </td>
             <td>
                 @Html.DisplayFor(modelItem => item.MdlInit)
             </td>
             <td>
                 @Html.DisplayFor(modelItem => item.SSN, "SSN")
             </td>
             <td>
                 @Html.DisplayFor(modelItem => item.DOB)
             </td>
             <td>
                 @Html.DisplayFor(modelItem => item.InitialEntryDate)
             </td>
             <td>
                 <a asp-page="./Edit" asp-route-id="@item.ClientId">Edit Client</a> |
                 <a asp-page="./Details" asp-route-id="@item.ClientId">Transactions</a>
             </td>
         </tr>
         }
     </tbody>
 </table>

 @{
     var prevDisabled = !Model.Clients.HasPreviousPage ? "disabled" : "";
     var nextDisabled = !Model.Clients.HasNextPage ? "disabled" : "";
 }


     <a asp-page="./Index"
         asp-route-SortOrder="@Model.CurrentSort"
         asp-route-pageIndex="@(Model.Clients.PageIndex - 1)"
         asp-route-currentFilter="@Model.CurrentFilter"

         class="btn btn-default @prevDisabled">
         Previous
     </a>

     <a asp-page="./Index"
         asp-route-sortOrder="@Model.CurrentSort"
         asp-route-pageIndex="@(Model.Clients.PageIndex + 1)"
         asp-route-currentFilter="@Model.CurrentFilter"

         class="btn btn-default @nextDisabled">
         Next
     </a>

Ultimately I need the pagination to retain the search terms and the sort order while moving through the pages of results.最终,在浏览结果页面时,我需要分页来保留搜索词和排序顺序。 If this is simply not possible, then I would like to know how to eliminate the pagination and use some other kind of collection to achieve the outcome of retaining the ability to search concurrently on multiple fields.如果这根本不可能,那么我想知道如何消除分页并使用其他类型的集合来实现保留在多个字段上同时搜索的能力的结果。

When creating the paging links you need to pass all query string parameters to generate the new page url.创建分页链接时,您需要传递所有查询字符串参数以生成新页面 url。

It can be done by hardcoding all query string values (including search filters) using asp-route-...="xxx" .可以通过使用asp-route-...="xxx"所有查询字符串值(包括搜索过滤器)进行硬编码来完成。

Another way is to get current page query string value (starting from '?') and replace only the page number and generate the new url:另一种方法是获取当前页面查询字符串值(从“?”开始)并仅替换页码并生成新的 url:


<a href="@CreateUrl(Model.Clients.PageIndex - 1)">Previous</a>
<a href="@CreateUrl(Model.Clients.PageIndex + 1)">Next</a>

@{
    string CreateUrl(int index)
    {
        // Split the query string to individual parameters
        // e.g. [ "pageIndex=1", "searchString=blablabla", ...]
        var queryStringList = Request.QueryString.Value.Split('&').ToList();

        // Loop throw the parameters and increase the page index
        for (int i = 0; i < queryStringList.Count(); i++)
        {
            var qs = queryStringList[i];
            queryStringList[i] = qs.StartsWith("pageIndex=") ? $"pageIndex={index}" : qs;
        }

        // Reconstrcu the url
        return string.Join("&", queryStringList);
    }
}

Or you may simply use regex to replace the value without splitting and recreating the url:或者您可以简单地使用正则表达式替换该值,而无需拆分和重新创建 url:

<a href="@CreateUrl(Model.Clients.PageIndex - 1)">Previous</a>
<a href="@CreateUrl(Model.Clients.PageIndex + 1)">Next</a>

@{
    string CreateUrl(int index)
    {
        var input = Request.QueryString.Value;
        var replacement = $"pageIndex={index}";
        var pattern = @"pageIndex=\d+";
        return System.Text.RegularExpressions.Regex.Replace(input, pattern, replacement);
    }
}

Or use a pagination tag helper nuget that can handle all complex pagination logic, like LazZiya.TagHelpers , install from nuget:或者使用可以处理所有复杂分页逻辑的分页标签助手 nuget,例如LazZiya.TagHelpers ,从 nuget 安装:

Install-Package LazZiya.TagHelpers -Version 3.0.2安装包 LazZiya.TagHelpers -版本 3.0.2

Add paging tag helper to _ViewImports:为 _ViewImports 添加分页标签助手:

@addTagHelper *, LazZiya.TagHelpers

Then use it where you need a paging control:然后在需要分页控件的地方使用它:

<paging 
    total-records="Model.TotalRecords" 
    page-no="Model.PageNo"
    query-string-key-page-no="pageIndex"
    query-string-value="@(Request.QueryString.Value)">
</paging>

See tutorial , live demo and docs查看教程现场演示文档

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM