ASP.NET'te en sevmediğim özelliklerden biri yaratılan HTML kodu üzerindeki
kontrolün pek de mümkün olmaması. Aslında bu sevmediğim özellik ASP.NET'in
işimizi bu kadar kolaylaştırabilmesini sağlayan en önemli altyapısı ile
ilişkili. Fakat derdime çare arayacak olsam aslında tam olarak da yaratılan HTML
kontrollerinin ID'lerine takıldığımı söyleyebilirim. Boyumu aşan ID'leri kontrol
edememek bir de bu ID'lere JavaScript ile ulaşmak zorunda kalmak ölümcül bir
deneyim!
Neden bahsediyorsun?
Bahsettiğim şey aslında basit bir Repeater bile olabilir. Örneğin sayfanıza
bir Repeater yerleştirdiniz ve içinde de çok basit bir Label bulunuyor. Aslında
tek yapmak istediğiniz elinizdeki ürünlerin isimlerini listelemek diyelim. Bu
durumda kabaca kullanacağınız Repeater yapısı aşağıdaki gibi olacaktır.
[ASP.NET]
<asp:repeater id="Repeater1" runat="server">
<ItemTemplate>
<asp:Label ID="lbl_UrunAdi" runat="server" Text='<%# Eval("Adi") %>'></asp:Label>
</ItemTemplate>
</asp:repeater>
Peki bu ASP.NET kodu çalıştığında ortaya HTML olarak ne çıkacak dersiniz?
Gelin aşağıdaki HTML'i beraber inceleyelim.
[HTML]
<span id="Repeater1_ctl00_lbl_UrunAdi">Örnek1</span>
<span id="Repeater1_ctl01_lbl_UrunAdi">Örnek2</span>
<span id="Repeater1_ctl02_lbl_UrunAdi">Örnek3</span>
<span id="Repeater1_ctl03_lbl_UrunAdi">Örnek4</span>
<span id="Repeater1_ctl04_lbl_UrunAdi">Örnek5</span>
<span id="Repeater1_ctl05_lbl_UrunAdi">Örnek6</span>
<span id="Repeater1_ctl06_lbl_UrunAdi">Örnek7</span>
<span id="Repeater1_ctl07_lbl_UrunAdi">Örnek8</span>
<span id="Repeater1_ctl08_lbl_UrunAdi">Örnek9</span>
<span id="Repeater1_ctl09_lbl_UrunAdi">Örnek10</span>
Yukarıdaki kodda da gördüğünüz üzere her bir Label / Span tagının ayrı bir
ID'si var. Zaten olması gereken de bu, çünkü bir sayfada ancak aynı ID'den bir
adet bulunabilir. Fakat ASP.NET'in bu farklı ID'leri yaratırken izlediği yol
biraz farklı. İlk olarak container elementin adı alınıyor sonra ctl ile başlayan
satır Index numarası kullanılıyor sonra da içerideki orijinal kontrolün adı
ekleniyor ve ortaya kocaman bir ID çıkıyor. Bu ID'lerin her birini üç
karakterlik isimlere kısaltmış olsak ciddi miktarda web sitesi trafiğini de
azaltmış olacağız. Hadi trafiği geçtik bu Label'lardan birine JavaScript ile
ulaşmak isterseniz ne yapacaksınız? Eminim çoğunuzun dinamik JavaScript kodları
yarattığı ve içlerine sunucu tarafından istedikleri kontrollerin ClientID'lerini
koydukları günler vardı. Geçmiş zamanla konuşuyorum çünkü ASP.NET 4.0 ile bu
sistem değişiyor.

Hoş geldin ClientIDMode!
Artık kontrol başına ClientIDMode belirleyerek söz konusu
kontrolün istemci taraflı ID'sinin ne şekilde yaratılacağını kontrol
edebiliyoruz. Peki ClientIDMode için gelen seçenekler nelerdir?
AutoID: Herşey eskisi gibi devam eder.
Inherit: Bir üst kontrolde bu özellik nasıl ayarlanmış ise
aynısı alt kontrolde de geçerli olur.
Predictable: Eski
ID'lere benzeye fakat şekli şemali kontrol edilebilir ID yapıları
oluşturulmasını sağlar. Bu yapı daha fazla DataBound kontrollerin içi için
kullanılır.
Static: Söz konusu kontrolün sunucu tarafındaki
ID'si ne ise istemci tarafındaki da bire bir aynı olur. Bu noktada bir sayfa
içerisinde aynı ID'nin tekrar kullanılmaması sizin sorumluluğunuzdadır.
Özellikle Repeater gibi yapıların içinde kullanımı tehlikeli olabilir.
Static
Eğer herhangi bir kontrolün ClientIDMode'unu Static olarak ayarlarsanız
sunucu tarafındaki ID doğrudan istemciye gönderilecektir. Örneğin bir üstteki
Repeater içerisindeki Label'ın ClientIDMode özelliğini Static yaparsak
alacağımız sonuç aşağıdaki gibi olur.
[HTML]
<span id="lbl_UrunAdi">Örnek1</span>
<span id="lbl_UrunAdi">Örnek2</span>
<span id="lbl_UrunAdi">Örnek3</span>
<span id="lbl_UrunAdi">Örnek4</span>
<span id="lbl_UrunAdi">Örnek5</span>
<span id="lbl_UrunAdi">Örnek6</span>
<span id="lbl_UrunAdi">Örnek7</span>
<span id="lbl_UrunAdi">Örnek8</span>
<span id="lbl_UrunAdi">Örnek9</span>
<span id="lbl_UrunAdi">Örnek10</span>
Gördüğünüz gibi tüm Span tagları aynı ID özelliğine sahip. Bu durum tabi ki
tehlikeli çünkü bu durumda bir JavaScript ile bu kontrollerin hiçbirini
bulamayız. Zaten durum kurallara aykırı fakat yaptığımız hata basit.
Static modu kesinlikle DataBound kontrollerin içerisindeki kontrollerde
kullanılmamalı. DataBound kontroller hariç sayfada tekil kullandığınız
kontroller için rahatlıkla Static modunu kullanabilirsiniz.
Predictable
Databound kontrollerin içi için kullanılabilecek en anlamlı çözüm Predictable
modudur. Bu modda varsayılan ayarları ile ilk önce container elementin ismi
alınır sonra iç elementin ismi alınır ve en sona da Index numarası
yerleştirilir. Yine en üstteki Repeater örneğimizi ele alalım ve
Repeater'ın ClientIDMode özelliğini aşağıdaki gibi
Predictable şeklinde düzenleyelim.
[ASP.NET]
<asp:Repeater ID="Repeater1" runat="server"
ClientIDMode="Predictable">
<ItemTemplate>
<asp:Label ID="lbl_UrunAdi" runat="server" Text='<%# Eval("Adi") %>'></asp:Label>
</ItemTemplate>
</asp:Repeater>
Kodumuzu çalıştırdığımız aldığımız HTML sonucu aşağıdaki şekilde olacaktır.
<span id="Repeater1_lbl_UrunAdi_0">Örnek1</span>
<span id="Repeater1_lbl_UrunAdi_1">Örnek2</span>
<span id="Repeater1_lbl_UrunAdi_2">Örnek3</span>
<span id="Repeater1_lbl_UrunAdi_3">Örnek4</span>
Gördüğünüz gibi en azından bildiğim isimler kullanılmış ve ana repeater'in
isminin yanına label'ın ismi sonra da Index numarası yerleştirilmiş. Bu noktada
maalesef Repeater ve Label'a verdiğimiz isimlerin uzunlukları da önem kazanıyor.
Predictable modunda kullanabileceğiniz bir diğer özellik ise
ClientIDRowSuffix özelliği. Fakat maalesef bu özelliği sadece DataKey
koleysiyonları tutan kontrollerde kullanabilirsiniz. Örneğin bir GridView bunun
için uygun olacaktır.
[ASP.NET]
<asp:gridview id="BirGrid" runat="server" autogeneratecolumns="false"
clientidmode="Predictable"
clientidrowsuffix="ID">
<Columns>
<asp:TemplateField HeaderText="ID">
<ItemTemplate>
<asp:Label ID="lbl_Adi" runat="server" Text='<%# Eval("Adi") %>' />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:gridview>
Yukarıda gördüğünüz GridView'ın ClientIDRowSuffix özelliğine
ID değeri verilmiş. Böylece yaratılan ID'lerin sonunda artık Index numarası
değil doğrudan veritabanından gelen ID değeri yerleştirilecek.
[HTML]
<table cellspacing="0" rules="all" border="1" id="BirGrid" style="border-collapse: collapse;">
<tr>
<th scope="col">
ID
</th>
</tr>
<tr>
<td>
<span id="BirGrid_lbl_Adi_3">Örnek1</span>
</td>
</tr>
<tr>
<td>
<span id="BirGrid_lbl_Adi_4">Örnek2</span>
</td>
</tr>
<tr>
<td>
<span id="BirGrid_lbl_Adi_5">Örnek3</span>
</td>
</tr>
<tr>
<td>
<span id="BirGrid_lbl_Adi_6">Örnek4</span>
</td>
</tr>
Hemen kodumuzdaki Label'ların ID'lerine bakarsak Grid'in adını, sonra
Label'ın adını ve en sonunda da ID değerlerini görebiliyoruz. Malum ID
değerlerin kayıtların sırası ile aynı olmayabilirler. Bu gibi bir teknik ile
kontrollerin ID'leri set edildiğinde JavaScript ile veritabanından gelen
değerlere göre sayfada uygun kontrolleri bulmak da çok daha kolaylaşıyor.
Başka nasıl ayarlanır?
Eğer isterseniz ClientIDMode özelliğini projelerinde sayfa bazında veya
uygulama bazında da ayarlayabilirsiniz.
<%@ Page Language="VB" AutoEventWireup="false"
ClientIDMode="Static" CodeFile="Default.aspx.vb" Inherits="_Default" %>
Yukarıdaki şekli ile bir sayfada ClientIDMode ayarlamak tüm sayfa için
geçerli olmasını sağlayacaktır. Ayrıca uygulama bazında da Web.Config içerisinde
gerekli ayarı yapabilirsiniz.
<system.web>
<pages clientIdMode="Predictable"></pages>
</system.web>
Hepinize kolay gelsin.