用于搜索表单的ASP.NET MVC分页

时间:2010-02-03 18:13:01

标签: asp.net-mvc design-patterns paging

我在MVC中阅读了几个不同的分页帖子,但没有一个描述我有类似搜索表单的情况,然后想要在用户后面显示搜索条件(带分页)的结果点击提交。

我的问题是,我正在使用的分页解决方案将创建< a href =“...”>将传递所需页面的链接如下:http://mysite.com/search/2/虽然这一切都很好和花花公子,我没有将查询结果发送到内存中的数据库或任何其他所以我需要再次查询数据库

如果结果由/ Search的POST控制器操作处理,并且数据的第一页是这样呈现的,那么当用户点击时,如何获得相同的结果(基于用户指定的表单标准)转到第2页?

一些javascript伏都教?利用会话状态?使我的GET控制器操作具有搜索条件所期望的相同变量(但是可选),当调用GET操作时,实例化FormCollection实例,填充它并将其传递给POST操作方法(通过满足DRY)? / p>

有人能指出我在这个场景中的正确方向,还是提供过去已经实施的示例?谢谢!

6 个答案:

答案 0 :(得分:0)

使搜索参数成为视图模型的一部分:

public SearchViewModel
{
    string SearchParameters { get; set; }
    List<SearchObjects> SearchResults { get;set; }
}

然后将搜索文本框设置为等于SearchParameters。

除非您带回所有结果,然后以某种方式将其存储在页面中,否则您无法“存储”搜索查询。这非常低效。 Web是无状态的,因此您必须返回数据库并重新查询以获得更多结果。

答案 1 :(得分:0)

我明白你在说什么;您可以更改表单以使用按钮并每次发回页面。或者,您可以将分页的URL中的所有条件作为查询字符串变量传递。或者您可以使用JQuery来发布帖子(它有一个$ .post方法,可以通过链接点击或其他点击(http://api.jquery.com/jQuery.post/)来调用。

HTH。

答案 2 :(得分:0)

如果您在查询字符串中包含搜索文本以及当前结果页面而不是POST搜索文本,则此问题就会消失。作为额外的好处,您的用户可以将搜索结果添加为书签。

要执行此操作,您的搜索按钮只需使用搜索框的当前值构建GET请求URL。这可以通过javascript或使用GET作为搜索表单的方法属性来完成,例如: <form method="get" action="/search">

答案 3 :(得分:0)

我的方法是使用一个Action来处理post和get方案。

这是我可以通过GET和POST方法处理的:

public ViewResult Index([DefaultValue(1)] int page,
                        [DefaultValue(30)] int pageSize,
                        string search,
                        [DefaultValue(0)] int regionId,
                        [DefaultValue(0)] int eventTypeId,
                        DateTime? from,
                        DateTime? to)
{
    var events = EventRepo.GetFilteredEvents(page, pageSize, search, regionId, eventTypeId, from, to);
    var eventFilterForm = EventService.GetEventFilterForm(from, to);

    var eventIndexModel = new EventIndexModel(events, eventFilterForm);

    return View("Index", eventIndexModel);
}

eventFilterForm是一种演示模型,其中包含搜索表单的一些IEnumerable<SelectListItem>属性。

eventIndexModel是一种结合了eventFilterForm和搜索结果的演示模型 - events

eventsIPagedList的一种特殊类型。您可以获得herehere的更多信息和代码。第一个链接讨论IPagedList,其中第二个链接具有您应该需要的高级分页方案。

高级分页具有以下使用方法:

public static string Pager(this HtmlHelper htmlHelper, int pageSize, int currentPage, int totalItemCount, RouteValueDictionary valuesDictionary)

我这样使用它:

<%= Html.Pager(Model.Events.PageSize,
               Model.Events.PageNumber,
               Model.Events.TotalItemCount,
               new
               {
                   action = "index",
                   controller = "search",
                   search = ViewData.EvalWithModelState("Search"),
                   regionId = ViewData.EvalWithModelState("RegionId"),
                   eventTypeId = ViewData.EvalWithModelState("EventTypeId"),
                   from = ViewData.EvalDateWithModelState("From"),
                   to = ViewData.EvalDateWithModelState("To")
               }) %>

这会创建如下所示的链接:

  

/事件/搜索regionId = 4和; eventTypeId = 39&安培;从时间= 2009/09/01安培;至= 2010/08/31&安培;页= 3

HTHS,
查尔斯

聚苯乙烯。 EvalWithModelState如下:

PPS中。如果您要将日期放入获取变量 - 我建议您阅读my blog post ...: - )

/// <summary>
/// Will get the specified key from ViewData. It will first look in ModelState
/// and if it's not found in there, it'll call ViewData.Eval(string key)
/// </summary>
/// <param name="viewData">ViewDataDictionary object</param>
/// <param name="key">Key to search the dictionary</param>
/// <returns>Value in ModelState if it finds one or calls ViewData.Eval()</returns>
public static string EvalWithModelState(this ViewDataDictionary viewData, string key)
{
    if (viewData.ModelState.ContainsKey(key))
        return viewData.ModelState[key].Value.AttemptedValue;

    return (viewData.Eval(key) != null) ? viewData.Eval(key).ToString() : string.Empty;
}

答案 4 :(得分:0)

我建议缓存搜索结果并为其提供ID。然后,对于每个分页链接,您可以将搜索ID作为参数(在每个搜索页面链接上)引用,并在操作中将其从缓存中提取,然后在其上进行查询。

使用此方法,您无需担心搜索表单的第一次POST提交以外的任何内容。

Refer to my post了解更多详情。

答案 5 :(得分:0)

我有同样的问题和here's what I did

  1. 从Nuget下载PagedList
  2. 更改您的表单以进行GET并创建一个与此类似的ViewModel类型(如果您像我一样喜欢AdventureWorks和Model Binding):
  3. `

    using PagedList;
    namespace SearchFormResultPagingExample.Models {
    
      public class SearchViewModel {
        public int? Page { get; set; }
        public string EmailAddress { get; set; }
        public string LastName { get; set; }
        public IPagedList<Contact> SearchResults { get; set; }
        public string SearchButton { get; set; }
      }
    }
    

    `

    3.使用ViewModel作为控制器操作方法的参数

    using System.Linq;
    using System.Web.Mvc;
    using SearchFormResultPagingExample.Models;
    using PagedList; //NOTE: use Nuget to reference PagedList
    
    namespace SearchFormResultPagingExample.Controllers {
        public class SearchController : Controller {
            const int RecordsPerPage = 25;
    
            public ActionResult Index(SearchViewModel model) {
                if (!string.IsNullOrEmpty(model.SearchButton) || model.Page.HasValue) {
                    var entities = new AdventureWorksEntities();
                    var results = entities.Contacts.Where(c => c.LastName.StartsWith(model.LastName) && c.EmailAddress.StartsWith(model.EmailAddress))
                        .OrderBy(o => o.LastName);
    
                    var pageIndex = model.Page ?? 0;
                    model.SearchResults = results.ToPagedList(pageIndex, 25);
                }
                return View(model);
            }
        }
    }
    

    在视图中使用寻呼机:

    @model SearchFormResultPagingExample.Models.SearchViewModel
    @using PagedList.Mvc;
    
    <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
    
    @using (Html.BeginForm("Index", "Search", FormMethod.Get)) {
        @Html.ValidationSummary(false)
        <fieldset>
            <legend>Contact Search</legend>
    
            <div class="editor-label">
                @Html.LabelFor(model => model.EmailAddress)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.EmailAddress)
                @Html.ValidationMessageFor(model => model.EmailAddress)
            </div>
    
            <div class="editor-label">
                @Html.LabelFor(model => model.LastName)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.LastName)
                @Html.ValidationMessageFor(model => model.LastName)
            </div>
    
            <p>
                <input name="SearchButton" type="submit" value="Search" />
            </p>
        </fieldset>
    }
    
    @if (Model.SearchResults != null && Model.SearchResults.Count > 0) {
        foreach (var result in Model.SearchResults) {
                <hr />
                <table width="100%">
                    <tr>
                        <td valign="top" width="*">
                            <div style="font-weight: bold; font-size:large;">@result.LastName, @result.FirstName</div>
                            @result.Title<br />
                            @result.Phone<br />
                            @result.EmailAddress
                        </td>
                    </tr>
                </table>
        }
            <hr />
    
            @Html.PagedListPager(Model.SearchResults,
                page => Url.Action("Index", new RouteValueDictionary() {
                   { "Page", page }, 
                   { "EmailAddress", Model.EmailAddress },
                   { "LastName", Model.LastName }
                }),
                PagedListRenderOptions.PageNumbersOnly)
    }
    

    MVC将强制查询到ViewModel类型参数的查询字符串。它很光滑!