SİTE
İÇİ ARAMA |
|
Blogroll |
|
|
|
DataGrid ve GridView Kontrollerinde Görünmez Kolonlar |
|
Gönderiliyor lütfen bekleyin... |
|
|
ASP.NET uygulamalarında, verileri tablo biçiminde görüntülerken, bazı kolonları
kullanıcılardan saklamak isteyebiliriz.Bu ihtiyacın birkaç sebebi
olabilir.Örneğin tablomuzun primary key kolonu, genelde programcının kullanacağı
bir değeri içerir ve kullanıcılar tarafından görülmesi tercih
edilmeyebilir.Benzer şekilde programcının, sayfadaki veritabanı işlemlerinde
kullanmak üzere tabloya aldığı; ancak kullanıcıların görmelerini istemediği
kolonlar olabilir. İşte bu gibi durumlarda akla ilk gelen yol, ilgili kolonun
visible özelliğine false atamaktır.
Web’te kullandığımız DataGrid ve GridView kontrolleri arasında,
görünmez kolonların ( visible özelliklerine false atanmış olan kolonlar ) işleyişi bakımından önemli farklar mevcuttur. Eğer
veritabanından gelen bilgi içerisinde, kullanıcılardan
saklamak istediğimiz kolonlar var ise her iki kontrol
(DataGrid ve GridView) için farklı şekilde düşünmemiz gerekir. Bu durum,
GridView kontrolünün görünmez kolonlara veri bağlamamasından kaynaklanır. Şimdi, isterseniz, bir web site projesi üzerinden ilerleyerek
problemi daha net görmeye ve çözüm yollarını incelemeye çalışalım.
Öncelikle yeni bir web site projesi açıp, sayfamızı aşağıdaki gibi oluşturalım.
Ben, yapacağımız örneklerde AdventureWorks veritabanını kullanacağım. Eğer
AdventureWorks sisteminizde bulunmuyor ve başka bir veritabanında
çalışıyorsanız, bağlantı ayarının yanı sıra HeaderText ve DataField
bildirimlerini de gelen veriye göre düzenlemeniz gerekir.
default.aspx |
<asp:TextBox ID="txtRowIndex"
runat="server" />
<asp:Button ID="btnGoruntule" runat="server" Text="Görüntüle"
OnClick="btnGoruntule_Click" />
<asp:SqlDataSource ID="dsProduct" runat="server"
ConnectionString="data
source=localhost;database=AdventureWorks;integrated security=SSPI"
SelectCommand="SELECT ProductID, Name, ListPrice, SellStartDate
FROM Production.Product">
</asp:SqlDataSource>
<asp:DataGrid ID="dgProducts" runat="server" AutoGenerateColumns="False"
OnItemDataBound="dgProducts_ItemDataBound" >
<Columns>
<asp:TemplateColumn HeaderText="RowIndex">
<ItemTemplate>
<asp:Label
ID="lblRowIndex" runat="server"></asp:Label>
<%-- Satır numalarını tutmak için faydalandığımız Label --%>
</ItemTemplate>
</asp:TemplateColumn>
<asp:BoundColumn HeaderText="ProductID"
DataField="ProductID" Visible="False" /> <%-- ProductID
kolonunu gizlemek istiyoruz --%>
<asp:BoundColumn HeaderText="Name"
DataField="Name" />
<asp:BoundColumn HeaderText="ListPrice"
DataField="ListPrice" />
<asp:BoundColumn HeaderText="SellStartDate"
DataField="SellStartDate" />
</Columns>
</asp:DataGrid> |
default.aspx.cs |
protected
void Page_Load(object sender, EventArgs e)
{
dgProducts.DataSource = dsProduct;
dgProducts.DataBind();
}
protected void btnGoruntule_Click(object sender, EventArgs e)
{
int satirSayisi=Convert.ToInt16(txtRowIndex.Text);
string gelenDeger = dgProducts.Items[satirSayisi].Cells[1].Text;
//İstenen satırın ProductID değeri
Response.Write(satirSayisi+" indeksli verinin ProductID
değeri:"+gelenDeger);
}
int index = 0;
protected void dgProducts_ItemDataBound(object sender, DataGridItemEventArgs
e)
{
//Template kolonumuzda satır numaralarını oluşturuyoruz
DataGridItem gelenSatir=e.Item;
try // e parametresiyle yakaladağımız satırın RowType özelliği
hataya sebep verecek bir değer içeriyorsa görmezden gel ( Header gibi )
{
Label lblIndex =
(Label)gelenSatir.Cells[0].FindControl("lblRowIndex");
lblIndex.Text = index.ToString();
index++;
} catch { }
} |
Sayfamızı oluşturduktan sonra çalıştırıp test
edelim.
Açılan sayfada TextBox içerisine tablodaki RowIndex’lerden birini yazıp
ProductID değerini elde edebiliyoruz. Yani erişilen kolonun görünür olup
olmaması herhangi bir sorun teşkil etmiyor.
Şimdi bir de GridView için, aynı işlemin ne gibi sonuçlar doğuracağını
görmek amacıyla projemize yeni bir web form ekleyip aşağıdaki gibi
tasarlayalım.
default2.aspx |
<asp:TextBox ID="txtRowIndex"
runat="server" />
<asp:Button ID="btnGoruntule" runat="server" Text="Görüntüle"
OnClick="btnGoruntule_Click" />
<asp:SqlDataSource ID="dsProduct" runat="server"
ConnectionString="data
source=localhost;database=AdventureWorks;integrated security=SSPI"
SelectCommand="SELECT ProductID, Name, ListPrice, SellStartDate
FROM Production.Product">
</asp:SqlDataSource>
<asp:GridView ID="gvProducts" runat="server" AutoGenerateColumns="false"
OnRowDataBound="gvProducts_RowDataBound">
<Columns>
<asp:TemplateField HeaderText="RowIndex">
<ItemTemplate>
<asp:Label
ID="lblRowIndex" runat="server" />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField HeaderText="ProductID"
DataField="ProductID" Visible="False" /> <%-- ProductID
kolonunu gizlemek istiyoruz --%>
<asp:BoundField HeaderText="Name"
DataField="Name" />
<asp:BoundField HeaderText="ListPrice"
DataField="ListPrice" />
<asp:BoundField HeaderText="SellStartDate"
DataField="SellStartDate" />
</Columns>
</asp:GridView> |
default2.aspx.cs |
protected
void Page_Load(object sender, EventArgs e)
{
gvProducts.DataSource = dsProduct;
gvProducts.DataBind();
}
protected void btnGoruntule_Click(object sender, EventArgs e)
{
int satirSayisi = Convert.ToInt16(txtRowIndex.Text);
string gelenDeger = gvProducts.Rows[satirSayisi].Cells[1].Text;
//İstenen satırın ProductID değeri
Response.Write(satirSayisi + " indeksli verinin ProductID değeri:"
+ gelenDeger);
}
int index = 0;
protected void gvProducts_RowDataBound(object sender, GridViewRowEventArgs
e)
{
//Template kolonumuzda satır numaralarını oluşturuyoruz
GridViewRow gelenSatir = e.Row;
try
{
Label lblIndex =
(Label)gelenSatir.Cells[0].FindControl("lblRowIndex");
lblIndex.Text = index.ToString();
index++;
} catch { }
} |
Default2.aspx sayfasını çalıştırıp, herhangi
bir satırın ProductID değerini elde etmeye çalışalım.
Gördüğünüz gibi, istediğimiz sonucu alamamıza rağmen, çalışma zamanında bir
istisnayla ( exception ) karşılaşmıyoruz. Başka bir deyişle, gizlenmiş ProductID
kolonu bize değer olarak boş bir string ifadesi döndürüyor.
Peki sebep nedir?
Her şey güvenlik için
DataGrid kullandığımızda,kolonun visible özelliğinin true ya da false
olduğuna bakılmaksızın veri bağlanıyor ve bu bilgi ViewState içerisinde yerini
alıyor.Eğer ihtiyacımız olan şey tablodaki bir kolonu kullanıcılardan
saklamaksa, tahmin edersiniz ki, bu pek güvenli bir yöntem değildir.ViewState
bilgisi enkript edilmediğinde istemciler tarafından okunur formatta elde
edilebilir.Bu da sayfamız için önemli bir güvenlik açığıdır.İşte bu yüzden,
ASP.NET 2.0 ile birlikte gelen GridView kontrolünde, gizlenmek istenen
kolonların korunumu adına alınmış bazı önlemler vardır.Yaptığımız örnekte
yaşadığımız problem de, aslında, görünmeyen kolonlara veri bağlanmamasından kaynaklanmaktadır.Öyleyse
GridView’de bir kolonu görünmez yapamıyorsak, gizlemek istediğimiz bir kolon
olursa nasıl bir yol izleyebiliriz?Bu amaçla GridView kontrolü içerisinde yer alan DataKeys
özelliğinden faydalanacağız.
|
ViewState bilgisi her ne kadar okunamaz görünse de, Base64 encoding yapılarak elde edilmiş basit bir değerdir ve çeşitli araçlarla okunur hale getirilmesi oldukça basittir.Bu yüzden ViewState içerisinde kredi kartı bilgisi gibi önem arz eden verileri saklamak çok tehlikeli sonuçlar doğurabilir. |
DataKeys kullanımı
Default2.aspx sayfamızı aşağıdaki gibi değiştirelim.
default2.aspx |
<asp:TextBox ID="txtRowIndex"
runat="server" />
<asp:Button ID="btnGoruntule" runat="server" Text="Görüntüle"
OnClick="btnGoruntule_Click" />
<asp:SqlDataSource ID="dsProduct" runat="server"
ConnectionString="data
source=localhost;database=AdventureWorks;integrated security=SSPI"
SelectCommand="SELECT ProductID, Name, ListPrice, SellStartDate
FROM Production.Product">
</asp:SqlDataSource>
<asp:GridView ID="gvProducts" runat="server" AutoGenerateColumns="false"
OnRowDataBound="gvProducts_RowDataBound" DataKeyNames="ProductID" >
<Columns>
<asp:TemplateField HeaderText="RowIndex">
<ItemTemplate>
<asp:Label
ID="lblRowIndex" runat="server" />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField HeaderText="Name"
DataField="Name" />
<asp:BoundField HeaderText="ListPrice"
DataField="ListPrice" />
<asp:BoundField HeaderText="SellStartDate"
DataField="SellStartDate" />
</Columns>
</asp:GridView> |
Farkettiyseniz,DataKeyNames özelliğine ProductID değerini atadıktan sonra
GridView’e bağladığımız kolonlar arasından ProductID’yi çıkarıyoruz.Aslında
çıkarıp çıkarmamazın bir önemi yok.Daha önce dediğimiz gibi GridView
içerisindeki görünmez kolonlara veri bağlanmıyor.Biz DataKeyNames özelliğini
kullanarak ilgili verilerin DataKeys koleksiyonunda tutulacağını
söylüyoruz.Dolayısıyla veriye bu özellik yardımıyla ulaşacağımız için ayrıca
bir kolon eklenmesine gerek kalmıyor. Ardından kod tarafına geçip, DataKeys özelliği
yardımıyla ProductID değerlerine erişelim.
default2.aspx.cs |
protected
void Page_Load(object sender, EventArgs e)
{
gvProducts.DataSource = dsProduct;
gvProducts.DataBind();
}
protected void btnGoruntule_Click(object sender, EventArgs e)
{
int satirSayisi = Convert.ToInt16(txtRowIndex.Text);
string gelenDeger =
gvProducts.DataKeys[satirSayisi].Value.ToString(); //İstenen satırın
ProductID değeri
Response.Write(satirSayisi + " indeksli verinin ProductID değeri:"
+ gelenDeger);
}
int index = 0;
protected void gvProducts_RowDataBound(object sender, GridViewRowEventArgs
e)
{
//Template kolonumuzda satır numaralarını oluşturuyoruz
GridViewRow gelenSatir = e.Row;
try
{
Label lblIndex =
(Label)gelenSatir.Cells[0].FindControl("lblRowIndex");
lblIndex.Text = index.ToString();
index++;
} catch { }
} |
Artık default2.aspx sayfamızı çalıştırdığımızda,
istenen satırın ProductID değerini elde edebildiğimizi görüyoruz.
Yaptığımız tek şey, gizlemek istediğimiz kolonu DataKeyNames özelliğinde
belirtmektir. Bundan sonra, DataKeys içerisindeki Key tipinden nesnelere
erişebiliyor ve ProductID değerlerini elde edebiliyoruz. ( Value özelliği
aracılığıyla )
Gelelim bu yöntemi daha güvenli kılan şeyin ne olduğuna. GridView’de bir kolonu
gizlediğinizde, bu verinin, korunması gereken bir veri olduğu kabul edilir.
Ancak kolona bağlanan veri, ViewState ile birlikte istemcilere okunur formatta (
enkript edilmemişse ) ulaşacağından; GridView, programcıyı DataKeys kullanmaya
zorlar.Çünkü biz DataKeyNames özelliğine değer atadığımızda, farkında olmadan
ViewState ve ControlState’in enkript
edileceğini de söylemiş oluyoruz ve böylece içeriğin korunumu sağlanıyor.
ASP.NET 2.0’la gelen bu yenilik güvenlik açısından faydalı görünüyor; ancak,
tahmin edersiniz ki,
DataKeyNames kullanmak, performans kaybına ve sayfa boyutunun artmasına
neden oluyor.Eğer performans kaygınız varsa ve DataKey değerlerinin
istemcilere açık şekilde gitmesi bir sorun yaratmıyorsa,enkript işlemini
engelleyerek belli bir performans artışı sağlayabilirsiniz.Bunun için
web.config içerisinden system.web altındaki pages tagının
viewStateEncryptionMode özelliğine "Never" değerini atamak gerekir. (
Varsayılan değeri "Auto" olduğu için - herhangi bir ayar yapmadıysanız -
DataKeyNames’e değer atadığınızda ViewState mutlaka enkript edilir. )
<pages viewStateEncryptionMode="Never" /> |
|
DataKeys, ControlState içerisinde tutulur. |
DataKeyNames, DataKeyField
özelliğine benzer olup, önemli bir farkı çoklu kolon kullanımına izin
vermesidir.Bunu nasıl yapacağımızı görmek amacıyla bir web form daha yaratalım ve sayfaya aşağıdaki kodu ekleyelim.
default3.aspx |
<asp:TextBox ID="txtRowIndex" runat="server" />
<asp:Button ID="btnGoruntule" runat="server" Text="Görüntüle"
OnClick="btnGoruntule_Click" />
<asp:SqlDataSource ID="dsProduct" runat="server"
ConnectionString="data
source=localhost;database=AdventureWorks;integrated security=SSPI"
SelectCommand="SELECT ProductID, Name, ListPrice, SellStartDate
FROM Production.Product">
</asp:SqlDataSource>
<asp:GridView ID="gvProducts" runat="server" AutoGenerateColumns="false"
OnRowDataBound="gvProducts_RowDataBound"
DataKeyNames="ProductID,Name" >
<Columns>
<asp:TemplateField HeaderText="RowIndex">
<ItemTemplate>
<asp:Label
ID="lblRowIndex" runat="server" />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField HeaderText="ListPrice"
DataField="ListPrice" />
<asp:BoundField HeaderText="SellStartDate"
DataField="SellStartDate" />
</Columns>
</asp:GridView> |
default3.aspx.cs |
protected
void Page_Load(object sender, EventArgs e)
{
gvProducts.DataSource = dsProduct;
gvProducts.DataBind();
}
protected void btnGoruntule_Click(object sender, EventArgs e)
{
int satirSayisi = Convert.ToInt16(txtRowIndex.Text);
string gelenProductID =
gvProducts.DataKeys[satirSayisi].Values[0].ToString(); //İstenen
satırın ProductID değeri
string gelenName =
gvProducts.DataKeys[satirSayisi].Values[1].ToString(); //İstenen
satırın Name değeri
Response.Write(satirSayisi + " indeksli verinin ProductID değeri:"
+ gelenProductID + "<br>");
Response.Write(satirSayisi + " indeksli verinin Name değeri:" +
gelenName);
}
int index = 0;
protected void gvProducts_RowDataBound(object sender, GridViewRowEventArgs
e)
{
//Template kolonumuzda satır numaralarını oluşturuyoruz
GridViewRow gelenSatir = e.Row;
try
{
Label lblIndex =
(Label)gelenSatir.Cells[0].FindControl("lblRowIndex");
lblIndex.Text = index.ToString();
index++;
} catch { }
} |
DataKeyNames’e değer atarken, kullanmak
istediğimiz kolonları virgülle ayırarak belirtebiliyoruz.Böylece birden fazla
kolon da DataKeys içerisinde tutulabiliyor.
TemplateField kullanımı
GridView’de visible özelliği false olan kolonlara veri bağlanmadığını
biliyoruz.Fakat bu kolon bir TemplateField olursa,içerisine koyacağımız bir
kontrolü veriyi elde etmek amacıyla kullanabiliriz.
Öyleyse projemize yeni bir web form ekleyerek, TemplateField kullanımını incelemeye çalışalım.
default4.aspx |
<asp:TextBox ID="txtRowIndex" runat="server" />
<asp:Button ID="btnGoruntule" runat="server" Text="Görüntüle"
OnClick="btnGoruntule_Click" />
<asp:SqlDataSource ID="dsProduct" runat="server"
ConnectionString="data
source=localhost;database=AdventureWorks;integrated security=SSPI"
SelectCommand="SELECT ProductID, Name, ListPrice, SellStartDate
FROM Production.Product">
</asp:SqlDataSource>
<asp:GridView ID="gvProducts" runat="server" AutoGenerateColumns="false"
OnRowDataBound="gvProducts_RowDataBound">
<Columns>
<asp:TemplateField HeaderText="RowIndex">
<ItemTemplate>
<asp:Label
ID="lblRowIndex" runat="server" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="ProductID"
Visible="false"> <%-- ProductID kolonu için bir TemplateField
tanımlayıp,visible özelliğine false atıyoruz. --%>
<ItemTemplate>
<asp:Label
ID="lblProductID" runat="server" Text=’<%# Eval("ProductID") %>’ /> <%-- ProductID kolonundan gelen veriyi, TemplateField’imizin
içerisindeki Label’ın Text özelliğine Eval metodu ile
bağlıyoruz--%>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField HeaderText="Name"
DataField="Name" />
<asp:BoundField HeaderText="ListPrice"
DataField="ListPrice" />
<asp:BoundField HeaderText="SellStartDate"
DataField="SellStartDate" />
</Columns>
</asp:GridView> |
default4.aspx.cs |
protected
void Page_Load(object sender, EventArgs e)
{
gvProducts.DataSource = dsProduct;
gvProducts.DataBind();
}
protected void btnGoruntule_Click(object sender, EventArgs e)
{
int satirSayisi = Convert.ToInt16(txtRowIndex.Text);
Label lblProductID
=(Label)gvProducts.Rows[satirSayisi].Cells[1].FindControl("lblProductID");
string gelenDeger = lblProductID.Text;
Response.Write(satirSayisi + " indeksli verinin ProductID değeri:"
+ gelenDeger);
}
int index = 0;
protected void gvProducts_RowDataBound(object sender, GridViewRowEventArgs
e)
{
//Template kolonumuzda satır numaralarını oluşturuyoruz
GridViewRow gelenSatir = e.Row;
try
{
Label lblIndex =
(Label)gelenSatir.Cells[0].FindControl("lblRowIndex");
lblIndex.Text = index.ToString();
index++;
} catch { }
} |
Default4.aspx dosyasını çalıştıralım.
Gördüğünüz üzere, TemplateField kolonumuzun içerisindeki Label kontrolümüze
erişebiliyoruz ve bunu kolonun gizlenmiş olmasına rağmen yapabiliyoruz. Yalnız
burada DataKeyNames özelliğine değer atamadığımız için herhangi bir enkript
işlemi gerçekleşmiyor.Bu sebeple, eğer korumak istediğiniz bir veri söz
konusuysa DataKeyNames kullanmak gerekir.Doğru bir kod tasarımı için de
kullanılması gereken yol budur.
Böylece bir makalenin daha sonuna gelmiş bulunuyoruz.Bir dahaki makalede
görüşmek üzere,hoşçakalın...
Cenk Özdemir
[email protected]
Makale:
DataGrid ve GridView Kontrollerinde Görünmez Kolonlar ASP.NET Cenk Özdemir
|
|
|
-
-
Eklenen Son 10
-
Bu Konuda Geçmiş 10
Bu Konuda Yazılmış Yazılmış 10 Makale Yükleniyor
Son Eklenen 10 Makale Yükleniyor
Bu Konuda Yazılmış Geçmiş Makaleler Yükleniyor
|
|
|