Question

What would be the best way to load, for example, the first 25 items of the IEnumerable of an Index view in ASP.NET MVC?

I have a model and have created a controller and views using scaffolding. In the index page I create a div containing some info for each instance in the model of the view (List of Question objects). I would like to display the first 25 items and give the user the possibility to load more using a link at the bottom saying "Load the next 25 questions...".

How would this be possible?

Was it helpful?

Solution

This is similar to paging except that you retain the previous fetches. Your view model needs to have one more property of a helper class:

public class PagingInfo
{
    public int TotalItems { get; set; }
    public int ItemsPerPage { get; set; }
    public int CurrentPage { get; set; }
    public int TotalPages
    {
        get { return (int)Math.Ceiling((decimal)TotalItems / ItemsPerPage); }
    }
}

public class QuestionsListViewModel
{
    public IEnumerable<Question> Questions { get; set; }
    public PagingInfo PagingInfo { get; set; }
}

And when you render the QuestionsListViewModel, use a similar Razor Code:

@foreach (var p in Model.Questions)
{
    // render Questions
}

@Html.ActionLink("Load next 25 items", "Questions", "Controller", new { page = Model.PagingInfo.CurrentPage + 1 }))

Questions is your Controller Action as follows:

    public ViewResult Questions(int page = 1)
    {
        QuestionsListViewModelmodel = new QuestionsListViewModel
        {
            // we need to get all items till now to render again 
            Questions = repository.Questions
                                  .Take(page * PageSize),
            PagingInfo = new PagingInfo
            {
                CurrentPage = page,
                ItemsPerPage = 25,
                TotalItems = repository.Questions.Count()
            }
        };

        return View(model);
    }

You can actually use the TotalItems property to give a smart message for loading next items.

If you don't want to go the MVC way, then you can leverage client side scripting to achieve the same.

OTHER TIPS

Have you considered PagedList library for pagination? All what you have to do is to reference PagedList library in your ASP.NET MVC application

To install PagedList.Mvc, run the following command in the Package Manager Console. You can use NuGet to get this package too.

PM> Install-Package PagedList.Mvc

Your viewmodel

public class QuestionViewModel
{
        public int QuestionId { get; set; }
        public string QuestionName { get; set; }
}

In your controller, reference PagedList

using PagedList;

and the Index method of your controller will be something like

public ActionResult Index(int? page)
{
            var questions = new[] {
                new QuestionViewModel { QuestionId = 1, QuestionName = "Question 1" },
                new QuestionViewModel { QuestionId = 1, QuestionName = "Question 2" },
                new QuestionViewModel { QuestionId = 1, QuestionName = "Question 3" },
                new QuestionViewModel { QuestionId = 1, QuestionName = "Question 4" }
            };

            int pageSize = 3;
            int pageNumber = (page ?? 1);
            return View(questions.ToPagedList(pageNumber, pageSize));
}

And your Index view

@model PagedList.IPagedList<ViewModel.QuestionViewModel>
@using PagedList.Mvc; 
<link href="/Content/PagedList.css" rel="stylesheet" type="text/css" />


<table>

@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.QuestionId)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.QuestionName)
        </td>
    </tr>
}

</table>

<br />

Page @(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of @Model.PageCount
@Html.PagedListPager( Model, page => Url.Action("Index", new { page }) )

if in short, you need to have some endpoint on backend that returns information page by page, e.g. http://my-website.com/questions/list?start=0&count=25. Let's say it returns information in JSON format. After that you can call this endpoint from front end (browser) side using AJAX. I would recommend using jQuery AJAX. As soon as you get data on browser side, you can use jQuery again and render the information whatever you want.

should you need to pull the items from your database you can modify your index method as follow:

 public ActionResult Index(int? page)
    {


        var question = (from e in db.Ques
                        select new
                        {

                            QuestionId = e.QuestionId,
                            QuestionName = e.QuestionName

                        }).ToList()

                      .Select(x => new QuestionViewModel()

                      {
                          QuestionId = x.QuestionId ,
                          QuestionName = x.QuestionName
                      });


            int pageSize = 2;
            int pageNumber = (page ?? 1);
            return View(question.ToPagedList(pageNumber, pageSize));

    }

Please note the View and model ,should remain as created above

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top