【问题标题】:How to use multiple persistent search strings with paging in MVC?如何在 MVC 中将多个持久搜索字符串与分页一起使用?
【发布时间】:2023-03-05 22:16:01
【问题描述】:

我希望在我的控制器中添加更多搜索字符串,这些字符串将在我的视图中通过分页持续存在。

目前,参数 searchString 可以在 currentFilter 中设置,只要它是唯一的参数,它就会一直存在。我希望再添加几个(searchString2、searchString3 等),但这些参数会丢失。

我正在寻找一种简单的方法来做到这一点。

学生索引:

@model PagedList.IPagedList<ContosoUniversity.Models.Student>
@using PagedList.Mvc;
<link href="~/Content/PagedList.css" rel="stylesheet" type="text/css" />

@{
    ViewBag.Title = "Students";
}

<h2>Students</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
@using (Html.BeginForm("Index", "Student", FormMethod.Get))
{
    <p>
        Find by name: @Html.TextBox("SearchString", ViewBag.CurrentFilter as string)
        <input type="submit" value="Search" />
    </p>
}
<table class="table">
    <tr>
        <th>
            @Html.ActionLink("Last Name", "Index", new { sortOrder = ViewBag.NameSortParm, currentFilter = ViewBag.CurrentFilter })
        </th>
        <th>
            First Name
        </th>
        <th>
            @Html.ActionLink("Enrollment Date", "Index", new { sortOrder = ViewBag.DateSortParm, currentFilter = ViewBag.CurrentFilter })
        </th>
        <th></th>
    </tr>


    @foreach (var item in Model)
    {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.LastName)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.FirstMidName)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.EnrollmentDate)
            </td>
            <td>
                @Html.ActionLink("Edit", "Edit", new { id = item.ID }) |
                @Html.ActionLink("Details", "Details", new { id = item.ID }) |
                @Html.ActionLink("Delete", "Delete", new { id = item.ID })
            </td>
        </tr>
    }

</table>
<br />
Page @(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of @Model.PageCount

@Html.PagedListPager(Model, page => Url.Action("Index",
    new { page, sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter }))

学生控制器 GET:

// GET: Student
public ViewResult Index(string sortOrder, string currentFilter, string searchString, int? page)
{
    ViewBag.CurrentSort = sortOrder;
    ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
    ViewBag.DateSortParm = sortOrder == "Date" ? "date_desc" : "Date";

    if (searchString != null)
    {
        page = 1;
    }
    else
    {
        searchString = currentFilter;
    }

    ViewBag.CurrentFilter = searchString;

    var students = from s in db.Students orderby s.LastName
                   select s;

    if (!String.IsNullOrEmpty(searchString))
    {
        //students = students.Where(s => s.LastName.Contains(searchString)
        //                       || s.FirstMidName.Contains(searchString));
    }
    switch (sortOrder)
    {
        case "name_desc":
            students = students.OrderByDescending(s => s.LastName);
            break;
        case "Date":
            students = students.OrderBy(s => s.EnrollmentDate);
            break;
        case "date_desc":
            students = students.OrderByDescending(s => s.EnrollmentDate);
            break;
        default:  // Name ascending 
            students = students.OrderBy(s => s.LastName);
            break;
    }

    int pageSize = 3;
    int pageNumber = (page ?? 1);
    return View(students.ToPagedList(pageNumber, pageSize));
}

【问题讨论】:

  • 您只需要在视图中为SearchString2SearchString3 属性添加文本框,并在您的GET 方法中添加匹配参数以及ViewBag 属性以将值传递给视图,并将值路由到PagedListPager 将它们传回(与您现有的 SearchString 完全相同)
  • 嗨。我不太明白如何更改代码,以便每个有“searchString”的地方都是几个字符串。看起来它也会因为更多的参数而变得笨拙。有没有办法将参数放入列表或其他东西中,然后直接引用子对象来代替像 list 这样的 searchString?我还需要为我的 currentFilter 参数引用它,因此分页将继续工作。

标签: c# asp.net-mvc


【解决方案1】:

以下是您应该在视图和控制器中拥有的内容。
(查看代码中的必要编辑,尤其是 URL 并查看控制器中的更改以使搜索项保留导航多个页面)

您的视图应如下所示:

@model PagedList.IPagedList<ContosoUniversity.Models.Student>
@using PagedList.Mvc;
<link href="~/Content/PagedList.css" rel="stylesheet" type="text/css" />

@{
   ViewBag.Title = "Students";
 }

 <h2>Students</h2>

 <p>
 @Html.ActionLink("Create New", "Create")
</p>
@using (Html.BeginForm("Index", "Student", FormMethod.Get))
{
<p>
    Find by name: @Html.TextBox("SearchString", ViewBag.CurrentFilter as string)
 Find by searchString2: @Html.TextBox("searchString2", ViewBag.CurrentFilter2 as string)
 Find by searchString3: @Html.TextBox("searchString3", ViewBag.CurrentFilter3 as string)
    <input type="submit" value="Search" />
</p>
}
 <table class="table">
 <tr>
    <th>
    @Html.ActionLink("Last Name", "Index", new { sortOrder =   ViewBag.NameSortParm, currentFilter = ViewBag.CurrentFilter })
    </th>
    <th>
        First Name
    </th>
    <th>
    @Html.ActionLink("Enrollment Date", "Index", new { sortOrder = ViewBag.DateSortParm, currentFilter = ViewBag.CurrentFilter })
    </th>
    <th></th>
 </tr>

  @foreach (var item in Model)
  {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.LastName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.FirstMidName)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.EnrollmentDate)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", new { id = item.ID }) |
            @Html.ActionLink("Details", "Details", new { id = item.ID }) |
            @Html.ActionLink("Delete", "Delete", new { id = item.ID })
        </td>
     </tr>
  }

  </table>
  <br />
   Page @(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of @Model.PageCount

@Html.PagedListPager(Model, page => Url.Action("Index",
new { page, sortOrder = ViewBag.CurrentSort, currentFilter =  ViewBag.CurrentFilter, currentFilter2 = ViewBag.CurrentFilter2, currentFilter3 = ViewBag.CurrentFilter3 }))

您的控制器可能类似于:(取决于您的业务需求)

// GET: Student
public ViewResult Index(string sortOrder, string currentFilter, string searchString, string currentFilter2, string searchString2,string currentFilter3, string searchString3, int? page)
{
  ViewBag.CurrentSort = sortOrder;
  ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
  ViewBag.DateSortParm = sortOrder == "Date" ? "date_desc" : "Date";

  if (searchString != null)
  {
    page = 1;
  }
  else
  {
    searchString = currentFilter;
  }

ViewBag.CurrentFilter = searchString;

if (searchString2 != null)
  {
    page = 1;
  }
  else
  {
    searchString2 = currentFilter2;
  }

ViewBag.CurrentFilter2 = searchString2;

   if (searchString3 != null)
  {
    page = 1;
  }
  else
  {
    searchString3 = currentFilter3;
  }

ViewBag.CurrentFilter3 = searchString3;

var students = from s in db.Students orderby s.LastName
               select s;

if (!String.IsNullOrEmpty(searchString))
{
    //students = students.Where(s => s.LastName.Contains(searchString)
    //                       || s.FirstMidName.Contains(searchString));
}
switch (sortOrder)
{
    case "name_desc":
        students = students.OrderByDescending(s => s.LastName);
        break;
    case "Date":
        students = students.OrderBy(s => s.EnrollmentDate);
        break;
    case "date_desc":
        students = students.OrderByDescending(s => s.EnrollmentDate);
        break;
    default:  // Name ascending 
        students = students.OrderBy(s => s.LastName);
        break;
}

 int pageSize = 3;
 int pageNumber = (page ?? 1);
 return View(students.ToPagedList(pageNumber, pageSize));
}

Stephen Muecke 在评论中提到的非常正确

【讨论】:

    【解决方案2】:

    虽然您可以在代码中整理一些地方,但最终您的方法是正确的。字符串需要在浏览器和服务器之间来回传递,这意味着要么使用 URL 参数,要么使用 POST,无论哪种方式,MVC 都会将其绑定到 ViewModel(或在您的情况下绑定到单个参数)。

    任何将其缓存在服务器上的尝试都需要会话处理,这对于您的要求来说过于复杂。

    【讨论】:

    • 我明白你在概念上所说的话,但类似于我上面对 Stephen Muecke 的回复,我不太明白如何获取要使用的 URL 参数,而不是我目前拥有的参数。我在上面使用过的教程。 stackoverflow.com/questions/5003953/… 似乎相关,但我仍然不清楚如何将其转化为我的案例。 POST 方法听起来很有希望,但这个概念似乎也超出了我目前的理解水平。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-25
    • 1970-01-01
    • 1970-01-01
    • 2017-04-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多