13 Nisan 2008

SQL Sorgusuna Tablo Adını Parametre Olarak Aktarmak

Web uygulamalarında en çok saldırı alabileceğimiz yerler veritabanı üzerinde çalıştırdığımız SQL sorgularımızdır. SQL Injection adı verilen teknik ile kötü niyetli kullanıcılar arka planda çalıştırdığımız SQL sorgularına ek SQL cümleleri ekleyebilmekte ve yeri geldiğinde "DROP DATABASE ..." gibi bir sorgu ile tüm veritabanını bile silebilmektedir! Gerek SQL Server ortamında hazırladığımız stored procedure'larda, gerekse uygulama tarafında kullandığımız ADO.NET nesnelerinde parametre (parameter) kullanarak bu tip tehditlerden veritabanımızı koruyabilmekteyiz. Parametreler SQL cümlelerinde sadece sütunlarda aranacak değerleri taşıyabilmekte, tablo veya sütun isimlerini ise taşıyamamaktadır. "Select * From Haberler Where HaberID=@id" gibi bir SQL cümlesinde HaberID sütununda aranacak değer parametre olarak aktarılabilir. Peki SQL cümlesine tablo adını parametre olarak aktarmak gibi bir durumda nasıl bir yolu izleyebiliriz? Yani "Select * From @TabloIsim" gibi bir SQL cümlesi yazabilsek ve parametre olarak Haberler bilgisini yolladığımızda sorgumuz Haberler tablosundaki, Duyurular bilgisini yolladığımızda da Duyurular tablosundaki tüm verileri getirse...


Tablo adını parametre olarak aktarma şansımız sadece stored procedure kullanma durumunda bulunmaktadır. Tabi ki sp içerisinde standart bir cümle yazmak yerine ufak bir hile ile bu işlemi gerçekleştirebileceğiz. Eğer sp içinde SQL cümlemizi bir değişkende saklayıp, alınan parametre değerini cümlemize eklersek tablo adını cümlemiz içerisine aktarabiliriz. Tabi ki cümle bir değişkende saklandığı için sp içerisinde bu cümleyi çalıştırmak ta gerekecektir. Aşağıda tablo adını parametre olarak alan basit bir stored procedure görülmektedir.

CREATE PROC TabloKayitlar
@tablo_isim nvarchar(30)
AS
BEGIN
   DECLARE @sql_str nvarchar(50)
   SET @sql_str = 'Select * From ' + @tablo_isim
   EXEC(@sql_str)
END

08 Nisan 2008

Accordion Kontrolünde Veritabanı ile Çalışmak

Bir önceki yazımda Accordion kontrolünün CSS ile kullanımından bahsetmiştim. Accordion kontrolünün içeriğini statik içerikle HTML kodları ile oluşturabileceğimiz gibi dinamik verilerle de oluşturabiliriz. Bir XML dosyasından, veritabanından veya koleksiyon gibi nesnelerden alınan veriler bu kontrole kolaylıkla yüklenebilir. Bu yazımda Accordion kontrolünü veritabanından alınan verilerle nasıl besleyebileceğimize bakıyoruz.

Accordion kontrolünde dinamik veri ile çalışmak Repeater ve DataList gibi kontrolleriyle benzerlik göstermektedir. Eğer SqlDataSource, XmlDataSource gibi veri kaynakları ile çalışırsak sayfada bağlanacak veri kaynağını belirtmek yeterli olmayacak, HTML kısmından Eval veya Bind metotlarıyla veri yükleme işlemini de gerçekleştirmemiz gerekecektir. HTML koduna istediğimiz gibi müdahale edebildiğimiz için aslında olumlu bir durum olduğunu belirtmekte fayda var. Yine programatik yollarla DataTable, DataSet veya koleksiyon nesneleri ile Accordion kontrolünün çalışmasını sağlayabiliriz. Dilerseniz iki ayrı örnekte bu iki farklı yolu nasıl uygulayabileceğimizi görelim.

DataSource Kontrolleri ile Çalışmak
Veriyi en kolay şekilde bağlayacağımız bu yolda sayfamızdaki DataSource nesnesini Accordion kontrolünün DataSourceID özelliğinde belirlememiz gerekecektir. Accordion kontrolünün ise HeaderTemplate ve ContentTemplate kısımlarında yüklenecek verilerin başlık ve içerik bilgilerini Eval metodu ile bağlıyor olacağız. Access'te oluşturulmuş bir veritabanında saklanan haberlerin listeleneceği sayfada Accordion kontrolü ile çalışmak aşağıdaki kodlardan da görüleceği gibi oldukça kolay!

<ajaxToolkit:Accordion ID="accHaberler" runat="server" HeaderCssClass="baslik" HeaderSelectedCssClass="secilenBaslik" ContentCssClass="icerik" DataSourceID="dsHaberler" Width="460">
<HeaderTemplate>
<%#Eval("Baslik") %>
</HeaderTemplate>
<ContentTemplate>
<%#Eval("Icerik") %><br />
Eklendiği tarih: <%#Eval("Tarih") %>
</ContentTemplate>
</ajaxToolkit:Accordion>
<asp:AccessDataSource ID="dsHaberler" runat="server" DataFile="~/App_Data/Site.mdb" SelectCommand="SELECT [Baslik], [Icerik], [Tarih] FROM [Haberler] ORDER BY [Tarih] DESC"> </asp:AccessDataSource>

Template alanları içerisine açılmış ASP etiketleri ile veri yükleme işlemini gerçekleştiriyoruz. HTML kodlarını istediğimiz şekilde değiştirebilme kolaylığı belki de bu yolun en önemli avantajı.

DataTable vb. Nesneler ile Çalışmak
Bazı durumlarda ise Accordion kontrolüne DataTable gibi veri nesneleri ile veri yüklemek isteyebiliriz. Programatik yollarla yapacağımız bu işlemlerde HTML tarafında müdahale şansımız daha zor olsa da programın ve verilerin akışını istediğimiz gibi değiştirebilme şansına sahip olabiliyoruz. Bu yöntemde bir döngü içerisinde AccordionPane nesneleri oluşturarak AccordionPane'in HeaderContainer ve ContentContainer'larındaki Controls koleksiyonuna kontroller ekleyebiliriz. Sunucu tarafında performans açısından Label gibi bir kontrol yerine LiteralControl kullanmak iyi bir pratik olacaktır. Aşağıda böyle bir işlemi nasıl yapabileceğimiz görülmektedir. Sayfamızın HTML kısmına eklenmiş accHaberler adında bir Accordion kontrolünü daha önceden eklediğimizi hatırlatayım.

...
using System.Data.OleDb; // Access veritabanına bağlanmak için
using AjaxControlToolkit; // AccordionPane kontrolüne erişmek için

public partial class Haberler : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string yol = Server.MapPath("App_Data/Site.mdb");

OleDbConnection con = new OleDbConnection("Provider=Microsoft.Jet.OleDB.4.0; Data Source=" + yol);
OleDbDataAdapter daHaberler = new OleDbDataAdapter("Select Baslik, Icerik, Tarih From Haberler Order By Tarih Desc", con);
DataTable dtHaberler = new DataTable();
daHaberler.Fill(dtHaberler);
foreach (DataRow dr in dtHaberler.Rows)
{
AccordionPane paneHaber = new AccordionPane();
paneHaber.HeaderContainer.Controls.Add(
new LiteralControl(dr["Baslik"].ToString()));
paneHaber.ContentContainer.Controls.Add(
new LiteralControl(dr["Icerik"].ToString()));
paneHaber.ContentContainer.Controls.Add(
new LiteralControl("<br>"));
paneHaber.ContentContainer.Controls.Add(
new LiteralControl("Ekleme tarihi: " + dr["Tarih"].ToString()));
accHaberler.Panes.Add(paneHaber);
// Oluşan AccordionPane'i Accordion kontrolüne ekliyoruz.
}
}
}

Görüldüğü gibi bir foreach döngüsü içinde DataTable'ın her satırı bir AccordionPane kontrolünün içeriğini oluşturmakta ve AccordionPane kontrolü de Accordion'un Panes koleksiyonuna eklenmektedir. Sayfayı çalıştırdığımızda her iki örnektede veritabanından getirilen verilerin Accordion kontrolüne yüklendiğini görebiliriz. Kontrolümüzü hazırladığımız imajlar ve CSS ile kullandığımızda göze hoş gelen bir tasarım elde edebiliriz. Aşağıda Accordion kontrolünün son hali görülmektedir.

AJAX Control Toolkit - Accordion Kontrolünde Veritabanı ile Çalışmak

05 Nisan 2008

Accordion'un CSS ile Etkin Kullanımı

AJAX Control Toolkit ile gelen en kullanışlı kontrollerden birisi Accordion kontrolüdür. Web sayfalarının genellikle Sık Sorulan Sorular veya Yardım gibi bölümlerinde sıra sıra dizilmiş başlıklar bulunur ve kullanıcı hangi başlığa tıklarsa dinamik olarak o maddenin altındaki içerik görünür hale gelir. Diğer başlıkların içerikleri ise saklı durumda bulunur. Aslında uzun içeriklerin listeleneceği web sayfalarında hem kaplayacağı az alan açısından hem de görsel olarak sayfamızı daha kullanışlı hale getirecek bir kontrol Accordion. Başlık ve içerik olarak iki ana kısımdan oluşan AccordionPane'leri taşıyan Accordion kontrolünü CSS kullanarak zengin ve göze hoş gelen tasarımlar ortaya çıkarabiliriz. Accordion'un HeaderCssClass, HeaderSelectedCssClass ve ContentCssClass özelliklerinde önceden hazırladığımız CSS sınıfları (class) tanımlayarak bu işlemleri basit halde gerçekleştirebiliriz. Hazırladığım basit bir örnekle önce CSS tanımlamalarını, ardından da sayfamızdaki Accordion kontrolünü nasıl tanımlayacağımıza bakalım.

Projemize ekleyeceğimiz style.css dosyasında başlık, seçilen maddenin başlığı ve içerik kısımlarının nasıl görüntüleneceğini belirliyorum. Göze hoş gelmesi için bir grafik programında hazırladığım gradient geçişleri olan 3 tane gif dosyasını bu alanların zeminlerinde kullanıyorum.

style.css
.baslik {
   font-size: 13px; font-family: Verdana; font-weight: bold; height:18px;
   text-indent: 5px; padding: 1px; margin-top: 1px; cursor: pointer;
   border-right: #ffcd70 1px solid; border-top: #ffcd70 1px solid;
   border-left: #ffcd70 1px solid; border-bottom: #ffcd70 1px solid;
   background-image: url(images/baslik_zemin.gif);
   background-position: top; background-repeat: repeat-x;
}

.secilenBaslik
{
   font-size: 13px; font-family: Verdana; font-weight: bold; height:18px;
   text-indent: 5px; padding: 1px; margin-top: 1px;
   border-right: #ffcd70 1px solid; border-top: #ffcd70 1px solid;
   border-left: #ffcd70 1px solid; border-bottom: #ffcd70 1px solid;
   background-image: url(images/secilen_baslik_zemin.gif);
   background-position: top; background-repeat: repeat-x;
}

.icerik {
   font-size: 11px; font-family: Verdana; padding: 5px;
   border-right: #ffcd70 1px solid; border-top: none;
   border-left: #ffcd70 1px solid; border-bottom: #ffcd70 1px solid;
   background-image: url(images/icerik_zemin.gif);
   background-position: left; background-repeat: repeat-y;
}

Açık olmayan başlıkların üzerine gelindiğinde farenin simgesini değiştirmek için başlık sınıfında cursor: pointer tanımlamasını yapmak daha güzel olacaktır. Gelelim sayfamızın tasarımına. CSS dosyamıza link vereceğimiz bir aspx dosyasında Accordion'un yukarıda belirttiğimiz özelliklerini CSS dosyasında tanımladığımız sınıflarla dolduruyoruz. Geriye kalan tek şey ise AccordionPane'lerin başlık ve içeriklerin doldurmak olacaktır.

Default.aspx
<head runat="server">
<title>Accordion'un CSS ile Etkin Kullanımı</title>
<link href="style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<form id="form1" runat="server">
<ajaxToolkit:ToolkitScriptManager ID="ScriptManager1" runat="server" />
<ajaxToolkit:Accordion ID="Accordion1" runat="server" HeaderCssClass="baslik"
HeaderSelectedCssClass="secilenBaslik" ContentCssClass="icerik"
Width="185">
   <Panes>
      <ajaxToolkit:AccordionPane ID="pane1" runat="server">
         <Header>Başlık-1</Header>
         <Content>İçerik-1</Content>
      </ajaxToolkit:AccordionPane>
      <ajaxToolkit:AccordionPane ID="pane2" runat="server">
         <Header>Başlık-2</Header>
         <Content>İçerik-2</Content>
      </ajaxToolkit:AccordionPane>
      <ajaxToolkit:AccordionPane ID="pane3" runat="server">
         <Header>Başlık-3</Header>
         <Content>İçerik-3</Content>
      </ajaxToolkit:AccordionPane>
   </Panes>
</ajaxToolkit:Accordion>
</form>
</body>


Sayfayı çalıştırdığımızda Accordion kontrolünün görünümü yandaki gibi olacaktır. Burada Accordion panelerinin genişlik ve yüksekliklerine göre zemin resimlerini hazırlamamız görünümün düzgün olmasındaki en önemli etkenlerden biri olacaktır.