如何在使用分页和多个复选框过滤时缩短网址

时间:2018-05-31 19:43:13

标签: asp.net-mvc url pagination url-shortener

我正在使用PagedList进行服务器端分页,并且视图中还有一个用于过滤数据的文本框,以及用于确定模型中哪些字段根据搜索文本进行过滤的复选框。

我目前的代码是

查看模型

public class SearchPagingViewModels
{
    public IPagedList<AllResolution> Resolutions { get; set; }
    public string Keyword { get; set; } // serach text
    public bool IsResYearChecked { get; set; } // used to filter the ResolutionYear field
    public bool IsResNumChecked { get; set; } // used to filter the ResolutionNumber field
    public bool IsResTextChecked { get; set; } // used to filter the ResolutionText field
}

控制器

public ViewResult Index(int? page string keyword, bool? isResYearChecked, bool? isResNumChecked, bool? isResTextChecked)
{
    int pageSize = 25;
    int pageNumber = (page ?? 1);
    bool searchYear = isResYearChecked.GetValueOrDefault();
    ....
    IQueryable<> resolutions = db.AllResolutions;
    if (searchKeyword != null)
    {
        if (searchYear)
        {
            resolutions = resolutions.Where(x => x.ResolutionYear.Contains(searchKeyword));
        }
        ....
    }
    resolutions = resolutions.OrderBy(c => c.ResolutionYear).ThenBy(c => c.ResolutionNumber);
    SearchPagingViewModels model = new SearchPagingViewModels
    {
        Keyword = keyword,
        IsResYearChecked = searchYear,
        ....
        Resolutions = resolutions.ToPagedList(pageNumber, pageSize)
    };
    return View(model);
}

查看

@model SearchPagingViewModels
....
@using (Html.BeginForm("Index", "Resolutions", FormMethod.Get))
{
    @Html.LabelFor(m => m.Keyword)
    @Html.TextBoxFor(m => m.Keyword)

    @Html.LabelFor(m => m.IsResYearChecked)
    @Html.CheckBoxFor(m => m.IsResYearChecked)

    // .. ditto for IsResNumChecked etc

    <input type="submit" value="search" />
}

<table>
    <thead>
        ....
    </thead>
    <tbody>
        @foreach (var task in Model.Resolutions)
        {
            // .... build table rows
        }
    </tbody>
</table>

@Html.PagedListPager(Model.Resolutions, page => Url.Action("Index", new { page, Keyword = Model.Keyword, IsResYearChecked = Model.IsResYearChecked, IsResNumChecked = IsResNumChecked IsResTextChecked = Model.IsResTextChecked }))

虽然这有效,但问题是for会生成一个冗长而丑陋的查询字符串,例如

.../Index?Keyword=someText&IsResYearChecked=true&IsResYearChecked=false&IsResNumChecked=false&IsResTextChecked=true&IsResTextChecked=false

现在我想添加额外的bool属性来过滤记录,使其更糟糕,并可能超出查询字符串限制。

有没有办法缩短网址?这会与路由有关吗?新的ViewModel是否可以实现这一目标?

1 个答案:

答案 0 :(得分:1)

您可以使用标有bool属性的enum替换所有[Flags]属性,其中enum中的每个值代表要搜索的模型中的属性。< / p>

[Flags]
public enum FilterProperties
{
    None = 0,
    ResolutionYear = 1,
    ResolutionNumber = 2,
    ResolutionText = 4,
    .... // more properties
}

,视图模型将是

public class SearchPagingViewModels
{
    public string Keyword { get; set; }
    public FilterProperties Filter { get; set; }
    public IPagedList<AllResolution> Resolutions { get; set; }
}

然后控制器方法变为

public ViewResult Index(int? page string keyword, FilterProperties filter = FilterProperties.None)
{
    IQueryable<AllResolution> resolutions = db.AllResolutions;
    if (searchKeyword != null)
    {
        if (filter.HasFlag(FilterProperties.ResolutionYear)
        {
            resolutions = resolutions.Where(x => x.ResolutionYear.Contains(feyword));
        }
        // .... more if blocks for other enum values
    }
    resolutions = resolutions.OrderBy(c => c.ResolutionYear).ThenBy(c => c.ResolutionNumber);
    SearchPagingViewModels model = new SearchPagingViewModels
    {
        Keyword = keyword,
        Filter = filter,
        Resolutions = resolutions.ToPagedList(pageNumber, pageSize)
    };
    return View(model);
}

您将查看

@using (Html.BeginForm("Index", "Resolutions", FormMethod.Get))
{
    @Html.LabelFor(m => m.Keyword)
    @Html.TextBoxFor(m => m.Keyword)
    @Html.ValidationMessageFor(m => m.Keyword)
    @Html.HiddenFor(m => m.Filter)
    foreach (Enum item in Enum.GetValues(typeof(Tables.Controllers.FilterProperties)))
    {
        if (item.Equals(Tables.Controllers.FilterProperties.None))
        {
            continue;
        }
        <div>
            <label>
                <input type="checkbox" value="@((int)(object)item)" checked=@Model.Filter.HasFlag(item) />
                <span>@item</span>
            </label>
        </div>
    }
    <span id="filtererror" class="field-validation-error" hidden >Please select at least one property to search</span>
    <input type="submit" value="Search" />
}

<table>
    ....
</table>
@Html.PagedListPager(Model.Resolutions, page => Url.Action("Index", new { page, Keyword = Model.Keyword, Filter = (int)Model.Filter }))

然后使用javascript对表单.submit()事件进行更新以更新Filter的隐藏输入值(注意我还假设如果{{1}的值,您希望至少选中一个复选框}}不是Keyword

null

您的网址(基于<script> var checkboxes = $('input:checkbox'); var keyword = $('#Keyword'); $('form').submit(function () { var filter = 0; // validate at least one checkbox must be checked if Keyword has a value if (keyword.val() && checkboxes.filter(':checked').length == 0) { $('#filtererror').show(); return false; } $.each(checkboxes, function () { if ($(this).is(':checked')) { filter += Number($(this).val()); } // disable checkboxes to prevent their value being added to the query string $(this).prop('disabled', true); }) $('#Filter').val(filter); }) checkboxes.click(function () { if (keyword.val() && checkboxes.filter(':checked').length == 0) { $('#filtererror').show(); } else { $('#filtererror').hide(); } }) </script> ResolutionYear正在检查)现在将是

ResolutionText

而不是

.../Index?Keyword=someText&Filter=5