Professional Documents
Culture Documents
NET
ASP.NET AJAX
ADO.NET
Makaleleri
Uğur UMUTLUOĞLU
www ww
w..uum muuttlluuoogglluu..ccoomm
hhttttpp::////uum
muuttlluuoogglluu..bbllooggssppoott..ccoom
m
uugguurr..uum muuttlluuoogglluu@
@nneettrroonn..ccoom m..ttrr
1
İçindekiler
Önsöz ................................................................................................................................... 3
ASP.NET............................................................................................................................... 4
ASP.NET Web Site Administration Tool ............................................................................ 5
HttpBrowserCapabilities ile Tarayõcõ Bilgilerine Ulaşmak ................................................... 8
AdRotator ile Reklam Yönetim Sistemi Geliştirmek.......................................................... 12
View State ile Durum Yönetimi ........................................................................................ 19
ASP.NET 2.0 - Sayfa Direktifleri (Page Directives) .......................................................... 29
ASP.NET 2.0 - Performans Yönetimindeki Yenilikler ....................................................... 38
GridView'e Programatik Veri Bağlamada Sayfalama ve Sõralama İşlemleri..................... 49
GridView Kayõtlarõnõ Okumak ve Metin Dosyasõna Aktarmak........................................... 54
GridView'deki Kayõtlarõ Excel Dosyasõna Aktarmak.......................................................... 61
ASP.NET 3.5 ile Gelen Yenilikler..................................................................................... 67
TreeView'da Veritabanõyla ve XML Dosyalarla Çalõşmak................................................. 74
Site Navigasyonu Hakkõnda Bilinmeyenler....................................................................... 84
TreeView Kontrolüne Kullanõcõ İsteğine Göre Veri Ekleme .............................................. 97
Diğer Konular....................................................................................................................140
Excel Dosyasõndaki Bilgilere Ulaşmak ............................................................................141
Datatable ile Sõralama ve Filtreleme İşlemleri .................................................................145
Adõm Adõm Team Foundation Server Single-Server Kurulumu .......................................154
2
Önsöz
Bu e-kitapta ASP.NET, ASP.NET AJAX ve ADO.NET gibi .NET teknolojileri ile ilgili yazmõş
olduğum makaleleri topluca bulabilirsiniz. Şimdilik üç ayrõ kategoride yer alan makaleler,
İçindekiler kõsmõnda yazõm tarihlerine göre sõralanmõştõr. Yine her kategorinin başlangõcõnda,
o kategoride yer alan makaleler ile ilgili anahtar kelimeler yer almaktadõr.
Uğur UMUTLUOĞLU
3
ASP.NET
Anahtar kelimeler
4
ASP.NET Web Site Administration Tool
16 Mart 2006
Bu makalede sizlere Visual Studio 2005 ile gelen ve ASP .NET uygulamalarõnda
kullanabileceğimiz yeniliklerden birisi olan Web Site Administration Tool'u anlatmaya
çalõşacağõm.
Web Site Administration Tool'un aslõnda bize çok büyük yenilikler getirmediğini, ancak
uygulamamõzda yapacağõmõz bazõ işlemleri hõzlõ, pratik ve derli toplu yapmamõzõ sağlayan bir
araç olduğunu söyleyerek başlayalõm. Bildiğiniz gibi ASP .NET ile birlikte gelen web.config
dosyasõnda yaptõğõmõz ayarlarõ uygulamamõzõn genelinde kullanarak işimizi bir noktadan,
daha az kod yazarak, hõzlõ ve güvenli bir şekilde yapabiliyorduk. web.config ile birlikte daha
hõzlõ yaptõğõmõz bu işlemleri, Web Site Administration Tool ile hiç kod yazmadan, özel
dizinlerde elle web.config dosyalarõ oluşturmadan çok daha hõzlõ bir şekilde yapabiliyoruz.
Aslõnda bu aracõn temel mantõğõ da bu. Sizin web.config dosyalarõnda XML tabanlõ kodlarõ
yazarak yapmanõz gereken ayarlarõ, bir web arayüzüyle kolay ve pratik bir şekilde yapmanõzõ
sağlamak.
Web Site Administration Tool'u açmadan önce önemli sayõlabilecek bir noktayõ belirtmek
istiyorum. Solution Explorer'dan uygulamamõzõn içerisinde yer alan App_Data klasörüne
bakacak olursak, bu klasörün altõnda herhangi bir dosya olmadõğõnõ göreceğiz. Tabii ki az
sonra buraya bazõ dosyalar gelecek. Web Site Administration Tool'a Visual Studio 2005'e
yeni eklenen bir menü olan Website menüsünün altõndaki ASP .NET Configuration'dan
ulaşabildiğimiz gibi Solution Explorer penceresinin en sağõndaki ASP .NET Configuration
kutucuğuna tõklayarakta ulaşabiliyoruz. ASP .NET Development Server aktif hale geliyor,
tarayõcõmõzda yeni bir pencere açõlõyor ve resimdeki gibi bir sayfayla karşõlaşõyoruz.
Security linkinden
- Authentication modunu değiştirebilir
5
- Kullanõcõ oluşturabilir ve yönetebilir
- Rol oluşturabilir ve yönetebilir
- Kullanõcõlarõ rollerle ilişkilendirebilir
- Rollerin dizinlere erişim haklarõnõ yönetebilirsiniz.
Application linkinden
- Uygulama genelinde kullanõlabilecek (web.config de tutulacak) değerleri oluşturabilir ve
yönetebilir
- Uygulamada e-posta göndermek için gerekli olan SMTP ayarlarõnõ yönetebilir
- Hata sayfalarõ ayarlarõ yapõlabilir
- Debugging ve tracing işlemleri ile ilgili ayarlarõ yapabilirsiniz.
Provider linkinden
- Uygulamanõzda kullanacağõnõz data sağlayõcõsõ ile ilgili ayarlarõ yapabilir
- Membership ve role sağlayõcõlar için farklõ data sağlayõcõsõ belirleyebilirsiniz.
Kullanõmõnda çok zorluk çekilmeyecek, basit ve kullanõşlõ bir araç. İsterseniz bu aracõ
kullanarak sitemizde kullanõcõlar ve roller oluşturalõm, bunlarõ aralarõnda ilişkilendirelim ve
rollerin dizine erişim haklarõnõ ayarlayõp web.config dosyalarõnda ne gibi değişiklikler
olduğunu gözlemleyelim.
Son olarakta oluşturduğumuz bir rolün yada kullanõcõnõn uygulamamõzdaki bir dizine erişim
haklarõnõ yapõlandõralõm. Örneğin ben uygulamamda varolan Editor klasörüne sadece editor
olarak tanõmladõğõm kullanõcõlarõn erişebilmesini istiyorum. Access Rules'tan Create access
rules seçeneğini tõklõyorum. Sol kõsõmdaki dosya yapõsõndan Editor klasörünü seçip,
6
rollerden editorü seçiyorum ve izinlerden de Allow seçeneğini seçiyorum ve OK diyorum.
Daha sonradan da diğer kullanõcõlarõn bu dizine erişimini engellemek için yine aynõ sayfadan
Anonymous users'a Deny iznini veriyorum. Artõk Editor klasörüme sadece editor rolünü
almõş kullanõcõlarõm erişebilecekler.
7
HttpBrowserCapabilities ile Tarayõcõ Bilgilerine
Ulaşmak
25 Nisan 2007
Web sayfamõza bağlanan istemcilerin kullandõklarõ tarayõcõlarõn (web browser) tipi, versiyonu,
eklentileri, özellikleri farklõ olabilmekte ve bu farklõlõklar bazõ durumlarda sorunlar
oluşturabilmektedir. Örneğin bir tarayõcõda düzgün ve sorunsuz görüntülenen bir sayfa, başka
bir tarayõcõda hatalõ olarak görüntülenebilmektedir. Bu noktada uygulama geliştirilirken
tarayõcõ bazlõ olarak bazõ kontrollerin yapõlmasõ ve buna göre de istemciye uygun içeriklerin
gönderilmesi gerekebilir.
Bir web uygulamasõ geliştirilirken, bazõ durumlarda istemcinin tarayõcõsõ hakkõnda bilgiler elde
etmek ve bu bilgiler doğrultusunda işlemler yapõlmak istenilebilir. ASP.NET web
uygulamalarõnda bu tip işlemleri kolay bir şekilde yapmamõzõ sağlayan
HttpBrowserCapabilities sõnõfõ bulunmaktadõr. HttpBrowserCapabilities sõnõfõndan
oluşturacağõmõz bir nesne örneği ile sayfamõza bağlanan ziyaretçinin kullandõğõ tarayõcõ ile
ilgili bilgilere erişebilir ve bu bilgilere göre farklõ sayfalara yönlendirme yapmak, farklõ içerikler
görüntülemek gibi işlemler yapabiliriz. Yine sitemize bağlanan ziyaretçilerin tarayõcõlarõnõn
istatistiklerini veritabanõnda tutmak için de bu sõnõfõ etkili bir şekilde kullanabiliriz.
8
İstemcide kurulu olan .NET Framework sürümünü getirir. (string değere
ClrVersion
dönüştürülerek kullanõlabilir)
Tarayõcõnõn cookie desteği olup olmadõğõnõ verir. (bool tipinde değer
Cookies
döndürür)
Bağlanan tarayõcõnõn crawler (Google, Yahoo gibi site indeksleyicileri)
Crawler
olup olmadõğõnõ verir. (bool tipinde değer döndürür)
Tarayõcõnõn desteklediği ECMA script versiyonunu verir. (string değere
EcmaScriptVersion
dönüştürülerek kullanõlabilir)
Tarayõcõnõn HTML frame desteği olup olmadõğõnõ verir. (bool tipinde
Frames
değer döndürür)
Tarayõcõnõn mobil bir cihaz üzerinde çalõşan tarayõcõ olup olmadõğõnõ
IsMobileDevice
verir. (bool tipinde değer döndürür)
JavaScript JavaScript özelliği JavaScript desteğinin olup olmadõğõnõ, VBScript ise
VBScript VBScript desteği olup olmadõğõnõ verir. (bool tipinde değer döndürür)
Tarayõcõnõn desteklediği Jscript versiyonunu verir. (string değere
JScriptVersion
dönüştürülerek kullanõlabilir)
Ziyaretçinin bulunduğu platform ile ilgili bilgileri verir. (string tipinde
Platform
değer döndürür)
Tarayõcõnõn Client Script CallBack desteği olup olmadõğõnõ verir. (bool
SupportsCallback
tipinde değer döndürür)
Type Tarayõcõnõn ismini ve tipini verir. IE7 gibi. (string tipinde değer döndürür)
Version Tarayõcõnõn versiyon numarasõnõ verir. (bool tipinde değer döndürür)
İstemcinin Win16 tabanlõ bir bilgisayarda çalõşõp çalõşmadõğõnõ verir.
Win16
(bool tipinde değer döndürür)
İstemcinin Win32 tabanlõ bir bilgisayarda çalõşõp çalõşmadõğõnõ verir.
Win32
(bool tipinde değer döndürür)
9
Response.Write("Tarayõcõ mõbil bir cihazda mõ çalõşõyor? : " + tarayici.IsMobileDevice +
"<br>");
Response.Write("Tarayõcõnõn Ecma script versiyon numarasõ : " +
tarayici.EcmaScriptVersion + "<br>");
Response.Write("Tarayõcõnõn çalõştõğõ işletim sistemi : " + tarayici.Platform + "<br>");
Response.Write("Tarayõcõnõn tipi: " + tarayici.Type + "<br>");
}
NOT: Tarayõcõ ile ilgili bilgilere erişmek için HttpBrowserCapabilities sõnõfõndan bir nesne
örneği oluşturmak zorunlu değildir. tarayici isimli nesne örneği üzerinden noktaya basarak
sõnõf üyelerine ulaşabildiğimiz gibi Request.Browser özelliği aracõlõğõ ile de aynõ üyelere erişip
işlemler yapabiliriz.
Günümüzde üçüncü parti yazõlõm olarak bir çok site web sayfalarõnõ ziyaret eden kullanõcõlar
ile ilgili bazõ bilgileri yukarõda kullandõğõmõz gibi farklõ yöntemlerle tutmaktadõr. Kendi web
uygulamamõzda da HttpBrowserCapabilities sõnõfõnõ kullanarak site ziyaretçilerinin tarayõcõlarõ
ile ilgili istatistikleri tutabiliriz. Yine bu özellikleri kullanarak tarayõcõnõn tipine göre farklõ
10
içerikler sunabilir, farklõ sayfalara yönlendirme işlemleri yapabilir. Örneğin, sitemiz ziyaret
edecek kullanõcõlarõn masaüstü bilgisayarlardaki tarayõcõlarõ kullanabilecekleri gibi, mobil bir
bilgisayardan da erişebilecekleri olasõ bir durumdur. Mobil tarayõcõlar ise normal bir tarayõcõ
kadar işlevsel olmadõklarõ için sayfalarõmõzdaki içeriklerin bazõlarõnõ görüntüleyemez veya
hatalõ görüntüler. Böyle bir durum karşõsõnda mobil bir tarayõcõ için farklõ sayfalar tasarlamak
ve gelen kullanõcõlarõ bu sayfalara yönlendirmek isteyebiliriz. Aşağõdaki gibi hazõrlanan bir
projenin anasayfasõ içerisinde gerekli kontroller ve yönlendirmeler yapõlõrsa istenildiği gibi
kullanõcõnõn doğru içeriğe erişmesi sağlanabilir. Yine kullanõcõnõn tarayõcõsõnõn Cookie,
JavaScript gibi sitenin işleyişi açõsõndan önem taşõyan bileşenleri desteklememesi
durumunda, site düzgün bir şekilde kullanõlamayacağõ için kullanõcõya bilgilendirici mesajlar
verilebilir.
11
AdRotator ile Reklam Yönetim Sistemi Geliştirmek
12 Mayõs 2007
12
dosyasõ içerisinde tanõmlõ olan <Impression> boğumundaki değer ise, o reklamõn gösterilme
sõklõğõnõ belirlemektedir. Bu sõklõk herhangi bir yüzdesel oran değil, diğer reklamlara göre ne
kadar sõklõkta görüntüleneceğidir. (Örneğin Impression değeri 10 olan bir reklam, Impression
değeri 5 olan bir reklama göre yaklaşõk 2 kat fazla gösterilecektir.) <Keyword> alanõnda ise
o reklama ait anahtar kelime veya kelimelerin tanõmlamasõ yapõlõr. AdRotator kontrolünün
KeywordFilter özelliğine verilecek anahtar kelime ile XML dosyasõndaki <Keyword>
alanõndaki kelimenin eşleşmesi durumunda, reklamõn/reklamlarõn seçilmesi ve
görüntülenmesi sağlanõr. Bu şekilde basit bir XML dosyasõna tanõmlanan reklam bilgileri ile
site içerisinde kullanõlabilecek reklam dönüşüm sistemi oluşturabiliriz.
XML ile AdRotator kullanõm oldukça pratik ve kolaydõr. Fakat burada bizleri kõsõtlayõcõ bazõ
özellikler olduğu gibi, yine yapõlmasõnõ isteyebileceğimiz bazõ ek işlemleri de
gerçekleştirmekte de bazõ sõkõntõlarla karşõlaşabiliriz. Reklamlarõ dinamik şekilde değiştirme
işlemi gerçekleştirmek için her seferinde XML dosyasõnõ açõp değişiklikler yapmak, aslõnda bir
programcõ için kõsõtlayõcõ bir unsurdur. Bu noktada reklamlarõ XML dosyasõnda saklamak
yerine veritabanõnda tutmak, özellikle sõklõkla güncellenecek reklam bilgileri için programcõya
veya site yöneticisine dinamik bir yapõ ve dolayõsõyle kolaylõk sağlayacaktõr. Yine reklamlarla
ilgili olarak; bir reklamõn kaç kez görüntülendiği, o reklama kaç kez tõklandõğõ gibi istatistiklerin
tutmakta böyle bir sistemde oldukça zengin bir işleyiş sunacaktõr.
13
Resim: Reklamlar Tablosu
Tablomuzdaki alanlarõ isimlendirirken AdRotator'a alanlarõ kolay bir şekilde tanõtabilmek için
AlternateText, ImageUrl, NavigateUrl, Impression ve Keyword kõsõmlarõnõ XML
dosyasõndaki aynõ isimlerle adlandõrmamõz gerekecektir. Bu şekilde tablo verileri AdRotator'a
bağlandõğõnde alanlar otomatik olarak algõlanacaktõr. ID tablonun primary key'i, Link reklam
URL'si, Durum reklamõn aktif olup olmadõğõ, Goruntuleme reklamõn görüntülenme sayõsõnõ
ve Tiklama reklama kaç kez tõklanõldõğõ bilgilerini taşõyacak alanlardõr. Bu şekilde
tasarladõğõmõz tablo içerisine artõk verilerimizi ekleyerek, AdRotator kontrolüne bu verileri
nasõl bağlayabileceğimizi görelim.
Burada sistemimizin kolay şekilde işleyebilmesi için NavigateUrl alanõ içerisine direk olarak
reklamõn URL'si yerine, sitemiz içerisinde hangi reklama tõklandõğõnõ yakalamamõzõ
sağlayacak bir sayfayõ eklememiz gerekecektir. (reklam.aspx) Yine bu sayfaya parametre
olarak yollayacağõmõz bilginin reklamõn ID kolonundaki değer olmasõ da işlemlerimizi
kolaylaştõracaktõr. Bu nedenle NavigateUrl alanõna ID değeri 1 olan reklam dosyasõ için
reklam.aspx?ID=1 gibi bir değer vermeliyiz.
Artõk tablodan alõnan verilerin AdRotator'a bağlanmasõ işlemini gerçekleştirebiliriz. Bunun için
öncelikli olarak AdRotator bulunan sayfamõzõn Page_Load kõsmõnda tablomuza bağlanõp,
reklam bilgilerini çekerek bir veri nesnesine bağlamak ve bu nesneyi de AdRotator'õn
DataSource özelliğine atamamõz gerekecektir. Aşağõda bu işlemin gerçekleşmesini sağlayan
kodlar bulunmaktadõr.
14
integrated security=true"))
// Tablodan reklam bilgilerini getirecek sorgu cumlesi hazirlaniyor
SqlCommand comm = new SqlCommand("SELECT AlternateText, ImageUrl,
NavigateUrl, Impression FROM Reklamlar WHERE Durum='True'", conn);
DataTable dt = new DataTable();
SqlDataAdapter da = new SqlDataAdapter(comm);
da.Fill(dt); // DataTable nesnesine eklenen veriler, AdRotator'a veri kaynagi olarak
gosteriliyor ve veriler yukleniyor
AdRotator1.DataSource = dt;
AdRotator1.DataBind();
}
AdRotator kontrolünün olaylarõ (event) içerisinde yer alan Ad_Created event'i, kontrolün
reklam kaynağõndan bilgiler aldõğõnda tetiklenen event'idir. Ad_Created event'ini bir metoda
bağlayacak olursak, metodun parametrelerinden ikincisinin AdCreatedEventArgs sõnõfõndan
(class) e adõnda bir değer taşõdõğõnõ göreceğiz. İşte buradaki e değeri, o an sayfaya eklenen
reklam hakkõnda bazõ bilgileri elde etmemizi sağlayacaktõr.
Burada karşõmõza çõkan NavigateUrl adresi içerisinde reklamõn ID değerini de taşõdõğõ için
bizim reklamõn bulunduğu satõrõ ele alabilmemizi sağlayacaktõr. AdRotator1_AdCreated
15
metodu içerisinde yapacağõmõz işlemlerle tablodaki Goruntuleme alanõndaki değerin
güncellenmesini ve 1 arttõrõlmasõnõ sağlayabiliriz. Aşağõdaki tabloda bu işlemler için gerekli
kodlar yer almaktadõr.
reklam.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
if (Request.QueryString["ID"] != null)
16
{
string reklamID = Request.QueryString["ID"];
Artõk sayfamõzõ çalõşõtõrõp görüntülenen reklama tõklama zamanõ! Birden fazla reklam
gösterimi yaparak ve bu reklamlarõn bazõlarõna tõklayarak Reklamlar tablosundaki
değişiklikleri gözlemleyebiliriz.
17
Resim: Gösterilen reklama tõklandõğõnda, o reklamõn tõklanma sayõsõnõ arttõrõldõ ve
reklamõn sitesine yönlendirme yapõldõ
18
View State ile Durum Yönetimi
08 Ağustos 2007
ViewState Olmasaydõ?
Çoğumuzun hatõrlayacağõ gibi, ASP veya PHP ile geliştirilen uygulamalarda bir sayfa
içerisindeki kontrollerin değerleri, sayfa post edildiğinde kaybolurdu ve tekrar elde etmek için
ekstra işlemler yapmamõz gerekirdi. ASP.NET'e geçiş yaptõğõmõz ilk zamanlarda en çok
dikkatimizi çeken durumlardan birisi de bir formu post ettiğimizde form üzerindeki verilerin
kaybolmamasõydõ. İşte ASP.NET uygulamalarõnda bizi bu sõkõntõdan kurtaran ve post
işleminden sonra da verilerin form üzerinde saklanmasõnõ sağlayan View State nesnesidir.
Dilerseniz View State nesnesinin uygulamalarda bize ne gibi bir kolaylõk sağladõğõnõ daha net
bir şekilde görebilmek için şu basit örneği gerçekleştirelim. Açtõğõmõz bir sayfaya iki tane
Label kontrolü ve iki tane Button kontrolü ekleyelim. Label kontrollerinden bir tanesinin
EnableViewState özelliğini true, diğerinin ise bu özelliğini false olarak ayarlayalõm.
(EnableViewState özelliği bir kontrolün özelliklerinin ViewState içerisinde taşõnõp
taşõnmamasõ durumunu belirler. Makalemizin ilerleyen kõsõmlarõnda EnableViewState
özelliğini tekrar inceliyor olacağõz.) Butonlardan bir tanesinin Click eventi içerisine aşağõdaki
ifadeleri ekleyelim. Diğer butonda ise herhangi bir değişiklik yapmayacağõz, sadece postback
yapmak amaçlõ kullanacağõz.
19
Resim: EnableViewState özelliği açõk olan kontrolün ve kapalõ olan kontrolün postback
işlemleri sonucundaki davranõşlarõ
Görüldüğü gibi ilk postback işlemi sonucunda butonun Click eventi aracõlõğõyla her iki labela
da değerler yazõldõ. Fakat sayfa üzerinde farklõ bir postback işlemi (labellarõn durumunu
değiştirmeyen bir postback işlemi) gerçekleştiğinde EnableViewState özelliği false olan label
kontrolü (Label1), bir önceki postbackten kazandõğõ değerini kaybetti. Diğer yandan,
ViewState nesnesi içerisinde değeri saklanan label (Label2) farklõ postback işlemlerinden
geçmesine rağmen önceki sayfadaki değerini kaybetmedi.
Adõm-1: Sayfamõza btnTikla adõnda bir button ve lblIcerik adõnda bir label kontrolü
ekleyelim. Button'un Text özelliğini Tõkla, label'õn Text özelliğini Merhaba olarak değiştirelim.
Sayfayõ çalõştõrdõktan sonra tarayõcõ üzerinde boş bir alana fare ile sağ tõklayõp Kaynağõ
Görüntüle (View Source) seçeneğinden oluşan sayfanõn HTML kodlarõna göz atalõm.
20
Resim: Kontrolleri ekledikten sonra __VIEWSTATE nesnesinin içeriği
Görüldüğü gibi bilgiler HTML kodlarõ içerisinde __VIEWSTATE adõ verilen hidden bir input
elementi bulunmaktadõr. Bir ASP.NET sayfasõnda varsayõlan olarak her zaman
__VIEWSTATE değeri saklanmaktadõr. Base64 formatõ kullanarak şifrelenen veriler sayfa
içerisinde saklanõr ve sayfanõn postback ile tekrar yüklenmesi durumunda gerekli bilgiler
çözümlenerek sayfa içerisinde kullanõlõr. Yukarõdaki resimde seçili olarak tutulan View State
değerine dikkat edelim.
Adõm-2: Sayfamõzdaki button'un Text özelliğini Click, label'õn Text özelliğini de Hello olarak
değiştirelim. Sayfayõ çalõştõrdõktan sonra tekrar HTML kodlarõ içerisindeki __VIEWSTATE
değerini kontrol edelim.
21
İki resimdeki seçili __VIEWSTATE alanlarõna dikkat edecek olursanõz, button ve label
kontrollerinin içeriğini değiştirmemize rağmen View State içerisinde saklanan değerin aynõ
şekilde kaldõğõnõ görebilirisiniz. Bunun sebebi şu anda View State içerisinde sadece
sayfamõzdaki kontrollerin hiyerarşik olarak diziliminin tutulmasõ ve bizim Design aşamasõnda
yapmõş olduğumuz değişikliklerin tutulmamasõdõr . Yani kontrolün özelliklerinde belirlediğimiz
atamalar direkt olarak HTML kodlarõ içerisinde <input type="submit" name="Button1"
value="Click" ... şeklinde tutulacağõ için bu bilgilerin __VIEWSTATE'e yazõlmasõna gerek
yoktur. Zaten View State'in en temel kullanõm amaçlarõndan biri de Design aşamasõnda
belirlenen kontrol özelliklerini saklamasõ değil, form üzerinde Postback işlemi yapõldõktan
sonra değişen kontrol değerlerinin taşõnmasõnõ ve sayfa tekrar yüklendiğinde bu verilerin
kaybolmamasõnõ sağlamaktõr. Dilerseniz son cümlede bahsettiğimiz olayõ Adõm-3'te görelim.
Adõm-3: Aşağõdaki kod örneğinde görüldüğü gibi, Button'un Click olayõ (event)
gerçekleştiğinde lblIcerik'in Text özelliğini ASP.NET olarak değiştirelim. Sayfayõ çalõştõrdõktan
sonra buttona tõklayarak Click eventini gerçekleştirelim ve Postback ile sayfayõ tekrar elde
edelim. Yeniden oluşan sayfanõn kodlarõna bakacak olursak aşağõdaki gibi __VIEWSTATE'in
içeriğinin değiştiğini görebiliriz.
Resim: Button'un Click eventinde label'in değeri değiştiği için bu değişiklik Postback
işlemi sonunda __VIEWSTATE'e yansõtõlmõştõr
22
(BackColor, Width, Height, ... gibi diğer özellikler) View State içerisinde saklanõr. Burada
kontroller ile ilgili söyleyebileceğimiz önemli ve ilginç bir hususta şudur ki; TextBox,
CheckBox ve RadioButton gibi kontrollerin postback esnasõnda değişen özellikleri View State
içerisinde taşõnmaz!
Her ne kadar resmin boyutunu küçültmüş olsamda, __VIEWSTATE'in oldukça fazla yer
kapladõğõ aşina bir şekilde görünmektedir. Yine sayfanõn HTML kodlarõnõ ayrõ bir dosyaya,
__VIEWSTATE içerisindeki metinsel kõsmõ da farklõ bir dosyada kaydedip aralarõndaki farkõ
kõyaslayacak olursak __VIEWSTATE değerinin sayfa içerisinde oldukça fazla yer kapladõğõnõ
göreceksiniz. Örneğin benim hazõrladõğõm bu örnekte sayfanõn tamamõ 6.66 KB, sadece
23
__VIEWSTATE içerisindeki değer ise 2.85 KB yer kaplamaktadõr. Yani View State'de
saklanan veri, boyut olarak sayfanõn neredeyse yarõsõnõ kaplamaktadõr. Burada oluşturulan
View State değeri her Postback işlemi gerçekleştiğinde sunucuya gönderileceği ve her sayfa
oluşumunda da istemciye getirileceği için sürekli olarak sunucu-istemci arasõnda fazladan
veri transferi söz konusu olacaktõr. İşte bu noktada uygulamayõ geliştiren kişi olarak bize
önemli bir performans ayarlamasõ görevi düşmektedir. GridView vb. bir kontrolün View State
içerisinde saklanmasõ, sayfanõn düzgün bir biçimde çalõşmasõ için gerekli midir, yoksa
gereksiz midir? Bir başka söylemle; sayfa, Postback olduğunda önceki halinde bulunan
verileri hatõrlamaya ihtiyacõ var mõdõr, yok mudur? Eğer cevabõmõz "Hayõr, bu sayfanõn tekrar
oluşturulmasõ esnasõnda, önceki halindeki GridView vb. bir nesnenin verisinin taşõnmasõna
gerek yok" ise, bu noktada sayfanõn sunucu-istemci arasõnda daha hõzlõ şekilde çalõşabilmesi
bu değerlerin View State içerisinde saklanmasõnõ engellememiz gerekmektedir. ASP.NET
sunucu kontrollerinin tamamõnda EnableViewState adõnda bir özellik bulunmaktadõr. Bu
özellik kontrolün postback işlemi sonucunda değişen değerlerinin View State içerisinde
saklanõp saklanmayacağõnõ belirler. bool tipinden bir değer alabilen EnableViewState
özelliğinin varsayõlan değeri true'dur. EnableViewState değerinin true olmasõ, kontrolün
özelliklerinin View State içerisinde saklanõr, false olmasõ durumunda ise saklanmaz. Eğer bir
kontrolün özelliklerinin View State içerisinde taşõnmasõnõ istemiyorsanõz, o kontrolün
EnableViewState özelliğini false olarak ayarlamanõz gerekecektir. Aşağõdaki örnek kod
parçasõnda bir GridView kontrolünün EnableViewState özelliğinin kapatõlmõştõr.
24
Resim: EnableViewState özelliğinin false olmasõ durumunda değişen değerler
ViewState'de taşõnmaz ve sayfanõn boyutu azalõr.
NOT: ViewState değerinin bazõ durumlarda çok ciddi boyutlara ulaşmasõ uygulamanõn
performansõ açõsõndan ciddi sorunlara yol açabilir. ViewState nesnesi içerisinde saklanan
değerlerin sõkõştõrõlarak daha küçük boyutlara ulaşõlmasõnõ sağlayan bazõ teknikler
bulunmaktadõr. Fakat bu konu başlõ başõna bir makale anlamõna geleceği için bu yazõmõzda,
bu detaya gimeyeceğiz. Arama motorlarõnda ViewState compression veya ViewState
sõkõştõrma şeklinde aramalar yapacak olursanõz çok sayõda kaynağa erişebilirsiniz.
25
protected void Page_Load(object sender, EventArgs e)
{
Page.EnableViewState = false;
}
ViewState["miktar"] = 128535;
ViewState["tablo"] = new DataTable("TestTable");
Görüldüğü gibi, ViewState içerisinde sakladõğõmõz değerler object tipinde saklanacağõ için
sayfa içerisinde bu verilere erişirken gerekli dönüşüm (cast) işlemlerini de gerçekleştirmek
gerekecektir. ViewState içerisinden saklanan bir değeri çõkarmak için Remove metodu,
programatik yollarla eklenen tüm verileri çõkarmak ise Clear metodu kullanõlabilir. Aşağõda bu
iki metodun kullanõmõ gösterilmiştir.
26
ViewState.Clear(); // ViewState'e eklenen tüm kayõtlar silinir. (Kontrol bilgileri silinmez!)
ViewState Güvenliği
ViewState istemci tarafõnda HTML kodlarõ içerisinde Base64 encoding formatõnda
şifrelenerek saklandõğõndan bahsetmiştik. Bildiğiniz gibi istemcinin bilgisayarõnda veri
saklamamõzõ sağlayan durum yönetim nesneleri arasõnda, ViewState dõşõnda QueryString ve
Cookie nesneleri de bulunmaktadõr. QueryString ve Cookie içerisinde taşõnan verilere
kullanõcõ kolay bir şekilde erişebilmekte ve değişiklikler yapabilmektedir. ViewState
nesnesinde taşõnan veriler ise şifrelenmiş bir şekilde taşõnacağõ için okunabilir olmayacaktõr
ve diğer nesnelere göre daha güvenli bir veri taşõma yöntemi sunacaktõr diyebiliriz. Fakat
burada unutmamamõz gereken bir nokta var ki; verilerin saklandõğõ Base64 encoding formatõ
acemi bir programcõ tarafõndan dahi çok kolay bir şekilde çözümlenebilir. Base64 encoding
formatõnda saklanan verilerin geriye dönüştürülmesi kolay bir şekilde gerçekleştirilebileceği
için, ViewState nesnesinin çözümlenmesi ve içerisinde saklanan değerlerin görüntülenmesi
de çok kolay olacaktõr. (Internette ViewState Decoder şeklinde bir arama yapacak olursanõz
ViewState değerlerini çözümleyen çok sayõda araç ile karşõlaşabilirsiniz.) Eğer ViewState
içerisinde gizli bir bir güvenlik açõğõna sebebiyet verebilir. Bundan dolayõ ViewState'in
şifrelenmiş bir şekilde veri saklamasõna güvenerek, bir kullanõcõ veya site için güvenlik
sorununa yol açabilecek verileri taşõmamalõyõz. Peki ViewState'de şifrelenerek taşõnan bu
verileri biraz daha güvenli bir biçimde saklamak mümkün olabilir mi? MAC (Machine
Authentication Check) adõ verilen bir yapõ aracõlõğõyla ViewState nesnesinin kullanõcõ
tarafõndan değiştirilip değiştirilmediği ASP.NET sayfasõ tarafõndan algõlanabilmekte ve
kullanõcõya hata gönderilebilmektedir. Bir ASP.NET sayfasõnõn MAC mekanizmasõ bu tip
güvenlik nedenleriyle varsayõlan olarak açõk tutulmakta ve sayfa postback işlemine tabi
tutulduğunda sunucu tarafõnda sayfanõn asõl ViewState değeri ile o an kendisine gelen
ViewState değerlerini karşõlaştõrõp eğer farklõlõk varsa; yani ViewState nesnesi değiştirilmiş
ise kullanõcõya hata gönderilecektir. Bu ayarõn açõk bõrakõlmasõ bahsettiğimiz gibi güvenlik
açõsõndan gereklidir. Fakat bu durumda sayfa üzerinde postback işlemi yapõldõğõnda sunucu
tarafõnda ekstra kontrol işlemleri yapõlacağõnõ ve performans açõsõndan bazõ kayõplarõmõz
olacağõnõ da unutmamak gerekir. Eğer sayfada ViewState'de taşõnan değerlerin kullanõcõ
tarafõndan değiştirilmesinin güvenlik açõsõndan bir sakõncasõ yok ise, bu özelliği kapatmak
isteyebiliriz. Sayfa bazõnda bu özelliği kapatmak istiyorsak Page direktifini, site genelinde
kapatmak istiyorsak web.config dosyasõnõ kullanabiliriz. Aşağõdaki örneklerde sadece bir
sayfa içerisinde ve web.config dosyasõ içerisinde eklenecek kodlar görülmektedir.
<system.web>
.....
.....
<pages enableViewStateMac="false"></pages>
27
.....
</system.web>
28
ASP.NET 2.0 - Sayfa Direktifleri (Page Directives)
26 Ağustos 2007
Sayfa direktifleri ASP.NET'in 1.0 sürümünden beri tüm sayfalarda kullanõlmaktadõr. ASP.NET
2.0 ile birlikte gelen bazõ yeni dosya tipleri (Master Sayfalar gibi) ve çalõşma mekanizmalarõ
(CrossPage Postback gibi) ile birlikte, yeni sayfa direktifleri de ASP.NET'in yapõsõna
eklenmiştir. Bu makalemizde bir sayfada kullanõlabilecek tüm direktifleri detaylõ bir şekilde ele
alõyor olacağõz. Aşağõdaki listede ASP.NET sayfalarõnda kullanõlabilecek sayfa direktiflerinin
listesi bulunmaktadõr.
1. Page
2. Assembly
3. Control
4. Implements
5. Import
6. Master
7. MasterType
8. OutputCache
9. PreviousPageType
10. Reference
11. Register
Aslõnda listenin ilk sõrasõnda gördüğümüz Page direktifi bize oldukça tanõdõk gelecektir. Zira
her .aspx uzantõlõ sayfanõn HTML kodlarõnõn en üst kõsmõnda bulunan Page direktifi üzerinde
değişiklik yapmasak dahi ne amaçla kullanõldõğõnõ az-çok bilmekteyiz. Page direktifinin
kullanõmõnõ şöyle bir bakacak olursak;
<% @Page ...... %>
şeklinde bir tanõmlamaya sahip olduğunu görürüz. Aslõnda bu tanõmlama tüm sayfa direktifleri
için geçerli bir tanõmlama şeklidir. Yukarõdaki listede gördüğünüz 11 sayfa direktifi <%
@DirektifAdõ şeklinde başlar, devamõnda gerekli niteliklerine (attribute) atamalar yapõlarak
ayarlamalar yapõlõr ve %> ifadesi ile de direktifin sonlandõrõldõğõ derleyiciye bildirilir. Burada
görülen <% %> ifadeleri asp söz diziminde, sunucu tarafõnda çalõştõrõlacak etiket anlamõna
gelmekte, @ işareti ise çalõştõrõlacak ifadenin bir sayfa direftifi ifadesi olduğunu belirtir. Direktif
içerisinde ise gerekli tanõmlamalar NitelikAdõ="Değeri" şeklinde yapõlacaktõr.
29
Dilerseniz sayfa direktiflerinin kullanõmõnõ, gerekli ve önemli nitelikleri ile birlikte tek tek ele
alalõm.
1. Page Direktifi
Page direktifi ASP.NET sayfalarõnda kullanõlan en temel ve önemli direktiftir. İçerisinde
yapõlan tanõmlamalar ile bulunduğu sayfanõn derleyici tarafõndan nasõl, ne şekilde ele
alõnacağõnõ ve hangi özelliklerle birlikte derlenip çalõştõrõlacağõnõ belirler. Page direktifi zorunlu
olmamakla birlikte, tüm .aspx sayfalarõnda bulunmaktadõr. Page direktifi ile birlikte
kullanõlacak önemli nitelikler (attribute) aşağõda bulunmaktadõr.
- Async: Sayfanõn asenkron şekilde çalõşmasõnõ belirler. true değeri alõrsa sayfa asenkron
şekilde çalõşabilir hale gelir, false değer aldõğõnda senkron şekilde çalõşõr.
- AutoEventWireup: Sayfanõn yaşam döngüsü içerisinde olaylarõ (event) için tanõmlanmõş
olan metot isimlerinin kullanõlõp kullanõlmayacağõnõ belirler. Eğer true değeri alõrsa Page_Init,
Page_Load, Page_PreRender gibi önceden tanõmlanmõş metot isimleri olaylara bağlanarak
kullanõlõr. Eğer false değeri alõrsa kullanõcõ kendisi olaylara farklõ metot isimleri bağlayabilir.
Varsayõlan değeri true'dur.
- CodeFile: Sayfanõn code-behind dosyasõnõ belirler. Yani aspx sayfasõ çalõştõrõldõğõnda hangi
kod sayfasõ ile birlikte derleneceği bu nitelik ile belirlenir. Default.asp.cs gibi.
- Culture: Sayfanõn para birimi, tarih ve ölçü birimleri gibi kültür (culture) bilgilerinin hangi dile
göre getirileceğini belirler.
- UICulture: Sayfanõn görsel arayüzündeki dile göre değişebilen içeriklerin sayfa
oluşturulduğunda hangi dil kullanõlarak üretileceğini belirler.
- EnableTheming: Site genelinde tema ayarlamalarõ açõk ise, temalandõrma işleminin
sayfaya uygulanõp uygulanmayacağõnõ belirler. Eğer web.config'den uygulama için bir tema
ayarlamasõ yapõlmõş ise ve bu nitelik true değerini taşõrsa tema sayfaya uygulanõr, false
değerini taşõrsa tema sayfaya uygulanmaz.
- EnableViewState: Sayfa içerisindeki kontrollerin PostBack işlemi sonucunda değişen
özelliklerinin ViewState nesnesi içerisinde taşõnõp taşõnmayacağõnõ belirler. true değeri alõrsa
sayfadaki bütün kontrollerin özellikleri ViewState'de taşõnõr, false değeri alõrsa taşõnmaz.
Varsayõlan değeri true'dur.
- ErrorPage: Sayfada hata oluşmasõ durumunda, sayfanõn hangi hata sayfasõna
yönlendirileceğini belirler.
- Inherits: Sayfanõn compile işlemi yapõlõrken hangi sõnõftan (class) kalõtõlacağõnõ ve hangi
sõnõfõn örnekleneceğini belirler. Varsayõlan olarak sayfanõn code-behind dosyasõnda yazõlan
sõnõf adõ, yani dosya ile aynõ ismi taşõyan sõnõf adõ bu değere atanõr. Default2.aspx sayfasõnda
Default2 gibi.
- Language: Sayfanõn hangi .NET destekli dil ile yazõldõğõnõ belirler. C# dilinde yazõlmõş ise
C#, VB.NET dilinde yazõlmõş ise VB gibi.
- MasterPageFile: Sayfa eğer bir master sayfadan türetilmiş ise, türetilen master sayfanõn
adõ atanõr. SiteMaster.master isimli master sayfadan türetilen sayfa için SiteMaster.master
bilgisini taşõr.
- MaintainScrollPositionOnPostback: Sayfanõn PostBack işlemi sonucunda yenilenmesi
durumunda, sayfanõn otomatik olarak kullanõcõnõn son olarak konumlandõğõ yere getirilmesi
işlemini yapar. Yani kullanõcõ scroll bar ile sayfayõ aşağõya doğru hareket ettirip, ardõndan da
sayfayõ yenilerse, yenileme işlemi sonrasõnda tarayõcõ sayfanõn en üstüne değil de
30
kullanõcõnõn son olarak kaldõğõ kõsma konumlanõr. true değeri alõrsa burada bahsedildiği gibi
davranõr. false değeri almasõ durumunda ise yenileme işlemi sonunda sayfanõn en üstüne
gelinir.
- Theme: Sayfanõn App_Themes klasöründe oluşturulmuş site şemalarõndan birini
uygulamasõnõ sağlar.
- Title: Sayfanõn tarayõcõdaki başlõk bilgisini belirler.
- Trace: Sayfada trace (izleme) işlemlerinin yapõlõp yapõlmayacağõnõ belirler. Varsayõlan
değeri false'dur ve trace işlemi yapõlmaz. true değeri atandõğõnda sayfada trace işlemi yapõlõr.
- ValidateRequest: Sayfadaki bilgilerin sunucuya gönderilmesi esnasõnda, form içerisinde
taşõnan bilgilerde güvenlik açõsõndan sorun çõkarabilecek içerikler var ise (örneğin kullanõcõ
bir TextBox içerisinde <span> <b> <script>....</script> gibi ifadeler yazdõysa) sayfanõn hata
vermesini ve bilgilerin gönderiminin iptal edilmesini sağlar. Güvenlik açõsõndan önemli bir
niteliktir. Varsayõlan değeri true'dur ve yukarõda bahsedildiği gibi bir işlem gerçekleşirse işlemi
iptal eder ve hata verir. false ise tehlikeli bir içerik bulunsa bile gönderilen bilgileri kabul
edecektir.
Yukarõdaki örnekte sayfanõn C# dili ile kodlandõğõ, sayfa olaylarõnõn varsayõlan metotlara
bağlandõğõ, sayfanõn C# kodlarõnõn Default.aspx.cs dosyasõnda bulunduğu, sayfanõn _Default
adõnda bir sõnõftan türetildiği, sayfanõn kültür (culture) bilgisinin tr-TR yani Türkçe dili olduğu,
sayfa içerisindeki kontrollerin değerlerinin ViewState içerisinde saklanmayacağõ ve sayfada
bir hata oluşursa sayfanõn otomatik olarak Hata.aspx isimli sayfaya yönlendirileceği
belirtilmiştir.
2. Assembly Direktifi
İlgili sayfaya kullanõcõnõn oluşturmuş olduğu bir assembly'nin eklenmesini sağlar. Böylece
sayfa içerisinde ilgili assembly'de bulunan tipler (class, struct gibi) kullanabilmektedir.
web.config dosyasõ içerisinde <assembly> düğümüne add etiketi ile uygulamaya assembly
ekleme işleminin sayfa bazõnda yapõlmasõnõ sağlar. Assembly direktifinin alabileceği iki nitelik
vardõr:
31
<%@ Assembly Name="AssemblyIsmi" %>
Assembly direktifinin iki niteliği de aynõ işlemi yapmakta ve bir Assembly direktifi içerisinde
aynõ anda bunlardan sadece bir tanesi kullanõlabilmektedir.
3.Control Direktifi
Bir user control'ünün (kullanõcõ kontrolü) özelliklerinin belirlenmesini sağlar. Böylece
ASP.NET'in bu user control'ünü ne şekilde ele alacağõ ve nasõl derleyeceği belirlenir.
Bildiğiniz gibi user control'ler ascx uzantõsõ ile saklanan, içerisinde ASP.NET kontrolleri ve
HTML kodlarõ bulundurabilen ve ASP.NET web sayfalarõnõn belirli parçalarõnõ oluşturan
dosya tipleridir. Bir aspx sayfasõ içerisindeki Page direktifi ile ascx kontrolünde kullanõlan
Control direktifinin hemen hemen aynõ işlevleri olduğunu söyleyebiliriz. Control direktifi
sadece user control'lerinde kullanõlabilmektedir.
Control direktifinin nitelikleri, Page direktifinin niteliklerine göre az sayõda olmakla beraber,
niteliklerin kullanõmõ ve yaptõklarõ işlemler hemen hemen aynõdõr. Yukarõda, Page direktifi
kõsmõndaki niteliklere ve açõklamalarõna göz atmak, Control direktifinin kullanõmõ ile ilgili bize
yeterli bilgi verecektir. Aşağõda Control direktifinin bir user control'ünde kullanõmõ ile ilgili bir
örnek yer almaktadõr.
4. Implements Direktifi
.NET Framework'te tanõmlõ olan bir interface'i (arayüz) sayfaya uygulamak için kullanõlan
direktiftir. Uygulanan interface'e ait metotlar ve property'ler (özellik) aspx dosyasõ içerisinde
açõlacak <script> etiketinde yazõlarak sayfaya uygulanabilir. Implements direktifi sadece
Interface niteliğini kullanmaktadõr.
Aşağõdaki örnekte, System.Web.UI namespace'i (isim alanõ) altõnda yer alan IValidator isimli
interface'in bir sayfaya Implements direktifi ile uygulanõşõ görülmektedir.
5. Import Direktifi
Sayfaya bir namespace'in eklenmesi için kullanõlan direktiftir. .NET Framework yapõsõnda
bulunan veya projede tanõmlanmõş olan herhangi bir namespace Import direktifi ile sayfaya
eklenebilir. web.config dosyasõ içerisinde uygulama genelinde kullanõlabilecek
namespace'lerin eklenmesi gibi, sadece bir sayfaya namespace'lerin eklenmesi işlemi için de
32
Import direktifi kullanõlabilir. Import direktifi ile sadece Namepace niteliği kullnõlõr.
Aşağõdaki örnekte Import direktifi ile bir sayfaya namespace eklemeleri yapõlmõştõr.
6. Master Direktifi
Bir Master page'in özelliklerinin belirlenmesini sağlayan direktiftir. Page direktifi web form
sayfalarõnda(aspx), Control direktifi user control'lerde(ascx) olduğu gibi, Master direktifi de
master page'lerin ASP.NET derleyicisi tarafõndan ne şekilde ele alõnacağõnõ belirler.
Kullanõlan nitelikler ve niteliklerin kullanõm amaçlarõ Page ve Control direktifleri ile hemen
hemen aynõdõr. Bu nitelikler için Page direktifi kõsmõndaki nitelik açõklamalarõna göz
atabilirsiniz. Aşağõda bir master page dosyasõnda kullanõlabilecek Master direktifi
görülmektedir.
7. MasterType Direktifi
Master page'den türetilen bir ASP.NET sayfasõndaki Page.Master property'si MasterPage
tipinden bir değer döndürmekte ve böylece master page ile ilgili işlemler yapõlabilmektedir.
Bazõ durumlarda master page sõnõfõ içerisinde tanõmlanmõş özel bir property (özellik) veya
metoda Page.Master özelliği ile direkt olarak erişilmek istenilebilir. Böyle bir durumda
Page.Master özelliğini ilgili master page'in tipine cast (dönüştürme) işlemi yapmak
gerekecektir. İlgili sayfadan master page'in nesne örneğine cast işlemi yapõlmadan erişilmek
istenilirse, bu sayfaya MasterType direktifi eklenmesi gerekecektir. MasterType direktifi
içerisinde tanõmlanan master page'in otomatik olarak Page.Master özelliğinin geri dönüş tipi
olmasõnõ sağlar ve böylece master page'deki özel property veya metoda direkt olarak erişme
işlemi gerçekleştirilebilir. Aşağõda MasterType direktifinin alabileceği nitelikler ve bu
niteliklerin açõklamalarõ yer almaktadõr.
- TypeName: Content page'de Master özelliğinin geri dönüş tipi olmasõ istenilen master
page'in tip adõnõ alõr.
- VirtualPath: Content page'de Master özelliğinin geri dönüş tipi olmasõ istenilen master
page dosyasõnõn dosya yolunu ve ismini alõr.
Örnekteki MasterType direktifi, content page içerisindeki Master özelliğinin geri dönüş tipinin
SiteSablonu.master isimli master page dosyasõ olduğunu belirler.
33
<%@ MasterType VirtualPath="~/SiteSablonu.master" %>
Resim-3: Master property'si master page'in nesne örneğini getirdiği için content
page'den direkt olarak master page üyelerine erişebiliriz
8. OutputCache Direktifi
ASP.NET uygulamalarõnda sayfanõn çõktõsõnõ önbelleğe alma işlemlerinde (Caching)
kullanõlan direktiftir. Sayfaya OutputCache direktifini eklediğimizde ve gerekli nitelikleri
tanõmladõğõmõzda, sayfanõn HTML çõktõsõ bellekte saklanõr, sayfa belirli bir süre boyunca
tekrar çalõştõrõlmaz ve bellekten okunur. OutputCache direktifi ile yapõlan önbellekleme
işlemleri sayfanõn daha hõzlõ şekilde istemciye gönderilmesini sağlar.
34
sadece sunucuda, istemcide veya proxy'de saklanmasõ sağlanabilir. Alabileceği diğer
değerler; Client, Server, Downstream, ServerAndClient ve None'dir.
- NoStore: Sayfanõn header (başlõk) bilgilerinde "no cache" bilgisinin gönderilip
gönderilmeyeceğini belirler.
- SqlDependency: Sayfanõn SQL Server veritabanõndaki bir tablonun değişimine bağõmlõ
olarak önbelleklenmesi durumunda kullanõlacak niteliktir. Bu özelliğe değer atayabilmek için,
web.config dosyasõndaki caching düğümünde bulunan sqlCacheDependency içerisine bir
veritabanõ tanõmlamasõ yapõlmalõdõr.
- VaryByControl: Sayfadaki bir kontrolün değişimine göre önbellekleme işleminin
yapõlmasõnõ sağlar. Değer olarak önbellekleme işleminin yapõlmasõnõ sağlayacak kontrolün ID
değerini almalõdõr.
- VaryByCustom: Farklõ değerlere ve kriterlere göre önbellekleme işlemlerinin yapõlmasõ
durumunda kullanõlacak niteliktir. Bu niteliğin alacağõ değerin yakalanõp ele alõnabilmesi için
Global.asax dosyasõ içerisindeki GetVaryByCustomString isimli metodun ezilmesi (override
edilmesi) gerekmektedir.
- VaryByHeader: Sayfanõn HTML kõsmõnda yer alan header (başlõk) bilgilerine göre
önbellekleme işlemlerinin yapõlmasõnõ sağlar.
- VaryByParam: Sayfanõn Url'den gelen QueryString parametrelerine göre önbelleğe alõnõp
alõnmayacağõnõ belirler. Varsayõlan değeri None'dir ve parametreleri dikkate almaksõzõn
sayfanõn belleğe alõnmasõnõ sağlar. QueryString'deki herhangi bir parametrenin adõnõ alarakta
bu değere göre sayfanõn farklõ kopyalarõnõn önbellekleğe alõnabilmesini sağlar. Bu niteliğin
her OutputCache direktifi içerisinde yazõlmasõ zorunludur.
Aşağõda bir sayfanõn HTML çõktõsõnõ QueryString bilgisine bakmaksõnõz 30 saniye süre ile
istemcinin bilgisayarõnda önbelleğe atan OutputCache direktifi bulunmaktadõr.
9. PreviousPageType Direktifi
Cross-Page PostBack işlemlerinde hedef sayfaya gelinen kaynak sayfanõn nesne örneğini
elde etmek için kullanõlan direktiftir. Normal koşullarda sayfanõn code-behind kõsmõnda elde
ettiğimiz PreviousPage nesnesi Page tipinden nesne örneği döndürmektedir. Eğer
PreviousPage nesnesin üzerinden önceki sayfanõn nesne örneğini elde etmek istiyorsak
sayfa içerisine PreviousPageType direktifi eklemek gerekecektir. PreviousPageType
direktifinin alabileceği nitelikler ve açõklamalarõ aşağõdadõr.
35
Dilerseniz PreviousPageType direktifinin sayfaya ne gibi bir etkisi olduğunu daha iyi
anlayabilmek için aşağõdaki resimleri inceleyelim. Resim-4'te PreviousPageType direktifi
eklenmemiş bir sayfada PreviousPage nesnesinin geri dönüş tipinin Page class'õ olduğunu
görebilirsiniz. Resim-5'te ise sayfaya PreviousPageType direktifi eklendiğinde sayfanõn
PreviousPage nesnesinin Source.aspx sayfasõnõn nesne örneğinin döndürdüğü
görülmektedir. Böylece artõk PreviousPage'den önceki sayfanõn nesne örneğine ulaşõlabilir ve
önceki sayfanõn class'õ içerisinde metot, property gibi üyeler çağrõlabilir.
Aşağõdaki Reference direktifi ile sayfaya referansõ eklenen Default2.aspx sayfasõnõn class'õna
erişilebilir.
36
- Assembly: Eklenecek user control'ün assembly'si. Eğer user control aynõ projede ise
kullanmaya gerek yoktur.
- Namespace: Eklenecek user control'ün hangi namespace içerisinde bulunduğunu belirler.
User control aynõ projede ise kullanmaya gerek yoktur.
- Src: User control'ün uygulamada bulunduğu yer ve dosya adõ.
- TagName: Kullanõlacak user control'ün adõ
- TagPrefix: HTML kodlarõ içerisinde user control ekleneceği zaman hangi etiket adõ ile
çağrõlacağõ bilgisidir. (TagName ve TagPrefix niteliklerinin kullanõmõ için aşağõdaki kod
örneklerine bakmakta fayda var)
Aşağõdaki Register direktifi ile sayfaya LoginKontrolum adõndaki bir user control'ü eklenmiştir.
Böylece sayfaya TagName ve TagPrefix bilgileri ile ilgili dosyadaki user control eklenebilir.
37
ASP.NET 2.0 - Performans Yönetimindeki Yenilikler
02 Eylül 2007
Bir web uygulamasõ geliştirilirken göz önüne alõnacak en önemli unsurlardan birisi de
uygulamanõn performansõdõr. ASP.NET'in ilk sürümleri ile birlikte gelen yeniliklerde özellikle
uygulamanõn performansõnõ arttõrma işlemlerini oldukça kolay, pratik ve gerçekten etkili bir
şekilde gerçekleştirebilmekteydik. En temel performans bakõmõ tekniklerimiz olan
OutputCache ile sayfa çõktõsõnõ, Cache nesnesi ile de sayfa içerisindeki bir nesneyi belirli bir
süre bellekte saklayabilmekte ve sonraki erişimlerde sayfanõn çok daha hõzlõ bir şekilde
çalõşabilmesini sağlayabilmekteyiz. ASP.NET 2.0 ile birlikte birçok alanda gelen yenilikler
arasõnda performans yönetimi konusunda da bazõ yeni teknikler ve kullanõm kolaylõklarõ
getirilmiştir. Bu yazõmõzda da ASP.NET 2.0 ile birlikte gelen bu yenilikleri inceliyor olacağõz.
1. Cache Profilleri (Cache Profiles) ile OutputCache mekanizmasõnõn daha kolay şekilde
yönetilebilmesi
2. Post-Caching ve Substitution kontrolü önbelleklenen sayfada dinamik alanlar
kullanabilme
3. SqlCacheDependency ile veritabanõndaki değişikliklere göre veri önbellekleme
4. DataSource kontrolleri ile önbellekteki veriler ile çalõşmak
5. Custom Dependency'ler oluşturabilme
ASP.NET'in ilk sürümünden beri bir sayfanõn tamamõnõn veya belirli bir kõsmõnõn HTML
çõktõsõnõn önbelleğe alõnmasõnõ ve sayfanõn çok daha hõzlõ bir şekilde çalõşmasõnõ
sağlayabilmekteyiz. Sayfa veya user control içerisine ekleyeceğimiz <%@ OutputCache ...
%> direktifi ile sayfanõn önbelleğe alõnma şeklini belirleyebiliyorduk. ASP.NET 2.0 ile birlikte
gelen Cache Profilleri ile birlikte sayfalarõmõzda ortak olarak kullanabileceğimiz OutputCache
ayarlamalarõnõ artõk web.config içerisinde düzenli bir şekilde saklayabilmekte ve sayfa
içerisinde OutputCache direktifinin bu profillerden birini kullanabilmesini sağlayabilmekteyiz.
Dilerseniz önce OutputCache direktifini sayfa içerisinde nasõl kullanabiliyorduk bir
hatõrlayalõm. Aşağõdaki kod parçasõnõ bir .aspx sayfasõndaki Page direktifinin alt kõsmõna
ekleyecek olursak; sayfa QueryString bilgisini dikkate almaksõzõn 60 saniye süre ile
önbelleğe alõnacaktõr.
38
Cache profillerin bize ne gibi bir noktada fayda sağladõğõnõ görebilmek için şöyle bir senaryo
üzerinde duralõm. Varsayalõm ki uygulamamõz çok sayõda sayfadan oluşuyor ve bu sayfalarõn
bir grubunu farklõ şekilde, diğer grubunu farklõ şekilde önbelleğe alma işlemini
gerçekleştirmek istiyoruz. Şöyle ki;
önbellekte saklama işlemi gerçekleştirelim. Böyle bir durumda yukarõdaki Grup 1 sayfalarõna
<%@ OutputCache Duration="600" VaryByParam="None" %> ifadesini, Grup 2
sayfalarõna da <%@ OutputCache Duration="300" VaryByParam="UrunID" %>
ifadelerini eklememiz gerekecekti. Varsayalõm ki belirli bir süre sonra Grup 1'deki sayfalarõn
çok uzun süre ile önbellekte tutulduğunu ve kullanõcõnõn güncel bilgiye erişemediğini gördük.
Yine Grup 2'deki sayfalarõnda sadece UrunID QueryString bilgilesine göre değil de, UrunID
ve Renk QueryString bilgilerine göre önbellekte saklanmasõnõ istiyoruz; yani sayfalardaki
OutputCache direktiflerini değiştirme ihtiyacõmõz var. Bu durum yukarõdaki 12-13 tane
sayfanõn tek tek açõlarak kod kõsõmlarõnda değişiklik yapõlmasõ anlamõna geliyor. Sayfa
sayõsõnõn 30-40 olduğunu düşünürsek durum biraz daha vahim hale geliyor:) İşte bu noktada
gruplanan iki OutputCache niteliğini web.config içerisinde saklayacak ve sayfalarõmõzda da
web.config'deki bu ayarlarõ kullanacak olursak artõk bilgileri tek bir noktada toplamõş ve
dolayõsõyla da bu değişiklikleri de çok basit bir şekilde sayfalara uygulamõş olacağõz. Peki
Cache profillerini web.config içerisinde ne şekilde saklayacağõz. Aşağõdaki kod parçalarõ ile
birlikte web uygulamasõna CacheProfil_A ve CacheProfil_B adõnda iki tane Cache profili
eklemiş oluyoruz.
<system.web>
.....
.....
<caching>
<outputCacheSettings>
<outputCacheProfiles>
<add name="CacheProfil_A" duration="600" varyByParam="None" />
<add name="CacheProfil_B" duration="300" varyByControl="UrunID"/>
</outputCacheProfiles>
</outputCacheSettings>
</caching>
</system.web>
39
<%@ OutputCache CacheProfile="CacheProfil_B" %>
ASP.NET'in önceki sürümlerinde sayfanõn tamamõnõ veya sadece belirli bir alanõnõ önbelleğe
alabiliyorduk. Fragment Caching adõ verilen bir teknikte sayfa içerisinde bir user-control
(ascx) dosyasõ ekleyerek sadece bu alanõn HTML çõktõsõnõ önbelleğe saklayabiliyor ve
sayfanõn diğer alanlarõnõn dinamik oluşmasõnõ sağlayabiliyorduk. Fakat sayfanõn tamamõnõ
önbellekten getirilirken sadece belirli bir alanõnõ dinamik oluşturma işlemini
gerçekleştiremiyorduk. ASP.NET 2.0 ile birlikte gelen yeniliklerle birlikte artõk bu tip bir
önbellekleme işlemini de gerçekleştirebilmekteyiz.
Fragment caching ile sayfanõn belirli bir alanõnõ önbelleğe alma işlemi oldukça pratik bir
işlemdi. Fakat burada yapõlacak işlemin biraz daha zor olacağõnõ söyleyebiliriz. Zira sayfanõn
dinamik olarak oluşturulacak kõsmõnõ her ne kadar bir kontrol aracõlõğõyla hazõrlõyor olsakta,
bu kontrolün içerisinde yazdõrõlacak HTML kodlarõnõ tamamen bizlerin yazmasõ gerekecek.
Post-Cache Substitution ile yapõlacak işlemde Response.WriteSubstitution metodu ile
HttpResponseSubstitutionCallback delegate'i (temsilci) aracõlõğõyla static bir metodu
işaretlememiz gerekir. Substitution kontrolü ile yapõlacak işlemde ise bu kontrolün
MethodName isimli özelliğin yine static olarak yazõlmõş özel bir metodun adõnõ vermeliyiz.
Tahmin edeceğiniz üzere sayfaya dinamik olarak gelecek HTML içerikler burada bahsetmiş
olduğumuz metotlardan getirilecektir. Dilerseniz bahsettiğimiz iki yolu sayfamõza nasõl
uygulayabileceğimiz bir bakalõm.
- Post-Cache Substitution
40
Bu yolu seçtiğimizde sayfamõzõn source kõsmõnda dinamik içeriğin geleceği kõsma
Response.WriteSubstitution metodu ile static metot çağrõmõnda bulunmamõz gerekir.
İsterseniz öncelikle burada bize gerekli olan metodu yazarak üzerinde biraz konuşalõm. Zira
bu metot ile ilgili konuşulmasõ gereken birkaç noktamõz var.
Yazacağõmõz metot dinamik içeriğimizi oluşturacak; yani HTML kodlarõmõzõ bize getirecek bir
metot olmalõdõr. Bundan dolayõ metodumuzun geri dönüş tipi string'dir ve return edilen HTML
kodlarõ dinamik içeriğimizi oluşturacaktõr. Bu sayfamõza bir istek geldiğinde sayfa içeriği
(dinamik alan dõşõndaki içerikler) önbellekten getirilecektir; yani sayfamõzõn tekrar
çalõştõrõlmasõna, dolayõsõyla da nesne örneğini oluşturulmasõna gerek yoktur. Bundan dolayõ
static bir metot yazacak olursak uygulamamõz sayfanõn nesne örneğine ihtiyaç duymadan bu
metodu çağõrabilecektir. Metodumuz HttpResponseSubstitutionCallback delegate'inin
işaretleyebileceği bir metot olmak zorunda olduğu için burada bir de HttpContext tipinden bir
metot parametresine ihtiyacõmõz vardõr. Bu parametre gelen istek ile ilgili bilgilerin
taşõnmasõnõ sağlar fakat pek kullanmaz. Böylece yazõlacak metodun detaylarõnõ irdelemiş
olduk. Peki metodu nasõl çağõracağõz. Aşağõdaki kodlarda görüldüğü gibi bir sayfa
tasarlayalõm.
......
<%@ OutputCache Duration="30" VaryByParam="none" %>
......
......
<form id="form1" runat="server">
<div>
Önbellekten gelen zaman: <%= DateTime.Now.ToLongTimeString() %>
<br /><br />
Dinamik zaman:
<% Response.WriteSubstitution(new
HttpResponseSubstitutionCallback(DinamikIcerik)); %>
</div>
</form>
.....
41
Resim: Post-Cache Substitution yolunu kullandõğõmõzda sadece belirli bir alanõn
dinamik oluşmasõnõ sağlayabiliriz.
- Substitution Kontrolü
Post-Cache Substitution yolu yazõlan metodu işaretlemede biraz zorlayõcõ olduğu için bu tip
durumlarda Substitution kontrolünü kullanmak daha kolay bir çözüm olabilir. Aslõnda bu iki
yolda da yapõlan işlemler aynõdõr, sadece kontrol üzerinde çalõştõğõmõzda metodu
işaretlememiz daha pratik olacaktõr. Aşağõdaki kodlarda Substitution kontrolünün sayfaya
nasõl uygulanabileceğini görebiliriz.
......
<%@ OutputCache Duration="30" VaryByParam="none" %>
......
......
<form id="form1" runat="server">
<div>
Önbellekten gelen zaman: <%= DateTime.Now.ToLongTimeString() %>
<br /><br />
Dinamik zaman:
<asp:Substitution ID="Substitution1" runat="server" MethodName="DinamikIcerik" />
</div>
</form>
.....
42
belirlemek yeterli olacaktõr. Böylece sayfadaki Substitution kontrolünün içeriği dinamik şekilde
oluşturulacaktõr. Substitution kontrolünün içeriği dõşõnda kalan bölgelerin içerikleri ise
önbellekten getirilecektir.
SqlCacheDependency çok detaylõ bir mevzu olduğu için başlõ başõna bir makale olarak ele
almakta fayda olabilir. Biz burada olabildiğince kõsa bir şekilde bu mekanizmayõ incelemeye
ve uygulamalarda nasõl kullanabileceğimizi göreceğiz. Öncelikli olarak
SqlCacheDependency'nin uygulama ve veritabanõ tarafõndaki bileşenlerini inceleyelim.
Veritabanõndaki bir tablonun değişimine göre önbellekleme işlemleri yapabilmek için mutlaka
veritabanõ ile bütünleşik şekilde çalõşmak, yani veritabanõ içerisinde bazõ nesneleri kullanmak
gerekecektir. Burada esas alõnacak durum verilerin asõl getirildiği tablonun verilerini kontrol
etmek yerine bizim aracõ bir tablo üzerinden asõl verilerin saklandõğõ tablonun kontrolünü
yapmaktõr. Zira verilerin saklandõğõ tablomuzda binlerce kayõt bile olabilir. Böyle bir tablonun
değişip değişmediğini trigger'lar aracõlõğõyla başka bir tabloya aktarmak ve kontrollerin bu
tablo üzerinden gerçekleştirmek çok daha hõzlõ olacaktõr. Uygulama içerisinde kullanacağõmõz
SqlCacheDependency tipindeki nesnemiz tablonun değişip değişmediğini belirli aralõklarla
veritabanõndan kontrolünü yapacak ve eğer tabloda değişiklik olmuşsa Cache'de saklanacak
verinin değiştirilmesini sağlayacak. Bu işleyişi daha iyi anlamak için aşağõdaki şekil üzerinden
konuşmaya devam edelim.
43
Resim: SqlCacheDependency mekanizmasõnõn çalõşma şekli
Bir projede SqlCacheDependency tekniğini uygulamak biraz zor bir yoldur. Gelin adõm adõm
bu işlemi nasõl gerçekleştirebileceğimize bakalõm.
Adõm-1
SQL Server'da ilgili notification table, trigger ve stored procedure'larõn kurulmasõ gereklidir.
aspnet_regsql.exe aracõ ile bu işlemi kolay bir şekilde gerçekleştirebileceğiz.
aspnet_regsql.exe .NET Framework SDK v2.0 ile birlikte gelen araçlardan biridir. SDK
Command Prompt'ta yazõlacak komutlarla önce ilgili tablonun bulunduğu veritabanõna ilgili
notification table, trigger ve stored procedure'larõn kurulmasõ gerekecektir. Başlat >
Programlar > Microsoft .NET Framework SDK v2.0 > SDK Command Prompt
seçeneğinden komut satõrõnõ açtõktan sonra aşağõdaki resimlerde görülen komutlarõ yazarak
bu işlemi gerçekleştirelim.
44
-E: Windows Authentication ile bağlan
-d AdventureWorks -ed: AdventureWorks veritabanõnõ aktif hale getir
-t Urunler -et: Urunler isimli tabloyu aktif hale getir
anlamõna gelmektedir. Farklõ durumlarda kullanõlabilecek parametreler için Command
Prompt'ta aspnet_regsql -? komutunu yazarak yardõm alabilirsiniz.
Veritabanõ aktif hale geldi. Bu işlem sonunda AdventureWorks veritabanõna notification table
ve stored procedure'lar kuruldu. Bir sonraki adõmda ise artõk ilgili tabloyu aktif hale
getirmemiz gerekecek. Aşağõdaki resimde gördüğümüz komutla da Urunler adõndaki tabloyu
aktif hale getireceğiz.
Bu komut ile de Urunler adõndaki tabloya gerekli trigger ve notification table'a da Urunler
tablosunun kaydõ yeni bir satõr olarak eklendi. Artõk bu tablo üzerinde gerçekleşen
değişiklikleri SqlCacheDependency nesnesi ile takibini yapabilecek ve Cache nesnesinde
saklanan verileri bu değişime göre güncelleyebileceğiz.
Adõm-2
Uygulamanõn SqlCacheDependency nesnesi ile veritabanõna bağõmlõ işlemleri sağlõklõ bir
şekilde gerçekleştirebilmek için web.config dosyasõnda bu işlemi uygulama bazõnda aktif hale
getirmek gerekecektir. Bu işlem için öncelikli olarak web.config dosyasõ içerisine bir
connectionString eklemek, ardõndan da SqlCacheDependency tanõmlamasõnõ yapmak
gerekecektir. Aşağõdaki kodlarda yapõlmasõ gereken tanõmlamalar görülmektedir.
45
Resim: web.config dosyasõna connectionString ekleme ve SqlCacheDependency
ayarlamalarõnõ yapmak
Adõm-3
Uygulamada SqlCacheDependency ile veritabanõna bağõmlõ şekilde Cache'de veri saklama
işlemlerini gerçekleştirmeden önce gerekli altyapõyõ hazõrladõk. Şimdi ise uygulamada
Cache'e atacağõmõz nesnenin SqlCacheDependency ile tablodaki değişimlere göre nasõl
güncellenebileceğine bakalõm. Bu işlem için Cache.Insert metodunun aşõrõ yüklenmiş
versiyonlarõndan birini kullanmamõz gerekecek.
46
protected void Page_Load(object sender, EventArgs e)
{
// Cache'de saklanan nesnenin null olup olmadõğõnõ kontrol ediyoruz. Eğer veritabanõnda
// değişim olursa nesne bellekten kaldõrõlõr; yani null olur. Böylece if bloğu çalõşõr
// ve güncel veriler tekrar alõnõp Cache'e aktarõlabilir.
if (Cache["veriler"] == null)
{
string baglanti = "data source=.; initial catalog=AdventureWorks; integrated
security=true";
string sorgu = "SELECT * FROM Urunler";
SqlDataAdapter da = new SqlDataAdapter(sorgu, baglanti);
DataTable dt = new DataTable();
da.Fill(dt);
47
kaldõrõlacak ve sayfanõn bu esnadan sonraki ilk çalõşmasõnda da Cache'e güncel veriler
atõlacaktõr. Böylece zamana bağõmlõ bir kontrol söz konusu olmadan verinin değişimine
bağõmlõ bir işlem gerçekleştirilebilecektir.
ASP.NET 2.0 öncesinde bir sayfada bulunan veri kontrollerini DataSet vb. veri kontrollerine
bağlayarak veri işlemleri gerçekleştiriyorduk. ASP.NET 2.0 ile birlikte gelen SqlDataSource,
AccessDataSource, ObjectDataSource gibi DataSource kontrolleri ile birlikte veri bağlama
işlemlerini artõk daha kolay ve pratik bir şekilde gerçekleştirebilmekteyiz. Bu yeni ASP.NET
kontrollerinin önbellekleme işlemlerini kolay bir şekilde gerçekleştirmemizi sağlayan
özelliklerinden biri de önbellekteki verilerle çalõşabilmesidir.. EnableCaching özelliğinin true
olarak ayarlanmasõ ve CacheDuration özelliğinin saniye cinsinden bir değere atanmasõ
durumunda bağlanan veriler belirli bir süre boyunca önbelleğe alõnacak ve buradan
okunacaktõr. Yine SqlCacheDependency özelliği ile bir SqlDataSource veri kaynağõnõn SQL
Server'daki tablonun değişim durumuna göre önbellekte saklanmasõ sağlanabilmektedir.
Aşağõdaki örnek kodlarda SqlDataSource kontrolünün SqlCacheDependency özelliği ile
veriyi önbellekte saklayabilmesi sağlanmaktadõr. Burada SqlCacheDependency özelliğinin
aldõğõ değer advConnDepend:Urunler şeklindedir. advConnDepend web.config dosyasõnda
tanõmlanan SqlCacheDependecy veritabanõnõn adõ, Urunler ise tablonun adõdõr.
Cache işlemlerinde kullanõlan CacheDependency sõnõfõ ASP.NET 1.1 sürümünde sealded bir
sõnõftõ ve kalõtõmda kullanõlamõyordu. ASP.NET 2.0 ile birlikte artõk normal bir sõnõf olarak
tanõmlanan CacheDependency sõnõfõ sayesinde kendi sõnõflarõmõzõ CacheDependency
sõnõfõndan kalõtabilir ve Cache'de veri saklama işlemlerinde kullanabiliriz. Böylece sadece
dosya ve klasör değişimlerine bağõmlõ olmaksõzõn, kendi özel durumlarõmõza göre sõnõfõmõzõ
düzenleyip Cache'de saklanacak verilerin bağõmlõlõk durumlarõnõ belirleyebiliriz.
48
GridView'e Programatik Veri Bağlamada Sayfalama
ve Sõralama İşlemleri
31 Ekim 2007
Gridview kontrolü ile web uygulamalarõnda kompleks veri işlemlerini dahi çok kolay bir
şekilde gerçekleştirebildiğimizi eminim ki çoğumuz oldukça iyi biliyoruz. Özellikle tasarõm
aşamasõnda Visual Studio 2005 arayüzünün sunduğu olanaklar ile (Wizard'lar, properties
penceresi, vb.) neredeyse kod yazmadan dahi bu işlemleri yürütebilmekteyiz. Fakat
profesyonel bir uygulama geliştirirken gridview kontrolünü bu araçlarõ kullanmadan
programatik yollarla kullanma ihtiyacõmõz olabilir. Böyle bir durumda da klasik
alõşkanlõklarõmõz DataTable ve DataSet nesneleri ile çalõşmamõz gerekecektir. Tabii ki bu tip
nesnelerle gridview kontrolüne programatik olarak veri bağlama işlemleri az önce
bahsettiğimiz araçlarla yapõlan işlemlere göre biraz daha uzun ve zor olacaktõr. Bu makalede
gridviewe programatik olarak veri bağlama işlemlerinde verileri sayfalama ve sõralama
işlemlerini ne şekilde yürütebileceğimizi ele alacağõz.
Default.aspx
Default.aspx.cs
49
SqlConnection conn = new SqlConnection("data source=.; database=AdventureWorks;
integrated security=true");
SqlCommand cmd = new SqlCommand("Select ProductID,Name,Color From
Production.Product Where ListPrice > 1500", conn);
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
da.Fill(dt);
Sayfamõzõ çalõştõrdõğõmõzda herhangi bir sorunun olmadõğõnõ ve verilerin düzgün bir şekilde
listelendiğini görebiliriz. Fakat başka bir sayfadaki verileri görüntülemek istediğimizde veya
herhangi bir kolona göre sõralama yapmaya çalõştõğõmõzda aşağõdaki resimlerde görülecek
şekilde hatalarla karşõlaşõrõz.
50
Resim: Sõralama işlemi yapõldõğõ esnada hata alõrõz
Bu hatalarõ almamõzõn sebebi gridviewi programatik olarak veriye bağladõğõmõz için ilgili
sayfalama ve sõralama işlemlerini de bizim belirlememiz gerektiğidir. Aldõğõmõz hatalar "The
GridView 'gvUrunler' fired event XXX which wasn't handled." şeklindeydi ki XXX
kõsmõndaki kelimeler de aslõnda ilgili event'lerin isimleridir. Burada bahsedilen hata gridview
ile ilgili daha önceden ele alõnmamõş belirli bir event'in fõrlatõlmasõdõr. Zira gridview birçok
işlemde olduğu gibi sayfalama ve sõralama işlemlerinde de arka planda ilgili eventleri
gerçekleştirmektedir. Bizim programcõ olarak burada ilgili eventleri yakalayacak olan
metotlarõ oluşturmamõz ve kodlamamõz gerekecektir. Sayfalama işlemi için ele alõnacak event
PageIndexChanging, sõralama işlemlerinde ise Sorting'dir. Öncelikli olarak gerekli
delegate'ler aracõlõğõyla bu eventleri birer metoda bağlõyor ve metotlarõn içerisini
dolduruyoruz. Aşağõdaki kodlarda bu işlemlerin ne şekilde yapõldõğõ görülmektedir. Burada
ilgili metotlara aktarõlan ikinci event parametresi bizim açõmõzdan oldukça önemlidir. Zira
sayfalama esnasõnda çalõşacak GridView1_SelectedIndexChanging metodundaki
GridViewSelectEventArgs tipindeki e parametresi ve sõralama işlemi esnasõnda çalõşacak
olan GridView1_Sorting metodundaki GridViewSortEventArgs tipinden e parametresi
buradaki eventler gerçekleşirken önemli bilgileri taşõmaktadõr.
Default.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
........
gvUrunler.AllowSorting = true;
gvUrunler.AllowPaging = true;
gvUrunler.PageSize = 10;
// Sayfalama ve sõralama event'lerini metotlara bağlõyoruz
gvUrunler.PageIndexChanging += new
GridViewPageEventHandler(gvUrunler_PageIndexChanging);
gvUrunler.Sorting += new GridViewSortEventHandler(gvUrunler_Sorting);
gvUrunler.DataSource = dt;
gvUrunler.DataBind();
}
51
// Sayfalama işleminde; yani PageIndexChanging event'i tetiklendiğinde çalõşacak metot
void GridView1_SelectedIndexChanging(object sender, GridViewSelectEventArgs e)
{
gvUrunler.PageIndex = e.NewSelectedIndex;
gvUrunler.DataBind();
}
// Veriyi tekrar yüklemeden önce sõralanacak alanõ ve sõralama kriterini belirlemek gerekir.
// DataTable nesnesini tekrar elde edip, görünümünü(DataView) değiştiriyoruz
DataTable dt = (DataTable)gvUrunler.DataSource;
dt.DefaultView.Sort = ViewState["siralananKolon"].ToString() + " " +
ViewState["siralamaYonu"].ToString();
gvUrunler.DataBind();
}
52
- PageIndexChanging event'i için yazõlan metotta: e parametresi çalõşma zamanõ esnasõnda
gridview ile ilgili bilgileri taşõr. e nesnesinden erişeceğimiz NewSelectedIndex isimli özelliği
bize o an istenen sayfa indeks numarasõnõ getirir. Burada yapacağõmõz işlem bu indeks
numarasõnõ elde edip gridviewin o anki PageIndex özelliğine eşitlemek. Ardõndan da
gridviewin görünümünü güncellemek için yeni verilerle yüklenmesini sağlamak
gerekecektir(DataBind metodu ile)
- Sorting event'i için yazõlan metotta: Burada ele alacağõmõz işlemler biraz daha karmaşõk
olacaktõr. Zira PageIndexChanging eventinde ihtiyacõmõz olan sayfanõn indeks numarasõnõ e
parametresinden elde edebiliyoruz. Sorting eventinde, yani sõralama işleminde ise iki bilgiye
ihtiyacõmõz olacaktõr; birincisi sõralama yapõlacak kolonun adõ, ikincisi ise sõralamanõn yönü
(Ascending, Descending). Yine metotla birlikte gelen e parametresi bize önemli bilgileri
taşõmaktadõr. Fakat e parametresi sõralanacak kolonun adõnõ doğru olarak getirse bile
sõralama yönünü her defasõnda Ascending olarak getirecektir. Bundan dolayõ ihtiyacõmõz olan
iki değerden birisine erişebilmek için ekstra çaba sarfetmemiz gerekecek. Burada sõralama
işlemi yapõlan kolona bir kez tõklanõrsa sõralama işlemini Ascending(ASC), ardõndan bir kez
daha aynõ kolona tõklanõrsa da Descending(DESC) yapmamõz gerekecektir. Özetle, her
zaman bir kolona ilk tõklandõğõnda ASC, ikinci tõklamada DESC, üçüncü tõklamada ASC...
şeklinde devam edecektir. Yine sayfa postback işlemini yaptõğõnda bir önceki sõralama
işleminin yönünü bilmemiz ve değiştirmemiz gerekecektir. Bu nedenle ViewState nesnesi
içerisinde bu değeri saklayarak her postback işleminde o anki sõralanacak kolonun durumuna
göre sõralama yönünü değiştirmemiz gerekecek. Örneğin Name kolonunu ilk sõralamamda
SQL cümlesinin sonuna Name ASC, Name kolonuna ikinci kez tõklandõğõnda Name DESC
şeklinde bir sõralama yapmamõz gerekecek. Bu esnada eğer ki Color sütununa tõklanõrsa
Color ASC şeklinde işleme devam etmemiz gerekecektir. Bu durumlarõ ele alabilmemiz için
gerekli koşullarõ bu metot içerisinde oluşturuyoruz. Son işlem olarakta DataTable
nesnesindeki verileri tekrar sõralayarak gridviewe yeniden bağlamamõz gerekecektir.
Gridviewin DataSource özelliğinden object tipinde elde ettiğimiz nesneyi önce DataTable
tipine cast ediyoruz. Ardõndan da datatable'õn görünümünü DataView nesnesi olarak elde
etmemizi sağlayan DefaultView özelliğine ait Sort özelliğine de sõralama cümlemizi
belirmemiz gerekecektir. Son olarakta gridview nesnesini DataBind metodu ile tekrar
yükleyecek olursak artõk verilerimiz düzgün bir şekilde sõralanarak görüntülecektir.
53
GridView Kayõtlarõnõ Okumak ve Metin Dosyasõna
Aktarmak
01 Kasõm 2007
ASP.NET 2.0 ile gelen yeni veri kontrollerinden GridView web uygulamalarõnda kullandõğõmõz
en zengin veri kontrolüdür. Bir programcõnõn birçok ihtiyacõnõ karşõlayabilecek gelişmiş
özelliklere sahip olan bu kontrolle tek satõr kod yazmadan dahi veriye bağlanabilmekte,
getirilen verileri sayfalayõp sõralayabilmekte, hatta yine kod yazmadan otomatik güncelleme
ve silme işlemlerini de gerçekleştirebilmekteyiz. Bu kontrol ile ilgili olarak programcõya düşen
görev ise kontrolün varolmayan özelliklerini çalõştõrabilecek işlemleri yapmak kalõyor. Bu
işlemlerden birisi de GridView'deki verilerin farklõ bir ortama aktarõlmasõ olacaktõr. Farklõ
ortamdan kastõmõz farklõ bir tabloya, farklõ bir nesneye veya bir dosyaya olabilir. Bu
makalemizde GridView kontrolünde bulunan verilere programatik yollarla nasõl
erişebileceğimize ve bu verileri txt uzantõlõ olarak bir metin dosyasõna nasõl
dönüştürebileceğimizi göreceğiz.
54
Şekil: Butona tõklandõğõnda o an gridviewde bulunan satõrlarõn Name alanlarõ sayfaya
yazdõrõldõ
Buradaki okuma işlemi belirli bir hücre üzerinden gerçekleştirildi. Eğer tüm hücreleri okumak
istersek sütun sayõsõnõ bilmek ve ona göre de foreach döngüsünün içerisine bir for döngüsü
açmak gerekecektir. Gridviewdaki sütunlar Columns kolleksiyonunda saklandõğõ için bu
kolleksiyonun Count özelliği bize toplam sütun sayõsõnõ getirecektir. Aşağõdaki kodlar ile de
griddeki tüm ve satõrlarõn tüm hücrelerini okuyabiliriz.
55
Gridview'õn Rows kolleksiyonu, sadece sayfa çalõştõrõldõğõ anda görüntülenen kayõtlarõ
içerisinde saklayacaktõr. Eğer grid kontrolünü sayfalandõrõlmõş şekilde kullanõyorsak ve birden
fazla sayfada veriler tutuluyorsa yukarõdaki kodlar çalõştõrõldõğõnda sadece o an üretilen
sayfada grid içerisine hangi satõrlar geliyorsa o satõrlarõn bilgilerine erişebiliriz. Eğer
amacõmõz griddeki bilgileri bir dosyaya aktarmak ise olaya farklõ yaklaşõmlarõmõz olabilir.
Sadece o an gridde görüntülenen satõrlarõ dosyaya kaydetmek isteyebileceğimiz gibi, belirli
sayõdaki satõrõ veya gride bağlanan tüm kayõtlarõda dosyaya kaydetmek isteyebiliriz.
Dilerseniz gridviewdaki kayõtlarõ metinsel bir dosyaya kaydetme işlemini gerçekleştiren ve bu
üç farklõ durumu gözönüne alan küçük bir uygulama yazalõm. Sayfaya ekleyeceğimiz
gridview kontrolünü bir SqlDataSuorce kontrolüne bağlayalõm. Sorgu olarak yukarõdaki
sorguyu aynen kullanabiliriz. Yine Update,Delete işlemleri içinde gerekli sorgularõ oluşturalõm.
Burada her ne kadar Update-Delete işlemi yapmayacak olsakta gride eklenecek Update-
Delete butonlarõnõn metinsel dosyamõza eklenmesini de nasõl engelleyebileceğimizi ele
alacağõz. GridView dõşõnda sayfaya bir RadioButtonList kontrolü ve bir de Button kontrolü
ekleyelim. RadioButtonList kontrolü ile sadece bu sayfadaki verileri kaydetme, ilk 50 veriyi
kaydetme ve tüm verileri kaydetme seçeneklerini ele alacağõz. Sayfamõzõn tasarõmõ ve
kodlarõ aşağõdaki gibi olacaktõr.
56
SortExpression="ModifiedDate" />
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$
ConnectionStrings:AdventureWorksConnectionString %>"
SelectCommand="SELECT [ProductID], [Name], [Color], [ListPrice], [ModifiedDate] FROM
[Production].[Product]"
DeleteCommand="DELETE FROM [Production].[Product] WHERE [ProductID] =
@ProductID"
UpdateCommand="UPDATE [Production].[Product] SET [Name] = @Name, [Color] =
@Color, [ListPrice] = @ListPrice, [ModifiedDate] = @ModifiedDate WHERE [ProductID] =
@ProductID">
<DeleteParameters>
<asp:Parameter Name="ProductID" Type="Int32" />
</DeleteParameters>
<UpdateParameters>
<asp:Parameter Name="Name" Type="String" />
<asp:Parameter Name="Color" Type="String" />
<asp:Parameter Name="ListPrice" Type="Decimal" />
<asp:Parameter Name="ModifiedDate" Type="DateTime" />
<asp:Parameter Name="ProductID" Type="Int32" />
</UpdateParameters>
</asp:SqlDataSource>
<asp:RadioButtonList ID="rblSecim" runat="server">
<asp:ListItem Value="0">Sadece bu kayõtlar</asp:ListItem>
<asp:ListItem Value="1">İlk 50 kayõt</asp:ListItem>
<asp:ListItem Value="2">Tüm kayõtlar</asp:ListItem>
</asp:RadioButtonList>
<asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Kayõtlarõ Kaydet"
Width="153px" />
57
gidilecek ve ilk 50 kayõt yüklenecektir. Böylece ilk 50 kaydõn txt formatõnda download
edilmesini sağlayabileceğiz.
- Tüm kayõtlar seçeneği seçilirse gridview kontrolünün AllowPaging özelliğini false
yapmamõz ardõndan DataBind metodunu çağõrmamõz gerekecek. Böylece yapõlacak
postback işleminin sonucunda gridde sayfalama yapõlmayacağõ için tüm kayõtlar yüklenecek,
dolayõsõyla da download işleminde tüm kayõtlar dosyaya yazdõrõlabilecek.
Sayfaya eklediğimiz butonun click eventine aşağõdaki kodlar eklendiğinde grid kontrolündeki
verileri istenilen şekilde download işlemine hazõrlamõş oluruz. Kodlarõn en alt kõsmõnda da az
sonra yazacağõmõz ve metinsel dosyaya kaydetme işlemini üstlenecek olan metodu
çağõrõyoruz.
// Sadece bu kayõtlar şõkkõ seçilirse ek bir işlem yapmaya gerek yoktur. Diğer iki şõkkõ ele
alõyoruz.
if (rblSecim.SelectedIndex == 1) // İlk 50 kayõt
{
gvUrunler.PageIndex = 0;
gvUrunler.PageSize = 50;
}
else if (rblSecim.SelectedIndex == 2) // Tüm kayõtlar
{
gvUrunler.AllowPaging = false;
}
gvUrunler.DataBind();
TextKaydet(); // Bu metot az sonra yazacağõmõz ve kayõtlarõ metinsel dosyaya aktaracak
olan metot
}
58
yenilenmeyecektir, dolayõsõyla da bizim design kõsmõnda yaptõğõmõz ayarlamalar geçerli
kalacaktõr. Aşağõdaki kodlarda da grid içerisindeki verileri metinsel dosyaya kaydetme
işlemini üstlenecek TextKaydet metodu bulunmaktadõr.
// Okuma işlemi bitti ve değişken hazõr. Artõk metinsel dosyanõn oluşturulmasõ ve kullanõcõ
tarafõndan
// yüklenmesi için gerekli işlemleri gerçekleştiriyoruz
Response.Clear();
Response.AddHeader("content-disposition", "attachment;filename=Urunler.txt");
Response.ContentType = "application/vnd.text";
Response.Write(sb.ToString());
Response.End();
}
59
Şekil: Sayfayõ çalõştõrdõğõmõzda işaretlediğimiz seçeneğe göre txt uzantõlõ dosyayõ
bilgisayarõmõza indirebiliriz
Böylece gridview içerisindeki kayõtlarõ okuma işlemini gerçekleştirerek alõnan bilgileri txt
uzantõlõ olarak metinsel bir dosya içerisinde sunmuş olduk. Özellikle basit anlamda kullanõcõ
arayüzlerinde yapõlan listeleme ve raporlama işlemlerinde işimizi görebilecek tarzda küçük bir
web uygulamasõ geliştirmiş olduk. Benzer yollarla okunan verileri başka bir kaynağa (farklõ bir
sunucudaki tabloya veya bir Excel dosyasõna gibi) aktarabiliriz.
60
GridView'deki Kayõtlarõ Excel Dosyasõna Aktarmak
02 Kasõm 2007
Önceki makalemizde gridviewdeki satõrlarõ okuma işlemini detaylõ şekilde ele aldõğõmõz için
bu konulara değinmeden griddeki verileri Excel dosyasõna nasõl aktarabileceğimize
geçiyorum. Öncelikli olarak burada yapõlan işlemde veriler Excel gibi bir dökümana
aktarõlacaktõr; yani içerisinde verileri çok daha farklõ bir formatta tutan bir dosya tipi. İşin en
güzel ve kolay tarafõ şu ki; kullanacağõmõz gridview nesnesi içerisindeki kayõtlarõ çok fazla
işlem yapmamõza gerek kalmadan kolay bir şekilde Excel dosyasõna aktarabileceğiz. Bu
işlemi yaparken iki farklõ yolu seçebiliriz:
Buradaki ilk yolu gördükten sonra "Neden Table nesnesi üzerinden bu işlemi yürütelim ki?"
gibi bir soru işareti aklõmõza gelebilir. Fakat gridview'daki kayõtlarõ direkt olarak bir Excel
dökümanõna aktarma işleminde bazõ sõkõntõlarla ve hatalarla karşõlaşõlabilmektedir. Açõkcasõ
internetten yapmõş olduğum araştõrmalarda bu işlemi gridviewdaki satõrlar üzerinden direkt
Excel'e aktarma yolunu seçersek hesapta olmayan hatalarla karşõlaşabilme durumumuz
olabiliyor. Bu nedenle 2. yolu kullanarak bu işlemi yürütmek daha sağlõklõ olabilir. Yine Table
nesnesi kullanõldõğõnda elde edilen veriler üzerinde değişiklik yapma gibi bir avantajõmõzda
olabildiği için bu yol biraz daha esnektir diyebiliriz. Dilerseniz ilk yolu kullanarak gridviewin
satõrlarõnõ Excel dosyasõna nasõl aktaracağõmõza bakalõm. Sayfamõza bir gridview kontrolü, bir
radiobuttonlist kontrolü ve buton kontrolü ekleyerek sayfamõzõ tasarlayalõm. Aşağõda
sayfamõzõn görünümü bulunmaktadõr.
61
Şekil: Kullanacağõmõz sayfanõn tasarõmõ ve kontrol isimleri
RadioButtonList'ten yapõlan seçim işlemine göre farklõ şekilde verileri Excel'e aktarmamõz
gerekecek. Yine gridviewde Edit-Delete-Select gibi command butonlarõ içeren bir kõsõm
olursa bu kõsmõ dosyaya yazdõrmak istemeyebiliriz. Bu işlem için GereksizKolonlariSil
adõnda bir metot oluşturup, gridview kontrolünün dosyaya yazõlmaya hazõr hale getirilmesi
işlemini aşağõdaki kodlarda görüldüğü gibi butonun click eventinde gerçekleştiriyoruz.
Yapõlan işlemlerle ilgili bilgiler yorum satõrlarõnda bulunmaktadõr.
GereksizKolonlariSil();
62
{
// Eğer Select, Edit ve Delete gibi CommandFieldlar aktif ise bu butonlarõn bulunduğu
sütunu gridden çõkarõyoruz
for (int i = 0; i < gvUrunler.Columns.Count; i++)
{
if (gvUrunler.Columns[i] is CommandField)
gvUrunler.Columns.RemoveAt(i);
}
}
Bu işlemlerle birlikte gridview kontrolünün içeriğini Urunler.xls olarak bir Excel dosyasõna
yazdõrabiliriz. Fakat sayfayõ çalõştõrõp dosyaya aktarma işlemini yaptõğõmõz esnada bir hata
almamõz gerekecektir. Zira yukarõda gvUrunler isimli gridviewõn RenderControl metodunu
çalõştõrmamõz çalõşma zamanõ esnasõnda HttpException istisnasõna sebep olacaktõr.
63
Şekil: gvUrunler'in RenderControl metodunu kullanarak yaptõğõmõz işlem başarõsõz
olacak ve çalõşma zamanõnda HttpException istisnasõ alacağõz
Buradaki hatanõn sebebi ASP.NET sayfasõnõn yapõsõ itibariyle çalõşma zamanõ esnasõnda
içerisinde bulunan bir kontrolü RenderControl metodu ile çözümlememize izin
vermemesidir. Bu hatayõ düzeltebilmek için Page class'õ içerisinde virtual olarak tanõmlanmõş
olan VerifyRenderingInServerForm isimli metodu ezmek(override işlemi) gerekecektir. Bu
işlemi Visual Studio 2005 editöründe gerçekleştirdiğimizde metodun gövdesinde otomatik
olarak base class'taki metodu çağõran base.VerifyRenderingInServerForm(control);
ifadesi bulunacaktõr. Bu metot parametre olarak Control tipinden nesneler almaktadõr ki; bu
nesneler sayfamõz içerisinde bulunan runat="server" tanõmlamasõ içeren sunucu
kontrollerimizdir. Bizim burada yapmamõz gereken işlem metot içerisinde gelen kontrole
bakmak ve eğer gridview kontrolü ise bu metodun çağrõlmasõnõ engellemek olacaktõr.
Aşağõdaki kodlarda bu işlemi nasõl yapacağõmõz görülmektedir.
64
Şekil: Seçime göre oluşan Urunler.xls dosyamõz
65
// Gridview'daki satõrlarõ döngü ile Rows kolleksiyonundan alõyor ve tabloya ekliyoruz
foreach (GridViewRow row in gvUrunler.Rows)
{
// GridViewRow class'õ TableRow class'õndan kalõtõldõğõ için Add metoduna parametre
olarak verilebilir
tablo.Rows.Add(row);
}
Response.Clear();
Response.AddHeader("content-disposition", "attachment;filename=Urunler.xls");
Response.ContentType = "application/ms-excel";
Response.Write(stringYaz.ToString());
Response.End();
}
Böylece gridview içerisinde yer alan kayõtlarõ bir Excel dökümanõna nasõl aktarabileceğimizi
iki farklõ yolu kullanarak görmüş olduk.
66
ASP.NET 3.5 ile Gelen Yenilikler
11 Aralõk 2007
.NET Framework 3.5 sürümünün resmen duyurulmasõyla ASP.NET'te 3.5 sürümüne ulaşmõş
oldu. Bildiğimiz gibi .NET Framework 3.0 ile önceki mimaride değişiklik olmamõştõ ama
Windows Presentation Foundation, Windows Communication Foundation, Workflow
Foundation ve Cardspace gibi yeni teknolojiler mimariye eklenmişti. 3.5 sürümüyle birlikte
ise önceki mimaride bazõ değişiklikler, yeni eklentiler ve yeni tipler getirildi. Özellikle Linq
(Language Integrated Query) adõndaki Dil ile Bütünleşik Sorgulama modeli bu sürümdeki
en göze çarpan yenilik oldu. Bu yazõmõzda Framework'ün ASP.NET kõsmõnda bizi ne gibi
yeniliklerin beklediğini incelemeye çalõşacağõz.
Aslõnda ASP.NET'i .NET Framework'ün 1.0 sürümünden beri takip edenler 1.1 sürümünden
2.0 sürümüne geçişteki köklü ve önemli yenilikleri hatõrlayacaktõr. Yazõmõza giriş yaparken
hemen şunu belirtelim ki 2.0 sürümünden 3.5 sürümüne geçişte bu denli büyük ve köklü
yeniliklerimiz olmayacak. Fakat AJAX ve Linq temelli olarak ta iki köklü yeniliğin geldiğini de
belirtmekte fayda var. Bir diğer konu da ASP.NET 3.5'in ardõndan yakõnda resmen
duyurulmasõ beklenen ASP.NET 3.5 Extension paketi. (Belki de yazõyõ okuduğunuzda bu
paket resmen duyrulmuş olacaktõr) ASP.NET MVC (Model View Controller) Framework, yeni
AJAX ve veri kontrolleri ile SilverLight kontrollerinin ekleneceği bu paketinde mimariye dahil
olmasõyla birlikte aslõnda daha da önemli yeniliklerin bizi beklediğini söyleyebiliriz.
Makalemizin son kõsmõnda bu paket ile ilgili de önemli bilgileri sizlerle paylaşmaya
çalõşacağõm.
ASP.NET 3.5 ile gelen en önemli ve köklü iki yenilik AJAX Extension entegrasyonu ve Linq
desteğidir. Aslõnda Linq C# 3.0 ile birlikte gelen bir yenilik ve platformdaki tüm uygulamalarda
kullanabileceğimiz gibi ASP.NET uygulamalarõnda da kullanabileceğiz. Aşağõdaki başlõklarda
gelen yenilikleri inceliyoruz.
.NET Framework 3.5 ile birlikte duyurulan yeni uygulama geliştirme ortamõmõz Visual Studio
2008'de açõlan her ASP.NET 3.5 artõk AJAX destekli olarak oluşturuluyor. Yani AJAX
Extension kontrollerini kullanarak hõzlõ şekilde AJAX uygulamalarõ geliştirebiliyoruz.
Yapõlacak tek işlem sayfaya gerekli AJAX Extension kontrollerini eklemek ve gerekli işlemleri
67
yapmak. Kurulum yapmaya, kontrolleri ToolBox'a eklemeye ve proje oluştururken ayrõ bir
proje şablonu seçmeye gerek yok. Bu sürümü ile birlikte bazõ eksiklikler ve sorunlar
giderilerek artõk ASP.NET AJAX'õn sunucu kontrolleriyle tam uyumlu şekilde çalõşmasõ da
sağlanõyor. Visual Studio 2008 ile birlikte Control Toolkit'te yer alan kontrollerin varolan
sunucu kontrollerine çok kolay şekilde entegre edilebilmesi de işimizi kolaylaştõracak bir
yenilik olarak göze çarpõyor. Önceki sürümde olduğu gibi AJAX kontrollerimiz
System.Web.UI isim alanõna eklenmiş durumda. Aşağõda Microsoft'un sunduğu .NET
Framework 3.5 isim alanlarõ ve sõnõflarõ posterinden System.Web.UI kesiti bulunmaktadõr.
(ScriptManagerProxy ve Timer kontrolleri nedendir bilinmez bu postere eklenmemiş ama
aşağõda güncellediğim posterin ilgili kesitini görebilirsiniz.)
68
3. Yeni Veri Kontrolleri
ASP.NET 3.5 ile gelen AJAX kontrolleri dõşõnda kontrol kütüphanemizde üç yeni kontrol daha
ekleniyor: ListView, DataPager ve LinqDataSource. ListView ve DataPager kontrolleri ile artõk
daha esnek veri görüntüleme işlemleri yapabiliyorken, LinqDataSource kontrolü ile de tüm
veri kontrollerini Linq sorgularõnõn sonucuna bağlayabiliyoruz.
- ListView
ListView veri görüntüleme, veri seçme-ekleme-güncelleme-silme gibi işlemleri
yapabileceğimiz bir kontrol. İlk bakõşta GridView kontrolüne benzetebileceğimiz bu kontrolün
GridView'den üç temel farklõlõğõ bulunmaktadõr. Bildiğimiz gibi GridView ile veri seçme-
güncelleme-silme gibi işlemleri otomatik olarak yapabiliyorken veri ekleme işlemini bu şekilde
gerçekleştiremiyorduk; ancak oluşturulacak bir template içerisinde ekstra işlemler yaparak bu
işlemi yapabiliyorduk. ListView ile artõk veri ekleme işlemlerini de otomatik olarak
gerçekleştirebileğiz (1. farklõlõk). ListView ile sayfalama işlemleri yaparken artõk DataPager
(bu yeni kontrole az sonra değineceğiz) gibi özel bir kontrol ile sayfalama template'ini de
özelleştirebiliyoruz (2. farklõlõk). Yine tasarõm aşamasõnda ListView kontrolü ile daha
özelleştirilebilir veri görüntüleme işlemleri yapabiliyoruz ki bu belki de ListView'in
GridView'dan en önemli farklõlõğõ (3. farklõlõk). ListView kontrolünü aslõnda GridView ve
DataList kontrolünün harmanlaşmõş versiyonu gibi düşünebiliriz. Tõpkõ GridView'deki gibi
kolay şekilde tüm veri işlemlerimizi çözebilirken, DataList'te olduğu gibi de arka planda HTML
kodlarõnõ kullanarak kontrolün görünümünü çok kolay şekilde istediğimiz gibi
değiştirebiliyoruz. ToolBox'ta Data Controls kõsmõnda yer alan bu kontrolü basit bir şekilde
nasõl kullanabileceğimizi görelim. Bu örnekte ListView'i bir SqlDataSource kontrolü ile SQL
Server veritabanõndaki bir tabloya bağlõyoruz. Bu kõsõm aslõnda önceki veri kontrollerinde
olduğu gibi, fakat bağlama işleminin ardõndan verilerin nasõl görüntüleceğini belirlememiz
gerekecektir. ListView'in sağ üst köşesindeki Smart-tag ikonuna tõklayarak açõlan pencereden
Configure ListView linkini seçiyoruz. Açõlan pencereden verilerin nasõl listeleneceğini, stil
ayarlarõnõ ve veri ekleme, güncelleme, silme, sayfalama işlemlerini aktif hale getirip
getiremeceğimizi belirliyoruz. Aşağõdaki resimde karşõmõza çõkacak pencere ve
yapabileceğimiz seçimler görünmektedir.
69
Resim: ListView'in "Configure ListView" penceresinden yapõlacak seçimler ve
açõklamalarõ
Aslõnda yukarõdaki resimde ilk ilgimizi çekecek durumlardan birisi verileri artõk yan yana da
dizebildiğimiz olabilir. ListView tõpkõ DataList kontrolü gibi arka planda HTML kodlarõ ile
özelleştirilebildiği için artõk görüntülenecek verileri esnek şekilde kullanõcõlara
görüntületebiliriz. Bu şekilde yine görsel kõsõmdan yapacağõmõz işlemlerle veriye çok kolay
erişebiliriz. ListView ile ilgili olarak kullanabileceğimiz bazõ önemli özellikler (property) ve
açõklamalarõnõ aşağõda bulabilirsiniz.
70
Resim: ListView ile görüntülenen veriler
- DataPager
ListView ile bütünleşik şekilde kullanabileceğimiz bu kontrol ile ListView'in veri sayfalama
template'ini şekillendirebilmekteyiz. ListView'in TemplateLayout şablonu içerisine eklenir.
Temel olarak esnek sayfalama template hazõrlamamõzõ sağlayan bu kontrolde ToolBox'õn
Data Controls grubunda yer alõyor. İki farklõ görünüm şekli bulunan bu kontrole eğer
istenilirse TextBox, DropDownList gibi kontroller eklenerek özelleştirebiliriz. Örneğin toplam
20 sayfadan oluşan verilerimizde bir TextBox'a 15 yazarak 15 numaralõ sayfaya gidilmesini
sağlayabiliriz. Burada akla gelen sorulardan birisi şu olabilir DataPager gibi etkin sayfalama
işlemleri yapabilen bu kontrolü sadece ListView kontrolü ile birlikte kullanõlabiliyor.
- LinqDataSourceaSource
LinQ ile yapõlan sorgu sonuçlarõnõ veri kontrollerine bağlanmasõnõ sağlayan kontroldür.
Aslõnda bu kontrolle birlikte .NET Framework 3.5 ve Visual Studio 2008 ile gelen yeni bir
dosya tipinden bahsetmekte fayda olacaktõr: yeni bir dosya eklerken karşõnõza LINQ to SQL
Classes tipi olarak gelen DataBase Markup Language (dbml) dosyalarõ. Gelişmiş bir
projedeki en büyük ihtiyaçlarõmõzdan birisi de veritabanõndaki tablolarõn class olarak
karşõlõklarõnõ uygulamamõzda oluşturmak olacaktõr. Aslõnda entity katmanõ oluşturarak daha
kolay şekilde veri ile çalõşmaktan bahsediyoruz. dbml dosyalarõ veritabanõndaki bir tablonun
tüm özelliklerini taşõyan class'õnõ oluşturmamõzõ sağlar. DataContext tipindeki nesneler
üzerinde Linq sorgularõ çalõştõrabiliriz. LinqDataSource kontrolümüzde bu amaca yönelik
kullanõlabilecek bir kontroldür.
71
gerçekleştirilebilecek. Yine Visual Studio 2008'de yeni bir web projesi oluştururken WCF
Service proje şablonu, projemize yeni bir dosya eklerken WCF Service dosyasõ (.svc)
karşõmõza çõkan yeniliklerden bazõlarõ.
ASP.NET 3.5 ile birlite gelen temel yenilikler bunlar. Gözümüze biraz az gelmiş olabilir ama
Microsoft geçtiğimiz günlerde çõkardõğõ ASP.NET 3.5 Extensions paketi ile artõk ASP.NET
3.5'i daha da güçlü hale getirdi. Bu yeni paket ile gelen yeni kontroller ve MVC Framework ile
artõk daha güçlü ve zengin web uygulamalarõ geliştirebiliyor olacağõz. Aşağõdaki kõsa yazõda
ASP.NET 3.5 Extensions paketini tanõmaya çalõşõyoruz.
Aslõnda Microsoft bunun bir benzerini ASP.NET 2.0'õn ardõndan ASP.NET AJAX Extension'õ
duyurarak yapmõştõ. Şimdi de benzeri bir strateji ile geliyorlar. AJAX ancak 3.5 sürümünde
mimariyle bütünleşti, belki 3.5 Extensions ile gelen yenilikler de ASP.NET 4.0 (böyle bir
sürüm olur mu bilinmez) ile bütünleşik gelecektir. Aslõnda ASP.NET 3.5 Extensions içerisinde
daha önceden duyurulan ASP.NET Futures paketindeki kontroller ile ASP.NET MVC
Framework'ün olduğunu söylesek pek te yanlõş olmaz. Aşağõda bizleri bekleyen yenilikleri
hakkõnda kõsa bilgileri bulabilirsiniz.
1. ASP.NET MVC Framework: MVC yani Model View Controller. MVC mimarisi aslõnda
daha önceden de duyulan bir tasarõm deseniydi (design pattern) programlama dünyasõnda.
Bu yaklaşõmdaki temel mantõk bir web projesini üç temel parçaya bölmek ve yapõlacak işleri
bu parçalar üzerinden yürütmektir. Hazõrladõğõmõz projelerde sõklõkla kullandõğõmõz
uygulamayõ iş katmanõ ile veri katmanõ olarak ayrõ parçalara bölmeyi buradaki yaklaşõm ile
benzeştirebiliriz. Aslõnda temel amaç uygulamayõ işe yarar belirli amaçlarõ olan parçalara
bölmek ve bir parçanõn değişiminden diğer parçalarõn etkilenmesini engellemektir. MVC
uygulamanõn Model, View ve Controller olarak üçe ayrõlmasõnõ benimseyen bir tasarõm
desenidir.
- Model veri ve durum bilgilerini taşõr. Burasõ DataTable, DataSet ve entity katmanõmõzdaki
sõnõflarõn bulunduğu bileşendir.
- View uygulamanõn arayüzlerinin bulunduğu bileşendir. Master sayfalar, aspx ve ascx gibi
kullanõcõnõn görüntüleyeceği dosyalar bu kõsõmda yer alõr.
- Controller ise arayüzler arasõndaki etkileşimi sağlayan, veri nesneleri üzerinde değişiklik
yapõlmasõnõ sağlayan bileşenlerdir. Örneğin, Controller katmanõndaki sõnõflar aracõlõğõyla etkin
URL Mapping işlemi yaparak artõk tarayõcõ üzerinden sayfalara istek yapmak yerine
nesnelere istekte bulunabiliyoruz. Yani URL üzerinden tarayõcõda görüntülenecek nesnenin
render edilmesi sağlanabiliyor.
72
3. Dinamik Veri (Dynamic Data) Desteği: Yine Futures paketinden tanõdõğõmõz bir özellik.
DynamicAutoData, DynamicList, DynamicNavigator, DynamicRssLink gibi bazõ veri
kontrolleri ile bir veritabanõnda yapacağõmõz Select, Insert, Update, Delete gibi işlemleri
neredeyse kod yazmadan gerçekleştirebilmemizi sağlõyor. .NET Framework 3.5 ile gelen
Database Markup Language (dbml) dosyalarõ ile dinamik veri kontrollerini birlikte
düşününce ve üstüne MVC Framework'ü de katõnca bu yeniliklerin MVC'nin Model katmanõnõ
oluşturacağõnõ söyleyebiliriz.
4. SilverLight Desteği: SilverLight artõk ASP.NET ile giderek bütünleşiyor. Tahminen yine
Futures paketindeki Media ve XAML kontrollerinin ekleneceği bu pakette ASP.NET ile
SilverLight'õn entegrasyonunun daha da kolaylaşacak. Yani daha interaktif daha zengin
içerikli sayfalar geliyor.
5. ADO.NET Veri Servisleri (Data Services): ADO.NET Entity Framework adõ verilen bu
pakette ASP.NET 3.5 Extensions ile birlikte duyurulacak. Object Relation Mapping (ORM)
desteği ile daha da güçlenen .NET Framework 3.5'teki veri işlemleri aslõnda bu framework
altõnda toplanõyor gibi. Artõk veri ile ilgili her türlü işlemi oluşturacağõmõz veya SqlMetal.exe
aracõ ile oluşturulacak class'lar ile gerçekleştireceğiz gibi.
ASP.NET 3.5 Futures paketiyle ilgili daha detaylõ bilgi edinmek, bilgisayarõnõza yüklemek ve
kullanmak için http://asp.net/downloads/3.5-extensions/ adresine göz atabilirsiniz.
73
TreeView'da Veritabanõyla ve XML Dosyalarla
Çalõşmak
05 Şubat 2008
ASP.NET 2.0 ile birlikte gelen site navigasyonu kontrolleri ile site haritalarõnõn kullanõcõlara
dinamik menülerle görüntülenmesi sağlanabilmekte ve daha profesyonel görünümler elde
edilebilmektedir. Bu kontrollerden biri olan TreeView’da ağaç görünümünde menüler
oluşturmamõzõ sağlamaktadõr. Genellikle proje içerisinde XML tabanlõ oluşturulan bir
.sitemap dosyasõ ile birlikte kullanõlõr. Sitemap dosyalarõ gerek oluşturulmasõ gerekse site
navigasyon kontrolleri ile kolay ve uyumlu çalõşmasõ açõsõndan biz yazõlõm geliştiricilere
büyük kolaylõklar sağlamaktadõr.
Sitemap dosyasõ belirli standartlar dahilinde yazõlmakta ve genellikle site içerisindeki linklerin
hiyerarşik yapõsõnõ saklamaktadõr. TreeView kontrolü site haritasõnõ taşõmak amacõyla
kullanõlabileceği gibi farklõ içerikleri de ilişkisel şekilde kullanõcõlara sunulmasõnõ da
sağlayabilecek bir yapõya sahiptir. Örneğin kendi hazõrladõğõmõz XML dokümanõndaki verilerin
süzülerek üst düğüm – alt düğüm ilişkisi ile bu kontrole yüklenmesini isteyebiliriz. Böyle bir
durumda akla gelen soru TreeView kontrolünü farklõ yapõdaki XML dosyalarõ ile nasõl
konuşturabileceğimizdir. Makalemizin ilk kõsmõnda bu sorunun çözümünü inceleyeceğiz.
Dilerseniz bu iki işlemin detaylarõnõ incelemeden önce TreeView kontrolünün yapõsõ hakkõnda
önemli bir noktaya değinelim. TreeView kontrolü Nodes koleksiyonu içerisinde TreeNode
tipiden nesneler saklayarak linklerin oluşturulmasõnõ sağlar. Aslõnda sayfa çalõştõrõldõğõnda
TreeView’da görünen tüm linkler birer TreeNode nesnesidir. TreeNode nesnesi de kendi
içerisindeki ChildNodes koleksiyonu içerisinde yine kendi tipinden yani TreeNode nesneleri
taşõyabildiği için iç içe linkler oluşturulabilmektedir. Sitemap dosyasõnõ TreeView kontrolüne
kaynak olarak gösterdiğimizde kullanõlan SiteMapDataSource kontrolünün yapmõş olduğu
işlem .sitemap dosyasõnõn içerisindeki yapõyõ çözümlemek ve bunlarõ TreeNode nesneleri
olarak TreeView kontrolüne bağlamaktõr. Aşağõdaki şekil TreeView kontrolüne bağlanan
TreeNode’larõn yapõsõnõ simgelemektedir.
74
Şekil: TreeView kontrolüne eklenen TreeNode nesnelerinin hiyerarşik yapõsõ
TreeNode sõnõfõnõn (class) yapõcõ metotlarõ (constructor) aracõlõğõ ile farklõ şekilde nesneler
oluşturulabilir. Burada oluşturulan nesneler TreeView kontrolündeki linkler olacağõ için sayfa
yüklendiğinde LinkButton veya HyperLink olarak getirilecektir. Dolayõsõyla oluşturulan link ya
aynõ sayfa üzerinde postback işlemi yapacak ya da başka bir sayfaya link verecektir. Aşağõda
bir TreeNode nesnesinin farklõ oluşturulma şekilleri bulunmaktadõr.
// Oluşan linkin metnini ilk parametre belirler. Bu linke tõklandõğõnda Deger1 değeri ile
postback işlemi yapar
TreeNode anaMenu1 = new TreeNode("Postback Link", "Deger1");
// Bir önceki link gibi çalõşõr. Linkin sol kõsmõnda son parametrede yer alan resim görüntülenir
TreeNode anaMenu2 = new TreeNode("Resimli Link", "Deger2", "menu.jpg");
// Oluşan link 4. parametrede belirlenen sayfaya gider. Son parametre ise hedef sayfanõn
açõlma şeklini belirler (“_blank” yeni bir pencerede açõlmasõnõ sağlar). 3. parametre burada
boş bõrakõlmõştõr fakat geçerli bir resim adresi verilerek linkin solunda resim görüntülenebilir
TreeNode anaMenu3 = new TreeNode("Sayfaya Link", "", "", "Sayfa.aspx", "_blank");
Default.aspx
<form id="form1" method="post" runat="server">
<asp:TreeView ID="agacMenu" runat="server" />
</form>
Default.aspx.cs
// Ana düğüm oluşturuluyor
TreeNode anaMenu1 = new TreeNode("Ana menü - 1", "", "", "AnaMenu1.aspx", "");
75
// Alt düğümleri oluşturmasõ için iki TreeNode nesnesi oluşturuluyor
TreeNode altMenu1 = new TreeNode("Alt menü - 1", "", "", "AltMenu1.aspx", "");
TreeNode altMenu2 = new TreeNode("Alt menü - 2", "", "", "AltMenu2.aspx", "");
Askerler.xml
<KarargahDestekGrubu>
76
<Asker Id="304" Ad="Onb. Eyüp ERDEM" />
<Asker Id="319" Ad="Çvş. Uğur UMUTLUOĞLU" />
<Asker Id="341" Ad="Çvş. Muhammet KURT" />
</Birim>
<Birim Ad="Muhafõz Bölüğü">
<Asker Id="177" Ad="Bahadõr ARSLAN" />
<Asker Id="192" Ad="Emrah USLU" />
<Asker Id="265" Ad="Çvş. Burak BATUR" />
<Asker Id="329" Ad="Onb. Osman ÇOKAKOĞLU" />
</Birim>
<Birim Ad="Lojistik Destek">
<Asker Id="155" Ad="Onb. Bülent SÖZGE" />
<Asker Id="281" Ad="Çvş. Özgür ALTUNTAŞ" />
<Asker Id="299" Ad="Burak Selim ŞENYURT" />
</Birim>
</KarargahDestekGrubu>
Default.aspx
77
elemanlarõ okunmasõ isteniliyorsa bu işlem kolay bir şekilde yapõlabilir. Amaç askerlerin
seçim işleminin yapõlmasõ olacağõ için asker isimlerinin eklendiği TreeNodeBinding
elementinin ShowCheckBox niteliği true olarak ayarlanõrsa listelenen asker isimlerinin sol
kõsmõna birer CheckBox kontrolü eklenecektir. Aşağõda bu değişikliğin nasõl yapõlacağõ,
CheckBox'lar olmadan TreeView'in görünümü ve CheckBox kontrolleri eklendiğinde
TreeView kontrolünün görünümü bulunmaktadõr.
Default.aspx
Bu şekilde TreeView kontrolünü kendi oluşturacağõmõz bir XML dosyasõ ile nasõl
besleyebileceğimizi görmüş olduk. Burada kilit noktamõz XmlDataSource kontrolü ile veri
kaynağõnõ belirlememiz ve TreeView'in DataBindings özelliğine ekleyeceğimiz
TreeNodeBinding nesneleri ile XML dosyadaki hangi etiketleri ve nitelikleri süzeceğimizi
belirlemektir. Son kõsõmda menümüzdeki asker isimlerine eklediğimiz CheckBox'larõ seçim
durumlarõna göre bir liste elde etme işlemini de aşağõdaki kodlarda gördüğünüz şekilde
gerçekleştirebiliriz. Öncelikli olarak sayfamõzõn HTML kõsmõnda bir Button nesnesi ekleyerek
bu butona tõklanmasõ durumunda listedeki seçili elemanlarõ ekrana yazdõralõm.
Default.aspx
78
Default.aspx.cs
Seçim işlemi yapõldõktan sonra aşağõdaki şekilde görüleceği gibi seçim listesini elde
edebiliyoruz.
79
kolaylaştõrõcõ bir işlem olacaktõr. Veritabanõndaki tablolarda saklanan kategori-alt kategori
tarzõndaki ilişkili verileri TreeView'e aktarmak için dilerseniz alõşveriş sitelerindeki gibi bir yapõ
üzerinden hareket edelim. Ürünlerimizin bulunduğu ana kategorilerimiz olsun; Elektronik
Eşya, Bilgisayar gibi... Yine bu ana kategorilerin altõnda da ürünlerimizi ayrõştõrmak için alt
kategorilerimiz olsun; Bilgisayar kategorisinin altõnda Dizüstü Bilgisayar ve Masaüstü
Bilgisayar gibi... Bu kategorilere aitte ürünlerimiz olsun. Yani 3 tane ana tablomuz içerisinde
bu bilgiler saklansõn: Kategoriler, AltKategoriler ve Urunler. Aşağõdaki şekillerde örnekte
kullanacağõm tablolarõn alan isimleri ve veri tipleri bulunmaktadõr.
Tablolarõ verilerle doldurduktan sonra öncelikli olarak normal bir veri işlemi ile üç tablodaki
verileri seçerek bir DataSet nesnesi içerisine dolduralõm. Burada işimizi kolaylaştõrmak için
DataSet içerisinde 3 farklõ DataTable içerisinde saklayacağõmõz bu verileri DataRelation
nesnesi ile ilişkili şekilde tutmak mantõklõ olacaktõr. Zira bir sonraki adõmda ilişkili kayõtlarõ
okurken elde edilen DataRow nesnelerinin GetChildRows() metodu ilişkili alt tablodaki
kayõtlara kolayca erişmemizi sağlayacaktõr. Tablo yapõlarõ incelenecek olunursa, Kategoriler
> AltKategoriler > Urunler şeklinde bir ilişkinin olduğu görülecektir. DataSet'e ekleyeceğimiz
DataRelation nesneleri de bu düzende belirlenecektir.
Default.aspx.cs
80
OleDbDataAdapter daKat = new OleDbDataAdapter("Select * From Kategoriler", con);
OleDbDataAdapter daAltKat = new OleDbDataAdapter("Select * From AltKategoriler",
con);
OleDbDataAdapter daUrunler = new OleDbDataAdapter("Select * From Urunler", con);
Default.aspx
Default.aspx.cs
// Kategorileri oku
foreach(DataRow dr in dsMenu.Tables["Kategoriler"].Rows)
81
{
TreeNode anaMenu = new TreeNode(dr["Ad"].ToString(), "", "",
"Kategori.aspx?Id=" + dr["KategoriID"].ToString(), "");
// Alt kategorileri oku
foreach(DataRow drAlt in dr.GetChildRows("Kat_AltKat"))
{
TreeNode altMenu = new TreeNode(drAlt["Ad"].ToString(), "", "",
"AltKategori.aspx?Id=" + drAlt["AltKategoriID"].ToString(), "");
// Ürünleri oku
foreach(DataRow drUrun in drAlt.GetChildRows("AltKat_Urun"))
{
TreeNode urunMenu = new TreeNode(drUrun["Ad"].ToString(), "", "",
"Urun.aspx?Id=" + drUrun["UrunId"].ToString(), "");
altMenu.ChildNodes.Add(urunMenu);
}
anaMenu.ChildNodes.Add(altMenu);
}
tvMenu.Nodes.Add(anaMenu);
}
}
82
Resim: Veritabanõndan getirilen veriler TreeView kontrolüne yüklendi
Görüldüğü gibi veritabanõndaki kayõtlarõ TreeView kontrolüne yükleme işlemi oldukça pratik
halde gerçekleştirilebiliyor. Burada bizim için en önemli noktalardan biri tabii ki veritabanõnda
saklanan kayõtlarõn tablolarda ilişkisel bir şekilde saklanmasõdõr. Bu tip bir işlemi yukarõdaki
şekilde gerçekleştirebileceğimiz gibi kendi Kategori, AltKategori ve Urun sõnõflarõmõzõ
oluşturup her bir sõnõf içerisinde bir alt birimindeki nesnelere ait liste koleksiyonlarõnõ
taşõyarak ta gerçekleştirebilirdik.
83
Site Navigasyonu Hakkõnda Bilinmeyenler
01 Mart 2008
ASP.NET 2.0 ile birlikte gelen site navigasyonu yapõsõ ve kontrolleri ziyaretçilerin site
içerisinde kolay şekilde gezinmelerini sağlayacak menüler oluşturabilmemizi sağlamaktadõr.
Projelerimizde pratik şekilde kullanabileceğimiz bu yapõlar birçok ihtiyacõmõzõ karşõlayacak
özelliklere sahiptir. Fakat bazen kendi özel durumlarõmõza göre bu kontrolleri değiştirmek
veya varolan yapõya ek nitelikler kazandõrmak isteyebiliriz. Aslõnda site navigasyonu
hakkõnda birçoğumuzun bilmediği özellikler belki de bizim projelerdeki bu tip ihtiyaçlarõmõzõ
karşõlayabilecektir. İşte bu makalede ASP.NET'te site navigasyonu hakkõnda bilinmeyen
yönleri keşfetmeye çalõşacağõz. Aşağõda beş başlõkta bu konularõn detaylarõnõ inceleyoruz.
Web.sitemap
<siteMap>
<siteMapNode url="Default.aspx" title="Anasayfa">
<siteMapNode url="Makale.aspx" title="Makaleler">
<siteMapNode url="Aspnet.aspx" title="ASP.NET" description="ASP.NET konusunda
makaleler" />
<siteMapNode url="Adonet.aspx" title="ADO.NET" description="ADO.NET konusunda
makaleler" />
<siteMapNode url="Cs.aspx" title="C#" description="C# konusunda makaleler" />
<siteMapNode url="SqlServer.aspx" title="SQL Server" description="SQL Server ile ilgili
makaleler" />
</siteMapNode>
<siteMapNode url="Videolar.aspx" title="Videolar" description="Teknik içerikli videolar">
<siteMapNode url="KonuAnlatimi.aspx" title="Konu Anlatõmõ" description=".NET içerikli
görsel videolar" />
<siteMapNode url="Webiner.aspx" title="Webiner" description="Web seminerlerinin
84
videolarõ" />
</siteMapNode>
<siteMapNode url="Forum.aspx" title="Forum" />
<siteMapNode url="Iletisim.aspx" title="İletişim" />
</siteMapNode>
</siteMap>
Sitenin genelinde şablon olarak kullanõlacak olan bir master sayfaya SiteMapPath,
TreeView ve SiteMapDataSource kontrollerini ekleyerek sitemap dosyasõndan getirilen
verileri sayfamõza yükleyelim. Sayfayõ çalõştõrõp sonucunu görerek neler yapabileceğimiz
üzerinde yazõmõza devam edelim. Aşağõda sayfamõzõn kodlarõ ve çõktõsõ bulunmaktadõr.
Sablon.master
85
birlikte TreeView kullanõldõğõnda zaten Anasayfa linki sürekli olarak SiteMapPath'de yer
alacağõ için TreeView'da en dõşta tüm node'larõ kapsayan Anasayfa node'unu göstermek
istemeyebiliriz. Fakat sitemap dosyasõnda da en dõşta bir SiteMapNode bulundurmak gibi bir
zorunluluğumuz olduğunu da belirtmiştik; yani web.sitemap'te bu linki bulundurmak
zorunludur. Peki TreeView'dan bu linki nasõl kaldõrabiliriz?
Sablon.master
...
<asp:SiteMapDataSource ID="SiteMapDataSource1" runat="server"
ShowStartingNode="false" />
...
86
içeriğinin sadece belirli bir kõsmõnõ görüntülemek istediğimiz durumlarda kullanabileceğmiz
birden fazla özellik bulunmaktadõr. Aşağõda bu özellikler ve açõklamalarõ bulunmaktadõr.
- StartingNodeUrl: Belirtilen adresin bulunduğu node'u ve alt node'larõnõ getirir. Değer olarak
string tipinden sayfanõn adurl bilgisini almaktadõr. Belirli sayfalarda sadece belirli bir
kategorinin ve alt kategorilerinin görüntülenmesi istenildiğinde kullanõlabilir. Örneğin sitede
editör olan bir kişi siteye giriş yaptõğõnda menü kõsmõnda sadece Editorler.aspx sayfasõ ve bu
sayfanõn altõnda kalan sayfalarõn görüntülenmesi istenildiğinde bu özellik "Editorler.aspx"
değerine ayarlanabilir.
87
StartingNodeUrl="Videolar.aspx" />
Web.sitemap
<siteMap>
<siteMapNode url="Default.aspx" title="Anasayfa">
<siteMapNode url="Default.aspx" title="Makaleler">
...
88
Resim: Sitemap dosyasõnda aynõ URL bilgisini taşõyan iki node bulunduğu için hata
oluştu
Görüldüğü gibi web.sitemap dosyasõnda birden fazla URL kullanõmõna izin verilmez. Fakat
bazõ durumlarda site haritasõnda aynõ linki birden kez fazla kullanma ihtiyacõ hissedebiliriz.
Böyle bir durumda maalesef aynõ linkleri kullanma şansõmõz olmayacaktõr. Ancak kendi özel
SiteMapProvider'larõmõzõ oluşturarak bu tip bir işlemi gerçekleştirebiliriz. Peki varolan yapõyõ
kullanarak bu işlemi nasõl gerçekleştirebiliriz? Bu işlem için iki yol seçilebilir. Bunlardan ilki
URL ReWriting ile farklõ url'leri aynõ sayfaya yönlendirme yapmak olabilir, fakat bu pek etkili
bir yöntem olmayacaktõr. Zira aynõ linki 3-4 yerde kullanmak için farklõ URL ReWriting
tanõmlamalarõ yapmak gerekebilir. Bir diğer yol ise asõl sayfa adresinin sonuna geçersiz
QueryString'ler yazmak olacaktõr. Her ne kadar etkili ve tavsiye edilecek bir yol olmasa da
böyle bir durumda kullanõlabilecek en kolay çözüm bu olacaktõr. Örneğin aynõ sayfayõ üç
farklõ yerde kullanmak istersek Sayfa.aspx, Sayfa.aspx?1 ve Sayfa.aspx?2 gibi üç farklõ url
kullanõp aynõ sayfaya link verebiliriz. Aşağõda web.sitemap dosyasõndaki url'lerin değiştirildiği
ve sayfanõn düzgün şekilde çalõştõğõ görülebilir.
Web.sitemap
<siteMap>
<siteMapNode url="Default.aspx" title="Anasayfa">
<siteMapNode url="Default.aspx?1" title="Makaleler">
...
89
Resim: Sitemap dosyasõnda aynõ olan URL bilgilerinin sonuna geçersiz QueryString'ler
eklendiğinde farklõ anahtar değerleri taşõndõğõ için aynõ sayfalar link verilebilir
90
SiteMapNode tipinden değerini getirir
Aynõ seviyede bir önceki kõsõmda bulunulan sayfa node'unun
PreviousSibling:
SiteMapNode tipinden değerini getirir
Sablon.master
...
<br><asp:Label ID="lblSayfaBilgi" runat="server" ForeColor="Red"/>
<br><asp:HyperLink ID="hlOnceki" runat="server" ForeColor="Blue"/>
<asp:HyperLink ID="hlSonraki" runat="server" ForeColor="Blue"/>
...
Sablon.master.cs
if(!String.IsNullOrEmpty(SiteMap.CurrentNode.Description))
lblSayfaBilgi.Text = "<br>Bu sayfada " + SiteMap.CurrentNode.Description + "
bulabilirsiniz.";
if(SiteMap.CurrentNode.PreviousSibling != null)
{
hlOnceki.Text = SiteMap.CurrentNode.PreviousSibling.Title + " <<";
hlOnceki.NavigateUrl = SiteMap.CurrentNode.PreviousSibling.Url;
}
if(SiteMap.CurrentNode.NextSibling != null)
{
hlSonraki.Text = ">> " + SiteMap.CurrentNode.NextSibling.Title;
91
hlSonraki.NavigateUrl = SiteMap.CurrentNode.NextSibling.Url;
}
}
Sitemap dosyalarõ içerisinde ek bilgileri kolay şekilde taşõyabilmektedir. Böyle bir durumda
uygulama içerisinden bu bilgilere ulaşmak ise beklediğimizden daha kolay olacaktõr. Ek
bilgileri saklamak için daha önceden bir yerlerde (SiteMap sağlayõcõsõ gibi) tanõmlama
yapmaya gerek yoktur. Nasõl ki bir sayfanõn url bilgisini siteMapNode içerisinde
tanõmlayabiliyorsak, bu bilgileri de aynõ şekilde tanõmlayabiliriz. Sayfa içerisinden okuma
işlemini ise biraz farklõ bir yoldan ama oldukça basit bir şekilde gerçekleştirilebilir. Dilerseniz
daha önceki örneklerde kullandõğõmõz sitemap dosyamõz üzerinde bir örnek yaparak bu
92
işlemleri nasõl gerçekleştirebileceğimizi görelim. Sitemizdeki kategorilerin her birisinde
bulunacak editör bilgilerini sitemap dosyasõnda ilgili sayfanõn node'unda saklayõp, ziyaretçi bir
kategoriyi gezdiğinde ilgili kategorinin editörünü sayfada görüntüleyeceğiz. Öncelikli olarak
sitemap dosyasõndaki her bir kategori node'una Editor adõnda bir nitelik tanõmlõyor ve ilgili
editörlerin isimlerini belirtiyoruz. Aşağõda web.sitemap dosyamõzõn bir kõsmõnda yapõlan
değişiklikler görülmektedir.
Web.sitemap
...
<siteMapNode url="Makale.aspx" title="Makaleler">
<siteMapNode url="Aspnet.aspx" title="ASP.NET" description="ASP.NET konusunda
makaleler" Editor="Uğur UMUTLUOĞLU" />
<siteMapNode url="Adonet.aspx" title="ADO.NET" description="ADO.NET konusunda
makaleler" Editor="Burak BATUR" />
<siteMapNode url="Cs.aspx" title="C#" description="C# konusunda makaleler"
Editor="Emrah USLU" />
<siteMapNode url="SqlServer.aspx" title="SQL Server" description="SQL Server ile ilgili
makaleler" Editor="Bülent SÖZGE" />
</siteMapNode>
...
Sablon.master.cs
93
indeksleyici üzerinden SiteMap.CurrentNode["Editor"] şeklinde okuyabilmekteyiz. Bu
şekilde sitemap dosyasõnda farklõ nitelikler tanõmlayõp sayfa içerisinden kolay şekilde
okunmasõnõ sağlayabiliriz. Aşağõda sayfamõzõn çõktõsõ görülmektedir.
web.config
<system.web>
...
<siteMap>
<providers>
94
<add name="SiteMapProvider2" siteMapFile="web2.sitemap"
type="System.Web.XmlSiteMapProvider, System.Web, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a"/>
</providers>
</siteMap>
</system.web>
web.sitemap
Sablon.master
...
<asp:Menu ID="Menu1" runat="server" DataSourceID="SiteMapDataSource2" Font-
Names="Verdana" Font-Size="12px"></asp:Menu>
<asp:SiteMapDataSource ID="SiteMapDataSource2" runat="server"
ShowStartingNode="False" SiteMapProvider="SiteMapProvider2" />
...
95
Sayfayõ çalõştõrdõğõmõzda daha önceden hazõrladõğõmõz TreeView kontrolünün
SiteMapDataSource1 kontrolü ile web.sitemap dosyasõndan, Menu kontrolünün ise
SiteMapDataSource2 kontrolü ile web2.sitemap dosyasõndan getirilen verilerle
doldurulduğunu görebiliriz. Aşağõda sayfamõzõn çõktõsõ bulunmaktadõr.
96
TreeView Kontrolüne Kullanõcõ İsteğine Göre Veri
Ekleme
04 Mart 2008
97
Resim: Spor.mdb isimli veritabanõ dosyamõzda bulunan tablolarõn yapõlarõ
Az öncede bahsettiğimiz gibi sayfa ilk yüklendiğinde TreeView'a sadece liglerin listesi
getirilecektir. Ne zaman ki kullanõcõ bir lige tõklarsa veritabanõndan sadece o ligin kulüpleri
getirilecektir. Kullanõcõ bir kulübe tõkladõğõnda da TreeView'õn node'larõna o kulübün
oyuncularõnõn listesi eklenecektir. Bu işlemi gerçekleştirmek için boş bir ASP.NET sayfasõna
bir TreeView kontrolü ve bir Label kontrolü ekleyelim. TreeView kontrolüne yüklenen bir lige
tõklandõğõnda o ligin kulüplerinin getirilmesi için sunucu tarafõnda bir metot çalõştõrõp lige ait
kulüpleri çekmemiz ve listeye eklememiz gerekecektir. Getirilen liglerden birine tõklanmasõ
durumunda TreeView kontrolünün TreeNodePopulate olayõ gerçekleşecektir. Bu olay
sunucu getirilen yeni verilerin o an tõklanan node'a eklenmesini sağlayacaktõr. Bu olayõn
tetiklenebilmesi için TreeView kontrolüne ait ExpandDepth özelliğinin (property) değerini "0"
olarak belirlememiz ve sadece en üstteki node'larõn yükleneceğini belirtmemiz
gerekmektedir. Aşağõda TreeView kontrolünde yapõlan değişiklikler ve sayfamõzõn kodlarõ
bulunmaktadõr.
Default.aspx
98
<asp:Label ID="lblOyuncuBilgiler" runat="server"></asp:Label>
</td>
</tr>
</table>
</div>
</form>
TreeView kontrolü ilk yüklendiğinde sadece en üst seviyedeki node'lar gelecektir. Sayfamõzõn
code-behind dosyasõnda yazacağõmõz kodlarla TreeView'a liglerin yüklenmesini sağlõyoruz.
Default.aspx.cs
OleDbDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
TreeNode kategori = new TreeNode(dr["Ad"].ToString(), dr["LigID"].ToString());
kategori.PopulateOnDemand = true;
tvLig.Nodes.Add(kategori);
}
con.Close();
}
99
Bağlanõlan veritabanõnnda çalõştõrõlan sorgu sonucu sadece ligler getirildi ve tvLig adõndaki
TreeView kontrolüne veriler eklendi. Buradaki en önemli noktalardan bir tanesi de eklenen
TreeNode nesnelerine ait PopulateOnDemand ("isteğe göre besle" diyebiliriz) özelliğidir.
bool tipinden değer alan bu özelliği true belirlememiz durumunda eklenen ligler istek
geldikçe alt node'larõnõ getirecektir. Oluşturulan lig node'larõna text olarak Ad, value olarak
LigID değerlerini atayõp PopulateOnDemand özelliğine true değerini verdikten sonra tvLig
adõndaki TreeView kontrolüne ekledik. Sayfanõn sorunsuz şekilde çalõşmasõ için
TreeNodePopulate olayõnõ bağladõğõmõz tvMenu_TreeNodePopulate metodunu şimdilik içi
boş bir şekilde tanõmladõk. Sayfa çalõştõrõldõğõnda sadece liglerin TreeView'a eklendiğini
göreceğiz.
Bir sonraki adõmda kullanõcõ herhangi bir linke tõklayarak o ligin altõndaki kulüpleri listelemek
isteyecektir. Bu noktada TreeNodePopulate olayõ tetiklenecek ve code-behind sayfamõzda
yazdõğõmõz tvMenu_TreeNodePopulate metodu çağrõlacaktõr. Bu metodun parametrelerine
bakacak olursak ikinci parametrenin TreeNodeEventArgs tipinden e adõnda bir nesne
olduğunu görürüz. e nesnesine ait Node özelliği tõklanõlan node'un nesne örneğini
getirecektir. Örneğin Türkiye Süper Lig'e tõklanmasõ durumunda bu node'un nesne örneğine
TreeNode tipinden erişebiliriz. Lige ait kulüpleri veritabanõndan çekerek ChildNodes
koleksiyonuna eklememiz durumunda artõk kulüpler ligin alt node'larõ olarak eklenecektir. Bir
sonraki adõmda da bir kulübe tõklandõğõnda oyuncular listeleneceği için burada tõklanõlan
linkin lig mi olduğu yoksa kulüp mü olduğunun ayõrt edilmesi gerekecektir. Eğer bir lige
tõklanmõşsa Kulupler tablosundan, bir kulübe tõklanmõşsa da Oyuncular tablosundan veriler
getirilecektir. TreeNode nesnesine ait Depth özelliği elde edilen node'un hiyerarşik olarak
hangi derinlikte olduğunu belirtmektedir. Ligler TreeView'da 0. derinlikte, kulüpler ise 1.
derinliktedir. Bu durumu da göze alarak aşağõdaki şekilde sayfamõzõn kodlarõna eklemeler
yapõyoruz.
100
Default.aspx.cs
OleDbDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
TreeNode kategori = new TreeNode(dr["Ad"].ToString(),
dr["KulupID"].ToString());
kategori.PopulateOnDemand = true;
kategori.SelectAction = TreeNodeSelectAction.Expand;
ligNode.ChildNodes.Add(kategori);
}
con.Close();
}
OleDbDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
101
string navigateUrl = "Default.aspx?OyuncuID=" + dr["OyuncuID"].ToString();
TreeNode kategori = new TreeNode(dr["Ad"].ToString(), "", "", navigateUrl, "");
kulupNode.ChildNodes.Add(kategori);
}
con.Close();
}
Resim: Kullanõcõdan gelen isteklere göre TreeView içeriği dinamik şekilde dolduruldu
Tüm verilerin bir defada gelmediğini görebilmek için sayfa götürülendikten sonra Kaynağõ
Görüntüle seçeneğinden sayfanõn HTML kodlarõ kontrol edilebilir. Yine linklere tõklandõğõnda
TreeNodePopulate olayõnõn tetiklenmesini de tvMenu_TreeNodePopulate metoduna bir
102
breakpoint ekleyerek görebiliriz.
Son olarakta QueryString ile taşõnan bilgileri alarak lblOyuncuBilgiler etiketine yazdõrabiliriz.
Bu işlemi Page_Load metodu içerisinde gerçekleştiriyoruz. Aşağõda sayfaya eklenen kodlar
ve sayfanõn çõktõsõ yer almaktadõr.
Default.aspx.cs
103
OleDbCommand cmd = new OleDbCommand("Select Ad, DogumTarih, Mevki From
Oyuncular Where OyuncuID=@id", con);
cmd.Parameters.AddWithValue("@id", oyuncuID);
con.Open();
OleDbDataReader dr = cmd.ExecuteReader(CommandBehavior.SingleRow);
dr.Read();
lblOyuncuBilgiler.Text = "Ad-Soyad: " + dr["Ad"].ToString() +
"<br>Doğum Tarihi: " + dr["DogumTarih"].ToString() +
"<br>Oynadõğõ Mevki: " + dr["Mevki"].ToString();
con.Close();
}
104
Böylece sayfa yukarõda anlattõğõmõz şekilde çalõşacaktõr. Visual Studio 2005'te yeni açtõğõmõz
bir ASP.NET AJAX-Enabled Web Site projesine (veya Visual Studio 2008'de .NET
Framework 3.5 ile açõlan normal bir ASP.NET projesine) önceki projedeki kodlarõmõzõ aynen
taşõyalõm. Yapacağõmõz tek değişiklik Default.aspx sayfasõnda TreeView kontrolünü bir
UpdatePanel içerisine bõrakmak olacaktõr. Tabii ki TreeView kontrolünün
PopulateNodesFromClient özelliğini false yapmamõz da gerekecektir. Aşağõda
oluşturduğumuz AJAX sayfasõndaki kodlar ve sayfanõn çõktõsõ yer almaktadõr.
Default.aspx
...
<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:TreeView ID="tvLig" runat="server"
OnTreeNodePopulate="tvMenu_TreeNodePopulate" ImageSet="Simple" ExpandDepth="0"
PopulateNodesFromClient="False">
<NodeStyle Font-Names="Tahoma" Font-Size="10pt" ForeColor="Black"
HorizontalPadding="0px" NodeSpacing="0px" VerticalPadding="0px" />
</asp:TreeView>
</ContentTemplate>
</asp:UpdatePanel>
<asp:UpdateProgress ID="UpdateProgress1" runat="server" DisplayAfter="0">
<ProgressTemplate>
Veriler yükleniyor. Bekleyiniz...
</ProgressTemplate>
</asp:UpdateProgress>
...
105
Resim: Dinamik yükleme işleminin UpdatePanel ve UpdateProgress ile
gerçekleştirilmesi
TreeView kontrolüne dinamik veri ekleme işlemini ASP.NET AJAX kontrolleri ile
gerçekleştirmeyi de görmüş olduk. Bu makalemizde TreeView kontrolüne kullanõcõdan gelen
isteklere göre dinamik şekilde veri ekleme işlemini inceledik. Özellikle çok sayõda node'lardan
oluşan yapõlarda TreeView kontrolünün içeriğini dinamik şekilde oluşturmak uygulamanõn
performansõ açõsõndan oldukça önemli olabilmektedir.
106
ASP.NET AJAX
Anahtar kelimeler
107
ASP.NET ATLAS
29 Mart 2006
Tarayõcõlarõn son yõllarda çõkardõklarõ yeni sürümleriyle birlikte yeni bir tanõmlama ile
karşõlaşmõş olduk: XMLHTTPRequest. Bu nesne sayesinde tarayõcõ ile sunucu asenkron (eş
zamanlõ olmayan) şekilde iletişime geçebiliyor ve XML tabanlõ bilgileri alma, gönderme gibi
işlemler yapõlabiliyordu. AJAX (Asynchornous JavaScript and XML) adõ verilen bu teknoloji
sayesinde, JavaScript dili aracõlõğõ ile bir sayfayõ tamamen sunucuya göndermeden
(postback atmadan) ya da yeni bir URL çağõrmadan sadece sayfamõzõn gerekli olan
kõsmõnda değişiklikler yapabiliyorduk. Son zamanlarda www.start.com, www.virtualearth.com
ve Google Suggest gibi birçok sitede bu teknolojinin örneklerini sõkça görüyoruz. Bu sitelerde
ortak olan nokta, sayfalarõn çoğunun server tarafõna tamamen gönderilmeden, sadece
güncellenecek olan kõsmõnõn server tarafõndan gelen bilgi ile yenilenmesidir. Bu teknolojiyi
ASP .NET ile geliştirdiğimiz sayfalara kolay şekilde entegre edebileceğimiz bir teknoloji var
mõ diye sorarsanõz, cevabõ; artõk evet:)
Microsoft’un Visual Studio 2005 ve ASP .NET 2.0 ile gelen yeni vizyonunda artõk yazõlõm
geliştirme kõsmõnda programcõnõn yükünün olabildiğince azaltõlmasõ, hazõrlanan projenin
daha etkili ve daha hõzlõ şekilde geliştirilmesi amaçlanõyordu. İşte bu doğrultuda ASP .NET
ekibi, ASP .NET 2.0’õn resmi olarak duyurulmasõnõn hemen ardõndan ATLAS’õn beta
sürümünü de duyurdu. ATLAS adõ verilen bu eklenti, ASP .NET 2.0 Web Uygulamalarõnda
AJAX teknolojisini çok kolay bir şekilde ve neredeyse hiç kod yazmaksõzõn kullanõlabilir hale
getirdi. Web 2.0 sürümünün dillerden düşmediği son zamanlarda web dünyasõna yeni bir
heyecan ve soluk getiren AJAX teknolojisi, ASP .NET - ATLAS sayesinde artõk çok kolay
şekilde uygulamalara eklenebilir oldu.
AJAX web uygulama geliştiriciler için çok önemli ve heyecan verici bir gelişme olmasõna
rağmen getirdiği bazõ sõnõrlamalarõ ve zorluklarõ da vardõ. Tarayõcõ tipine göre farklõ DOM
objeleri tanõmlamak, uygulamayõ geliştirebilmek için ileri sayõlabilecek düzeyde JavaScript
kodu yazmak gibi... ATLAS bu kõsõtlamalarõ ve zorluklarõ ortadan kaldõrdõğõ gibi, aynõ
zamanda nesne tabanlõ bir ortam olan .NET Framework'ün nimetlerinden de faydalanmamõzõ
sağladõ.
108
ATLAS kontrolleri sayesinde AJAX'ta yapabildiğimiz birçok şeyi kod yazmadan yapabiliyoruz.
Bu sayede artõk web uygulamalarõ daha etkileşimli ve daha zengin hale getirilebiliyor, sayfa
tamamen sunucuya gönderilmeyip, tekrar tamamen geri alõnmadõğõ için de sayfalarõmõz artõk
çok daha hõzlõ çalõşabilir hale geliyor.
Makalenin son kõsmõnda ASP .NET - ATLAS'a nasõl ulaşabileceğimizi ve nasõl kurup
kullanabileceğimizi anlatmaya çalõşacağõm. Daha önceden de bahsettiğim gibi ATLAS şu an
hala geliştirme aşamasõnda olan ve tam sürüm olarak henüz piyasaya sürülmemiş olan bir
ürün. Ürünü geliştiren ekip genellikle her ay içerisinde yenilenmiş sürümünü ATLAS'õn resmi
sitesi olan http://atlas.asp.net adresinden ücretsiz olarak download edilebilir halde
duyuruyorlar. Yine bu adresten bu ürün ile ilgili bir çok demo videoya ve yazõlõ kaynağa
ulaşabilirsiniz. Download bölümünden ATLAS Setup linkinden ASP.NET “Atlas” March
Community Technology Preview (CTP) dosyasõnõ ücretsiz olarak indirip bilgisayarõnõza
kurabilirsiniz. Visual Basic .NET ve C# .NET dilleri ile uygulama geliştirmenizi sağlayan bu
kurulumu tamamladõktan sonra, Visual Studio 2005'te yeni bir Web Site Projesi açacak
olursanõz, önceki ekranlardan farklõ olarak My Templates'in altõnda Atlas Web Site adõnda
bir template olduğunu göreceksiniz. Bu seçeneği seçerek yeni bir ATLAS uygulamasõ
açabilir, kontroller ve uygulama üzerinde ekli olarak gelen dosyalar sayesinde sayfalarõnõzda
ATLAS'õ kullanabilirsiniz.
109
Resim: Atlas Web Site Template'in seçilmesi
ATLAS önümüzdeki günlerde adõndan daha çok bahsedilecek, üzerinde durulmasõ gereken
ve önümüzdeki yõllarda uygulamalarõmõzda sõk sõk kullanacağõmõz çok yeni bir teknoloji.
Umarõm bu yeni teknolojiyi genel olarak sizlere iyi ve anlaşõlõr bir şekilde aktarabilmişimdir.
ATLAS'õn en son çõkan sürümünde (şu an için Mart ayõnda çõkan sürümü) birkaç yeni kontrol
daha eklendi. Bu yazõda ATLAS kontrollerinden en çok kullanõlanlarõ olan ScriptManager,
UpdatePanel, UpdateProgress ve TimerControl kontrollerine göz atacağõz.
ScriptManager
Sayfalarõmõzda ATLAS'õ kullanmamõzõ sağlayan ve her sayfaya mutlaka eklenmesi gereken
kontroldür. Sayfamõzdaki ATLAS kontrollerinin doğru olarak çalõştõrõlabilmesi için bu
kontrolümüzü sayfamõzõn en üst kõsmõna eklemiş olmamõz gerekmektedir.
110
</Services>
</atlas:ScriptManager>
UpdatePanel
Sadece kendi içerisindeki alanõn güncellenmesini sağlar. İçerisine eklenmiş olan HTML
kodlarõ ve ASP .NET kontrolleri dahil olmak üzere herşeyi, bir olay tetiklendiği anda ya da bir
değişiklik olduğu anda tekrar güncellemektedir. UpdatePanel içerisinden güncellenen bir
sayfa tamamen sunucu tarafõna gönderilmez (post-back olmaz) ve bu olay esnasõnda
UpdatePanel'in dõşõndaki hiçbir alan güncellenmez.
- New Web Site menüsünden yeni bir "ATLAS" Web Site projesi açalõm. Uygulamaya
başlamadan önce Solution Explorer'dan uygulama dosyalarõna bakacak olursanõz bin
dizininin altõnda uygulamamõzda ATLAS'õ kullanmamõzõ sağlayan Microsoft.Web.Atlas.dll
adlõ dosyanõn bulunduğunu görebileceksiniz. Yine web.config dosyasõnda ATLAS'õ bu
projedeki tüm sayfalarõmõzda kolayca kullanmamõzõ sağlayan gerekli ayarlamalarõn yapõlmõş
olduğunu görebilirsiniz.
111
<atlas:ScriptManager> kontrolü ekleyelim ve bu kontrolün EnablePartialRendering
özelliğini True yapalõm.
- UpdatePanel'in dõşõna Button2 adõnda bir buton daha ekleyelim. Bu butonun Click olayõnõ
UpdatePanel'in içerisindeki <Triggers> alt elementine ControlEventTrigger olarak ekleyelim.
(Aşağõdaki örnekteki gibi)
Basit bir örnek ile UpdatePanel'i anladõğõmõzõ umuyorum. UpdatePanel'in içerisine farklõ
kontroller (Calendar, Gridview, vb.) ekleyerek sayfanõn çalõşmasõnõ tekrar
gözlemleyebilirsiniz.
UpdateProgress
Bu kontrol ise UpdatePanel'de güncelleme işlemi yapõldõğõnda ziyaretçiye güncelleme
işleminin yapõldõğõnõ gösteren kontroldür. Örneğin bir güncelleme işlemi yapõldõğõnda
"Yükleniyor" "Güncelleniyor" şeklinde bir yazõnõn ya da benzer bir resim dosyasõnõn
görünmesini istiyorsanõz bu kontrol sayesinde bu işlemi yapabilirsiniz.
112
<atlas:UpdateProgress ID="UpdateProgress1" runat="server">
<ProgressTemplate>
<img src="images/indicator.gif" /><br />
Bilgiler güncelleniyor.....<br />
</ProgressTemplate>
</atlas:UpdateProgress>
TimerControl
TimerControl adõndan ve konumuzun gidişatõndan da tahmin edebileceğimiz üzere,
sayfamõzõn post-back atmaksõzõn, belirli aralõklarla UpdatePanel kontrolündeki bilgilerin
güncellenmesini sağlayan kontroldür. Belirttiğimiz zaman aralõklarõnda sayfamõzdaki
UpdatePanel'in içerisindeki bilgileri güncellenmesini sağlar.
<Triggers>
<atlas:ControlEventTrigger ControlID="Button2" EventName="Click" />
<atlas:ControlEventTrigger ControlID="TimerControl1" EventName="Tick" />
</Triggers>
Yukarõdaki kodlardan ilkine bakacak olursak, burada sayfamõza bir ATLAS TimerControl
kontrolü eklemiş bulunuyoruz. Interval değeri ile Timer'õmõzõn ne kadar sürede bir
tetikleneceğini belirtiyoruz. Interval="5000" tanõmlamasõndaki 5000 aslõnda 5 saniyeye eşit.
Yani her saniye için değerimizi 1000 değer arttõrmamõz gerekecek. Bu sayede
UpdateControl'ümüzü timer aracalõğõ ile tetikleyebiliyoruz. Yalnõz az önce de bahsetmiş
olduğum gibi, UpdateControl'ün dõşarõdaki bir değişiklikle güncellenmesi için UpdatePanel
kontrolümüze trigger eklememiz gerekiyordu. Burada da Timer kontrolümüz için
UpdatePanel'imizin <Triggers> elementine gerekli kodlarõ eklememiz gerekecek. (Alt
113
kõsõmdaki kodlardan görebilirsiniz.) Buradaki EventName değerine dikkat edecek olursak
Tick değerini görüyoruz. Tick TimerControl1 kontrolümüzün bir eventi. Buradaki örnekte
Timer kontrolümüzün her 5 saniyede bir Tick eventi çalõşacak ve UpdatePanel'imizdeki
değerler tüm sayfa post-back olmadan, ya da biz buton vb. bir kontrole müdahale etmeden
güncellenecektir.
114
AJAX: Asenkron JavaScript ve XML
18 Ocak 2007
Son zamanlarda özellikle web programcõlõğõ ile ilgilenenlerin sõklõkla duyduğu bir terim AJAX.
Microsoft’un tam sürümünü çõkarmaya hazõrlandõğõ ve yeni nesil web sayfalarõnda sõklõkla
kullanacağõmõz ASP .NET AJAX’a geçiş yapmadan önce AJAX adõ verilen uygulama
geliştirme yaklaşõmõnõ ele almamõz, temellerini öğrenmemiz iyi olacaktõr. Peki nedir AJAX?
Bizlere nasõl bir teknoloji ve ne gibi yenilikler sunuyor?
AJAX aslõnda yeni bir programlama dili ya da programlama aracõ değildir. Daha önceden de
var olan bazõ teknolojileri kullanarak bize nasõl uygulama geliştireceğimizi gösteren yeni bir
programlama modelidir. AJAX yani Asenkron JAvascript ve XML, temel olarak JavaScript
dilindeki XMLHTTPRequest nesnesini kullanarak web sayfalarõ üzerinde asenkron bir şekilde
veri iletişimini sağlayan programlama modelidir. Yani bir web sayfasõ yüklendikten sonra,
aynõ sayfa üzerinde iken arka tarafta sunucu ile iletişime geçmeyi ve veri transferi
yapmamõza olanak sağlar. Dilerseniz bu kõsmõ biraz daha açmak için klasik modelde
programlanan bir web sayfasõnõn ve AJAX modelinde programlanan bir web sayfasõnõn nasõl
çalõştõğõnõ inceleyelim.
115
üzerinde görüntülenir(2). AJAX’õn getirdiği yenilik işin bundan sonraki kõsõmlarõnda karşõmõza
çõkacaktõr. Yüklenen web sayfasõ üzerinde yeni bir istekte bulunacağõmõz zaman, istemci
tarafõnda çalõşacak olan bir Javascript kodu, arka planda asenkron bir şekilde sunucuya
istekte bulunur(3). Sunucudan alõnan bilgi yine asenkron bir şekilde getirilir ve gelen yeni
içerik ile birlikte sayfamõzda ilgili kõsõmlar güncellenir(4). Bu sayede yeni bir istek durumunda
web sayfamõz sadece güncelleyeceğimiz verileri alacaktõr. Sayfa tamamen PostBack işlemi
tabi tutulmayacaktõr, kõsmi bir PostBack işlemi gerçekleşecektir ve sayfanõn tamamen
yenilenmesine gerek kalmayacaktõr. Bu işlem süresinde sayfa tamamen PostBack
edilmeyeceği için farklõ bir sayfa beklemesi olmayacak ve aynõ sayfa üzerinde kalõnacaktõr.
(Aşağõdaki şekilde AJAX çalõşma modeli anlatõlmõştõr.)
İki çalõşma modelini ele alõrsak AJAX bizlere klasik çalõşma modeline göre daha hõzlõ ve
verimli bir çalõşma ortamõ sunmaktadõr. İstemciye sadece sayfanõn güncelleyeceğimiz kõsmõnõ
getirildiğimiz için daha küçük veri parçalarõnõn transfer edilmesiyle sunucu ve istemci
arasõndaki trafik azalmakta ve sayfalar daha hõzlõ bir şekilde yenilenmektir. Yine sayfamõzõ
ziyaret eden kullanõcõlar aynõ sayfa üzerinde kalacaklarõ için site ile etkileşimleri artacaktõr. Bu
sayede artõk web uygulamalarõ masaüstü uygulamalarõn sağladõğõ hõza ve zenginliğe giderek
yaklaşmaktadõr.
116
sürümleri) XMLHTTPRequest nesnesini bulundurduğu için uygulama geliştiriciler olarak
bizlerin bu modeli kullanmasõnda da herhangi bir sakõncasõ kalmamõştõr. Şu anda giderek
yaygõnlaşmakta olan AJAX uygulamalarõ şüphesiz ki giderek artarak gelecekte karşõmõza çok
daha sõk çõkacaktõr. Gelişen teknolojilerle paralel olarak internet hõzlarõnõn artõşõnõ da göze
alõrsak, gelecekte web uygulamalarõnõn neredeyse masaüstü uygulamalar kadar hõzlõ ve
verimli çalõşabileceğini düşünebiliriz.
Nasõl Çalõşõr?
Peki, AJAX mimarisi nasõl çalõşõyor ve bir web sayfasõnõn asenkron bir şekilde sunucuyla
iletişime geçmesini nasõl sağlõyor? Yazõmõzõn başõnda da bahsettiğim gibi AJAX mimarisi
temel olarak XMLHTTPRequest nesnesini kullanõr. XMLHTTPRequest web tarayõcõsõ
üzerinde bulunan bir bileşendir. JavaScript dilindeki XMLHTTPRequest nesnesi aracõlõğõ ile
bu bileşeni kullanabilmekteyiz. Bu nesne sayfa yüklendikten sonra istemci ve sunucunun
asenkron şekilde haberleşmesini sağlar. İstemci tarafõndaki web tarayõcõsõ, sunucudan
asenkron şekilde veri isteğinde bulunur.(Request) Sunucu tarafõnda ise alõnan isteğe göre bir
çõktõ üretilir ve veriler yine asenkron şekilde istemcinin web tarayõcõsõna gönderilir.(Response)
Alõnan veriler DOM(Document Object Model) ve Javascript sayesinde dinamik bir şekilde
sayfaya yüklenmesi sağlanõr. Bu esnada sayfada kõsmi PostBack işlemi olmakta ve yapõlan
işlemler sayfanõn arka tarafõnda yapõlmaktadõr. İşlem süresince tarayõcõdaki sayfa aynen
kalmakta ve sadece güncellenen alanlarda değişiklikler olmaktadõr.
117
sayfamõzda <body> içerisine bir tane span elementi ve tipi buton olan bir input elementi
ekleyelim.
<span id="lblGuncelle"></span>
<input type="button" value="Güncelle" onclick="AsenkronCagriYap()" />
Yeni bir XMLHTTPRequest nesnesi oluşturmak için bilmemiz gereken 3 farklõ isimlendirme
vardõr. Tarayõcõnõn içerisinde bulunan bileşene göre ActiveXObject(“Msxml2.XMLHTTP”),
ActiveXObject(“Microsoft.XMLHTTP”) ve XMLHTTPRequest() ile nesne oluşturabiliriz.
Mozilla, Opera, Safari gibi tarayõcõlar için ise aşağõdaki tanõmlama yapõlõr.
var nesne = new XMLHTTPRequest();
Buradan şöyle bir sonuç çõkõyor. İstemci tarafõnda farklõ tarayõcõlar olabileceği için bizim bu
ihtimali düşünüp yazacağõmõz fonksiyonda yukarõdaki tüm ihtimalleri denemeliyiz. Bunun için
JavaScript içerisinde try-catch bloklarõ yazarak tarayõcõya göre yeni bir nesne oluşturmalõyõz.
(Aşağõdaki kod üzerinde çok fazla dõrmaya gerek yok. Zira buradaki try-catch yapõsõ C# .NET
ve VB .NET’teki yapõyla hemen hemen aynõdõr.)
function NesneOlustur()
{
var nesne;
try
{
nesne = new ActiveXObject("Msxml2.XMLHTTP"); // IE 6.0+ tarayõcõlar için
}
catch(e)
{
try
{
118
nesne = new ActiveXObject("Microsoft.XMLHTTP"); // IE 5.5 tarayõcõlarõ için
}
catch(e)
{
try
{
nesne = new XMLHTTPRequest(); // Firefox, Opera 8.0+ ve Safari tarayõcõlarõ için
}
catch(e)
{
alert("Tarayõcõnõz AJAX'õ desteklemiyor!!!");
return null;
}
}
}
return nesne;
}
open metodu 3 parametre almaktadõr. İlk parametre; isteği hangi metodu kullanarak
yapacağõmõzdõr. (GET veya POST) İkinci parametre hangi adrese istekte bulunacağõmõzdõr.
(Örneğin sonuc.aspx) Son parametre ise isteğin asenkron bir şekilde gerçekleşip
gerçekleşmeyeceğidir. (true değeri asenkron şekilde olacağõ anlamõna gelir.)
open nesnesinin 2 ve 5 parametre almõş aşõrõ yüklenmiş halleri de vardõr. Yukarõdaki kullanõm
genel olduğu için bu bize yetecektir.
send metodu ise open ile hazõrladõğõmõz isteği sunucuya gönderir. Eğer open ile açacağõmõz
istek POST metodunu kullanõyorsa, send metodu parametre olarak gönderilecek veriyi
taşõyabilir. Send metodunu parametresiz veya null parametresi ile de kullanabilmekteyiz.
İsteğimiz sunucuya gönderildi. Artõk sunucudan gelecek olan cevabõ bekleyip eğer sonuç
dönerse bu sonucu HTML kõsmõnda yazmamõz kaldõ. Bu işlemi yapabilmemiz için yine
XMLHTTPRequest içerisinde bulunan onreadystatechange eventhandler’õ ve readystate
özelliğini kullanmamõz gerekiyor.
119
onreadystatechange eventhandler’õ sunucuya istekte bulunduktan sonraki durum
değişikliklerini yakalar. Burada bahsettiğimiz durumlar ise 5 tanedir ve bu durumlarõ
readystate özelliğini kullanarak elde edebiliriz. Bu durumlar;
0 = İstek hazõrlanmadõ
1 = İstek hazõrlandõ
2 = İstek gönderildi
3 = İstek değerlendiriliyor ve sonuç bekleniyor
4 = İstek tamamlandõ ve sonuç geldi
nesne.onreadystatechange = function
{
if (nesne.readystate == 4)
{
// sonucu HTML’e yazdõr
}
}
// Yeni bir fonksiyon yazmamõza gerek kalmadan onreadystatechange olayõnõ isimsiz bir
fonksiyona bağlõyoruz
yeniNesne.onreadystatechange = function()
{
// Eğer readystate 4 değerine sahipse asenkron işlem bitmiş ve veriler getirilmiş demektir
if(yeniNesne.readystate == 4)
{
// Getirilen veriyi HTML kõsmõndaki lblGuncelle içerisine dinamik bir şekilde yazdõrõyoruz
document.getElementById('lblGuncelle').innerHTML = yeniNesne.responseText;
}
}
}
120
Son olarak belirtmemiz gereken nokta ise document.getElementById('lblGuncelle').
innerHTML şeklinde HTML kõsmõndaki lblGuncelle span elementine ulaşõyor ve bu elementin
içerisine istek sonucunda gelecek olan bilgiyi yazdõrõyoruz. yeniNesne.responseText ise Text
formatõnda gelecek olan veriyi almamõzõ sağşõyor. (responseXML ise DOM’a uygun XML
formatõnda gelen veriyi almamõzõ sağlar) Sayfamõzõ çalõştõracak olursak sadece butonu
bulunan bir sayfamõz olacak. Burada span elementi ile belirttiğimiz boş bir alan daha var.
Uygulamamõzõn doğru çalõşõp çalõşmadõğõnõ görebilmemiz için sayfamõzõn bulunduğu dizine
Ogranciler.htm adõnda bir dosya oluşturmamõz gerekiyor. Bu dosyanõn içerisine örnek
olmasõ açõsõndan birkaç satõrlõk yazõ ekleyebiliriz. Sayfamõzda bulunan butona tõkladõğõmõzda
butonun onclick olayõ çalõşacak ve AsenkronCagriYap() isimli JavaScript fonksiyonumuz
çağõrõlacaktõr. Bu fonksiyon asenkron çağrõ işlemini gerçekleştirecek ve getirilen bilgiyi
lblGuncelle adõnõ verdiğimiz span elementinin içerisine yazacaktõr.
Metotlar:
abort() = nesne üzerinden yapõlan isteği durdurur.
getAllResponseHeaders() = Gelen cevabõn başlõk bilgilerini getirir.
getResponseHeader("headerLabel") = Parametre olarak verilen başlõk bilgisini getirir.
setRequestHeader("headerLabel", "value") = Gönderilen başlõk bilgisine istenilen değeri
atar.
Özellikler:
status = Sunucudan dönen cevabõn numarasal kodudur. Örneğin 404 kodu “Not Found” yani
istekte bulunduğumuz sayfa bulunamadõ anlamõna gelir. 200 ise “OK” değeri dönderir ve
işlemin tamamlandõğõnõ belirtir.
statusText = status özelliğinin metin karşõlõğõnõ verir.
Son kõsõmda belirtilen metot ve özellikler üzerinde fazla durmamõza gerek olmadõğõnõ
düşünüyorum. AJAX’õ kullanarak asenkron veri alõş-verişini yapabilmek için örneğimizde
kullandõğõmõz open ve send metotlarõ, onreadystatechange eventhandler’õ ile readystate
özelliği bizim için yeterli olacaktõr.
121
ASP.NET AJAX Uygulamalarõ ile İlgili Sorunlar ve
Çözümleri
13 Mart 2007
AJAX uygulama modeli, her geçen gün uygulamalarda daha da sõk kullanõlõr hale geliyor.
ASP.NET uygulama geliştiricileri olarak bizler de Microsoft’un ücretsiz sunmuş olduğu AJAX
kütüphanesi olan ASP.NET AJAX’õ projelerimizde kullanarak, daha persormanslõ ve zengin
uygulamalar geliştirebiliyoruz. ASP.NET AJAX uygulamalarõ geliştirirken elbetteki bazõ
durumlarda sõkõntõlar, sorunlar yaşanabilecektir. Bu yazõda bu nitelikteki bazõ sorunlarõ ve
hatalarõ ele alarak bu durumlarda ne gibi çõkõş yollarõna başvurabileceğimize değineceğiz.
ASP.NET AJAX’õn ATLAS sürümlerinde yapõlan bir projenin kullanacağõ assembly dosyalarõ
projenin Bin dizinine atõlõyor ve assembly dosyalarõ ile birlikte taşõnan proje, bulunduğu tüm
bilgisayarda sorunsuz bir şekilde çalõşabiliyordu. ASP.NET AJAX v1.0 ile artõk bir AJAX
projesinin kullanacağõ assembly dosyalarõ GAC(Global Assembly Cache) içerisine atõldõğõ
için, projeye referans dosyasõ olarak eklemeler yapõlmõyor ve projeniz GAC’daki dosyalarõ
kullanõyor. Bu nedenle hazõrlamõş olduğunuz bir ASP.NET AJAX projesinin sunucuda veya
başka bir bilgisayarda çalõşabilmesi için, o bilgisayara ASP.NET AJAX Extension 1.0’õn
kurulu olmasõ gerekecektir. Sunucuda AJAX projelerini çalõştõramama gibi bir durumda
yapõlmasõ gereken işlemler, projenize gerekli dll dosyalarõnõ eklemek ve web.config
dosyasõnda bazõ değişiklikleri yapmak olacaktõr.
- Öncelikli olarak projenize gerekli dll dosyalarõnõ eklemeniz gerekecektir. ASP.NET AJAX
dosyalarõnõn kullandõğõ assembly dosyalarõ System.Web.Extension ve
System.Web.Extension.Design dll dosyalarõdõr. Bu dosyalarõ AJAX Extension kurulu
bilgisayarõnõzdaki C:\Program Files\Microsoft ASP.NET\ASP.NET 2.0 AJAX
Extensions\v1.0.61025 dizininde bulabilirsiniz. Projenize Bin isimli bir dizin oluşturmanõz ve
dll dosyalarõnõ bu dizine eklemeniz gerekecektir.
122
- Daha sonra uygulamanõzdaki web.config dosyasõnda bazõ değişiklikler yapmanõz
gerekecek. web.config içerisindeki tanõmlamalarõ dikkatli şekilde inceleyecek olursanõz,
tanõmlamalarõn type özelliği içerisinde ...System.Web.Extensions, Version=1.0.61025.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35 şeklinde ifadeler bulunur. Bu
ifadeler yapõlacak olan işlemlerde kullanõlacak assembly dosyasõnõn GAC içerisinden
okunacağõnõ belirten ifadelerdir. web.config’deki bu ifadelerde yer alan Version=1.0.61025.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35 kõsõmlarõnõ çõkarmanõz gerekecektir.
Aşağõdaki şekilde değişiklik yapõlacak alanlar gri zemin üzerinde gösterilmiştir. Web.config
içerisindeki bu alanlar ve aynõ tanõmlamalarõn geçtiği diğer alanlarda değişiklik yapmak
gerekecektir.
type kõsõmlarõnda yapacağõnõz bu değişikliklerden sonra artõk projeniz Bin dizinindeki dll
dosyalarõnõ kullanacaktõr. Projenizle birlikte bu dll dosyalarõnõ da sunucuya attõktan sonra, son
işlem olarak uygulamanõn bulunduğu dizini sitenizde virtual directory (sanal dizin) olarak
tanõmlayacak olursanõz, artõk projeniz sorunsuz bir şekilde çalõşacaktõr.
123
- web.config dosyasõnda değişiklik yapabilmek için öncelikle bir ASP.NET AJAX
uygulamasõndaki web.config dosyasõna ihtiyacõmõz olacaktõr. Eğer klasik uygulamanõzdaki
web.config dosyasõ içerisinde hiç değişiklik yapmadõysanõz (yani uygulama ilk açõldõktan
sonra web.config dosyasõna herhangi bir ekleme-çõkarma veya değişiklik yapmadõysanõz),
yapõlacak işlem oldukça basit olacaktõr: ASP.NET AJAX uygulamanõzdan aldõğõnõz
web.config dosyasõnõ aynen klasik uygulamanõza eklemek. Eğer klasik uygulamnõzdaki
web.config dosyasõnda değişiklikler yaptõysanõz, ASP.NET AJAX projesindeki web.config’den
- <configSections></configSections>
- <pages></pages> kõsmõ içerisindeki <controls></controls>
- <compilation></compilation> kõsmõ içerisindeki <assemblies></assemblies>
- <httpHandlers></httpHandlers>
- <httpModules></httpModules>
- <system.web.extensions></system.web.extensions>
- <system.webServer></system.webServer>
124
kontrolünün EnableSortingAndPagingCallbacks değerini True ve DetailsView kontrolünün
EnablePagingCallbacks değerini True olarak değiştirmeniz durumunda bu kontroller kendi
Callback özelliklerini kullanarak güncellenecek ve UpdatePanel içerisinde kõsmi güncelleme
gerçekleşmeyecektir. Bu değerleri değiştirmezseniz, yani varsayõlan değerleri olan False
değerlerini taşõrlarsa UpdatePanel’iniz düzgün bir şekilde çalõşacaktõr.
125
AJAX Uygulamalarõnda UpdatePanel Kullanõmõ
24 Nisan 2007
UpdatePanel kontrolü, ASP.NET AJAX uygulamalarõnda, bir web sayfasõ içerisinde kõsõmlar
oluşturulmasõnõ ve bu kõsõmlarõn asenkron şekilde güncellenmesini sağlayan kontroldür.
ASP.NET AJAX uygulamalarõnda, bir sayfa PostBack işlemine tabi tutulmadan, sadece
UpdatePanel içerisi güncellenebilir. Bu şekilde web sayfalarõ daha hõzlõ çalõşõr hale geldiği
gibi, sunucu ile istemci arasõndaki veri trafiği de önemli derecede azalõr.
UpdatePanel kontrolü, sayfa içerisinde bir alan oluşturarak, (HTML kõsmõnda <div> veya
<span> etiketi ile oluşan bir alan) içerisine eklenen kontrollerin görüntülenmesini ve asenkron
bir şekilde bu kontrollerin içeriklerinin güncellenmesini sağlar.
<ContentTemplate></ContentTemplate> ve <Triggers></Triggers> kõsõmlarõ olmak üzere
iki kõsõmdan oluşmaktadõr. <ContentTemplate> kõsmõnda, UpdatePanel içerisinde yer alacak
içerikler bulunur.(ASP.NET kontrolleri, HTML kontrolleri, resim dosyalarõ, metinler vb.)
Sadece bu kõsõmda yer alan bileşenler, kõsmi güncelleme işleminden etkilenir. <Triggers>
kõsmõnda ise UpdatePanel'in çalõşmasõnõ; yani güncelleme işleminin gerçekleşmesini
sağlayacak olaylarõn bağlanmasõ işlemi gerçekleştirilir. (Bir Button kontrolünün Click olayõ
veya DropDownList kontrolünün SelectedIndexChanged olayõ gibi durumlarõn panele
bağlanmasõ) ContentTemplate ve Triggers kõsõmlarõ UpdatePanel içerisinde şu şekilde
kullanõlmaktadõr.
126
Durum-1: Kontrol UpdatePanel içerisinde ise:
UpdatePanel’i güncelleyecek kontrol UpdatePanel’in içerisinde yer alõyorsa, bu kontrolün
varsayõlan olayõnõn gerçekleşmesi UpdatePanel’i otomatik olarak tetikleyecektir. Yani biz
herhangi bir ayarlama veya atama yapmasak dahi, UpdatePanel içerisinde yer alan Button
gibi bir kontrole tõklandõğõnda panelin içerisindeki veriler güncellenecektir. Default.aspx ve
Default.aspx.cs dosyalarõnda aşağõ değişiklikleri yapõp, uygulamayõ çalõştõralõm.
Default.aspx
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:Label ID="Label1" runat="server" Text=""></asp:Label> <br />
<asp:Button ID="Button1" runat="server" Text="Button" />
</ContentTemplate>
</asp:UpdatePanel>
Default.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
Label1.Text = DateTime.Now.ToLongTimeString();
}
Açõlan sayfada butona tõklandõğõnda Label1 üzerindeki tarih bilgisinin asenkron bir şekilde
güncellendiğini görebiliriz. Burada dikkat edeceğiniz gibi panele herhangi bir trigger bağlama
işlemi yapmamamõza rağmen güncelleme işlemi otomatik olarak yapõldõ. UpdatePanel’in
içerisine eklenen kontrolün otomatik olarak paneli güncellemesini sağlayan UpdatePanel
kontrolünün ChildrensAsTrigger isimli özelliğidir. ChildrensAsTrigger özelliği varsayõlan
olarak True değeri taşõdõğõ için UpdatePanel içerisine eklenen bir kontrolün olayõ, biz
belirtmesek bile panele trigger olarak eklenecektir. Eğer ChildrensAsTrigger özelliği False
olarak değiştirilirse, panel içerisine eklenen bir kontrol otomatik olarak paneli güncellemez.
127
eklemek gerekecektir. Örneğin UpdatePanel dõşõnda kalan btnDisari isimli bir butonu panele
trigger olarak bağlamak için aşağõdaki ifadeleri UpdatePanel’e eklemek gerekecektir.
Bu işlem HTML kodlarõ içerisinden gerçekleştirilebileceği gibi, sayfanõn Design kõsmõnda iken
UpdatePanel seçilip Properties penceresinden Triggers özelliğine tõklanõrsa, açõlan
pencereden de istenilen kontrol ve kontrolün olayõnõ seçmek trigger eklemek için yeterli
olacaktõr.
128
Resim: UpdatePanel'e AsyncPostBackTrigger eklenmesi
Default.aspx
<asp:UpdatePanel ID="UpdatePanel2" runat="server">
<ContentTemplate>
<table style="background-color:#B5DDDD; width:200px">
<tr><td>
<asp:Label ID="Label2" runat="server"></asp:Label> <br />
<asp:Button ID="Button2" runat="server" Text="Button-2" />
</td></tr>
</table>
</ContentTemplate>
</asp:UpdatePanel>
129
Label2 kontrolünün de asenkron şekilde güncellenmesi için Default.aspx.cs dosyasõndaki
Page_Load kõsmõnõ şu şekilde değiştirelim:
Default.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
Label1.Text = DateTime.Now.ToLongTimeString();
Label2.Text = DateTime.Now.ToLongTimeString();
}
Bu işleyiş aslõnda normal şartlarda pekte istenilen bir durum olmayacaktõr. Zira birbirinden
ayrõlmõş iki farklõ panelin sadece kendi triggerlarõ tarafõndan tetiklenmesi istenilebilir. Fakat
burada ise UpdatePanel1 içerisindeki bir kontrol tetiklendiğinde UpdatePanel2 içerisi de
güncellenmektedir. UpdatePanel'lerin bu şekilde çalõşmalarõnõ sağlayan UpdateMode
özellikleridir. Sayfamõza eklediğimiz bir UpdatePanel'in UpdateMode özelliği varsayõlan
olarak Always değerini taşõmaktadõr. UpdateMode özelliğinin Always olmasõ durumunda
sayfa içerisindeki herhangi bir UpdatePanel'in tetiklenmesi panelinde tetiklenmesini
sağlayacaktõr. Eğer UpdateMode özelliği Conditional değerini alõrsa, panel sadece kendi
triggerlarõ aracõlõğõyla tetiklenecektir. Bu noktada UpdatePanel1'in UpdateMode özelliğini
Conditional yapacak olursanõz, sayfayõ çalõştõrdõğõnõzda UpdatePanel1'in sadece kendi
triggerlarõ tarafõndan tetiklenebileceğini göreceksiniz. Fakat UpdatePanel2'nin UpdateMode
özelliği hala Always olduğu için UpdatePanel1'deki bir güncelleme, UpdatePanel2'yi de
tetikleyecektir.
130
UpdatePanel1'in UpdatePanel2'in UpdatePanel1 UpdatePanel2
UpdateMode UpdateMode triggerõ triggerõ
özelliği özelliği tetiklenirse tetiklenirse
Her iki panelde Her iki panelde
Always Always
güncellenir. güncellenir.
UpdatePanel2
Her iki panelde güncellenir,
Conditional Always
güncellenir. UpdatePanel1
güncellenmez.
UpdatePanel1
güncellenir, Her iki panelde
Always Conditional
UpdatePanel2 güncellenir.
güncellenmez.
UpdatePanel1 UpdatePanel2
güncellenir, güncellenir,
Conditional Conditional
UpdatePanel2 UpdatePanel1
güncellenmez. güncellenmez.
Default.aspx
<asp:UpdatePanel ID="UpdatePanel3" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<table style="width: 300px; background-color: #9999ff">
<tr><td>
<asp:Label ID="lblDisKisim" runat="server"></asp:Label><br />
<asp:Button ID="Button3" runat="server" Text="Ana Panel" /><br />
<br />
<asp:UpdatePanel ID="UpdatePanel4" runat="server">
<ContentTemplate>
<table style="width: 200px; background-color: #99ccff">
<tr><td>
131
<br />
<asp:Label ID="lblIcKisim" runat="server"></asp:Label><br />
<asp:Button ID="Button4" runat="server" Text="İç Panel" />
</td></tr>
</table>
</ContentTemplate>
</asp:UpdatePanel>
</td></tr> </table>
</ContentTemplate>
</asp:UpdatePanel>
Default.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
Label1.Text = DateTime.Now.ToLongTimeString();
Label2.Text = DateTime.Now.ToLongTimeString();
lblDisKisim.Text = DateTime.Now.ToLongTimeString();
lblIcKisim.Text = DateTime.Now.ToLongTimeString();
}
Ana panelde bulunan butona tõklanmasõ durumunda panelin tamamõ (iç panel de dahil)
güncellenecektir. İç panelde bulunan butona tõklandõğõnda ise sadece iç panel
güncellenecektir. Bazõ durumlarda, özellikle sayfanõn tasarõmõ gereği bir UpdatePanel
içerisinde başka bir UpdatePanel kullanõlmasõ durumu ile karşõlaşabiliriz.
132
ASP.NET AJAX’a Giriş
09 Eylül 2007
Merhabalar. Bu yazõmõzda web dünyasõnda son yõllara damgasõnõ vuran AJAX uygulama
tekniğini kõsaca ele alõp Microsoft’un ASP.NET uygulama geliştiricilere ücretsiz olarak
sunmuş olduğu ASP.NET AJAX isimli ücretsiz AJAX kod kütüphanesini uygulamalarõmõzda
nasõl kullanabileceğimizi inceleyeceğiz.
AJAX; yani Asenkron JavaScript ve XML adõ verilen uygulama modelini kullanarak istemci
ile sunucu arasõnda asenkron şekilde işlemler yapabilmekteyiz. Temel olarak bu işlemler
JavaScript dilini kullanarak tarayõcõnõn yapõsõndaki XmlHttpRequest bileşeni üzerinden
yürütülmektedir. Böylece web sayfalarõnõn tamamen güncellenmesine gerek kalmadan,
sadece belirli alanlarõnõ yenileyebilir ve böylece daha hõzlõ çalõşan web sayfalarõ
geliştirebiliriz. Burada bahsettiğimiz işlem aslõnda web dünyasõnda devrim niteliğinde bir
yenilikti. Google ve Microsoft gibi şirketlerin gerçekleştirdiği projelerle son iki yõl içerisinde
giderek duyulan AJAX ismi, artõk günümüz web projelerinin vazgeçilmez bir parçasõ olmuştur.
Yeni yapõlan birçok web projesi AJAX destekli olarak geliştirildiği gibi, eski web projelerinin
birçoğu da AJAX destekli hale getirilmektedir. Bu nedenle AJAX artõk biz web uygulama
geliştiricileri için oldukça önemli hale gelmiştir.
Peki, bir ASP.NET uygulamasõnda ASP.NET AJAX’õ nasõl kullanabiliriz? Öncelikle Visual
Studio 2005 veya Visual Web Developer 2005 gibi bir araçta bu kütüphaneyi kullanabilmek
133
için ASP.NET AJAX’õn resmi web sitesinden 1.3 MB’lõk küçük bir dosyayõ bilgisayarõmõza
indirmek ve kurulum gerçekleştirmek gerekecektir. http://www.asp.net/ajax/downloads/
adresindeki Download ASP.NET Extensions v1.0 linkinden indireceğimiz dosyayõ
bilgisayarõmõza kurduğumuzda Visual Studio 2005’e gerekli proje şablonu ve AJAX kontrolleri
eklenecektir. Böylece artõk yeni bir AJAX web projesi oluşturabileceğiz. Dilerseniz artõk böyle
bir projeyi nasõl geliştirebileceğimize bakalõm.
Bu örneği Visual Studio 2005 uygulama arayüzünde geliştireceğim. Yeni bir proje açmak
için File > New > Web Site seçeneğini seçiyoruz. Açõlan pencereden ASP.NET AJAX-
Enabled Web Site şablonunu seçerek projemizi oluşturuyoruz. Ben projenin dili olarak C#’õ
seçiyorum.
Böylece yeni bir ASP.NET AJAX projesi oluşturduk. ASP.NET AJAX Extensions kurulumunu
gerçekleştirdiğimizde Visual Studio 2005 Toolbox’õna AJAX Extensions isminde yeni bir
kontrol grubu açõlõr ve buraya AJAX uygulamalarõna özel beş tane kontrol eklenir:
ScriptManager, UpdatePanel, UpdateProgress, Timer ve ScriptManagerProxy. Bu
kontrollerin görevlerine kõsaca inceleyelim.
134
Resim: Visual Studio 2005 Toolbox’õna eklenen AJAX Extensions kontrolleri
ScriptManager:
Sayfanõn AJAX destekli çalõşmasõnõ sağlayan en temel kontroldür. İstemci için gerekli
JavaScript kodlarõnõn üretilmesi ve sayfadaki diğer AJAX kontrollerinin uyumlu bir şekilde
çalõşmasõnõ sağlar. Diğer AJAX kontrollerini kullanabilmek için sayfamõzda mutlaka bir tane
ScriptManager kontrolü bulunmalõdõr.
UpdatePanel:
Sayfa içerisinde asenkron şekilde güncellenebilir alanlar oluşturulmasõnõ sağlayan kontroldür.
Böylece sayfada sadece bu alanlarõn içeriğinin asenkron şekilde güncellenerek sayfanõn
daha hõzlõ çalõşmasõ sağlanabilir.
UpdateProgress:
Asenkron güncelleme işlemi gerçekleşirken kullanõcõyõ güncelleme işleminden haberdar
edebilmek için kullanabileceğimiz kontroldür. Kontrolün içeriği sadece güncelleme
yapõldõğõnda sayfada görüntülenir, güncelleme işlemi bittiğinde ise kaybolur.
Timer:
UpdatePanel kontrolünün içeriği kullanõcõnõn isteği ile güncellenebileceği gibi bazõ
durumlarda belirli zaman aralõklarõyla da güncellenebilir. Timer kontrolü ile UpdatePanel
içeriğinin belirli zaman aralõklarõnda güncellenmesi sağlanabilir.
ScriptManagerProxy:
Bazõ durumlarda bir master sayfanõn (master page) içerik sayfasõnda ScriptManager kontrolü
kullanma ihtiyacõ olabilir. Eğer master sayfada ScriptManager var ise, içerik sayfasõna ikinci
bir ScriptManager kontrolü eklemek soruna yol açacaktõr. İşte böyle bir durumda içerik
sayfasõna ScriptManager yerine ScriptManagerProxy kontrolü ekleyerek işlemleri
yürütebiliriz. ScriptManagerProxy bu tip bir sayfada ScriptManager kontrolüne servis ve script
ekleme işlemlerini gerçekleştirir.
Projeyi açtõğõmõzda dikkatimizi çeken ilk şeylerden birisi aspx sayfamõzdaki ScriptManager
kontrolü olacaktõr. Hali hazõrda gelen ScriptManager kontrolü dõşõnda sayfamõza
UpdatePanel kontrolünü de ekleyecek olursak asenkron işlemler yürütebiliriz. Web
sayfalarõnda gezinirken çoğumuz bir kayõt formundan il bilgisini seçtiğimizde sayfanõn
yenilenmeden ile ait ilçeleri listelediğini görmüşüzdür. Dilerseniz bu şekilde bir uygulamayõ
135
gerçekleştirmeye çalõşalõm. İl ve ilçe bilgilerini saklamak için iller ve ilceler olmak üzere
Microsoft Office Access’te iki tablo oluşturalõm.
Bu tablolarõn içeriğini test amaçlõ olmak üzere birkaç il ve ilçe ile dolduralõm. Uygulama
tarafõnda ekleyeceğimiz kontroller ve yapacağõmõz işlemlere gelecek olursak; sayfaya
eklediğimiz UpdatePanel kontrolünün içeriğine iki tane DropDownList kontrolü ekleyelim.
Bunlardan ilkinin adõ ddlIller, diğerinin adõ ise ddlIlceler olsun. ddlIller’in DropDownList
Tasks penceresinden Enable AutoPostBack seçeneği aktif hale getirelim. İlk olarak ddlIller
kontrolünü iller tablosuna bağlayalõm. Bu işlemi pratik bir şekilde yine DropDownList Tasks
penceresindeki Choose Data Source seçeneğinden gerçekleştirebiliriz.
- Select a data source seçeneğinden New Data Source seçerek açõlan pencereden
Access Database ikonunu seçip OK diyelim.
- Açõlan pencereden Access dosyamõzõ seçelim ve Next diyelim.
- Karşõmõza çõkan pencereden ise tablo isimleri kõsmõndan iller tablosunu ve alt kõsõmdaki
sütun listesinden il_kod ve il_ad alanlarõnõ seçelim ve Next diyelim. Ardõndan da Finish
butonuna tõklayõp ana menümüze dönelim.
- Ana ekrandan ise ikinci açõlõr menüde il_ad, üçüncü açõlõr menüde ise il_kod
seçeneklerini aktif yapalõm. Böylece ilk açõlõr menü kontrolüne illeri bağlamõş olduk.
Şimdi yapõlacak işlem ise ilçeler açõlõr menüsüne seçilen ilin ilçelerini getirebilmek. ddlIlceler
kontrolü için de yukarõdaki ilk iki adõmõ aynen gerçekleştirdikten sonra;
- Karşõmõza çõkan pencereden ilceler tablosunu seçelim. Sütunlar listesinden ise sadece
ilce_kod ve ilce_ad sütunlarõnõ seçelim.
- Aynõ pencerede sağ kõsõmda bulunan WHERE butonuna tõklayalõm. Açõlan pencerede
Column kõsmõndan ilce_il_kod, Operator kõsmõndan =, Source kõsmõndan Control’ü
136
seçelim. Sağ kõsõmdaki ControlID kõsmõndan ise ddlIller’i seçelim. Sağ kõsõmda yer alan
Add butonu ile yaptõğõmõz seçimleri parametre olarak SQL cümlemize ekleyelim ve OK
butonuna tõklayalõm.
- Son ekranda Finish’i seçip ana ekranõmõza dönelim. Burada da ikinci açõlõr menüden
ilce_ad sütununu, üçüncü açõlõr menüden ilce_kod sütununu seçelim ve OK diyelim.
Resim: İlçeler menüsüne seçilen ilin ilçelerinin getirilebilmesi için SQL cümlemize
gerekli parametre ekleme işlemini gerçekleştiriyoruz
Artõk sayfamõz yenilenmeden iller seçeneğinden seçilen şehre ait ilçeleri diğer menümüze
ekleyecektir. Hiç JavaScript kodu yazmadan nasõl oldu bu iş diyecek olursanõz burada
ASP.NET AJAX’õn ne denli önemli bir araç olduğunu görüyoruz. Normal bir web sayfasõnda
kullandõğõmõz içeriklerimizi UpdatePanel içerisine ekleyecek olursak artõk panel içerisindeki
bileşenler otomatik olarak asenkron güncellenebilir hale gelecektir. Artõk sayfamõzõ çalõştõrõp
sonuçlarõ görelim.
137
Resim: İl menüsünden seçilen ile ait ilçeler sayfanõn yenilenmesine gerek kalmadan
alttaki menüye doldurulur
Trigger kõsmõna eklenen Button1 isimli kontrolün Click event’i (olayõ) gerçekleştiğinde, yani
butona tõklandõğõnda UpdatePanel içeriği güncellenecektir. Fakat dikkat ettiyseniz biz
yaptõğõmõz örnekte yukarõdaki gibi bir trigger eklemesi yapmadõk. Bu UpdatePanel
kontrolümüzün varsayõlan davranõşlarõndan birisidir. UpdatePanel içerisinde bulunan bir
kontrolün panele trigger olarak bağlamasõna gerek yoktur. Bu kontrol üzerinde gerçekleşecek
bir olay otomatik olarak paneli güncelleyecektir. Paneli güncelleyecek kontrol eğer tasarõm
gereği UpdatePanel dõşõnda yer alõyorsa, bu kontrolün yukarõdaki kodlarda görüldüğü gibi
Triggers kõsmõna eklenmesi gerekir.
138
köşesine güncelleme işlemi yapõldõğõnõ belirten bir yazõ veya resim ekleyelim.
UpdateProgress kontrolüne eklediğimiz içerik sayfa yüklendiğinde kullanõcõya
görüntülenmez. Güncelleme işlemi başladõğõnda bu kontrolün içeriği görünür hale gelir ve
güncelleme işlemi bittiğinde ise kaybolur. Sayfaya eklediğimiz UpdateProgress kontrolünün
DisplayAfter özelliği güncelleme işleminden kaç milisaniye sonra UpdateProgress’in
görüntüleneceğini belirler. Bu özelliği 0 olarak belirleyelim ve kontrolün içerisine güncelleme
işlemini belirten bir resim dosyasõ ve metin ifade ekleyelim.
Eğer yapõlacak güncelleme işlemi zamana bağõmlõ olacaksa AJAX kontrollerinden olan
Timer’i UpdatePanel’e ekleyerek panel içeriğinin belirli zaman aralõklarõyla güncellenmesini
sağlayabiliriz. Timer kontrolünün Interval özelliği kaç milisaniyede bir panelin
güncelleneceğini belirler. Örneğin Interval özelliği 30000 olursa panel içeriği 30 saniyede bir
otomatik olarak güncellenir.
Bu yazõmõzda Microsoft’un ASP.NET uygulamalarõnda hõzlõ ve çok kolay bir şekilde AJAX’õ
uygulamamõzõ sağlayan ASP.NET AJAX isimli kütüphanesi ile nasõl uygulama
geliştirebileceğimizi gördük. ASP.NET AJAX ile ilgili olarak www.nedirtv.com sitesindeki
ASP.NET AJAX isimli videolarõ inceleyebilirsiniz. Bir sonraki yazõmõzda görüşmek dileğiyle…
139
Diğer Konular
Anahtar kelimeler
140
Excel Dosyasõndaki Bilgilere Ulaşmak
27 Kasõm 2005
Bildiğimiz gibi MS Excel, .xls tipi dosyalarda verileri saklamamõzõ ve bu veriler üzerinde
işlemler yapabilmemizi sağlamaktadõr. Peki bu verilere .NET ortamõnda nasõl ulaşabiliriz? Bu
aşamaya geçmeden, öncelikle bu işlemi yapabilmemiz için Excel’de dosyamõzõ ne şekilde
hazõrlamamõz gerektiğini anlatacağõm.
Hazõrlayacağõm örnekte bir sõnõftaki öğrencilerin isimlerinin ve 3 tane sõnav notlarõnõn
bilgilerini Excel dosyamõzda tutalõm. Açtõğõmõz Excel dosyasõnda 4 adet sütunumuz olsun.
“AdSoyad”, “Sinav1”, “Sinav2” ve “Final” sütunlarõ. Daha sonra bu sütunlarõn altlarõnõ gerekli
bilgilerle dolduralõm.
Bilgilerin olduğu alanõ seçerek bu alana bir ad veriyoruz, böylece seçili alanõmõz tanõmlõ bir
hale geliyor. Bunun için Ekle > Ad > Tanõmla menüsünü seçiyoruz ve buradan bu alana
vereceğimiz ismi yazõp (Bu uygulamada ben NotTablosu adõnõ verdim) önce “Ekle” diyor ve
daha sonra eklenen bu isim seçili iken “Tamam” diyoruz.
141
NotTablosu WHERE Final=80” şeklindeki bir komut, bize bu tabloda Final notunun 80’e eşit
olduğu satõrlarõ getirecektir.
Şimdi sõra geldi ADO.NET ile Excel dosyamõza bağlanmaya ve verileri almaya. Bunun için bir
uygulama oluşturuyoruz. Ben örnek olarak bir ASP.NET Web Uygulamasõ oluşturuyorum.
Uygulamamõzdaki WebFrom1.aspx dosyasõna bir buton ve 1 datagrid nesnesi ekliyorum.
Butona tõkladõğõmda Excel dosyasõndaki veriler alõnarak datagride yüklenecek. Uygulamanõn
kodlarõna gelince; öncelikle veritabanõ ile ilgili işlemler için System.Data.OleDb (Excel
dosyasõna bağlanmamõz için gerekli) ve System.Data.SqlClient isim alanlarõnõ uygulama
kodlarõnõn başlangõcõna ekleyip butonun Click Event’ ine aşağõdaki kodlarõ yazõyoruz.
da.Fill(dt)
Conn.Close()
Kodlardan da anlayacağõnõz gibi genel yapõ bir Access veritabanõndan veri almakla hemen
hemen aynõ. Tek farklõlõk Excel dosyasõna bağlandõğõmõzõ belirten ConnStr değişkenindeki
Extended Properties=Excel 8.0 bilgisi. Sonraki aşamada projemizi çalõştõrõp açõlan formdaki
Veriyi Yükle butonuna tõkladõğõmõzda datagrid Notlar_1.xls dosyasõndaki tanõmlõ alandaki
verilerle dolacaktõr. (Önemli bir not: Notlar_1.xls dosyasõnõn uygulamamõzla aynõ yerde
bulunmasõ gerekmektedir.)
142
Bu kõsma kadar bir xls dosyasõnda tanõmladõğõmõz alandaki bilgileri ADO.NET nesnelerii ile
nasõl alabileceğimizi anlatmaya çalõştõm. Şimdi elimizdeki bu verileri basit bir örnekle
veritabanõna kaydetmeye çalõşalõm. WebForm1.aspx dosyasõna Veritabanõna Kaydet adõnda
bir buton ekliyorum ve butonun Click Event’ ine aşağõdaki kodlarõ yazõyorum.
Dim SqlStr As String = "INSERT INTO Notlar (AdSoyad, Sinav1, Sinav2, Final) " & _
"VALUES ('" & dt.Rows(sayi)(0) & "', " & dt.Rows(sayi)(1) & ", " & dt.Rows(sayi)(2) & ", " &
dt.Rows(sayi)(3) & ")"
da.SelectCommand = MyCommand
da.Fill(dt)
Next
143
Kodlardan ve açõklama satõrlarõndan da anlayacağõnõz gibi dt adlõ DataTable içerisindeki
verileri bir for döngüsü içerisinde satõr satõr çekerek döngünün her dönmesinde bir satõrõ MS
SQL Server içerisinde varolan “Deneme” veritabanõndaki “Notlar” tablosuna ekledik. Bu
tabloyu kendi veritabanõnõza kolayca eklemek için aşağõdaki kodlarõ kullanabilirsiniz.
144
Datatable ile Sõralama ve Filtreleme İşlemleri
11 Temmuz 2007
145
Şekil: Formumuzun tasarõmõ ve kontrollerin isimleri
Yine uygulamamõzda kullanõlacak verileri tutacağõmõz Urunler isimli tablonun tasarõmõnõ da şu
şekilde gerçekleştirelim:
İlerleyen kõsõmlarda daha düzgün bir şekilde ilerleyebilmek için gerekli olan nesnelerin
tanõmlamalarõnõ ve Form_Load'da yapõlacak işlemleri hazõrlayalõm.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Data.OleDb; // Veritabanõ işlemleri için gerekli isim alanõnõ ekliyoruz.
namespace DataTable_SortFilter
{
public partial class Form1 : Form
146
{
// Connection, DataAdapter ve DataTable nesnelerini field olarak tanõmlõyoruz.
OleDbConnection con;
OleDbDataAdapter da;
DataTable dtUrunler;
public Form1()
{
InitializeComponent();
}
DataTable nesnemizi verilerle doldurduk. Şimdi yavaş yavaş sõralama ve filtreleme işlemlerini
nasõl gerçekleştirebileceğimize bakalõm.
147
alan UrunID sütunu olacaktõr. UrunID'si 5 olan bir kaydõn DataRow tipinden bilgilerine şu
şekilde ulaşabiliriz.
Hazõrlamõş olduğumuz Windows uygulamasõndaki btnFind isimli butonun vazifesi txtID isimli
textbox'a girilen rakamsal değerin bulunduğu kaydõn bilgilerini getirmek olacaktõr. btnFind
isimli butonumuzun Click event'inde çalõşacak olan metodu aşağõdaki gibi dolduralõm.
// Hatalõ bilgi veya olmayan bir ID girildiğinde uygulamanõn düzgün çalõşmasõ için
// işlemleri try-catch içerisinde ele alõyoruz.
try
{
int urunID = Convert.ToInt32(txtID.Text);
// Kullanõcõdan ID değerini aldõk. Rows kolleksiyonunun Find metodu parametre olarak
// verilen değeri satõrlar içerisinde arar ve bulduğu satõrõ DataRow tipinde geriye
// döndürür. Böylece satir isimli DataRow nesnemizin indekleyicileri ([]) aracõlõğõyla
// sütun isimlerini vererek kaydõn bilgilerine ulaşabiliriz.
DataRow satir = dtUrunler.Rows.Find(urunID);
string satirBilgileri = satir["UrunID"].ToString() + " - " + satir["Ad"].ToString() +
" - " + satir["Fiyat"].ToString() + " YTL";
MessageBox.Show(satirBilgileri, urunID + " ID'li ürünün bilgileri");
}
catch (Exception ex)
{
MessageBox.Show("Satõr bulunamadõ!");
}
}
Uygulamayõ çalõştõrdõğõmõzda gridi doldurup varolan bir kaydõn UrunID bilgisini txtID isimli
textboxa yazõp butona tõklatõrsak o ürün ile ilgili UrunID, Ad ve Fiyat gibi bilgileri mesaj kutusu
içerisinde görebiliriz.
148
Şekil: Find metodu ile ID bilgisi verilen kaydõn bilgilerine ulaşmak
Böylece Find metodunu kullanarak primary key sütunumuzdaki bir bilgiye göre ilgili kaydõn
değerlerine nasõl ulaşabileceğimizi görmüş olduk. Find metodunun kullanõmõnõ inceleyecek
olursak bir de aşõrõ yüklenmiş halinin olduğunu görebiliriz. Metodun ikinci versiyonu ise object
tipinden bir dizi ister. Eğer tablomuzun primary key alanõnõ birden fazla sütun oluşturuyorsa,
Find metodunun bu versiyonunu kullanarak birden fazla kriter belirterek arama işlemi
yapabiliriz. Örneğin dtUrunler tablomuzun primary key alanõnõn sadece UrunID sütunundan
değilde, UrunID ve Ad sütunlarõnõn birleşiminden oluştuğunu varsayalõm. Böyle bir durumda
arama kriterini sadece UrunID alanõ üzerinden değil, hem UrunID hem de Ad alanõ üzerinden
verebiliriz. Aslõnda Find(object key) versiyonu primary key alan üzerinden WHERE UrunID=5
gibi bir arama yaparken, Find(object[] keys) versiyonu ise UrunID ve Ad sütunlarõnõn primary
key olduğu bir durumda WHERE UrunID=5 AND Ad='Çikolata-Fõndõklõ' şeklinde bir arama
yaparak sonucu getirir. Find metonun aşõrõ yüklenmiş halinin kullanõmõnõ aşağõdaki örnekte
görebilirsiniz.
// Object tipindeki dizimizin ilk değer UrunID, ikinci değeri Ad sütunu için.
object[] urunID_Ad = {5, "Çikolata-Fõndõklõ"};
DataRow satir = dtUrunler.Rows.Find(urunID_Ad);
149
Fiyat<2 ORDER BY Ad gibi) Bu tip durumlarda veritabanõna tekrar SELECT sorgularõ
göndermeden DataTable nesnesi üzerinden de sorgulama işlemleri gerçekleştirebiliriz.
DataTable sõnõfõ içerisinde yer alan Select metodu bu görevi üstlenmektedir. Verilen krtier ve
sõralama ifadesine göre DataTable içerisindeki veriler üzerinde kriterlere uyan karakterleri
DataRow dizisi olarak geriye döndürür. Select metodunun versiyonlarõnõ inceleyecek olursak;
- filterExpression: Filtreleme ifadesi. WHERE ile kullanõlacak ifade. Örneğin; "Fiyat>1 AND
Fiyat<5" gibi.
- sort: Sõralama ifadesi. ORDER BY ile kullanõlacak ifade. Örneğin Fiyat DESC gibi.
- recordStates: Bildiğiniz gibi DataTable içerisindeki veriler üzerinde çalõşma zamanõnda
değişiklikler yapabiliyoruz. recordStates parametresi DataTable içerisindeki kayõtlarõn
durumuna göre seçme işleminin hangi kayõtlar arasõndan yapõlacağõnõ belirler. Silinmiş
kayõtlar arasõndan seç, değiştirilmeyen kayõtlar arasõndan seç gibi... DataViewRowState
enum'õ (numaralandõrõcõ) tipinden değer alõr. Bu değerler ve anlamlarõnõ aşağõdaki listede
bulabilirsiniz.
150
// Tablodaki tüm kayõtlarõ getirir.
DataRow[] satirlar = dtUrunler.Select();
Yukarõdaki ifadelerin tamamõndan dönen sonuç DataRow dizisi şeklindedir. Dizi olarak gelen
bu kayõtlarõ bir foreach döngüsü içerisinde uygulama ortamõna aktarabiliriz. Getirilen
sonuçlarõn label1 isimli bir Label kontrolüne yazõmõnõn örnek kodlarõ aşağõda yer almaktadõr.
// Seçilen satõrlar dtUrunler isimli tabloya ait olduğu için başka yapõya sahip
// bir DataTable nesnesine yüklenemez! Buradaki sorunu aşabilmek için yeni
// bir DataTable nesnesini dtUrunler isimli tablonun Copy metodu ile oluşturuyoruz.
// Yani dtGecici isimli tablomuz dtUrunler tablosu ile aynõ yapõya sahip oluyor.
151
// Fakat bize sadece o an seçilen veriler gerekli(satirlar dizisi). Bu nedenle de
// dtGecici'deki row'larõ Clear metodu ile siliyoruz. Select metodunun kullanõmõnda
// benzer durumlarda sõkõntõ çõkabilmektedir. Burada ele almadõğõmõz DataView nesnesi
// bu problemleri çözebilecek şekilde dizayn edilmiştir.
DataTable dtGecici = dtUrunler.Copy();
dtGecici.Clear();
152
durumlarda DataTable sõnõfõ içerisinde yer alan Select metodu ile birden fazla satõr üzerinde
seçme işlemleri, yine DataTable içerisinde bulunanan Rows kolleksiyonuna ait Find metodu
ile de tek kaydõ seçme işlemlerini gerçekleştirebiliriz. Bu işlemleri yaparken sorgulamalar
veritabanõ üzerinde değil de, DataTable nesnemiz üzerinde gerçekleşeceği için bilgisayarõn
belleğinde tutulan bir veri üzerinde gerçekleşen bu işlemler daha hõzlõ olacaktõr. Bu noktada
bu işlemler yapõlõrken veritabanõ üzerinde yapõlacak değişikliklerin uygulamaya
yansõmayacağõnõ da unutmamamõz gerekir.
153
Adõm Adõm Team Foundation Server Single-Server
Kurulumu
07 Mart 2007
Bu yazõda Team Foundation Server kullanabilmemiz için gerekli olan araçlarõn kurulumunu
adõm adõm inceleyeceğiz. Yine Visual Studio 2005 üzerinde takõm projesi oluşturup bu
projede çalõşabilmek için gerekli olan Team Explorer kurulumunu ve Visual Studio 2005'te
yeni bir takõm projesini nasõl oluşturabileceğimizi göreceğiz. Bu dökümanda anlatõlan kurulum
Team Foundation Server Single-Server Deployment kurulumudur. Kurulum Windows
Server 2003 - Standart Edition üzerinde yapõlmõştõr.
154
TFSSERVICE kullanõcõsõ ile aynõ yetkilere sahip olmasõ yeterli olacaktõr.
- TFSPROXY: Team Foundation Server Proxy tarafõndan kullanõlacak olan kullanõcõdõr.
Remote bilgisayarlarda administrator kullanõcõsõ olmasõ gereklidir. Bu kullanõcõ kurulum
işlemlerinde kullanõlmayacaktõr.
- Control Panel > Administrative Tools kõsmõndan Configure Your Server Wizard’a girin.
- İlk iki ekranõ Next’i seçerek geçin. Ekrana gelen Server Role penceresinden Application
Server (IIS, ASP.NET) seçip Next’e tõklayõn.
- Gelen ekrandan sadece Enable ASP.NET seçeneğini seçin ve kurulumu tamamlayõn.
(Frontpage Server Extensions seçilmemelidir)
- Kurulum bittikten sonra http://windowsupdate.microsoft.com adresinden son güncellemeleri
yapõn.
Not: IIS krulumunu, benzer şekilde Control Panel > Add/Remove Programs kõsmõndaki
Windows Components seçeneğinden de gerçekleştirebilirsiniz.
- TFS için kurulacak olan SQL Server 2005 sürümü Standart Edition veya Enterprise
Edition olmalõdõr.
- Kurulum CD'lerinden CD-1’i açõn. Start ekranõndan Install’õn altõndaki Server components,
tools, Books Online, and samples seçeneğini seçin. Bir sonraki aşamada Prerequestlerin
kurulumu yapõlacaktõr.
- Sonraki kõsõmda sistem ve donanõm gereksinimleri test edilecektir.
- Registration kõsmõnda gerekli Key'i girip Next’i seçin.
- Componenets to Install ekranõndan sadece aşağõdaki bileşenleri seçiniz:
* SQL Server Database Services
* Analysis Services
* Integration Services
* Reporting Services
* Workstation components, Books Online, and development tools
- Components to Install penceresindeki Advanced seçeneğinden açõlan penceredeki ağaç
yapõsõnõ açõnõz ve;
* Database Services’in altõndaki Replication’a tõklayõn. Buradan Entire feature will be
unavailable seçeneğini seçiniz.
* Client Components’in altõndan Management Tools dõşõndaki tüm bileşenlerde Feature
will be unavailable seçeneğini seçiniz.
* Documentation, Samples, and Sample Databases’in altõndaki SQL Server Books
Online seçeneğinden Feature will be unavailable seçeneğini seçiniz.
155
- Instance penceresinden Default Instance seçin. (Kurulumun başarõlõ bir şekilde
yapõlabilmesi için Default Instance seçilmelidir. Named Instance'õn seçilmesi durumunda TFS
kurulumu başarõsõz olacaktõr.)
- Service Account ekranõndan Use the built-in System Account’u seçip listeden Local
System’i seçin.
- Start services at the end of the setup seçeneğinden tüm servisleri seçin.
- Authentication Mode kõsmõndan Windows Authentication seçeneğini seçin.
- Collocation Settings kõsmõndan dili Latin1_General seçin ve aşağõdaki kõsõmdan Accent–
sensetive seçeneğini seçin.
- Report Server Installation Options penceresinde Install the default configuration’õ
seçin.
- Error and Usage Report Settings penceresindeki iki seçeneği isteğinize göre
seçebilirsiniz.
- Son aşamada yapõlacak olan kurulumun özeti görüntülenir. Install seçeneğine tõklayarak
kuruluma başlayõn.
- Bu kurulumdan önce SQL Server 2005 – Service Pack 1’in yüklenmesi sağlõklõ olacaktõr.
http://go.microsoft.com/fwlink/?LinkId=65988 adresinden SQL Server 2005 – Service Pack 1
‘i yükleyin ve kurulumu yapõn.
- Hotfix kurulumu için öncelikle SQL Server Configuration Manager’i açõn ve SQL Server
2005 Services’in altõndaki SQL Server Browser’õ Stop seçeneğinden durdurunuz.
- Team Foundation Server DVD'si içerisindeki SQLServerKB klasörünü açõn ve AS2005-
KB914595-x86-ENU.exe isimli hotfix installer dosyasõnõ çalõştõrõn. (Eğer 64 bit sistem
üzerinde çalõşõyorsanõz diğer dosyalardan uygun olanõnõ seçin)
- Kurulum bittikten sonra SQL Server Configuration Manager’da SQL Server Browser’õ
Automatic konumda ve çalõşõr durumda olduğunu kontrol edin. Çalõşmõyorsa çalõşõr hale
getirmeniz gerekmektedir.
- SQL Server 2005 Network Configuration’da Protocols for MSSQLServer’a tõklayarak
TCP/IP‘nin enabled olduğuna emin olun.
156
sayfa üzerinde hiçbir ayar değişikliliğinin yapõlmamasõ gerekmektedir. SharePoint üzerindeki
gerekli ayarlarõ daha sonradan Team Foundation Server yapacaktõr. Bu sayfanõn açõlmamasõ
durumunda http://go.microsoft.com/fwlink/?LinkId=52668 adresini ziyaret ederek sorunun
olasõ sebebini ve çözümünü araştõrõnõz.)
Team Foundation Server kurulumuna geçmeden önce yapõlan kurulumlar ile ilgili güncelleme
işlemlerinin yapõlabilmesi için Windows Update sitesini ziyaret ediniz ve varsa gerekli
güncelleme işlemlerini yapõnõz. (Adres: http://windowsupdate.microsoft.com)
- Kurulum tamamlandõktan sonra All Programs > Microsoft SQL Server > Configuration
Tools kõsmõndan Reporting Services Configuration’õ açõnõz. TFS’in kurulu olduğu
makinanõn adõnõ (yani bulunduğunuz makina) ve database instance adõnõ yazõn. (Bu isimlerin
otomatik olarak gelmesi gerekiyor)
- Sol kõsõmdaki butonlardan Encryption Keys seçeneğine tõklayõnõz. Gelen ekrandan
Backup’a tõklayõnõz. Çõkan ekrana bir şifre ile şifrenin tutulacağõ dosyanõn kaydedileceği yeri
ve dosya adõnõ belirleyiniz. (Bu işlem Reporting Services Encryption Key’in yedeklenmesi
amacõyla yapõlmaktadõr. Zorunlu bir işlem değildir.)
- Internet Explorer’da adres kõsmõna
http://localhost:8080/services/v1.0/Registration.asmx adresini yazõn ve açõlan sayfadan
GetRegistrationEntries linkine tõklayõn. Açõlan sayfadaki Invoke butonuna tõklayõnõz. (Metin
kutusuna herhangi bir değer girmenize gerek yok.) Karşõnõza gelen XML metinde
<Type>vstfs</Type> şeklinde bir kõsõm var ise herhangi problem yok demektir.
157
Team Foundation Server'a bağlanarak proje içerisinde çalõşabilmek için farklõ yazõlõmlar
kullanõlabilir. Yazõlõm geliştirici veya programcõ olarak TFS üzerindeki projelerle çalõşabilmek
için Visual Studio 2005'i kullanmamõz gerekecektir. Bu kõsõmda da Visual Studio 2005 ile TFS
sunucusuna bağlanabilmek için gerekli olan Team Explorer'õn kurulumunu göreceğiz. Bu
kurulum TFS'e bağlanacak bilgisayarlara yapõlacaktõr. TFS kurulu olan makinada da Visual
Studio 2005 kullanõlacaksa, aynõ şekilde bu makinaya da kurulumu gerçekleştirebiliriz.
Kurulum için şu adõmlarõ takip etmemiz gerekecektir:
Team Explorer kurulumunu yaptõktan sonra, Visual Studio 2005’te TFS sunucusuna
bağlanabilmek için Tools menüsünden Connect to Team Foundation Server seçeneğine
tõklayõn. Açõlan pencereden Servers butonuna tõklayõn. Açõlan pencereden Add butonuna
tõklayõn ve Team Foundation Server Name kõsmõnda bağlanacağõnõz sunucunun adõnõ veya
IP numarasõnõ girin. Daha sonra Close butonuna tõklayõn ve OK seçeneğini seçin. (Listede
bağlanabileceğiniz proje var ise bu projeyi seçerek OK butonuna tõklayabilir ve projeye
bağlanabilirsiniz) Bağlanma esnasõnda sizden TFS sunucusuna bağlanma yetkisi olan
kullanõcõ adõ ve şifresi istenecektir. Sunucuda bulunan ve TFS’e bağlanma yetkisi olan bir
kullanõcõ hesabõnõ kullanmanõz gerekmektedir. Bu şekilde TFS sunucuna bağlanabilir ve
yetkileriniz çerçevesinde bir projeye dahil olabilir veya yeni bir proje oluşturabilirsiniz.
Visual Studio 2005’te yeni bir takõm projesi oluşturmak için File > New > Team Project’i
seçin ve açõlan pencereden bağlanacağõnõz TFS sunucusunu seçin. Gelen ekranda
oluşturulacak projenin adõnõ belirterek ve sonraki aşamada projenizde kullanacağõnõz şablonu
158
seçin. MSF for Agile ve MSF for CMMI şablonlarõndan birini seçebilir veya kendi
oluşturduğunuz proje şablonlarõnõ kullanabilirsiniz. MSF for CMMI, CMMI proje süreçlerini
takip edebilmek için kullanõlabilecek bir şablon olduğu için küçük ve orta büyüklüklerdeki
projelerde pek tercih edilmez. MSF for Agile veya kendi oluşturduğunuz proje şablonlarõ
yeterli olacaktõr. Proje şablonu seçildikten sonra. sõradaki ekranda eğer proje ile ilgili
açõklamalar varsa yazõn ve Next’i tõklayõn. Projenin kaynak kodlarõnõn tutulacağõ yeri seçin.
Ekrana, oluşturacağõnõz proje ile ilgili bilgiler getirilir. Son kõsõmda Finish’e tõklayarak projeyi
oluşturun.
159