Asp.NET MVC’de PagedList Kullanarak Verileri Sayfalama

Web projelerinde, veritabanında bulunan binlerce satırlık verilerle hizmet vermemiz gereken noktalarda sayfalamayı tercih ederiz.Bunun en temel noktası kullanıcılara görsel olarak yeterli veri akışı göstermenin yanında, server’da oluşturulan sitedenin performans açısından daha hızlı derlenebilmesi, veritabanına olan yükün minimize edilmesi ve web sitenin kullanışlılığı açısından daha kaliteli bir yapıya büründürülmesi gibi faktörlerde temel etkenler arasındadır.Bir sayfa oluşumu sürecinde binlerce veriyi veritabanından talep edip, kullanıcılara sunmak, hem veritabanına ağır bir yüklenme olacaktır hemde kullanıcı açısından sunulan yoğun bilgiden kaynaklanan kompleks bir ekranla karşılaşıldığından dolayı amaca dönük hizmet istemsizce verimsizleşecektir.

Aslında sayfalama tekniği olarak kendi algoritmalarımızı geliştirebileceğimiz gibi bu konu üzerine oluşturulan türlü türlü Componentler üzerinde de sayfalama işlemimizi gerçekleştirebiliriz.Bu yazımızda ilgili konu üzerine geliştirilmiş olan PagedList Componenti’ni derinlemesine inceleyeceğiz.Tabi bu Component’in diğerlerinden ek olarak artı ve eksileri mevcuttur.Lakin PagedList’in şahsen tercih sebebim olmasında aşağıda belirttiğim bir kaç husus temel etkenlerdir;

  • PagedList ile yapıla sayfalamalar QueryString mantığıyla çalıştığı gibi Ajax ile dinamik sayfalama esnekliği sunmaktadır.
  • Arkaplanda veritabanından tüm veriler çekilip sayfalama yapılmamakta, bilakis bir sayfada yapılacak adet kadar veri için veritabanına talep oluşturulmaktadır.
  • Sayfalama için farklı şablonlar sunması.

Belirttiğim bu hususlar haricinde PagedList’in daha fazla artı ve eksisi olduğunu unutmayınız.

Bir Asp.NET MVC projesinde PagedList ile sayfalama yapmak için nelere ihtiyacımız var sorusunu peşin cevaplandırmamız gerekirse eğer;

Şimdi bir MVC projesinde nasıl PagedList entegre ediliyor ve veri sayfalanıyor teferruatlandıralım.

Yapacağımız örnekte, Northwind veritabanında çalışma gerçekleştireceğiz ve LINQ desteği ile sayfalamayı sağlayacağımızı ve ayriyetten ilgili konuyu temelden izah edebilmek için boş bir Asp.NET MVC projesi üzerinden çalışmamızı örneklendireceğimizi öncelikle bildiriyorum.

Öncelikle projemize yukarıda vermiş olduğum linklerdeki ilgili Packageları entegre etmemiz gerekiyor.

Tabi entegre işlemini göstermeden önce yukarıda vermiş olduğum linklerin zamanla geçersiz olabilme ihtimali olduğu için bu Packagelara nasıl ulaşabileceğinizi izah etmektede fayda var.

www.nuget.org adresine girip, karşımıza çıkan sayfada arama kutusuna “PagedList” anahtar sözcüğünü yazıyor ve aratıyoruz.
Asp.NET MVC'de PagedList Kullanarak Verileri Sayfalama
Arama ekranında çıkan PagedList.Mvc linkine tıkladığımız zaman aşağıdaki ekran görüntüsünde de gördüğünüz gibi karşımıza bir kod çıkmaktadır.
Asp.NET MVC'de PagedList Kullanarak Verileri Sayfalama-2
Bu kodu kopyalıyoruz ve Visual Studio’da “Package Manager Console” penceresine yapıştırıyoruz.

“Package Manager Console” menüsünü açmak için “Tools” -> “Nuget Package Manager” -> “Package Manager Console” kombinasyonunu takip ediyoruz.
Asp.NET MVC'de PagedList Kullanarak Verileri Sayfalama-3
İlgili kombinasyonu takip ettikten sonra karşımıza aşağıdaki gibi bir pencere gelmektedir.
Asp.NET MVC'de PagedList Kullanarak Verileri Sayfalama-4
Gelen bu pencereye kopyalamış olduğumuz Packege kodunu yapıştırıyor ve Enter tuşuna basıyoruz.
Asp.NET MVC'de PagedList Kullanarak Verileri Sayfalama-5

Dikkat!!!
PagedList Componenti, 4.5 Framework’ünde çalışmaktadır.

Bu işlemi gerçekleştirdikten sonra projemizin “References” klasörüne göz atarsak eğer “PagedList” ve “PagedList.Mvc” DLL’lerinin yüklendiğini görmüş olacağız.
Asp.NET MVC'de PagedList Kullanarak Verileri Sayfalama-6

Ayriyetten projemizin “Content” klasörüne göz atarsak eğer “PagedList.css” CSS dosyasının eklendiğini göreceğiz.Bu dosya PagedList Componenti’nin style yapısını oluşturmaktadır.İsterseniz siz değiştirebilirsiniz.Bu dosyayı PagedList’i kulanacağımız ilgili sayfaya ya da Layout sayfasına entegre edeceğiz.
Asp.NET MVC'de PagedList Kullanarak Verileri Sayfalama-7
PagedList Componenti’ni projemize entegre etmiş olduk.
“jQuery Unobtrusive Validation” ve “jQuery Unobtrusive Ajax” kütüphanelerinide aynı şekilde projeye entegre edebilirsiniz.Tabi bu kütüphaneler projenizde varsayılan olarak gelmiş olabilir.Ola ki yoktur ya da silmiş olabilirsiniz, bu şekilde yüklemeyi gerçekleştirebilirsiniz.

Şimdi projemizde Layout sayfamızı düzenleyelim.

<!DOCTYPE html>
<html>
<head>
    <link href="~/Content/PagedList.css" rel="stylesheet" />
    <script src="~/Scripts/jquery-1.10.2.min.js"></script>
    <script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>
    <script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
    <script src="~/Scripts/jquery.validate.min.js"></script>
</head>
<body>
        @RenderBody()
</body>
</html>

Gördüğünüz gibi yazımız boyunca PagedList’te yapacağımız her türlü işlemde bize sıkıntısız eşlik edecek kütüphaneleri Layout’a entegre etmiş olduk.

Şimdi “Home(Controller).cs” isimli bir Controller sınıfı oluşturup “Index” Action’ının View katmanındaki .cshtml sayfasında sayfalama ekranımızı oluşturalım.

<h2>Müşteriler</h2>

<div id="dvMusteriListesi">
    <table>
        <thead>
            <tr>
                <th>Şirket Adı</th>
                <th>Müşteri Adı</th>
                <th>Şehir</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td></td>
                <td></td>
                <td></td>
            </tr>
        </tbody>
    </table>
</div>

“Index.cshtml” dosyamızı yukarıdaki gibi oluşturuyorum.Birazdan veritabanından çekeceğimiz verileri bu tabloda repeat ederek göstereceğiz.

“Models” katmanında veritabanımızı Linq To Sql ile oluşturup, “Home(Controller).cs” isimli Controller sınıfımızdaki “Index” Action’ında aşağıdaki işlemlerimizi yapalım.

using PagedList;
using PagedList.Mvc;

namespace PagedListExample.Controllers
{
    public class HomeController : Controller
    {
        VeriTabaniDataContext Veri = new VeriTabaniDataContext();
        public ActionResult Index(int? SayfaNo)
        {
            int _sayfaNo = SayfaNo ?? 1;
            var MusteriListesi = Veri.Musterilers.OrderByDescending(m => m.MusteriID).ToPagedList<Musteriler>(_sayfaNo, 10);

            return View(MusteriListesi);
        }
    }
}

Gördüğünüz gibi sayfaya “PagedList” ve “PagedList.Mvc” DLL’lerini using ettikten sonra ToPagedList Extension metodunu kullanabiliyoruz.Bu metod IQueryable tipler üzerine Extension olarak inşaa edilmiş ve geriye IPagedList tipinden değer dönmektedir.

@using PagedList
@using PagedList.Mvc
@using PagedListExample.Models
@model IPagedList<Musteriler>

<h2>Müşteriler</h2>

<div id="dvMusteriListesi">
    <table>
        <thead>
            <tr>
                <th>Şirket Adı</th>
                <th>Müşteri Adı</th>
                <th>Şehir</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var Musteri in Model)
            {
                <tr>
                    <td>@Musteri.SirketAdi</td>
                    <td>@Musteri.MusteriAdi</td>
                    <td>@Musteri.Sehir</td>
                </tr>
            }
        </tbody>
    </table>

    @Html.PagedListPager(Model, _sayfaNo => Url.Action("Index", "Home", new { SayfaNo = _sayfaNo }))
</div>

“Home(Controller).cs” isimli Controller sınıfımızın “Index” isimli Action metodun View katmanındaki “Index.cshtml” görüntüsünü yukarıdaki gibi değiştiriyorum.

Ne gibi değişiklikler yaptım izah edelim.

  • 1 – 4 satır aralığında, projemize entegre etmiş olduğumuz “PagedList” ve “PagedList.Mvc” DLL’lerini bu sayfada kullanabilmek için entegre ettim.Ayriyetten Models katmanına rahat ulaşabilmek için projedeki Models entegre edilmiştir ve Index Action’ından gelecek modeli yakalayacak IPagedList tipini entegre ettim.
  • 18 – 25 satır aralığında, IPagedList modelinin içinde dönerek ne kadar veri varsa listeledim.Tabi burada ne kadar veri derken, bizim Controller’da ToPagedList Extension medoyla yaptığımız ayar baz alınmaktadır.Evet, IPagedList tipi, bir IEnumerable tipi olduğu gibi içinde rahatça dönebilir ve T yerine verilen referansın propertylerine döngü esnasında sıkıntısız ulaşabilirim.Nihayetinde Generic bir koleksiyon gibi düşünebilirsiniz.
  • 29. satırda ise, “PagedList” ve “PagedList.Mvc” dll’leri sayesinde sayfamızda kullanabildiğimiz PagedListPager metodu bize sayfaya gelen ve içinde dönülen modele bağlı bir sayfalama oluşturulmaktadır.Metot, birinci parametresinde sayfalama yapılacak koleksiyonu isterken, ikinci parametresinde bir Func tipinden metod talep etmektedir.Bu metodu biz lambda ile işaretlemekteyiz._sayfaNo parametresi o anki sayfayı temsil ederken, oluşturulan linke ilgili sayfa gönderilmektedir.Buradan anlayacağımız PagedList Componenti hangi sayfada olduğunu _sayfaNo parametresi sayesinde kendisi tutabilmekte ve bizi bu zahmetten arındırmaktadır.

Şimdi projemizi derleyip çalıştıralım.
Asp.NET MVC'de PagedList Kullanarak Verileri Sayfalama-8

Gördüğünüz gibi sayfalama işlemi başarıyla gerçekleştirilmiştir.
Burada bir hususa değinmek istiyorum.Dikkat ederseniz eğer PagedList ile yapılan sayfalama neticesinde bir QueryString değeri ile(Örn, ?SayfaNo=3) o anki sayfa elde edilmektedir.Haliyle bir MVC projesinin temel mekanizması olan Routing sistemine ters bir yapı olarak görebiliriz.Tabi, gidip ilgili route’u oluşturup QueryString değerini ortadan kaldırarak normal bir şekilde MVC’ye yakışır bir link oluşturtabiliriz.Eğer PagedList’i bu şekilde kullanacaksanız sizlere tavsiyem bu duruma dikkat ediniz.

Peki PagedList’in nimetleri bu kadar mı? diye sorabilirsiniz.Daha durun, aceleye gerek yok.Daha sayfalama şablonlarına değineceğiz ve ayriyetten ajax ile sayfalama gerçekleştireceğiz.Yani sayfada git – gel kalkacak.Ha birde filtreleme yapacağız ama onu sanırım bir sonraki yazıya ayırmakta fayda var diye düşünüyorum.

Evet, şimdi gelin sayfalama şablonlarına göz atalım.

    <h3>Varsayılan sayfalama</h3>
    @Html.PagedListPager(Model, _sayfaNo => Url.Action("Index", "Home", new { SayfaNo = _sayfaNo }))
    <div class="t"></div>

    <h3>Önceki, Sonraki</h3>
    @Html.PagedListPager(Model, _sayfaNo => Url.Action("Index", "Home", new { SayfaNo = _sayfaNo }), PagedListRenderOptions.Minimal)
    <div class="t"></div>

    <h3>Önceki, Sonraki ve hangi sayfadasınız</h3>
    @Html.PagedListPager(Model, _sayfaNo => Url.Action("Index", "Home", new { SayfaNo = _sayfaNo }), PagedListRenderOptions.MinimalWithPageCountText)
    <div class="t"></div>

    <h3>Önceki, Sonraki ve hangi sayfadasınız. Toplam kayıt sayısı</h3>
    @Html.PagedListPager(Model, _sayfaNo => Url.Action("Index", "Home", new { SayfaNo = _sayfaNo }), PagedListRenderOptions.MinimalWithItemCountText)
    <div class="t"></div>

    <h3>Sayfa numaraları</h3>
    @Html.PagedListPager(Model, _sayfaNo => Url.Action("Index", "Home", new { SayfaNo = _sayfaNo }), PagedListRenderOptions.PageNumbersOnly)
    <div class="t"></div>

    <h3>Önceki, sonraki ve sayfa numaraları</h3>
    @Html.PagedListPager(Model, _sayfaNo => Url.Action("Index", "Home", new { SayfaNo = _sayfaNo + 1 }), PagedListRenderOptions.OnlyShowFivePagesAtATime)
    <div class="t"></div>


    <h3>Kişiselleştirilmiş sayfalama</h3>
    @Html.PagedListPager(Model, _sayfaNo => Url.Action("Index", "Home", new { SayfaNo = _sayfaNo }), new PagedListRenderOptions { LinkToFirstPageFormat = "<< İlk", LinkToPreviousPageFormat = "< Önceki", LinkToNextPageFormat = "Sonraki >", LinkToLastPageFormat = "Son >>" })
</div>

Yukarıda sadece PagedListPager metodunun prototiplerini paylaştım.Bu sayfalama şablonlarını en iyisi aşağıdaki ekran görüntüsünde olduğu gibi inceleyebilirsiniz.
Asp.NET MVC'de PagedList Kullanarak Verileri Sayfalama-9

Evet, istediğiniz şablonu seçip işleminizi gerçekleştirebilirsiniz.

Şimdi PagedList ile ilgili son olarak dinamik bir şekilde sayfalamayı irdeleyelim ve yazımızı noktalayalım.

Dinamikten kasıt her sayfa talebinde Ajax işlemleriyle sayfayı git gel yapmadan yenilemesidir.Bunun için oturup satır satır Ajax komutlarıyla uğraşmayacağız.Bu işlemleri bizim için PagedList Componenti’nin geliştiricileri halletmişler(Allah razı olsun).Biz sadece ufak tefek değişiklikler neticesinde bu işlemi aktifleştireceğiz.

Öncelikle “Home(Controller).cs” katmanımızdaki “Index” Action metodunda gelen talep Ajax ile mi? yoksa normal mi? kontrol ettirmeliyiz.

using PagedList;
using PagedList.Mvc;

namespace PagedListExample.Controllers
{
    public class HomeController : Controller
    {
        VeriTabaniDataContext Veri = new VeriTabaniDataContext();
        public ActionResult Index(int? SayfaNo)
        {
            int _sayfaNo = SayfaNo ?? 1;
            var MusteriListesi = Veri.Musterilers.OrderByDescending(m => m.MusteriID).ToPagedList<Musteriler>(_sayfaNo, 10);

            if (Request.IsAjaxRequest())
            {
                return PartialView("~/Views/Home/_MusteriListesi.cshtml", MusteriListesi);
            }

            return View(MusteriListesi);
        }
    }
}

Yukarıdaki kod bloğunu incelerseniz eğer Request.IsAjaxReques() metodu ile gelen talebin Ajax ile mi? yoksa normal mi? geldiğini kontrol ediyoruz.Eğer Ajax ile gelmişse, geriye bir PartialView gönderiyoruz.

“Views/Home” klasörü içerisinde “_MusteriListesi.cshtml” isimli bir PartialView oluşturdum.Bu PartialView’in içeriği aşağıdaki gibidir.

@using PagedList
@using PagedList.Mvc
@using PagedListExample.Models
@model IPagedList<Musteriler>

<table>
    <thead>
        <tr>
            <th>Şirket Adı</th>
            <th>Müşteri Adı</th>
            <th>Şehir</th>
        </tr>
    </thead>
    <tbody>
        @foreach (var Musteri in Model)
            {
            <tr>
                <td>@Musteri.SirketAdi</td>
                <td>@Musteri.MusteriAdi</td>
                <td>@Musteri.Sehir</td>
            </tr>
        }
    </tbody>
</table>

@Html.PagedListPager(Model, _sayfaNo => Url.Action("Index", "Home", new { SayfaNo = _sayfaNo }), PagedListRenderOptions.EnableUnobtrusiveAjaxReplacing(new AjaxOptions { UpdateTargetId = "dvMusteriListesi" }))

Anlayacağınız “Index.cshtml” dosyasındaki sayfalama alanını PartialView’e koydum.”Index.cshtml” de ki ilgili alana ise aşağıdaki gibi PartialView’i çağırmam yeterlidir.

@using PagedList
@using PagedList.Mvc
@using PagedListExample.Models
@model IPagedList<Musteriler>

<h2>Müşteriler</h2>

<div id="dvMusteriListesi">
    @Html.Partial("~/Views/Home/_MusteriListesi.cshtml", Model)
</div>

Artık sayfalama esnasında Ajax işlemleri neticesinde geri dönecek olan tabloyu PartialView olarak döndüreceğiz.Bu işlemi yapabilmek için PartialView’imizdeki komutu inceleyeniz.

@Html.PagedListPager(Model, _sayfaNo => Url.Action("Index", "Home", new { SayfaNo = _sayfaNo }), PagedListRenderOptions.EnableUnobtrusiveAjaxReplacing(new AjaxOptions { UpdateTargetId = "dvMusteriListesi" }))

“_MusteriListesi.cshtml” isimli PartialView’de ki ilgili komutu ben yukarıya aldım.Bu komutta tek değişiklik PagedListRenderOptions.EnableUnobtrusiveAjaxReplacing() metodunu kullanarak sayfalamayı Ajax ile yap demiş oluyoruz ve netice olarak gelen verileri “dvMusteriListesi” değerine sahip div elemanında göster diyoruz.

Projemizi derleyip çalıştırdığımızda sayfa git gel yapmadan sayfalamanın çalıştığını görüyoruz.Yaptığımız işlemi aşağıdaki videodan daha net görebilirsiniz.

Evet, PagedList Componenti’nin teferruatıyla nasıl kullanıldığını incelemiş olduk.
Yazımızı sonuna kadar okuma zahmetine katlandığınız için sizlere teşekkür ederim.

Sonraki yazılarımda görüşmek üzere…
Hepinizi iyi çalışmalar dilerim…

Kaynak : https://www.youtube.com/watch?v=0opJw6w8mmY, http://www.apostylee.com/pagedlist-mvc-paging-data/

Bunlar da hoşunuza gidebilir...

7 Cevaplar

  1. M. Kürşat YILDIRIM dedi ki:

    Teşekkürler. Çok işime yaradı.

  2. Mustafa dedi ki:

    Merhaba gencay bey filtrelemede bir sıkıntım var yardımcı olabilirmisiniz

  3. senol dedi ki:

    sonucta her defasında veriyi komple çekip içinden istedigin sayfa verilerini veriyor hertürlü ağır bir yapı ben özel olarak tasarladım yaptım adonet ile ilk count ile veriyi sayıyırum sonra sayfa numarasına göre istedigim veriyi çekiyorum

    • Gençay dedi ki:

      Doğrusu o tabi ki de 🙂 Ve itiraf etmem gerekirse eğer bende kendi çalışmalarımda hedef verileri getiren sayfalama yapılarını geliştirmeyi tercih ediyorum.

  4. Hüseyin dedi ki:

    Güzel makale çok teşekkür ederim.

  5. Semih dedi ki:

    Elinize sağlık, güzel anlatım, çok işime yaradı.
    Teşekkürler

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

*