具有分页的ASP.NET MVC搜索表单

Jon*_*let 1 asp.net asp.net-mvc

我不知所措,因为我必须遗漏一些东西.刚刚完成ASP.NET MVC 1.0(WROX),我试图实现一个执行简单搜索的视图,然后在表中呈现结果.然后,我希望能够通过结果页面.

所以我有一个来自ListingsController的搜索操作,从FormCollection获取一些值并相应地过滤结果:

        //
    //POST: /Listings/Search
    //      /Listings/Page/2
    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Search(FormCollection collection,int? page)
    {
        var listings = listingRepository.GetListings();

        //filter
        if (collection["TypeOfHouse"] != null)
        {
            string[] typeList = collection["TypeOfHouse"].Split(',');

            foreach (string type in typeList)
            {
                listings = from l in listings
                           where l.TypeOfHouse == type
                           select l;
            }
        }

        //display the first page of results
        int pageSize = 25;
        var paginatedListings = new PriviledgeV1.Helpers.PaginatedList<Listing>(listings, 0, pageSize);



        return View("Results", paginatedListings);
    }
Run Code Online (Sandbox Code Playgroud)

最初,结果视图将使用第1页的前25条记录进行渲染.然后,我有一个处理"分页"的结果操作:

    public ActionResult Results(int? page)
    {
        int pageSize = 25;
        var listings = listingRepository.GetListings();
        var paginatedListings = new PriviledgeV1.Helpers.PaginatedList<Listing>(listings, page ?? 0, pageSize);

        return View(listings);
    }
Run Code Online (Sandbox Code Playgroud)

麻烦是因为我不再拥有FormCollection,我无法正确筛选结果.因此,如果我尝试使用/ Listings/Results?page = 2从第1页移至第2页,则结果操作将触发,它将返回所有结果,而不是搜索操作中的过滤结果集.

我真的很困惑这里要做什么,以及为什么没有博客/教程解释这一点,这通常标志着我错过了一些东西.

谢谢!

Hac*_*ese 5

我想有几种方法可以尝试实现这一目标.

  1. 通过查询字符串而不是post传递搜索参数.可以理解的是,对于高级搜索参数,这可能是复杂和混乱的
  2. 将POST的结果存储到隐藏元素.让您的分页控制POST每次都执行相同的操作,而不是单独的Results操作.
  3. 将查询参数存储在会话中持久存储的对象中.

我相信我们可以从那里获得更多创意,但这应该会给你一个开始.看起来你只关心搜索表单中的一个字段,TypeOfListing.您应该能够通过查询字符串很容易地保留它,因此上面的方法#1.


更新

这是我为了在客户端维护您的搜索而放在一起的简单方法.该技术涉及三个部分:

  1. 在页面请求之间维护表单.
  2. 使用表单中的隐藏元素管理页面状态.
  3. 让JavaScript拦截您的Paging链接,更新页码隐藏元素,然后重新提交表单.

这是所有各种部分的代码.请注意,我使用jQuery,以防您喜欢其他内容.我捏造了数据源,只是在实际数据中.此外,我还包括PagedList和PaginationHelper.如果你愿意,可以自己替换.

\ Controllers\HomeController.cs(搜索是相关部分):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MvcApplication2.Controllers
{
    [HandleError]
    public class HomeController : Controller
    {
        List<String> _data;

        public HomeController()
        {
            _data = new List<String>();
            _data.Add("Merry");
            _data.Add("Metal");
            _data.Add("Median");
            _data.Add("Medium");
            _data.Add("Malfunction");
            _data.Add("Mean");
            _data.Add("Measure");
            _data.Add("Melt");
            _data.Add("Merit");
            _data.Add("Metaphysical");
            _data.Add("Mental");
            _data.Add("Menial");
            _data.Add("Mend");
            _data.Add("Find");
        }

        public ActionResult Search()
        {
            Int32 pageNumber, pageSize = 5, total, first;
            String typeOfListing;
            PagedList<String> results;

            if (Request.HttpMethod == "GET")
            {
                return View();
            }

            if (!Int32.TryParse(Request.Form["PageNumber"], out pageNumber)) pageNumber = 1;
            typeOfListing = Request.Form["TypeOfListing"];

            first = (pageNumber - 1) * pageSize;
            total = (from s in _data
                     where s.Contains(typeOfListing)
                     select s).Count();
            results = new PagedList<String>(
                            (from s in _data
                             where s.Contains(typeOfListing)
                             select s)
                             .Skip(first)
                             .Take(pageSize), 
                            total, pageNumber, pageSize);


                return View(results);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

\ Helpers\PaginationHelper.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Text;
using System.Web.Routing;
using System.Web.Mvc;
using System.Web.Mvc.Html;

namespace MvcApplication2.Helpers
{
    public static class PaginationHelper
    {
        public static String Pager(this HtmlHelper helper, Int32 pageSize, Int32 pageNumber, Int32 total, String actionName, RouteValueDictionary values)
        {
            StringBuilder output = new StringBuilder();
            Int32 totalPages = (Int32)Math.Ceiling((Double)total / pageSize);

            if (values == null)
                values = helper.ViewContext.RouteData.Values;

            if (pageNumber > 1)
                output.Append(CreatePageLink(helper, values, "< Previous ", pageNumber - 1, pageSize));

            for (Int32 i = 1; i <= totalPages; i++)
            {
                if (i == pageNumber)
                    output.Append(i);
                else
                    output.AppendFormat(CreatePageLink(helper, values, i.ToString(), i, pageSize));

                if (i < totalPages)
                    output.Append(" | ");
            }

            if (pageNumber < totalPages)
                output.Append(CreatePageLink(helper, values, " Next >", pageNumber + 1, pageSize));

            return output.ToString();
        }

        private static String CreatePageLink(HtmlHelper helper, RouteValueDictionary values, String text, Int32 pageNumber, Int32 pageSize)
        {
            RouteValueDictionary routeDictionary = new RouteValueDictionary(values);
            routeDictionary.Add("page", pageNumber);
            routeDictionary.Add("pageSize", pageSize);

            return helper.ActionLink(text, null, routeDictionary);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

\ PagedList.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace MvcApplication2
{
    public class PagedList<T> : List<T>
    {
        public Int32 TotalCount { get; protected set; }
        public Int32 PageNumber { get; protected set; }
        public Int32 PageSize { get; protected set; }

        public PagedList(IEnumerable<T> items, Int32 total, Int32 pageNumber, Int32 pageSize)
            : base(items)
        {
            TotalCount = total;
            PageNumber = pageNumber;
            PageSize = pageSize;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

\ Views\Home\Search.aspx:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<PagedList<String>>" %>
<%@ Import Namespace="MvcApplication2" %>
<%@ Import Namespace="MvcApplication2.Helpers" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    Search
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <script type="text/javascript">
        $(function() {
            var results = $("#searchResults");
            if (results && results.children().length > 2) {
                $("#searchForm").hide();
                $("#searchResults .pager>a").click(submitForm);
            }
        });

        function submitForm() {
            var m = this.href.match(/page=(\d+)/i);
            if (m) {
                $("#PageNumber").attr("value", m[1]);
                $("#searchForm").submit();
            }
            return false;
        }
    </script>
    <form id="searchForm" action="<%= Url.Action("Search") %>" method="post">
        <input type="hidden" value="1" id="PageNumber" name="PageNumber" />
        <fieldset>
            <legend>Search</legend>
            <label for="TypeOfListing">Type of Listing</label>
            <%= Html.TextBox("TypeOfListing", Request.Form["TypeOfListing"]) %>
            <input type="submit" id="btnSubmit" name="btnSubmit" value="Search" />
        </fieldset>
    </form>
   <% if (Model != null)
   {
   %>
    <div id="searchResults">

        <div class="results-count">Displaying <%=this.Model.Count %> of <%=this.Model.TotalCount %> results. <%=Html.ActionLink("Start a new search", "Search") %>.</div>
        <%
               foreach (String result in Model)
               { 
        %>
        <div class="result"><%=result %></div>

        <%     }
        %>

        <div class="pager"><%= Html.Pager(Model.PageSize, Model.PageNumber, Model.TotalCount, null, null) %></div>
    </div>
    <%
     } 
    %>
</asp:Content>
Run Code Online (Sandbox Code Playgroud)