farkmt2official 1
farkmt2official
cemalggevenc 1
cemalggevenc
Bvural41 1
Bvural41
yarka0000 1
yarka0000
kralhakan2009 1
kralhakan2009
Vahsi Uzman 1
Vahsi Uzman
Hikaye Ekle

ASP.NET Core Select (Dropdown) Listesi Doldurma

  • Konuyu başlatan Konuyu başlatan Silverhand
  • Başlangıç tarihi Başlangıç tarihi
  • Cevaplar Cevaplar 1
  • Görüntüleme Görüntüleme 8

Ayyıldız2 | 2008 TR Yapısı • 1-99 Orta Emek Destan • Oto Avsız • 10 Temmuz 21:00 HEMEN TIKLA!

ASP.NET Core Select (Dropdown) Listesi Doldurma Örneği​


turkmmo-aspnetcore.png


Dropdown listeleri web formlarının vazgeçilmez parçası. Şehir seçimi, kategori seçimi, ülke seçimi, departman seçimi... Her yerde karşınıza çıkıyor. ASP.NET Core'da dropdown doldurmak birkaç farklı şekilde yapılabiliyor ve ben her birinin avantajını dezavantajını gördüm. Geçen bir HR portalı projesinde iç içe dropdown'lar yapmam gerekti, ülke seçince şehirler değişecek, şehir seçince ilçeler değişecek. Cascading dropdown denen bu yapı biraz karmaşık olabiliyor ama temeli iyi bilirseniz üstüne kolayca inşa edebilirsiniz. Şimdi temel dropdown doldurmadan başlayalım ve adım adım daha ileri senaryolara geçelim.

SelectListItem ve SelectList Kavramları​


ASP.NET Core'da dropdown doldurmak için SelectListItem sınıfını kullanıyoruz. Bu sınıfın Text (görünen metin), Value (gönderilecek değer), ve Selected (seçili mi) property'leri var. Bir List<SelectListItem> oluşturup bunu ViewBag, ViewData veya ViewModel ile view'a gönderiyoruz. Tag Helper tarafında ise asp-items attribute'u ile bu listeyi dropdown'a bağlıyoruz.

SelectList sınıfı da var, bu daha pratik. Bir koleksiyondan doğrudan SelectList oluşturabiliyorsunuz. Mesela veritabanından çektiğiniz bir entity listesini, hangi property'nin Value hangi property'nin Text olacağını belirterek doğrudan SelectList'e çevirebilirsiniz. Ben genelde SelectList kullanıyorum çünkü daha az kod yazıyorsunuz.

Bir de enum'lardan dropdown doldurmak var ki bu çok sık lazım oluyor. ASP.NET Core'un Html.GetEnumSelectList metodu ile enum değerlerini doğrudan dropdown'a çevirebilirsiniz. Türkçe gösterim için Display attribute kullanabilirsiniz. Enum bazlı dropdown'lar özellikle durum (status) alanları için çok pratik. Ben bunu sipariş durumu, kullanıcı rolü gibi yerlerde sık kullanıyorum.

Dropdown doldururken dikkat etmeniz gereken bir şey var. Eğer placeholder bir seçenek istiyorsanız, yani "Lütfen seçiniz..." gibi bir başlangıç değeri, bunu manuel olarak listenin başına eklemeniz gerekiyor. Ya da asp-items attribute'undan sonra bir option tag'ı koymak yerine SelectList constructor'ında placeholder belirleyebilirsiniz.

ViewModel Yaklaşımı​


C#:
public class UrunFormViewModel
{
    [Required(ErrorMessage = "Ürün adı zorunludur.")]
    [Display(Name = "Ürün Adı")]
    public string UrunAdi { get; set; }

    [Required(ErrorMessage = "Kategori seçimi zorunludur.")]
    [Display(Name = "Kategori")]
    public int KategoriId { get; set; }

    [Display(Name = "Alt Kategori")]
    public int? AltKategoriId { get; set; }

    [Required(ErrorMessage = "Marka seçimi zorunludur.")]
    [Display(Name = "Marka")]
    public int MarkaId { get; set; }

    [Display(Name = "Durum")]
    public UrunDurumu Durum { get; set; }

    // Dropdown listeleri
    public List<SelectListItem> Kategoriler { get; set; } = new();
    public List<SelectListItem> AltKategoriler { get; set; } = new();
    public List<SelectListItem> Markalar { get; set; } = new();
}

public enum UrunDurumu
{
    [Display(Name = "Aktif")]
    Aktif = 1,

    [Display(Name = "Pasif")]
    Pasif = 2,

    [Display(Name = "Stokta Yok")]
    StoktaYok = 3,

    [Display(Name = "Yayından Kaldırıldı")]
    YayindanKaldirildi = 4
}

ViewModel'de hem form alanlarını hem de dropdown listelerini bir arada tutuyoruz. Bu yaklaşım ViewBag kullanmaktan çok daha temiz ve type-safe. Ben ViewBag'den uzak duruyorum çünkü dynamic olduğu için IDE desteği yok ve typo yaparsanız runtime'da hata alırsınız. ViewModel her zaman daha güvenli.

Controller Tarafı​


C#:
public class UrunController : Controller
{
    private readonly ApplicationDbContext _context;

    public UrunController(ApplicationDbContext context)
    {
        _context = context;
    }

    [HttpGet]
    public async Task<IActionResult> Ekle()
    {
        var model = new UrunFormViewModel();
        await DropdownlariDoldur(model);
        return View(model);
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Ekle(UrunFormViewModel model)
    {
        if (!ModelState.IsValid)
        {
            // Dropdown'ları tekrar doldur çünkü POST'ta kaybolurlar
            await DropdownlariDoldur(model);
            return View(model);
        }

        var urun = new Urun
        {
            Ad = model.UrunAdi,
            KategoriId = model.KategoriId,
            AltKategoriId = model.AltKategoriId,
            MarkaId = model.MarkaId,
            Durum = model.Durum
        };

        _context.Urunler.Add(urun);
        await _context.SaveChangesAsync();

        TempData["Basari"] = "Ürün başarıyla eklendi.";
        return RedirectToAction("Liste");
    }

    // Cascading dropdown için AJAX endpoint
    [HttpGet]
    public async Task<IActionResult> AltKategorileriGetir(int kategoriId)
    {
        var altKategoriler = await _context.AltKategoriler
            .Where(a => a.KategoriId == kategoriId)
            .Select(a => new { value = a.Id, text = a.Ad })
            .ToListAsync();

        return Json(altKategoriler);
    }

    private async Task DropdownlariDoldur(UrunFormViewModel model)
    {
        model.Kategoriler = await _context.Kategoriler
            .OrderBy(k => k.Ad)
            .Select(k => new SelectListItem
            {
                Value = k.Id.ToString(),
                Text = k.Ad
            })
            .ToListAsync();

        model.Markalar = await _context.Markalar
            .Where(m => m.Aktif)
            .OrderBy(m => m.Ad)
            .Select(m => new SelectListItem
            {
                Value = m.Id.ToString(),
                Text = m.Ad
            })
            .ToListAsync();
    }
}

Burada çok önemli bir nokta var. POST action'ında ModelState geçersiz olduğunda dropdown'ları tekrar doldurmanız gerekiyor. Çünkü form submit edildiğinde sadece seçilen değerler gelir, dropdown listeleri gelmez. Bu noktayı unutanlar "Object reference not set" hatası alır ve kafayı yer. Ben bunu bir helper metod olarak ayırdım (DropdownlariDoldur) böylece hem GET hem POST'ta aynı kodu tekrar yazmıyorum.

View Tarafı​


HTML:
@model UrunFormViewModel

<form asp-action="Ekle" method="post">
    <div class="mb-3">
        <label asp-for="UrunAdi" class="form-label"></label>
        <input asp-for="UrunAdi" class="form-control" />
        <span asp-validation-for="UrunAdi" class="text-danger"></span>
    </div>

    <div class="mb-3">
        <label asp-for="KategoriId" class="form-label"></label>
        <select asp-for="KategoriId" asp-items="Model.Kategoriler" class="form-select" id="kategoriSelect">
            <option value="">-- Kategori Seçiniz --</option>
        </select>
        <span asp-validation-for="KategoriId" class="text-danger"></span>
    </div>

    <div class="mb-3">
        <label asp-for="AltKategoriId" class="form-label"></label>
        <select asp-for="AltKategoriId" asp-items="Model.AltKategoriler" class="form-select" id="altKategoriSelect">
            <option value="">-- Önce Kategori Seçiniz --</option>
        </select>
    </div>

    <div class="mb-3">
        <label asp-for="MarkaId" class="form-label"></label>
        <select asp-for="MarkaId" asp-items="Model.Markalar" class="form-select">
            <option value="">-- Marka Seçiniz --</option>
        </select>
        <span asp-validation-for="MarkaId" class="text-danger"></span>
    </div>

    <div class="mb-3">
        <label asp-for="Durum" class="form-label"></label>
        <select asp-for="Durum" asp-items="Html.GetEnumSelectList<UrunDurumu>()" class="form-select">
        </select>
    </div>

    <button type="submit" class="btn btn-success">Ürün Ekle</button>
</form>

@section Scripts {
    <partial name="_ValidationScriptsPartial" />
    <script>
        $('#kategoriSelect').on('change', function() {
            var kategoriId = $(this).val();
            var altSelect = $('#altKategoriSelect');

            altSelect.empty().append('<option value="">Yükleniyor...</option>');

            if (kategoriId) {
                $.getJSON('@Url.Action("AltKategorileriGetir")?kategoriId=' + kategoriId, function(data) {
                    altSelect.empty().append('<option value="">-- Alt Kategori Seçiniz --</option>');
                    $.each(data, function(i, item) {
                        altSelect.append($('<option>').val(item.value).text(item.text));
                    });
                });
            } else {
                altSelect.empty().append('<option value="">-- Önce Kategori Seçiniz --</option>');
            }
        });
    </script>
}

Burada cascading dropdown örneği de var. Kategori değiştiğinde AJAX ile alt kategoriler getiriliyor. Bu pattern çok yaygın ve bilmeniz gereken temel bir yapı. Dikkat edin, enum için Html.GetEnumSelectList kullandık, ne kadar pratik değil mi?

İpuçları ve Dikkat Edilecekler​


Dropdown'larda çok fazla eleman olduğunda (mesela 1000+ şehir) performans sorunu yaşayabilirsiniz. Bu durumda Select2 veya Chosen gibi aranabilir dropdown kütüphaneleri kullanın. Bunlar hem arama hem de lazy loading destekliyor. Ben 50'den fazla eleman olan her dropdown'da Select2 kullanıyorum.

Bir de multi-select dropdown'lar var. HTML'de select elemanına multiple attribute'u eklerseniz çoklu seçim yapılabilir. Model'de bunu int[] veya List<int> olarak karşılarsınız. Ama UX olarak çoklu seçim dropdown'ları pek kullanıcı dostu değil, checkbox listesi genelde daha iyi bir alternatif.

Son olarak, dropdown verilerinizi cache'lemeyi düşünün. Kategori listesi gibi sık değişmeyen veriler için her request'te veritabanına gitmek gereksiz. IMemoryCache veya IDistributedCache kullanarak bu verileri cache'leyebilirsiniz. Bu özellikle yoğun trafikli uygulamalarda fark yaratır.
 
Emeğiniz ve katkınız için teşekkür ederiz!
Konunuz gerekli incelemelerden geçerek onaylandı. Topluluğumuza katkılarınızın devamını bekliyoruz.
İyi forumlar! 🎉
 

Şu an konuyu görüntüleyenler (Toplam : 0, Üye: 0, Misafir: 0)

Geri
Üst