How to remain/retain on the same page when using PagedList.mvc
Asked Answered
P

3

7

I am using PagedList.Mvc and I have added a nice way to navigate across various pages in an MVC web application. However, when I click on an "edit" or "details" tab and save changes I am sent back to the 1st page. I want to remain on the same page where the changes were made.

Here is the code I have in the controller:

// GET: Item
    public ActionResult Index(int? page)
    {
        var items = db.Items.Include(i => i.PurchaseOrder);
        return View(items.ToList().ToPagedList(page ?? 1, 3));
    }

Here is the code I have in the view:

    @using PagedList;
@using PagedList.Mvc;

@model IPagedList<PurchaseOrders.Models.Item>

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.First().ItemDescription)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.First().Quantity)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.First().Price)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.First().DueDate)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.First().DateReceived)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.First().Comments)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.First().PurchaseOrder.PurchaseRequest_)
        </th>
        <th></th>
    </tr>

@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.ItemDescription)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Quantity)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Price)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.DueDate)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.DateReceived)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Comments)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.PurchaseOrder.PurchaseRequest_)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", new { id=item.ItemId }) |
            @Html.ActionLink("Details", "Details", new { id=item.ItemId }) |
            @Html.ActionLink("Delete", "Delete", new { id=item.ItemId })
        </td>
    </tr>
}
</table>
@Html.PagedListPager(Model, page => Url.Action("Index", new { page }))
Phyllida answered 12/8, 2014 at 18:32 Comment(0)
K
8

You could pass an additional 'page` parameter to your edit method, for example

In your Index method, add

ViewBag.CurrentPage = page; // or use a view model property

Then your link would be

@Html.ActionLink("Edit", "Edit", new { id=item.ItemId, page = ViewBag.CurrentPage})

Then your edit method

[HttpGet]
public ActionResult Edit(int ID, int page)
{
  ViewBag.CurrentPage = page; // pass current page to edit view

And your edit view

 @using (Html.BeginForm(new { page = ViewBag.CurrentPage })) {

And in you post method

[HttpGet]
public ActionResult Edit(EditModel model, int page)
{
  .... // Save 
  return RedirectToAction("Index", new { page = page });
Klaus answered 12/8, 2014 at 23:56 Comment(0)
A
1

In this case the page is stored in the ViewBag which makes it ephemeral (the ViewBag is only available for the current request).

In the controller, you're telling it if you get null use 1 as your current page. so null is always retuned and you get the 1st page everytime.

You need to provide the current page Number to your views that you navigate to (Edit/Create) and then provide it back to the original page when you're done. You can use the TempData,that works well on HTTP redirects and lives longer than viewbag or viewData. You can also move it arround with your models when calling actions and then give it back to the index action that needs a page number. You can use sessions too. BTW, TempData is using session behind the scenes. UPDATED: Code to add in your index action:

var page = TempData["page"];

Code to add in the Create or Edit Submit action

    //Get the page number
   var page = TempData["page"];
   //Set it back to Tempdata (because Tempdata is only for redirects) otherwise it will be lost
   TempData["page"]=page;

add the value of the parameter to TempData["page"] when calling back the index action again You can also access it from Index action directly since we repopulated it:

var page = TempData["page"];  
return View(items.ToList().ToPagedList(page ?? 1, 3)); 
Alert answered 12/8, 2014 at 18:45 Comment(3)
How do I do this? An anonymous type cannot have multiple properties with the same name...Phyllida
Simply, add TempData["page"] = pageNumber; in the Action where you set it the first time and get it like this from the destination action: var page = TempData["page"]; Then you can give it back from that action to the source again by calling the action with the appropriate page number as a parameter. In your case the Source is Index(int? page) and the destination is the create or Edit action.Alert
the code in Create or Edit Submit action can be simplified with TempData.Keep("page");Silures
D
0

I also had this problem.

I tried to put it in the URL at first but it seems a bit weird to have ?page=2 in our URL.

So I replaced it with using TempData

What you need to do is this:

Store the page in TempData when you are in your Index() action method;

public const string PAGE_QUERY_STRING_KEY = "page";

public ActionResult Index(int page = 1)
{
    TempData[PAGE_QUERY_STRING_KEY] = page;

    ...
}

Then use TempData.Peek(), instead of TempData[], everywhere else (to retain the value of your page between requests which are related to your current Index page) --- in your Edit, Create, Details, etc. action methods:

public ActionResult Edit(...)
{
    ...

    return RedirectToAction(nameof(Index), new { page = TempData.Peek(PAGE_QUERY_STRING_KEY) });

    // do not do this because this will remove the temp data
    // return RedirectToAction(nameof(Index), new { page = TempData[PAGE_QUERY_STRING_KEY])
}

... and in your views:

<!--(Edit.cshtml)-->
...
<p>
    @Html.ActionLink("Back to List", "Index", 
        new { page = TempData.Peek(FLP.Web.Controllers.UsersAdminController.PAGE_QUERY_STRING_KEY) })
</p>
Dyad answered 13/7, 2018 at 8:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.