Mini Dükkan Projesi Ders 006 Pagination

Projemizde pagination yani sayfalama işlemlerine devam edelim.

View Model’in Eklenmesi

Yapmam gereken işlemleri özetlersem, kaç sayfam var? Hangi sayfadayım? Ürünlerimin sayısı? Bunu yapabilmek için bir view model classı oluşturmak en kolay yol. Böylelikle controller ve view arasındaki veri geçişini sağlayabilirim. Şimdi Models/ViewModels klasörü altında yeni bir class oluşturuyor ve adını SayfalamaBilgi.cs  veriyorum. Kodlarımızı yazalım:

Bu dersin video eğitimi:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace MiniDukkan.Models.ViewModels
{
    public class SayfalamaBilgi
    {
        public int ToplamUrunSayisi { get; set; }
        public int SayfaBasiGosterilecekUrun { get; set; }
        public int GuncelSayfa { get; set; }

        public int ToplamSayfalar => (int)Math.Ceiling((decimal)ToplamUrunSayisi / SayfaBasiGosterilecekUrun);
    }
}

TagHelper Classının Eklenmesi:

View modelimizi oluşturduk sıra geldi TagHelper sınıfının oluşturulmasına. Projeme Altyapı adında bir klasör ekliyorum. Bu klasör içine de bir class ekliyor ve adını SayfaLinkTagHelper.cs veriyorum. TagHelper kavramına şu an çok değinmek istemiyorum, ama ilerleyen videolarda daha detay bilgi vereceğim. Şunu şimdilik bilin yeter, ASP.NET Core projelerinde TagHelper kullanımı çok ama çok önemli. Ben projemde Altyapı adında bir klasör oluşturdum bu klasöre daha çok projemin ana işlevi ile ilgili olmayan classları ekleyeceğim. Sizler farklı yollar izleyebilirsiniz, bu bir kural değil arkadaşlar.

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.Routing;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
using MiniDukkan.Models.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace MiniDukkan.Altyapi
{
    [HtmlTargetElement("div",Attributes ="sayfa-model")]
    public class SayfaLinkTagHelper : TagHelper
    {
        private IUrlHelperFactory urlHelperFactory;

        public SayfaLinkTagHelper(IUrlHelperFactory helperFactory)
        {
            urlHelperFactory = helperFactory;
        }

        [ViewContext]
        [HtmlAttributeNotBound]
        public ViewContext ViewContext { get; set; }

        public SayfalamaBilgi SayfaModel { get; set; }

        public string SayfaAction { get; set; }

        public override void Process(TagHelperContext context, TagHelperOutput output)
        {
            IUrlHelper urlHelper = urlHelperFactory.GetUrlHelper(ViewContext);

            TagBuilder sonuc = new TagBuilder("div");
            for (int i = 1; i <= SayfaModel.ToplamSayfalar; i++)
            {
                TagBuilder tag = new TagBuilder("a");
                tag.Attributes["href"] = urlHelper.Action(SayfaAction, new { urunSayfa = i });
                tag.InnerHtml.Append(i.ToString());
                sonuc.InnerHtml.AppendHtml(tag);
            }

            output.Content.AppendHtml(sonuc.InnerHtml);
        }
    }
}

Buradaki kodları biraz açıklarsak her bir ürünün sayfalarına karşılık gelen öğeler ile ilgili div elementinin içini dolduruyorum. Belirttiğim gibi taghelperlar hakkında çok detaya girmeyeceğim. Ancak şimdilik  C# mantığını anlatmanın en kullanışlı yollarından biri olduklarını bilmeniz yeterli. Buradaki kodlar biraz karmaşık gelebilir ama C# ve HTML’i bir arada birleştirmek çok da kolay değil. Taghelper mantığı bu açıdan bizi biraz rahatlatıyor.

Şimdi yazdığımız bu taghelper’i uygulamamıza kayıt etmemiz gerekli. _ViewImports.cshtml dosyama geliyorum ve kodlarımı yazıyorum.

@using MiniDukkan
@using MiniDukkan.Models
@using MiniDukkan.Models.ViewModels
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, MiniDukkan

View Model Data Ekleme:

SayfalamaBilgi view modeli sınıfının bir örneğini sağlamam gerektiğinden taghelperimi kullanmaya tam olarak hazır değilim. Bunu yapabilmek için Models / ViewModels klasörü altında UrunlerListesiViewModel.cs adında bir class oluşturuyorum. Kodlarımı yazıyorum.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace MiniDukkan.Models.ViewModels
{
    public class UrunlerListesiViewModel
    {
        public IEnumerable< Urun > Urunler { get; set; }
        public SayfalamaBilgi SayfalamaBilgi { get; set; }
    }
}

Buradan HomeController classıma geçiyorum. Burada Index action metodumu düzenliyorum. UrunlerListesiViewModel classımı sayfamda gösterilen ürünlerin detayları ile birlikte ve sayfalandırma detayları ile birlikte düzenleme işlemi yapacağım.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using MiniDukkan.Models;
using MiniDukkan.Models.ViewModels;

namespace MiniDukkan.Controllers
{
    public class HomeController : Controller
    {
        private IDukkanRepository repository;
        public int SayfaBoyutu = 3;

        public HomeController(IDukkanRepository repo)
        {
            repository = repo;
        }




        //private readonly ILogger< HomeController > _logger;

        //public HomeController(ILogger< HomeController > logger)
        //{
        //    _logger = logger;
        //}

        //public IActionResult Index()
        //{
        //    return View(repository.Urunler);
        //}


        public ViewResult Index(int urunSayfa = 1)
        => View(new UrunlerListesiViewModel { Urunler = repository.Urunler.OrderBy(u => u.UrunID).Skip((urunSayfa - 1) * SayfaBoyutu).Take(SayfaBoyutu), SayfalamaBilgi = new SayfalamaBilgi { GuncelSayfa = urunSayfa, SayfaBasiGosterilecekUrun = SayfaBoyutu, ToplamUrunSayisi = repository.Urunler.Count() } }
        );
        
        
        

        //public IActionResult Privacy()
        //{
        //    return View();
        //}

        //[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
        //public IActionResult Error()
        //{
        //    return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        //}
    }
}

Akabinde Index.cshtml dosyasını güncelliyorum.

@model UrunlerListesiViewModel

@foreach (var u in Model.Urunler)
{
    

@u.UrunAd

@u.Aciklama

@u.Fiyat.ToString("c")

}

Burada @model kısmı ile farklı bir veri modeli ile çalışacağımı belirttim, değişiklik yaptım. Ayrıca foreach döngümde de güncelleme yaptım.

Sayfa Linklerini Gösterme:

Artık Index sayfasına sayfa linklerini ekleyebilirim. Yaptıklarımı özetlersem, sayfalama bilgisini içeren view modeli oluşturdum. Bu bilgiyi ilgil View’e aktarmak için controllerimı düzenledim. Yeni model tipimi @model ile tanımladım. Geriye kalan tek şey tag helperin sayfa bağlantılarını oluşturmak için işleyeceği bir HTML öğesinin eklenmesi. Index sayfama tekrar dönüyor ve ekliyorum.

@model UrunlerListesiViewModel

@foreach (var u in Model.Urunler)
{
    

@u.UrunAd

@u.Aciklama

@u.Fiyat.ToString("c")

}

Projemi çalıştırıyorum.

Görüleceği üzere linkler gelmiş durumda. Tabi hiç şık değil, son derece basit bir görünüme sahip. Bununla ilgileneceğim tabii ki. Şimdilik önemli olan sayfalar arası geçiş ve ürünlerin listelenmesi.

URL Düzenleme:

Sayfalama linklerim çalışıyor ama sayfa bilgilerim adres satırında çok da iyi görünmüyor.

http://localhost/?urunSayfa=2

Bu görünüm pek hoş değil, ben şöyle bir görünüm elde etmek istiyorum:

http://localhost/Sayfa2

Bunun için ASP.NET Core’un Route özelliği üzerinde çalışacağım. Bunun için startup classımda düzenleme yapıyorum:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using MiniDukkan.Models;

namespace MiniDukkan
{
    public class Startup
    {
        public Startup(IConfiguration config)
        {
            Configuration = config;
        }

        public IConfiguration Configuration { get; set; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews();
            services.AddDbContext< MiniDukkanContext >(opts => opts.UseSqlServer(Configuration["ConnectionStrings:MiniDukkanConnection"]));

            services.AddScoped< IDukkanRepository, EFDukkanRepository >();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }
            app.UseStaticFiles();

            app.UseRouting();

            app.UseStatusCodePages();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
            endpoints.MapControllerRoute("sayfalama", "Urunler/Sayfa{urunSayfa}",
                new { Controller = "Home", action = "Index" });
                endpoints.MapDefaultControllerRoute();
                    
            });

            HamVeri.VeriDoldur(app);
        }
    }
}

Burada MapControllerRoute ile değişikliğimi gerçekleştiriyorum. Dikkat edilmesi gereken nokta değiştirmek istediğim route bilgisini MapDefaultControllerRoute metodunu çağırmadan önce belirtmem gerekiyor. İlgili TagHelper vasıtası ile artık sayfama gezinme linklerini eklemiş oldum. Şimdi uygulamayı çalıştırıp sonucu görelim:

Şimdilik bu kadar bir sonraki yazıda görüşmek üzere.

Bir cevap yazın

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