dcpartners
dcpartners

Reputation: 5446

Paging issue in Razor Pages with .Net Core 2.1

We are following tutorial for Paging - https://learn.microsoft.com/en-us/aspnet/core/data/ef-rp/sort-filter-page?view=aspnetcore-2.1 and we are having an issue in relation to button Next and Previous for paging :

Severity Code Description Project File Line Suppression State Error CS1061 'IList' does not contain a definition for 'HasPreviousPage' and no accessible extension method 'HasPreviousPage' accepting a first argument of type 'IList' could be found (are you missing a using directive or an assembly reference?)

@{
    var prevDisabled = !Model.TournamentAtheletes.HasPreviousPage ? "disabled" : "";
    var nextDisabled = !Model.TournamentAtheletes.HasNextPage ? "disabled" : "";
}

<a asp-page="./Index"
   asp-route-sortOrder="@Model.CurrentSort"
   asp-route-pageIndex="@(Model.TournamentAtheletes.PageIndex - 1)"
   asp-route-currentFilter="@Model.CurrentFilter"
   class="btn btn-default @prevDisabled">
    Previous
</a>
<a asp-page="./Index"
   asp-route-sortOrder="@Model.CurrentSort"
   asp-route-pageIndex="@(Model.TournamentAtheletes.PageIndex + 1)"
   asp-route-currentFilter="@Model.CurrentFilter"
   class="btn btn-default @nextDisabled">
    Next
</a>

Any ideas?

I do have PaginatedList.cs class:

public class PaginatedList<T> : List<T>
    {
        public int PageIndex { get; private set; }
        public int TotalPages { get; private set; }

        public PaginatedList(List<T> items, int count, int pageIndex, int pageSize)
        {
            PageIndex = pageIndex;
            TotalPages = (int)Math.Ceiling(count / (double)pageSize);

            this.AddRange(items);
        }

        public bool HasPreviousPage
        {
            get
            {
                return (PageIndex > 1);
            }
        }

        public bool HasNextPage
        {
            get
            {
                return (PageIndex < TotalPages);
            }
        }

        public static async Task<PaginatedList<T>> CreateAsync(
            IQueryable<T> source, int pageIndex, int pageSize)
        {
            var count = await source.CountAsync();
            var items = await source.Skip(
                (pageIndex - 1) * pageSize)
                .Take(pageSize).ToListAsync();
            return new PaginatedList<T>(items, count, pageIndex, pageSize);
        }
    }

Here's my backend code for that index.cshtml:

public class IndexModel : PageModel
    {
        private readonly AthlosifyWebArchery.Data.ApplicationDbContext _context;

        public IndexModel(AthlosifyWebArchery.Data.ApplicationDbContext context)
        {
            _context = context;
        }

        public string AtheleteNameSort { get; set; }

        public string GenderSort { get; set; }

        public string TotalRankingScoreSort { get; set; }

        public string CurrentSort { get; set; }

        public string CurrentFilter { get; set; }

        public class TournamentAtheleteViewModel
        {
             public string AtheleteName { get; set; }

            public string Gender { get; set; }

            public string Contingent { get; set; }

            public double TotalRankingScore { get; set; }
        }

        [BindProperty]
        public IList<TournamentAtheleteViewModel> TournamentAtheletes { get;set; }

        public async Task OnGetAsync(string sortOrder, string currentFilter, string searchString, int? pageIndex)
        {
            CurrentSort = sortOrder;

            AtheleteNameSort = String.IsNullOrEmpty(sortOrder) ? "atheletename_desc" : "";
            GenderSort = sortOrder == "gender" ? "gender_desc" : "gender";
            TotalRankingScoreSort = sortOrder == "totalrankingscore" ? "totalrankingscore_desc" : "totalrankingscore";

            if (searchString != null)
            {
                pageIndex = 1;
            }
            else
            {
                searchString = currentFilter;
            }

            CurrentFilter = searchString;


            IQueryable<TournamentAtheleteViewModel> atheletes  = _context.TournamentBatchItem
                                    .GroupBy(t => new { t.AtheleteName, t.Gender, t.Contingent })
                                    .Select(t => new TournamentAtheleteViewModel { AtheleteName = t.Key.AtheleteName,
                                                                                    Gender = t.Key.Gender,
                                                                                    Contingent = t.Key.Contingent,
                                                                                    TotalRankingScore = t.Sum(i => i.RankingScore) });
            if (!String.IsNullOrEmpty(searchString))
            {
                atheletes = atheletes.Where(s => s.AtheleteName.Contains(searchString)
                                                    || s.Contingent.Contains(searchString));
            }


            switch (sortOrder)
            {
                case "atheletename_desc":
                    atheletes = atheletes.OrderByDescending(s => s.AtheleteName);
                    break;
                case "gender":
                    atheletes = atheletes.OrderBy(s => s.Gender);
                    break;
                case "gender_desc":
                    atheletes = atheletes.OrderByDescending(s => s.Gender);
                    break;
                case "totalrankingscore":
                    atheletes = atheletes.OrderByDescending(s => s.TotalRankingScore);
                    break;
                case "totalrankingscore_desc":
                    atheletes = atheletes.OrderBy(s => s.TotalRankingScore);
                    break;
                default:
                    atheletes = atheletes.OrderBy(s => s.AtheleteName);
                    break;

            }

            int pageSize = 3;

            //TournamentAtheletes = await atheletes.AsNoTracking().ToListAsync();
            TournamentAtheletes = await PaginatedList<TournamentAtheleteViewModel>.CreateAsync(
                                    atheletes.AsNoTracking(), pageIndex ?? 1, pageSize);




        }
    }

Upvotes: 0

Views: 1060

Answers (1)

ProgrammingLlama
ProgrammingLlama

Reputation: 38727

By declaring your list as this:

IList<TournamentAtheleteViewModel> TournamentAtheletes { get; set; }

You're explicitly stating that the only methods guaranteed to exist are those declared by the interface IList<T>, which doesn't declare HasPreviousPage or HasNextPage.

The reason this happens is imagine I declare:

IList<TournamentAtheleteViewModel> TournamentAtheletes = new List<TournamentAtheleteViewModel>();

List<T> certainly doesn't declare your methods, so this would cause a runtime exception if I called .HasPreviousPage.

Because of this, you need to change this declaration to:

PaginatedList<TournamentAtheleteViewModel> TournamentAtheletes { get; set; }

Upvotes: 2

Related Questions