使用分页列表时丢失所有视图模型数据

问题描述 投票:0回答:2

刚刚使用 Paged List 插件将分页添加到我的视图中,我只能将一页的数据带回。如果您单击“下一步”或任何其他可用的页码,该页面将自行重新提交,并且您最终会得到一个空白表格。

我单步执行代码,发现传递回控制器的视图模型对象完全为空。有谁知道解决这个问题的方法(即在导航到不同的分页列表页面时保留视图模型数据)?

查看模型

public class ZipCodeIndex
{
    [DisplayName("Zip Code")]
    public string searchZip { get; set; }
    public IEnumerable<SelectListItem> StateCodes { get; set; }
    [DisplayName("Effective on this date")]
    public string searchDate { get; set; }
    [DisplayName("State")]
    public string searchState { get; set; }
    [DisplayName("Territory")]
    public string searchTerritory { get; set; }
    [DisplayName("New Territory")]
    public string newTerritory { get; set; }
    [DisplayName("New Description")]
    public string newDescription { get; set; }
    [DisplayName("New Effective Date")]
    public string newEffectiveDate { get; set; }

    public IPagedList<ZipCodeTerritory> pagedTerritoryList { get; set; }
    public List<ZipCodeTerritory> zipCodeTerritory { get; set; }

    public ZipCodeIndex() 
    {
        zipCodeTerritory = new List<ZipCodeTerritory>();
        SetStateCodes();
    }

    //Set state code drop down list
    private void SetStateCodes()
    {
        AgentResources db = new AgentResources();
        StateCodes = (from z in db.ZipCodeTerritory
                      select z.StateCode).Select(x => new SelectListItem
                      {
                          Text = x,
                          Value = x
                      }).Distinct().ToList();

        db.Dispose();
    }
}

控制器

    public ViewResult Index(int? page, string errorMessage = "", ZipCodeIndex search = null)
    {
        //set Paged List counter variables
        int pageNumber = page ?? 1;
        int pageSize = 300;

        //If TempData conntains information method call came from another controller action
        if (TempData.Count > 0)
        {
            //Instantiate ZipCodeIndex view model object if it exists
            search = (ZipCodeIndex)TempData["ZipCodeIndexData"];

            //Clear out previous search results
            search.zipCodeTerritory.Clear();
        }

        //Proceed with search
        try
        {
            //If search criteria is null page is loading for the first time so send blank view 
            if (String.IsNullOrWhiteSpace(search.searchZip) &&
                String.IsNullOrWhiteSpace(search.searchDate) &&
                String.IsNullOrWhiteSpace(search.searchState))
            {
                if (!string.IsNullOrWhiteSpace(search.searchTerritory))
                {
                    ViewBag.ErrorMessage = "State or Zip Code required for search.";
                }

                //Convert list to IPagedList for pagining on Index
                search.pagedTerritoryList = search.zipCodeTerritory.ToPagedList(pageNumber, pageSize);

                return View(search);
            }

            //Determine if necessary search criteria has been sent
            if (String.IsNullOrWhiteSpace(search.searchZip) && String.IsNullOrWhiteSpace(search.searchState))
            {
                ViewBag.ErrorMessage = "Either State or Zip Code Must be Specified";

                //Convert list to IPagedList for pagining on Index
                search.pagedTerritoryList = search.zipCodeTerritory.ToPagedList(pageNumber, pageSize);

                return View(search);
            }

            DateTime effectiveDate;

            //Convert date string to DateTime type
            if (String.IsNullOrWhiteSpace(search.searchDate))
            {
                effectiveDate = DateTime.MinValue;
            }
            else
            {
                effectiveDate = Convert.ToDateTime(search.searchDate);
            }

            //Conduct search by State Code/Date alone
            if (String.IsNullOrWhiteSpace(search.searchZip))
            {
                if (string.IsNullOrWhiteSpace(search.searchTerritory))
                {
                    search.zipCodeTerritory = (from z in db.ZipCodeTerritory
                                               where z.StateCode.Equals(search.searchState) &&
                                                     z.EffectiveDate >= effectiveDate
                                               select z).ToList();
                }
                else
                {
                    search.zipCodeTerritory = (from z in db.ZipCodeTerritory
                                               where z.StateCode.Equals(search.searchState) &&
                                                     z.IndDistrnId.Equals(search.searchTerritory) &&
                                                     z.EffectiveDate >= effectiveDate
                                               select z).ToList();
                }

                //Convert list to IPagedList for pagining on Index
                search.pagedTerritoryList = search.zipCodeTerritory.ToPagedList(pageNumber, pageSize);

            }

            return View(search);
    }

查看

@model Monet.ViewModel.ZipCodeIndex

@{
    ViewBag.Title = "Zip Code Territory Search";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

@using PagedList.Mvc;
@using PagedList;

<h2>Zip Code Territory</h2>

    @using (Html.BeginForm("Index", "ZipCodeTerritory", FormMethod.Post))
    {
        <div class="error" id="searchErrors">
            @ViewBag.ErrorMessage            
        </div>    
        <br/>
        <div id="searchBox" class="boxMe">
            <div id="zipBox">
                @Html.Raw("Zip Code")
                @Html.TextAreaFor(model => model.searchZip, new { style = "width: 300px;", placeholder = "Enter up to 35 comma separated zip codes" }) 
            </div>
            <div id="dateBox">
                @Html.LabelFor(model => model.searchDate)
                @Html.TextBoxFor(model => model.searchDate, new { style="width: 80px;"})
                <div id="terrBox">
                     @Html.LabelFor(model => model.searchTerritory)
                     @Html.TextBoxFor(model => model.searchTerritory, new { style = "width: 30px;padding-left:10px;", maxLength = 3 })                   
                </div>
            </div>
            <div id="stateBox">
                @Html.LabelFor(model => model.searchState)
                @Html.DropDownListFor(model => model.searchState, Model.StateCodes, "  ")
                <button type="submit" id="SearchButton">Search</button>
            </div>
        </div>
        <div style="clear: both;"></div>
    }

<br/>
@Html.ActionLink("Create New", "Create")
<br/>
<br/>
<div class="error" id="updateErrors">
    @ViewBag.UpdateAction            
</div>
@if (Model.zipCodeTerritory.Count > 0)
{
    using (Html.BeginForm("Update", "ZipCodeTerritory", FormMethod.Post))
    {
        @Html.HiddenFor(model => model.searchZip)
        @Html.HiddenFor(model => model.searchDate)
        @Html.HiddenFor(model => model.searchState)

        <div id="cloneBox">
            @Html.LabelFor(model => model.newTerritory)
            @Html.TextBoxFor(model => model.newTerritory, new { style = "width: 30px;padding-left:10px;", maxLength = 3 })
            @Html.LabelFor(model => model.newDescription)
            @Html.TextBoxFor(model => model.newDescription, new { style = "width: 250px;padding-left:10px;", maxLength = 30 })  
            @Html.LabelFor(model => model.newEffectiveDate)     
            @Html.TextBoxFor(model => model.newEffectiveDate, new { style = "width: 80px;padding-left:10px;" })   
        </div>
        <br/>
        <div id="buttonDiv">
            <button type="submit" id="CloneButton" name="button" value="clone">Update Selected Items</button>
            <button type="submit" id="deleteButton" name="button" value="delete">Delete Selected Items</button>            
        </div>
        <div id="pagingDiv">
            @Html.PagedListPager(Model.pagedTerritoryList, page => Url.Action("Index", new { page })) 
        </div>
        <table id="thetable" class="tablesorter" >
            <thead>
                <th>@Html.CheckBox("SelectAll")</th>
                <th>Channel</th>
                <th>Territory</th>
                <th>Description</th>
                <th>State</th>
                <th>Zip</th>
                <th>Effective</th>
                <th>End Date</th>
                <th>Last Update By</th>
                <th>Last Update Date</th>
                <th></th>
            </thead>
            <tbody id="tableBody">
                @for (int i = 0; i < Model.pagedTerritoryList.Count; i++)
                {
                    <tr>
                        <td>
                            @Html.CheckBoxFor(model => model.pagedTerritoryList[i].Update)
                            @Html.HiddenFor(model => model.pagedTerritoryList[i].Update)
                        </td>
                        <td>
                            @Html.DisplayFor(model => model.pagedTerritoryList[i].ChannelCode)
                            @Html.HiddenFor(model => model.pagedTerritoryList[i].ChannelCode)
                        </td>
                        <td>
                            @Html.DisplayFor(model => model.pagedTerritoryList[i].IndDistrnId)
                            @Html.HiddenFor(model => model.pagedTerritoryList[i].IndDistrnId)
                        </td>
                        <td>
                            @Html.DisplayFor(model => model.pagedTerritoryList[i].DrmTerrDesc)
                            @Html.HiddenFor(model => model.pagedTerritoryList[i].DrmTerrDesc)
                        </td>
                        <td>
                            @Html.DisplayFor(model => model.pagedTerritoryList[i].StateCode)
                            @Html.HiddenFor(model => model.pagedTerritoryList[i].StateCode)
                        </td>
                        <td>
                            @Html.DisplayFor(model => model.pagedTerritoryList[i].ZipCode)
                            @Html.HiddenFor(model => model.pagedTerritoryList[i].ZipCode)
                        </td>
                        <td>
                            @Html.DisplayFor(model => model.pagedTerritoryList[i].EffectiveDate)
                            @Html.HiddenFor(model => model.zipCodeTerritory[i].EffectiveDate)
                        </td>
                        <td>
                            @Html.DisplayFor(model => model.pagedTerritoryList[i].EndDate)
                            @Html.HiddenFor(model => model.pagedTerritoryList[i].EndDate)
                        </td>
                        <td>
                            @Html.DisplayFor(model => model.pagedTerritoryList[i].LastUpdateId)
                            @Html.HiddenFor(model => model.pagedTerritoryList[i].LastUpdateId)
                        </td>
                        <td>
                            @Html.DisplayFor(model => model.pagedTerritoryList[i].LastUpdateDate)
                            @Html.HiddenFor(model => model.pagedTerritoryList[i].LastUpdateDate)
                        </td>
                        <td>
                            @Html.ActionLink("Edit", "Edit", new { id = Model.pagedTerritoryList[i].Id })
                            @Html.HiddenFor(model => model.pagedTerritoryList[i].Id)
                        </td>
                    </tr>
                }
            </tbody>
        </table>
    }
}

编辑

找到这篇文章并相应地更改了我的

@Html.PagedListPager
,但是没有运气(仍然传递
null
视图模型对象,现在甚至传递空
page
参数...)

    <div id="pagingDiv">
        @Html.PagedListPager(Model.pagedTerritoryList, page => Url.Action("Index", new RouteValueDictionary()
            {
                { "Page", Page},
                { "search", Model }
            }), PagedListRenderOptions.PageNumbersOnly)
    </div>
.net asp.net-mvc asp.net-mvc-3 pagination pagedlist
2个回答
3
投票

我知道这个问题已经有一年左右的时间了,但我最近找到了这个问题的简单解决方案并想分享。最后一个答案部分正确,但是有一种更简单的方法可以实现这一点。

这里是一些将视图模型数据从视图传递到控制器并保留数据的示例代码。

假设这是您的视图模型:

public class SearchViewModel
{
    public int? Page { get; set; }
    public string data1 { get; set; }
    public string data2 { get; set; }
    public string data3 { get; set; }
    public string data4 { get; set; }
    public IPagedList SearchResults { get; set; }
    public string SearchButton { get; set; }
}

以及您的简单视图模型构造方法(没有实际的搜索代码,用作示例):

public ActionResult Index(SearchViewModel model) {

    //code using and constructing your returned search results

    var pageNumIndex = model.Page ?? 1;
    model.SearchR = results.ToPagedList(pageIndex, 25);
    return View(model);
}

那么在您看来,@Html.PagedListPager 看起来像:

@Html.PagedListPager(Model.SearchR, Page => Url.Action("Index", new RouteValueDictionary() {
    { "Page", Page },
    { "data1", Model.data1 },
    { "data2", Model.data2 },
    { "data3", Model.data3 },
    { "data4", Model.data4 },
}),
PagedListRenderOptions.PageNumbersOnly)

此方法将 RouteValueDictionary() 直接实现到 Html.PagedListPager 中。

我一直在努力寻找使用 viewmodel 方法的 @Html.PagedListPager 的解决方案,直到发现 RouteValueDictionary() 直接方法。


0
投票

您修改后的代码只会将参数发送到Index页面:页面和搜索。 Page 是您想要的页面值,但搜索可能是模型类的 ToString。

我自己一直在努力解决这个问题,并提出了以下解决方案: 我已将此方法添加到我的模型中,并且

public RouteValueDictionary GenerateRouteValueDictionary(int page)
    {
        Page = page;
        RouteValueDictionary dic = new RouteValueDictionary
        {
            { QueryHelper.Print(() => Page), Page },
            { QueryHelper.Print(() => PreviousSortField), PreviousSortField },
            { QueryHelper.Print(() => SortOrder), SortOrder },
            { QueryHelper.Print(() => SearchString), SearchString }, 
            { QueryHelper.Print(() => IncludeHidden), IncludeHidden },
            { QueryHelper.Print(() => SearchOperator1), SearchOperator1 },
            { QueryHelper.Print(() => SearchField1), SearchField1 },
            { QueryHelper.Print(() => SearchField1Value), SearchField1Value },
            { QueryHelper.Print(() => WhereOperator), WhereOperator },
            { QueryHelper.Print(() => SearchOperator2), SearchOperator2 },
            { QueryHelper.Print(() => SearchField2), SearchField2 },
            { QueryHelper.Print(() => SearchField2Value), SearchField2Value },
            { QueryHelper.Print(() => FilterByDummyLocations), FilterByDummyLocations },
            { QueryHelper.Print(() => FilterByDummyProfile), FilterByDummyProfile },
            { QueryHelper.Print(() => FilterNoDevice), FilterNoDevice }
        };
        return dic;
    }

从我的 cshtml 中,我生成分页列表,如下所示:

@Html.PagedListPager(Model.SearchResults, page => Model.GenerateRouteValueDictionary(page)));

(QueryHelper.Print 只是一种打印我提供的属性名称的方法......所以我有效地为每个链接重新创建查询字符串。可能不是处理这个问题的最好方法,但它有效。

还有一种替代方法,您首先在模型上设置页码,然后提供模型本身:

@Html.PagedListPager(Model.SearchResults, page => Url.Action(action, Model.SetPage(page)))

并使用这个附加模型方法:

    public SearchPbxUsersModel SetPage(int page)
    {
        Page = page;
        SearchPbxUsersModel myModel = this.MemberwiseClone() as SearchPbxUsersModel;
        myModel.SearchResults = null;
        return myModel;
    }

除了克隆之外,您还可以将任何您不喜欢的值设为 null(甚至必须将某些值设为 null,例如 IPgedList pagedTerritoryList)。

这两种方法都有一个警告:

如果您还有多选控件,那么无论哪种方式您都会陷入困境,并且必须手动编写自己的操作链接(多么痛苦)。使用第一种方法不起作用,因为使用多选时,您多次拥有多选控件的查询字符串属性(并且不适用于任何字典),而使用第二种方法时,您的容器保存选定的值(例如List 或 IEnumerable)将获得 ToString()'ed,因此您的模型将保存一个值,即容器的 tostring,而不是看到您选择的值。

© www.soinside.com 2019 - 2024. All rights reserved.