Uğur UMUTLUOĞLU w ww ww w..uum muuttlluuoogglluu..ccoom m hhttttpp::////uum muuttlluuoogglluu..bbllooggssppoott..ccoom m uugguurr..uum muuttlluuoogglluu@ @nneettrroonn..ccoom m..ttrr
Son Güncelleme: 18 May õs 2008 Bu materyali istedi ğiniz şekilde dağõtabilir ve sitenizde yayõnlayabilirsiniz.
1
İçindekiler Önsöz................ Önsöz .................................. .................................... ................................... ................................... .................................... ................................... .......................... ......... 3 ASP.NET................ ASP.NET.................................. .................................... .................................... .................................... .................................... ................................ ..................... ....... 4 ASP.NET ASP.NET Web Site Administr Administratio ation n Tool ..................................... ....................................................... .................................... ..................... ... 5 HttpBrowserCapabilities HttpBrowserCapabilities ile Tarayõcõ Bilgilerine Ulaşmak ...................................... ................................................... ............. 8 AdRotator ile Reklam Yönetim Sistemi Geliştirmek.............. tirmek................................. ..................................... ......................... ....... 12 View State ile Durum Yönetimi Yönetimi .................................... ....................................................... ...................................... ................................. .............. 19 ASP.NET ASP.NET 2.0 - Sayfa Sayfa Direkti Direktifleri fleri (Page Directives) Directives) .................................... ....................................................... ...................... ... 29 ASP.NET ASP.NET 2.0 - Performan Performanss Yönetimi Yönetiminde ndeki ki Yenilikl Yenilikler er .................................. .................................................... ..................... ... 38 GridView'e Programatik Veri Bağlamada Sayfalama ve Sõralama İşlemleri.... lemleri..................... ................. 49 GridView Kayõtlar õnõ Okumak ve Metin Dosyasõna Aktarmak.................................... Aktarmak........................................... ....... 54 GridView'deki Kayõtlar õ Excel Dosyasõna Aktarmak. Aktarmak.................... ....................................... ...................................... .................. 61 ASP.NET ASP.NET 3.5 ile Gelen Gelen Yenilikl Yenilikler.............................. er............................................... .................................. .................................. ..................... .... 67 TreeView'da Veritabanõyla ve XML Dosyalarla Çalõşmak......................................... mak................................................. ........ 74 Site Navigasyonu Hakkõnda Bili Bilinmey nmeyenle enler............ r............................. ................................... .................................... ........................ ...... 84 TreeView Kontrolüne Kullanõcõ İsteğine Göre Göre Veri Veri Ekleme Ekleme ....................................... .............................................. ....... 97 ASP.NET ASP.NET AJAX AJAX ................. .................................... ..................................... .................................... ..................................... ..................................... ......................10 ....107 7 ASP.NET ASP.NET ATLAS............................ ATLAS............................................. ................................... .................................... .................................... ...........................10 .........108 8 AJAX: Asenkron JavaScript ve XML...............................................................................115 ASP.NET AJAX Uygulamalar Uygulamalar õ ile İlgili Sorunlar ve Çözümleri.........................................122 AJAX Uygulamalar Uygulamalar õnda UpdatePanel Kullanõmõ..................................... ....................................................... .........................126 .......126 ASP.NET AJAX’a Giriş .................................... ...................................................... .................................... .................................... ...........................13 .........133 3 Diğer Konular............ Konular.............................. .................................... .................................... .................................... .................................... ................................1 ..............140 40 Excel Dosyasõndaki Bilgilere Ula şmak.................................. mak.................................................... .................................... ........................141 ......141 Datatable ile Sõralama ve Filtreleme İşlemleri lemleri.................. ..................................... ...................................... ............................14 .........145 5 Adõm Adõm Team Team Foundation Foundation Server Server Single-Server Single-Server Kurulumu ................. ......... ................. .................. .............154 ....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. Kitapta görmüş olduğunuz makalelerin çevrimiçi versiyonlar õnõ yazgelistir.com ve msakademik.net adreslerinden adreslerinden de takip edebilirsiniz. Şimdilik yirminin üzerindeki teknik içerikli makalenin yer ald õğõ bu kitabõ yeni makaleler yazdõkça güncellemeye çalõşacağõm. Ekitap’õn güncel versiyonu için www.umutluoglu.com adresini takip edebilirsiniz. edebilirsiniz. Bu kitabõ sitenizden veya forumlardan paylaşabilirsiniz.
Uğur UMUTLUOĞLU
3
ASP.NET Anahtar kelimeler AdRotator Caching Performans
ASP.NET 2.0 Excel
ASP.NET AJAX
HttpBrowserCapabilities
LINQ
Site Navigasyonu SiteMap TreeView Veritabanõ Örnekleri
Sayfa Direktifleri
SqlCacheDependency ViewState
GridView
ASP.NET 3.5
Website Administration Tool
Xml
4
ASP.NET Web Site Administ Administration ration 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 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. 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 '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.
- Kullanõcõ oluşturabilir ve yönetebilir - Rol oluşturabilir ve yönetebilir 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, ç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. Security sayfasõna geldiğimizde buradan Users, Rules, Access Rules kõsõmlar õnõ ve bunlar õn üzerinde yine bu 3 k õsõmla ilgili ayarlar õ aşama aşama yapabileceğimiz bir link görüyoruz. Ben örneğimizi alt taraftaki Users, Rules, Access Rules kõsõmlar õnõ kullanarak yapacağõm. Users kõsmõna baktõğõmõzda bizim şu anda Windows authentication tipini kullandõğõmõzõ ve dolayõsõyla kullanõcõ yönetiminin yönetiminin aktif olmadõğõnõ söylüyor. Alt kõsõmdaki select authentication type linkine tõklayarak buradan from the internet seçeneğini seçiyoruz ve sağ alttaki Done linkine tõklõyoruz. web.config dosyamõza bakacak olursak authentication modunun artõk Forms olduğunu görüyoruz. Böylece kullanõcõ yönetimi artõk aktif hale geldi. Users kõsmõnda Create user, Manage users linklerinden artõk kullanõcõ oluşturabilir ve kullanõcõlar õ yönetebiliriz. Birkaç kullanõcõ hesabõ oluşturduktan sonra Roles kõsmõndan rolleri aktif hale getirip bir rol olu şturalõm ve kullanõcõlar õn bazõlar õnõ bu rol ile ilişkilendirelim.
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.
Şimdi uygulamamõza dönüp web.config dosyalar õna ve App_Data klasörünün içeriğine bakalõm. Solution Explorer'dan Refresh butonuna tõkladõğõmõzda App_Data klasörünün klasörünün içerisinde bir SQL Server 2005 veritaban õ dosyasõ oluştuğunu göreceğiz. Bu veritabanõndaki ilgili tablolarda oluşturduğumuz kullanõcõlarla ve rollerle ilgili bilgilerin tutulduğunu görebiliriz. görebiliriz. (Aslõnda bu veritabanõnõ dosyasõnõn bir çok işlevi ve getirdiği birçok kolaylõk var, ama onu ayr õ bir konu olarak yazmak gerekir.) web.config dosyalar õnda da daha önceden belirtti ğimiz gibi bazõ değişikliklerin oldu ğunu göreceğiz. Örneğin Editor klasörüne bakacak olursak, burada önceden bulunmayan ancak yaptõğõmõz işlemlerden sonra olu şan ve bu dizinle ilgili erişim bilgilerini tutan web.config dosyasõnõ görebiliriz. Dosyanõn içerisindeki kodlar ise asl õnda çokta yabancõ olmadõğõmõz kodlar. encoding="utf-8"?> tion/v2.0">
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, t ipi, versiyonu, eklentileri, özellikleri farklõ olabilmekte ve bu farklõlõklar bazõ durumlarda sorunlar oluşturabilmektedir. turabilmektedir. Örneğin bir tarayõcõda düzgün ve sorunsuz görüntülenen görüntülenen bir sayfa, başka bir tarayõcõda hatalõ olarak görüntülenebilmektedir. 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. HttpBrowserCa HttpB rowserCapabilities pabilities 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. HttpBrowserCapabilities HttpBrowserCapabilities sõnõf õ, HttpCapabilitiesBase sõnõf õndan türetilmiştir ve System.Web isim alanõ (namespace) altõnda yer almaktadõr. Oluşturulacak nesne örne ği ile Request.Browser özelliği üzerinden işlemler yapõlabilmektedir. Nesne üzerinden ü zerinden erişeceğimiz özellik (property) ve metotlar aracõlõğõyla tarayõcõya ait bilgileri alabilir, bu bilgilere göre i şlemler yapabiliriz. Nesne örneği oluştururken kullanõcõnõn tarayõcõ bilgilerini elde edebilmek için;
HttpBrowserCapabilities tarayici = Request.Browser; şeklinde bir tanõmlama yapõlmalõdõr. Oluşturulan HttpBrowserCapabilities nesne örneği üzerinden erişebileceğimiz bazõ önemli üyeler şunlardõr: Özellik Adõ
İşlevi
ActiveXControls
Tarayõcõnõn ActiveX desteği olup olmadõğõ hakkõnda bilgi verir. (bool tipinde değer döndürür)
Beta
Tarayõcõnõn beta sürümü olup olmadõğõ hakkõnda bilgi verir. (bool tipinde değer döndürür)
Browser
Varolan tarayõcõ bilgilerini verir. (string tipinde de ğer döndürür)
8
ClrVersion
İstemcide kurulu olan .NET Framework sürümünü getirir. (string değere dönüştürülerek kullanõlabilir)
Cookies
Tarayõcõnõn cookie desteği olup olmadõğõnõ verir. (bool tipinde değer döndürür)
Crawler
Bağlanan tarayõcõnõn crawler (Google, Yahoo gibi site indeksleyicileri) indeksleyicileri) olup olmadõğõnõ verir. (bool tipinde de ğer döndürür)
EcmaScriptVersion
Tarayõcõnõn desteklediği ECMA script versiyonunu verir. (string değere dönüştürülerek kullanõlabilir)
Frames
Tarayõcõnõn HTML frame desteği olup olmadõğõnõ verir. (bool tipinde değer döndürür)
IsMobileDevice
Tarayõcõnõn mobil bir cihaz üzerinde çalõşan tarayõcõ olup olmadõğõnõ verir. (bool tipinde değer döndürür)
JavaScript VBScript
JavaScript özelliği JavaScript desteğinin olup olmadõğõnõ, VBScript ise VBScript desteği olup olmadõğõnõ verir. (bool tipinde de ğer döndürür)
JScriptVersion
Tarayõcõnõn desteklediği Jscript versiyonunu verir. (string değere dönüştürülerek kullanõlabilir)
Platform
Ziyaretçinin bulunduğu platform ile ilgili bilgileri verir. verir. (string tipinde değer döndürür)
SupportsCallback
Tarayõcõnõn Client Script CallBack desteği olup olmadõğõnõ verir. (bool tipinde değer döndürür)
Type
Tarayõcõnõn ismini ve tipini t ipini 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)
Win16
İstemcinin Win16 tabanlõ bir bilgisayarda çalõşõp çalõşmadõğõnõ verir. (bool tipinde değer döndürür)
Win32
İstemcinin Win32 tabanlõ bir bilgisayarda çalõşõp çalõşmadõğõnõ verir. (bool tipinde değer döndürür)
HttpBrowserCapabilities'in HttpBrowserCapabilities'in özelliklerini daha yakõndan inceleyebilmek için örnek bir uygulama geliştirelim. Açacağõmõz ASP.NET web uygulamasõnda sayfamõzõn Page_Load olayõ için aşağõdaki kodlar õ Default.aspx.cs dosyasõna ekleyelim. protected void Page_Load(object sender, EventArgs e) { // İstemcinin tarayõcõsõ ile ilgili bilgilere ula şabilmek için HttpBrowserCapabilities HttpBrowserCapabilities nesnesini // aynõ tipten değer getiren Request.Browser Request.Browser özelli ö zelliği aracõlõğõyla oluşturmalõyõz. HttpBrowserCapabilities HttpBrowserCapabilities tarayici = Request.Browser ; Response.Write("Taray õcõ beta sürüm mü? : " + tarayici.Beta + " "); Response.Write("Taray õcõnõn cookie desteği var mõ? : " + tarayici.Cookies + " ");
9
Response.Write("Taray õcõ mõbil bir cihazda mõ çalõşõyor? : " + tarayici.IsMobileDevice + " "); Response.Write("Taray õcõnõn Ecma script versiyon numarasõ : " + tarayici.EcmaScriptVersion + " "); Response.Write("Taray õcõnõn çalõştõğõ işletim sistemi : " + tarayici.Platform + " "); Response.Write("Taray õcõnõn tipi: " + tarayici.Type + " "); } Uygulamayõ çalõştõrdõğõmõzda kendi tarayõcõlar õmõz ve çalõştõğõmõz sistem ile ilgili olarak aşağõdaki gibi bir sonuç elde edeceğiz.
Tarayõcõ ile ilgili bilgilere ulaşmak NOT: Tarayõcõ ile ilgili bilgilere eri şmek için HttpBrowserCapabilities 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. yapabiliriz.
Nesne örneği veya Request.Browser özelliği üzerinden taray õcõ özelliklerine ulaşabiliriz 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 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 bilgisayarlardaki tarayõcõlar õ kullanabilecekleri 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 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.
Tarayõcõnõn özelliklerine göre kullan õcõya farklõ içerikler sunabiliriz.
11
AdRotator ile Reklam Yönetim Sistemi Geliştirmek 12 May õs 2007
AdRotator, ASP.NET uygulamalar õnda dönüşümlü olarak reklamlar õ veya tanõtõcõ resim dosyalar õnõ görüntülenmesini görüntülenmesini sağlayan kontroldür. Resim dosyalar õnõ görüntülemenin yanõnda, hangi resim dosyasõnõn ne sõklõkla görüntüleceği gibi bir işlevselli ği de yapõsõ itibariyle sağlamaktad õr. Yine anahtar kelime tanõmlamalar õ (keyword) ile yayõnlacak reklamlar õ sahip olduklar õ kelimelere göre süzülmesi ve buna göre yayõnlanmasõnõ otomatik olarak sağlamaktad õr. Bu işlemleri yapabilmek için temel olarak uygulama içerisindeki bir XML dosyasõ kullan õlmaktadõr. Belirli bir formatta yazõlan reklam bilgileri, XML dosyas õ içerisine kaydedilerek AdRotator kontrolüne bağlanõp reklamlar õn kolay bir biçimde site içerisinde dönüşümlü şekilde görüntülenmesi sağlanõr. Aşağõdaki 3 tane reklam içeren ve AdRotator için kullanõlabilecek özelliklere sahip bir XML dosyasõ örneği bulunmaktadõr. NedirTVimages/nedirtv.j images/nedirtv.jpg pghttp://www.nedirtv.c http://www.nedirtv.com rl> 5videoMS MS Akademik Akademikimages/msakad images/msakademik.gif > http://www.msakad http://www.msakademik.net vigateUrl> 3makaleYazgeliştirimages/yazgeli images/yazgelistir.gif > http://www.yazgeli http://www.yazgelistir.com gateUrl> 5makale Bu şekilde hazõrlanan bir XML dosyasõ AdRotator kontrolünün AdvertisementFile özelliğine dosya yolu belirtilerek ba ğlanõp kullanõlabilir. Dosyadaki her boğumu bir reklamõ tanõmlar. Buradaki resmin alt metnini, resim dosyasõnõn yolunu ve adõnõ, ise resme tõklandõğõnda hangi URL'ye gidileceğini belirler. XML
12
dosyasõ içerisinde tanõmlõ olan 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 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 f azla gösterilecektir.) gösterilecektir.) 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 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 reklamlarla ilgili olarak; bir reklamõn kaç kez görüntülendiği, o reklama kaç kez t õklandõğõ gibi istatistiklerin istatistiklerin tutmakta böyle bir sistemde oldukça zengin bir işleyiş sunacaktõr. Yukar õda bahsedilen bahsedilen sorunlar õ XML dosyasõnõ kullanarak gerçekleştirmek zahmetli ve zor işlemler gerektirecektir. AdRotator ile ilgili olarak bu sorunlar õ aşmak için, öncelikli olarak AdRotator kontrolüne bağlanacak olan verileri bir XML dosyasõndan getirmek yerine, veritabanõndaki bir tablodan getirmek gerekecektir. Bu bize reklamlar õn değiştirilmesini, yeni reklamlar õn eklenmesini sağlamak ve reklamlar hakkõnda istatistikler tutmak için oldukça esnek ve kolay bir yapõ sağlayacakt õr. Bunun için öncelikli olarak kendimize bir tablo oluşturup, reklamlar ile ilgili yukar õdaki XML dosyasõndaki bilgileri bu tablo içerisinde taşõyalõm. Tablomuzu oluşturmaya geçmeden önce tablomuzda başka ne gibi bilgileri de tutabileceğimizi düşünelim. XML dosyasõndaki bilgilerin d õşõnda yine yukar õda bahsettiğimiz reklam görüntüleme sayõsõ, reklama tõklama sayõsõ, hatta reklamõn o an güncel olup olmadõğõ gibi bilgileri de aynõ tablo içerisinde tutmak yapacağõmõz işlemleri oldukça kolaylaştõracaktõr. Gelin bu şekilde kendimize Reklamlar adõnda bir tablo oluşturalõm. Aşağõdaki şekilde, SQL Server üzerinde kurulmuş bir tablonun kolon isimleri ve taşõyacağõ değerler görünmektedir. görünmektedir.
13
Resim: Reklamlar Tablosu Tablomuzdaki alanlar õ isimlendirirken 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.
Resim: Reklamlar tablosu içerisine dört tane reklam eklendi 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 bulunmakt b ulunmaktad adõr. protected void Page_Load(object sender, EventArgs e) { // Ornek isimli veritabanina baglanti baglanti cumlesi olusturuluyor. olusturuluyor. SqlConnection conn = new SqlConnection("data source=.; initial catalog=Ornek;
14
integrated security=true")) security=true")) // Tablodan reklam bilgilerini getirecek sorgu cumlesi hazirlaniyor SqlCommand comm = new SqlCommand("SELECT AlternateText, ImageUrl, ImageUrl, NavigateUrl, Impression FROM Reklamlar WHERE Durum='True'", conn); DataTable dt = new DataTable(); SqlDataAdapter da = new SqlDataAdapter(comm); SqlDataAdapter(comm); da.Fill(dt); // DataTable nesnesine nesnesine eklenen veriler, AdRotator'a veri kaynagi olarak gosteriliyor ve veriler yukleniyor AdRotator1.DataSource AdRotator1.DataSource = dt; AdRotator1.DataBind(); }
Böylece sayfa çalõştõr õldõğõnda tabloda o an aktif olan reklamlar õn bilgileri AdRotator'a bağlanacak ve AdRotator dönüşümlü bir şekilde reklamlar õn görüntülenmesini sa ğlayacak. Peki reklam bilgilerini sayfamõzda görüntüledik, ama şu anda sayfamõzda hangi reklam yer alõyor? Yukar õdaki işlemler tablodan tüm reklam bilgilerini getirdi. Bir DataTable nesnesine atõlan reklamlar kontrolümüzün kontrolümüzün DataSource özelliğine bağlandõ. AdRotator ise bu reklamlardan bir tanesini kendi içerisindeki algoritma ile seçti ve sayfada görüntüledi. İşte bu noktada AdRotator'un hangi reklamõ seçtiğini yakalamamõz ve buna göre de sayfada görüntülenen reklamõn tablodaki Goruntuleme alanõnõ 1 arttõrmamõz gerekecek. Böylece reklam yönetim sistemimizdeki en önemli işlemlerden biri olan reklam görüntüleme say õsõnõ tutmayõ başaracağõz. 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 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.
Resim: e nesnesi üzerinden o an sayfaya eklenen reklam hakk õnda bilgiler elde edilebilir 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 güncellenmesini ve 1 arttõr õlmasõnõ sağlayabiliriz. Aşağõdaki tabloda bu işlemler için gerekli kodlar yer almaktadõr. protected void AdRotator1_AdCreated(obj AdRotator1_AdCreated(object ect sender, AdCreatedEventArgs e) { SqlConnection conn = new SqlConnection("data source=.; initial catalog=Ornek; integrated security=true"); security=true"); string id = e.NavigateUrl; // 15. karakterden karakterden sonraki deger bize reklamin ID degerini verecektir. reklam.aspx?ID=3 reklam.aspx?ID=3 icerisinden 3 degeri gibi... id = id.Substring(15); id.Substring(15); // id degeri alinan reklamin bulundugu satirda Goruntuleme alanini 1 arttirarak guncelliyoruz SqlCommand comm = new SqlCommand("UPDATE SqlCommand("UPD ATE Reklamlar SET Goruntuleme=Goruntuleme+1 WHERE ID=@ID", conn); comm.Parameters.AddWithValue("@ID", comm.Parameters.AddWithValue("@ID", id); conn.Open(); comm.ExecuteNonQuery(); conn.Close(); }
! NOT: Buradaki id.SubString(15) ifadesi reklam.aspx?ID=1 reklam.aspx?ID=1 gibi bir linkteki 1 değerini alabilmek için yap õlan string bölme işlemidir. Dosya adõnõn ve parametre adõnõn farklõ olmasõ durumunda bu ifadede değişiklik yapmak gerekecektir. Böylece sayfaya getirilen reklamõ AdCreated event'i içerisinde yakaladõk ve görüntülenme sayõsõnõ tablo içerisinde güncelleme işlemi yaparak arttõrdõk. Şimdi sõra reklama tõklanmasõ durumunda tablodaki ilgili reklamõn Tiklanma alanõnõn 1 arttõr õlarak, reklamlar õn tõklanma sayõlar õnõn tutulmasõnda. Dikkat edeceğiniz gibi reklam bilgilerini sakladõğõmõ tabloda reklamõn adresinin Link alan õnda tuttuk. NavigateUrl NavigateUrl alanõnda ise sitemizin içerisindeki bir dosyanõn linkini verdik. Az sonra hazõrlayacağõmõz bu sayfada tõklanan reklamõn Tiklanma alanõnõn arttõr õlmasõ işlemini gerçekleştirerek, sayfanõn asõl reklam linkine yönlendirilmesini yönlendirilmesini sağlayacağõz.
reklam.aspx.cs sayfasõnõn Page_Load metodu içerisinde öncelikli olarak QueryString'den QueryString'den ID bilgisini almak, ID'ye sahip reklamõn Tiklanma alan õnõ güncellemek ve reklamõn asõl adresine yönlendirme yapmak gerekiyor. Aşağõda bu işlemleri gerçekleştirmek 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"] Request.QueryString["ID"];; SqlConnection conn = new SqlConnection("data source=.; initial catalog=Ornek; catalog=Ornek; integrated security=true"); security=true"); // Reklamõn tõklanma sayõsõ güncelleniyor SqlCommand comm = new SqlCommand("UPDATE SqlCo mmand("UPDATE Reklamlar SET Tiklama=Tiklama+1 WHERE ID=@ID", conn); comm.Parameters.AddWithValue("@ID", comm.Parameters.AddWithValue("@ID", reklamID); conn.Open(); comm.ExecuteNonQuery(); conn.Close(); // Reklamõn URL adresi al õnõyor SqlCommand selectComm = new SqlCommand("SELECT Link FROM Reklamlar WHERE ID=@ID",conn); selectComm.Parameters.AddWithValu selectComm.Parameters.AddWithValue("@ID", e("@ID", reklamID); conn.Open(); string url = selectComm.ExecuteScal selectComm.ExecuteScalar().ToString() ar().ToString();; // Reklamõn URL'si alõnda conn.Close(); // Reklamõn adresine yönlendirme yap õlõyor Response.Redirect(url); } } 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 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õ Bu makalemizde makalemizde AdRotator kontrolüne bağlanacak reklam verilerini veritabanõnda bir tablo içerisinde nasõl tutabileceğimizi gördük. Yine tabloda tutulan reklamlarda ilgili olarak reklam õn aktif olup olmadõğõ, reklamõn gösterim sayõsõ ve reklama tõklama sayõsõnõ da tutarak sitemiz için komple reklam yönetim sistemi geliştirmiş olduk. Umar õm projelerinizde kullanabileceğimiz faydalõ bir sistem geliştirmişizdir.
18
View State ile Durum Yönetimi 08 Ağ ustos ustos 2007
ASP.NET uygulamalar õnda durum yönetiminde (state management) veri taşõma işleminde kullanõlan nesnelerden biri de View State'dir. View State, bir ASP.NET sayfasõ içerisinde bulunan kontrollerin özelliklerinin ve programc õnõn istediği verilerin saklanmasõnõ sağlar. Varsayõlan olarak biz belirtmesek bile, sayfada Postback işlemi gerçekleştiğinde kontrollere ait bilgiler sunucu taraf õnda HTML kodlar õ üretilirken şifrelenmiş bir şekilde View State içerisine yazõlõr. Sayfa tekrar t ekrar yüklendiğinde ise kontrollerin özellikleri bu nesneden okunur. Böylece Postback işlemi sonucunda kontroller üzerinde yapõlan değişiklikler sayfa tekrar yüklendiğinde kaybedilmeden elde edilebilir.
ViewState Olmasayd õ? Çoğumuzun hatõrlayacağõ gibi, ASP veya PHP ile geliştirilen uygulamalarda 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 durumlardan birisi de bir f ormu post ettiğimizde form üzerindeki verilerin kaybolmamasõydõ. İşte ASP.NET uygulamal u ygulamalar ar õ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 uygulamalarda bize ne gibi bir b ir 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. ekleyelim. Label kontrollerinden kontrollerinden bir tanesinin t anesinin EnableViewState özelli ğini true, diğerinin ise bu özelliğini false olarak ayarlayalõm. (EnableViewState (EnableViewState özelliği bir kontrolün özelliklerinin özelliklerinin ViewState içerisinde ta şõnõp taşõnmamasõ durumunu belirler. Makalemizin ilerleyen k õsõmlar õnda EnableViewS E nableViewState tate ö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. protected void Button1_Click(object sender, EventArgs e) { Label1.Text = "EnableViewState'i kapalõ olan label"; Label2.Text = "EnableViewState'i açõk olan label"; }
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.
ViewState Hangi Durumlarda, Hangi Kontrollerin De ğerlerini Saklar? View State içerisinde içerisinde sadece formda f ormda bulunan input elementleri değil, GridView, DetailsView DetailsView ve Calendar diğer ASP.NET sunucu kontrollerinin özellikleri özellikleri de saklanmaktad saklanmaktadõr. HTML kodlar õ içerisinde taşõnan View State nesnesini gözlemlemek için isterseniz basit bir web uygulamasõ açalõm. Bu noktada View State içerisinde kontrollerin değerlerinin saklanmasõ ile ilgili önemli birkaç hususa değinebilmek için dilerseniz uygulaman õn gidişatõnõ aşağõdaki gibi takip edelim.
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 __VIEWSTATE nesnesinin ne snesinin içeriği Görüldüğü gibi bilgiler HTML kodlar õ içerisinde __VIEWSTATE adõ verilen hidden bir input elementi bulunmaktad bulunmaktadõr. Bir ASP.NET sayfasõnda varsayõlan olarak her zaman __VIEWSTATE de ğeri saklanmaktad 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.
Resim: Button ve label içeriğinin değiştirilmesinden sonra __VIEWSTATE'in saklad õğõ değer
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. 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 özellikleri özelliklerinde nde belirlediğimiz atamalar direkt olarak HTML kodlar õ içerisinde
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 Bu sonuç, __VIEWSTATE __VIEWSTATE içerisinde formdaki kontrollerin dizilimi dõşõnda Postback işlemi sonucunda kontrollerin özelliklerinde yap õlan değişikliklerin de tutulduğunun bir göstergesidir. Kontrol üzerinde sadece değişen Text özelliği değil, değişen diğer tüm özellikler de
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!
Hangi Durumlarda Verilerin ViewState İçerisinde Taşõnmasõ Engellenmeli? Kontrollerin değerlerinin ne gibi durumlarda View State St ate içerisinde saklanõp saklanmayacağõ konusunda genel bir fikre sahip olduğumuzu düşünüyorum. Yukar õda yapõlan Adõm-3 işleminden sonra eğer dikkatinizi çektiyse label kontrolü üzerinde yapt õğõmõz değişiklikten dolayõ __VIEWSTATE __VIEWSTATE içerisindeki verinin boyutu arttõ. Peki sayfamõzda büyük miktarda veri saklayan bir kontrol (örneğin GridView gibi) kullansak ve bu kontrolün içeriğini Postback işlemi sonucunda değiştirsek, __VIEWSTATE'in boyutu ne şekilde değişir? Gelin sayfamõza bir GridView nesnesi ekleyerek ne gibi değişiklikler olduğunu gözlemleyelim. gözlemleyelim. Bu örneği sayfaya eklediğim GridView'i AdventureWorks veritabanõ altõnda yer alan Production.Product tablosuna bağlayarak gerçekleştirdim.
Resim: GridView'e doldurulan veriler ve HTML k õsmõnda yer alan __VIEWSTATE nesnesinin içeriği Her ne kadar resmin boyutunu boyutunu küçültmüş olsamda, olsamda, __VIEWSTATE'in __VIEWSTATE'in oldukça fazla fa zla 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. 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 engellememiz gerekmektedir. gerekmektedir. ASP.NET sunucu kontrollerinin tamamõnda EnableViewState adõnda bir özellik ö zellik bulunmaktadõr. Bu özellik kontrolün postback işlemi sonucunda değişen değerlerinin View State içerisinde içerisinde saklanõp saklanmayaca 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. Yukar õdaki resimde gördüğünüz gibi __VIEWSTATE nesnesinin içeriği ciddi anlamda azalmõştõr. Benim yaptõğõm testte, sayfanõn boyutu 6.66 KB'dan 3.96 KB gibi bir değere düştü.
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. Bir kontrolün ViewState V iewState özelliğini kapatma işlemini kontrolün EnableViewState EnableViewState özelliği üzerinden gerçekleştirebileceğimiz gibi, bir sayfa içerisindeki içerisindeki tüm kontrollerin ViewState özelliğini de sayfamõzõn Page direkti d irektififi içerisinden içerisinden veya Page nesnesi üzerinden yine EnableViewState özelliği ile kapatabiliriz. Aşağõdaki örnek kodlarda bu i şlemlerin nasõl gerçekleştirileceği gösterilmiştir.
protected void Page_Load(object sender, EventArgs e) { Page.EnableViewState Page.EnableViewState = false; } Sayfamõzõn EnableViewState özelliğini kapatmamõz durumunda artõk kontrollerin postback sonrasõnda değişen özellikleri ViewState içerisinde tutulmayacaktõr. Fakat böyle bir durumda oluşan HTML kodlar õ içerisine bakacak olursanõz, __VIEWSTATE alanõnda hala bazõ bilgiler olacağõnõ görebilirsiniz. görebilirsiniz. Her ne kadar kontrollerin de ğişen özellikleri art õk bu nesnede saklanmasa da, sayfaya eklene kontrollerin hiyerar şik yapõsõ burada tutulmaya devam edilecektir.
ViewState Nesnesi İçerisinde Kendi Verilerimizi Saklamak View State ile sayfa içerisindeki kontrollerin özellikleri dõşõnda kendi istediğimiz verileri de taşõyabilmekteyiz. View State ile aynõ adõ taşõyan ViewState isimli nesne aracõlõğõyla istenilen verileri saklayabilir ve aynõ sayfa üzerinde gerçekleşen Postback işlemlerinden sonra bu verileri okuyabiliriz. ViewState nesnesinin yap õsõnõ inceleyecek olursak geriye StateBag adõnda bir nesne örneği döndürdüğünü ve içerisindeki nesneleri IDictionary tipinde bir kolleksiyonda sakladõğõnõ görebiliriz. görebiliriz. Indeksleyiciler Indeksleyiciler arac õlõğõyla içerisinde key-value çiftleri taşõyabilmektedir. yabilmektedir. Burada key değerimiz string, value değerimiz ise object tipinden olmalõdõr. Yine saklanacak olan object tipindeki değer serileştirilebilir (serializable) olmak zorundadõr. Yani .NET ortamõnda kendi yazd õğõmõz serileştirilebilir tipleri de ViewState içerisinde saklayabiliriz. saklayabiliriz. Aşağõdaki kod örneğinde ViewState nesnesine int ve DataTable tipinden değerlerin atanmasõ gösterilmiştir.
ViewState["miktar"] = 128535; ViewState["tablo"] = new DataTable("TestTable"); İndeksleyiciler aracõlõğõyla ViewState'e ekleme yapõlabileceği gibi, Add metodunu kullanarakta ViewState.Add("KeyAdõ", value) şeklinde bir nesne eklenebilir. Bu şekilde ViewState'e atõlan değerler Postback işlemi sonunda sayfanõn HTML kodlar õ içerisinde saklanacaktõr. Postback işlemleri sonucunda hala aynõ sayfa üzerindeysek bu verilere aşağõdaki şekilde erişebiliriz. int sayi = (int)ViewState["miktar"] (int)ViewState["miktar"];; DataTable dtTest = (DataTable)ViewState["tablo"]; (DataTable)ViewState["tablo"]; Görüldüğü gibi, ViewState V iewState içerisinde sakladõğõmõz değerler object tipinde saklanaca 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.
ViewState.Remove("tablo"); // tablo isimli nesne ViewState'den ViewState'den çõkar õlõr
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 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.) 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. 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. <%@ Page P age Language="C#" AutoEventWireup="true" EnableViewStateMac="true" CodeFile="Default.aspx.cs" CodeFile="Default.aspx.cs" Inherits="_Default" Inherits="_Default" %>
..... .....
27
..... Bu yazõmõzda, durum yönetiminde yönetiminde sõklõkla kullandõğõmõz ViewState nesnesinin davranõşlar õnõ, nerelerde ne şekilde verileri saklad õğõnõ, bu nesne içerisinde ne şekilde nesneler saklayabileceğimizi, performans ve güvenlik açõsõndan dikkat etmemiz gereken noktalar õ incelemeye çalõştõk.
28
ASP.NET 2.0 - Sayf Sa yfa a Direktifleri (Page Directives) 26 Ağ ustos ustos 2007
Sayfa direktifleri, ASP.NET uygulamal u ygulamalar ar õnda bir sayfanõn temel anlamdaki özelliklerini, davranõşlar õnõ, kullanacağõ bazõ dõş kaynaklar õn tanõmlamalar õnõn yapõlmasõnõ sağlayan ve ASP.NET sayfalar õnõn Source kõsmõnda (HTML kodlar õnõn olduğu kõsõmda) en üste yerleştirilen kod parçalar õdõr. Sayfa direkti d irektifleri fleri ile yapõlan ayarlamalar sayfanõn derleyici taraf õndan nasõl çalõşacağõnõ, nasõl ele alõnacağõnõ ve hangi kaynaklar õ kullanacağõnõ belirler. Bu anlamda bir ASP.NET sayfasõ ile çalõşõrken bu tip ayarlamalar ayarlamalar õ yapmamõzõ sağlayan sayfa direktifleri yakõndan tanõmak, kullanõmõna hakim olmak, biz ASP.NET programcõlar õ için önemli olacaktõr. Sayfa direktifleri ASP.NET'in 1.0 sürümünden sürümünden beri tüm 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 direktiflerinin listesi bulunmaktadõr. 1. Page 2. Assembly 3. Control 4. Implements 5. Import 6. Master 7. MasterType 8. OutputCache 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 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 zo zorunlu runlu 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 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 nit elik 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. uygulanmaz. - EnableViewState: Sayfa içerisindeki kontrollerin 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 ö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 örneklenec ö rneklenece eğ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 b ilgisini belirler. - Trace: Sayfada trace (izleme) işlemlerinin 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 içerisinde taşõnan bilgilerde güvenlik aç õsõndan sorun çõkarabilecek içerikler içerikler var ise (örneğin kullanõcõ bir TextBox içerisinde <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 bilgileri kabul edecektir. Aşağõdaki kod örnekğinde bir ASP.NET sayfasõna uygulanabilecek Page direktifi görülmektedir.
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 assembly'de bulunan tipler (class, struct gibi) kullanabilmektedir. kullanabilmektedir. web.config dosyasõ içerisinde 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: - Name: İlgili assembly'nin ad õnõn verilmesi gereklidir. Burada assembly dosyasõnõn uzantõsõnõ yazmaya gerek yoktur. - Src: İlgili assembly dosyasõnõn bulunduğu yer ve dosya adõnõn verilmesi gereklidir. Assembly direktifinin örnek kullanõmlar õ aşağõda görülmektedir. görülmektedir.
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 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, at mak, 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.
<%@ Control C ontrol Language="C#" AutoEventWireup="true" AutoEventWireup="true" CodeFile="Login.ascx.cs" Inherits="Login" Inherits="Login" EnableViewState="false" EnableViewState="false" %>
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 uygulanabi u ygulanabilir. lir. Implements direktifi sadece Interface niteliğini kullanmaktadõr.
- Interface: Sayfaya uygulanacak .NET interface'inin interface'inin belirtilmesi gereklidir. 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.
- Namespace: Sayfaya eklenecek namespace'in namespace'in belirtilmesi gerekir. Aşağõdaki örnekte Import direktifi ile bir b ir sayfaya namespace eklemeleri yapõlmõştõr.
6. Master Direktifi Bir Master page'in özelliklerinin özelliklerinin belirlenmesini sağlayan direktiftir. Page direktifi web form sayfalar õnda(aspx), Control direktifi user control'lerde(ascx) 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 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. tirilebilir. Aşağõda MasterType 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 Master özelli ö zelliğinin geri dönüş tipinin SiteSablonu.master isimli master page dosyasõ olduğunu belirler.
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 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 OutputCache direktifi ile yapõlan önbellekl ö nbellekleme eme işlemleri sayfanõn daha hõzlõ şekilde istemciye gönderilmesini sağlar.
- CacheProfile: web.config içerisinde tanõmlõ olan Cache profillerinden birinin sayfaya uygulanõlmasõ istenilen durumda kullanõlan niteliktir. - DiskCacheable: Verilerin disk ve benzeri bir depolama cihazõna alõnõp alõnamayacağõnõ belirler. - Duration: Önbelleğe alõnacak sayfanõn ne kadar süre ile bellekten okunaca okunacağõnõ belirler. Saniye cinsinden rakamsal değer almaktadõr. - Location: Önbelleklenen verilerin nereye kaydedileceğini belirler. Varsayõlan olarak Any değerini taşõr. Bu değer verilerin istemci, proxy ve sunucuda ta şõnabildiğini belirtir. İstenirse 34
sadece sunucuda, istemcide veya proxy'de saklanmasõ sağlanabilir. Alabilece ği diğer değerler; Client, Server, Downstream, ServerAndClient ServerAndClient ve None'dir. - NoStore: Sayfanõn header (başlõk) bilgilerinde "no cache" bilgisinin gönderi gönderilip lip 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 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 GetVaryByCustomString isimli metodun ezilmesi (override edilmesi) gerekmektedir. 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 V aryByParam:: Sayfanõn Url'den gelen QueryString parametrelerine 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 PreviousPageT PreviousPageType ype direktifi eklemek gerekecektir. P PreviousPag reviousPageType eType direktifinin alabile a labilece ceği nitelikler ve açõklamalar õ aşağõdadõr.
- TagName: PreviousPage nesnesinin hangi sõnõf õn nesne örneğini oluşturacağõnõ belirler. - VirtualPath: PreviousPage nesnesinin hangi sayfayõnõn nesne örneğini oluşturacağõnõ belirler. Aşağõdaki PreviousP P reviousPageType ageType direktifi eklendiği sayfada PreviousPag P reviousPage e nesnesinin Source.aspx sayfasõnõn nesne örneğini dönmesini sağlar.
Dilerseniz PreviousPageType PreviousPageType direktifinin sayfaya ne gibi bir etkisi et kisi olduğunu daha iyi anlayabilmek için aşağõdaki resimleri resimleri inceleyelim. Resim-4'te PreviousPageType PreviousPageType direktifi eklenmemiş bir sayfada PreviousPage nesnesinin geri dönü ş tipinin Page class' õ olduğunu görebilirsiniz. görebilirsiniz. Resim-5'te ise sayfaya PreviousPageType 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.
Resim-4: PreviousPageType direktifi eklenmemi ek lenmemiş bir sayfada PreviousPage PreviousPage nesnesinin geri dönü ş tipinin Page class'õdõr
Resim-5: PreviousPageType direktifi eklendi ğinde PreviousPage nesnesinin geri dönüş tipi Source.aspx sayfas õnõn nesne örneğidir
10. Reference Direktifi Uygulamada bulunan bir ASP.NET sayfasõnõn veya ASP.NET user control'ün sayfaya referans olarak eklenmesi ve sayfa ile birlikte derlenmesini sağlar. Böylece eklenen sayfanõn veya user control'ün class'õna sayfa içerisinden erişilebilir.
- Control: Sayfaya referansõ eklenecek kontrol dosyasõnõn adõ. - Page: Sayfaya eklenecek olan aspx sayfasõnõn dosya adõ. - VirtualPath: Projede bulunan bir dosyanõn yolu ve dosya ad õ. Page ve Control niteliklerinin niteliklerinin yerine de kullanõlabilir. Aşağõdaki Reference direktifi ile sayfaya referansõ eklenen Default2.aspx sayfasõnõn class'õna erişilebilir.
<%@ Reference VirtualPath="~/Default2.aspx" %>
11. Register Direktifi Register direktifi projede veya bir assembly dosyada bulunan user control'ün sayfaya kayõt edilmesi işleminde kullanõlmaktadõr. Hazõrlanan bir user control'ün sayfadaki HTML etiketleri içerisine ASP.NET sunucu kontrolü gibi eklenebilmesi için öncelikli olarak sayfada kayõtlõ olmasõ; yani Register direktifi ile eklenmesi gerekecektir. gerekecektir. Aşağõda Register direktifi ile kullanõlabilecek nitelikler nitelikler ve açõklamalar õ yer almaktadõr. 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 niteliklerinin kullan õmõ için aşağõdaki kod örneklerine bakmakta fayda var) Aşağõdaki Register direktifi ile sayfaya LoginKontrolum LoginKontrolum adõndaki bir user control'ü eklenmiştir. Böylece sayfaya TagName ve TagPrefix bilgileri ile ilgili dosyadaki user control eklenebilir.
Böylece ASP.NET uygulamalar õnda kullanabileceğimiz 11 sayfa direktifini detaylõ bir şekilde incelemiş olduk.
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. tirebilmekteydik. En temel performans bakõmõ tekniklerimiz 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. 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. ASP.NET 2.0 ile gelen yenilikleri şu başlõklar altõnda toplayabiliriz: toplayabiliriz: 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 Dilerseniz yukar õdaki başlõklar õ bizlere ne gibi yenilikler getirdiği ve uygulamalarda nas õl kullanacabileceğimiz hususunda detaylõ bir şekilde ele alalõm.
1. Cache Profilleri (Cache Profiles) 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. layabilmekteyiz. Sayfa veya user control içerisine ekleyeceğimiz <%@ OutputCache ... %> direktifi ile sayfanõn önbelleğe alõnma şeklini belirleyebiliyorduk. belirleyebiliyorduk. ASP.NET 2.0 ile birlikte gelen Cache Profilleri ile birlikte sayfalar õmõzda ortak olarak kullanabilece kullanabileceğimiz OutputCache ayarlamalar õnõ artõk web.config içerisinde içerisinde düzenli bir şekilde saklayabilmekte ve sayfa içerisinde OutputCache direktifinin bu profillerden birini kullanabilmesini 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.
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;
Grup 1: A, B, C, D, E, F ve G sayfalar õnõ 600 saniye süre ile, QueryString verilerini dikkate almadan Grup 2: K, L, M, N, O ve P sayfalar õnõda 300 saniye süre ile UrunID QueryString değerine göre önbellekte saklama işlemi gerçekleştirelim. Böyle bir durumda yukar õdaki Grup 1 sayfalar õna <%@ OutputCache Duration="600" VaryByParam="None" VaryByParam="None" %> ifadesini, Grup 2 D uration="300" VaryByParam="UrunID" VaryByParam="UrunID" %> sayfalar õna da <%@ OutputCache Duration="300" 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 bilgilerine göre önbellekte saklanmasõnõ istiyoruz; yani sayfalardaki 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. ..... ..... varyByControl="UrunID"/> Oluşturulan bu profilleri sayfalarda kullanabilmek için yapmam õz gereken OutputCache direktifi içerisindeki CacheProfile özelli ğini uygun profile name değerine atamak olacaktõr. Aşağõda CacheProfile_B profilini kullanan bir sayfaya yazõlacak OutputCache direktifi görülmektedir.
39
<%@ OutputCache CacheProfile="CacheProfil_B" %> Böylece Cache profillerini kullanarak sayfalar içerisinde kulland õğõmõz OutputCache direktifi bilgilerini web.config dosyasõndan okuyor ve daha yönetilebilir hale getirmiş oluyoruz.
2. Post-Caching ve Substitution Kontrolü Önbelleklenen Sayfada Dinamik Alanlar Kullanabilme 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 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. tiremiyorduk. ASP.NET 2.0 ile birlikte gelen yeniliklerle yeniliklerle birlikte artõk bu tip bir önbellekleme işlemini de gerçekleştirebilmekteyiz.
Resim: Substitution kontrolü ile önbelleklenen sayfadaki parçalar õn işleyişi 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. 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. protected static string DinamikIcerik(HttpContext ctx ) { return "" + DateTime.Now.ToLongTimeString() + ""; } 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" Duration="30" VaryByParam="none" %> ...... ...... .....
41
Resim: Post-Cache Substitution yolunu kullandõğõmõzda sadece belirli bir alan õn dinamik oluşmasõnõ sağlayabiliriz. Response.WriteSubstitution metodu ile sayfanõn HTML kõsmõna DinamikIcerik isimli metodun geriye döndürdüğü string ifade yazõlmõştõr. Burada çalõşma zamanõ esnasõnda bir metodu işaretlemek söz konusu olduğu için new HttpResponseSubstitutionCallback(DinamikIcerik) şeklinde delegate nesnesi olu şturup DinamikIcerik DinamikIcerik isimli metodu işaretlememiz gerekir. Bu teknikte gerek metodun yazõmõnda gerekse metodun çağr õmõnda biraz zorlukla kar şõlaşabileceğizi söyleyebiliriz.
- 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 kontrolünün sayfaya nasõl uygulanabilece uygulanabileceğini görebiliriz. ...... <%@ OutputCache Duration="30" Duration="30" VaryByParam="none" %> ...... ...... ..... Görüldüğü gibi Substitution kontrolünin MethodName MethodName özelliğini metodun adõ olarak
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 içerikleri ise önbellekten getirilecektir. getirilecektir.
3. SqlCacheDependency ile Veritaban õndaki Değişikliklere Göre Veri Önbellekleme ASP.NET 2.0'dan önceki sürümlerde sürümlerde önbellekleme işlemleri CacheDependency sõnõf õ ile zamana bağõmlõ kalmadan, bir dosyanõn veya klasörün değişim durumuna göre gerçekleştirilebilmekteydi. tirilebilmekteydi. Yine bu sõnõf aracõlõğõyla veritabanõnda bir tablodaki de ğişimlere bağõmlõ kalarak önbellekleme işlemleri yapõlabilmekteydi. labilmekteydi. Fakat bu işlemleri yapabilmek için gerek vertiabanõnda oluşturulacak nesneler(tablo, nesneler(tablo, trigger ve stored procedure gibi) gerekse uygulamada yapõlacak işlemler programcõ için oldukça zor işlemlerdi. ASP.NET 2.0'da gelen yeni SqlCacheDependency class'õ ve aspnet_regsql.exe aracõnõn SqlCacheDependency SqlCacheDependency seçenekleri ile gerek veritabanõnda oluşturulacak nesneler, gerekse uygulama içerisinde yapõlacak işlemler artõk çok daha kolay bir hale geldi. SqlCacheDependency 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 t abloya aktarmak ve kontrollerin bu tablo üzerinden gerçekleştirmek çok daha hõzlõ olacaktõr. Uygulama içerisinde kullanaca ğõmõz SqlCacheDependency 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 Görüldüğü gibi Cache nesnesinde saklanan veriler SqlCacheDependency nesnesi ile bütünleşik şekilde veritabanõndaki tabloya bağõmlõ bir biçimde tutulmaktadõr. Cache'de saklanan veriler istenildiğinde SqlCacheDependency nesnesi veritabanõndaki değişim olup olmadõğõnõ kontrol etmek için haber veren tabloya t abloya (notification (notification table) bakacak ve değişim yoksa Cache'de saklanan veri aynen kullan õlacaktõr. Eğer SqlCacheDependency SqlCacheDependency nesnesi notification table'da ilgili kaydõn değiştiğini görürse (ki bu Urunler tablosunda bir de ğişiklik yapõldõğõ anlamõna gelir) Cache'deki nesnenin kaldõr õlmasõnõ sağlar. Bu noktadan sonra programcõ uygulamada yazdõğõ kodlar ile Cache'den kaldõr õlmõş nesneyi tekrar doldurarak d oldurarak uygulamaya güncel verilerin aktar õlmasõnõ sağlayacaktõr. Bir projede SqlCacheDependency 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 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. parametrelerden Not: Komutlarda yaz õlan parametrelerden -S localhost: localhost isimli sunucu
44
lan -E: Windows Authentication ile ba ğ lan AdventureWorks veritaban õnõ aktif hale getir -d AdventureWorks -ed: AdventureWorks -t Urunler -et: Urunler isimli tabloyu aktif hale getir anlamõna gelmektedir. Farkl õ durumlarda kullan õlabilecek parametreler için Command Prompt'ta aspnet_regsql aspnet_regsql -? komutunu yazarak yard õm alabilirsiniz.
Resim: AdventureWorks AdventureWorks veritaban õnda SqlCacheDependency nesneleri kuruldu ve veritabanõ aktif hale geldi 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 h ale getirmemiz gerekecek. Aşağõdaki resimde gördüğümüz komutla da Urunler ad õndaki tabloyu aktif hale getireceğiz.
Resim: Urunler isimli tablo veritaban õnda aktif hale geldi 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 connectionString eklemek, ardõndan da SqlCacheDependency SqlCacheDependency tanõmlamasõnõ yapmak gerekecektir. Aşağõdaki kodlarda yapõlmasõ gereken tanõmlamalar görülmektedir. görülmektedir.
45
Resim: web.config dosyasõna connectionString ekleme ve SqlCacheDependen S qlCacheDependency cy ayarlamalar õnõ yapmak düğümü içerisine eklenen düğümünün niteliklerinden enabled="true" ifadesi SqlCacheDependency'i uygulamada aktif hale getirir. poolTime="3000" ise notification table'a ne kadarlõk sürede bir bakõlacağõnõ; yani tablonun güncellenip güncellenmedi güncellenmediğinin ne kadar sürede bir kontrol edileceğini belirler. (3000 değeri 3 saniye anlamõna gelir) alt düğümünde ise hangi veritabanlar õnõn kaydedileceği belirlenir. ile eklenen veritaban õnda name="advConnDepend" ifadesi kaydedilen veritaban õnõn adõnõ, connectionStringName="advConn" ise hangi bağlantõ cümlesinin kullanõlacağõnõ belirler. Buradaki advConn isimli bağlantõ cümlesinin düğümünde olmasõ gereklidir. 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 ne snenin SqlCacheDependency 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. public void Insert(string key, object value, CacheDependency dependencies); Metodun parametrelerine bakacak olursak ilk parametre Cache'de saklanacak verinin çağr õlacak adõ, ikinci parametre Cache'de saklanacak veri, üçüncü parametre ise CacheDependency CacheDependency tipinden saklanacak verinin dosya veya veritabanõna bağõmlõ kalmasõnõ sağlayan nesnemiz olacaktõr. Bizim üçüncü ü çüncü parametre olarak kullanaca kullanacağõmõz CacheDependency CacheDependency sõnõf õndan kalõtõlan SqlCacheDependency sõnõf õndan bir nesne olacakt õr. İsterseniz şöyle bir senaryo üzerinden SqlCacheDependency SqlCacheDependency nesnesinin kullanõmõna bakalõm. Bir sayfada bulunan GridView kontrolünde kontrolünde veritabanõndan getirilen ürünleri listeleyelim. Burada getirilen veriler performans açõsõndan her defasõndan veritabanõnda değil de Cache'den getirilsin istiyoruz. Yine SqlCacheDependency ile Cache'de saklad õğõmõz verileri tabloda güncelleme oldu ğu sürece güncellenmesini güncellenmesini istiyoruz. A şağõdaki kodlar böyle bir işlemi nasõl gerçekleştirebileceğimizi göstermektedir.
46
protected void Page_Load(object sender, EventArgs e) { // Cache'de saklanan nesnenin null olup olmad õğ õnõ kontrol ediyoruz. E ğ er veritaban õnda ğ er // değ i 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 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, SqlDataAdapter(sorgu, baglanti); DataTable dt = new DataTable(); da.Fill(dt); // SqlCacheDep SqlCacheDependency endency nesnesini olu şturuyoruz. İ lk lk parametre web.config'de tanõmlanan // SqlCacheDep SqlCacheDependency endency database'i. İ kinci kinci parametre ise veritaban õnda kontrol edilecek // olan tablonun ad õ olacakt õr. SqlCacheDependency tabloyaBaglan = new SqlCacheDependency("advConnDepend", SqlCacheDependency("adv ConnDepend", "Urunler"); // dt isimli DataTable nesnesini Cache'e at õyoruz. İ lk lk parametremiz Cache nesnesinin ad õ, // ikinci parametre Cache'de saklanaca saklanacakk nesne; yani DataTable nesnesi, üçücü parametre // ise tabloyaBaglan isimli SqlCacheDependency nesnesi olacakt õr. Art õk Cache'de saklanan // veri Urunler tablosundaki de ğ i iş imlere bağ õml õ olacakt õr. Değ i iş im olmad õğ õ sürece // değ erler erler şu an olu şturulan nesneden al õnacakt õr. Tabloda değ i iş im oldu ğ unda bu kod ğ unda bloğ u u // tekrar çal õşacağ õ için Cache'de saklanan verileri güncellenmesi otomatikmen gerçekleşir. Cache.Insert("veriler", Cache.Insert("veriler", dt, tabloyaBaglan); } // GridView kontrolünün DataSource de ğ eri eri Cache'den getiriliyor. Gelen de ğ er er object tipinde oldu ğ u ğu // için DataTable'a cast i şlemi gerçekle ştiriyoruz. GridView1.DataSource GridView1.DataSource = (DataTable)Cache["veril (DataTable)Cache["veriler"]; er"]; GridView1.DataBind(); }
Böylece DataTable nesnesini artõk Urunler tablosundaki değişimlere bağõmlõ kõlarak Cache'de saklayabiliriz. Urunler tablosunda de ğişiklik olmadõğõ sürece veriler aynen Cache'de saklanacak, ne zaman ki tabloda değişiklik olursa o zaman veriler Cache'den
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.
4. DataSource Kontrolleri ile Önbellekteki Verilerle Çal õşmak 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. tirebilmekteyiz. Bu yeni ASP.NET kontrollerinin önbellekleme işlemlerini kolay bir şekilde gerçekleştirmemizi sağlayan özelliklerinden özelliklerinden biri b iri 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 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 SqlCacheDependency özelliği ile veriyi önbellekte saklayabilmesi sa ğlanmaktad õr. Burada SqlCacheDependency özelliğinin advConnDepend:Urunler şşeklindedir. advConnDepend web.config dosyas õnda aldõğõ değer advConnDepend:Urunler tanõmlanan SqlCacheDependecy veritabanõnõn adõ, Urunler ise tablonun adõdõr. " SelectCommand="SELECT * FROM [Urunler]" EnableCaching="true" SqlCacheDependency="advConnDepend:Urunler">
5. Custom Dependency'ler Olu şturabilme 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 Cache'de veri 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 o lanaklar 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. Eğer daha önceden gridviewi sadece tasar õm aşamasõnda SqlDataSource veya AccessDataSource gibi bir datasource kontrolüne bağlayarak kullandõysanõz, sayfalama işlemi için gridviewin AllowPaging özelliğini, sõralama işlemi için de AllowSorting özelliğini true olarak ayarlamanõz gerektiğini hatõrlayacaksõnõzdõr. Bu iki özellik gridviewe otomatik olarak verileri sayfalama ve sõralama özelliği kazandõr õr. Yine sayfalama işlemi ile ilgili olarak gridview'in PageSize özelliği sayfalama yapõldõğõnda her sayfada kaç tane kayõt görüntüleneceğini belirler. Tasar õm aşamasõnda bu üç özellik bizim tüm sõralama ve sayfalama işlemlerimiz için yeterli olacaktõr; ancak gridviewe programatik yollarla veri bağlayacağõmõz zaman AllowPaging AllowPaging ve AllowSorting özelliklerini özelliklerini true olarak ayarlamak yeterli olmayacaktõr. Zira gridview kendisine bağlanan verilerin ne şekilde sayfalanacağõnõ ve sõralanacağõnõ bizim belirlememizi bekleyecektir. Dilerseniz boş bir ASP.NET sayfasõna gridview kontrolü ekleyerek üzerinde çalõşmaya başlayalõm. Eklenecek E klenecek gridview kontrolünün adõna gvUrunler diyelim. Aşağõdaki kodlarda gvUrunler kontrolü ve sayfanõn code-behind kõsmõndaki veri bağlama işlemlerimiz görülmektedir.
SqlConnection SqlConnection conn = new SqlConnection("data source=.; database=AdventureWorks; database=AdventureWorks; integrated security=true"); security=true"); SqlCommand SqlCommand cmd = new SqlCommand("Select SqlCommand("Select ProductID,Name,Color ProductID,Name,Color From Production.Product Where Where ListPrice > 1500", conn); SqlDataAdapter da = new SqlDataAdapter(cmd); DataTable dt = new DataTable(); da.Fill(dt); // GridView kontrolünün özelliklerini ve veri ba ğ lama lama i şlemlerini gerçekle ştiriyoruz. // Sayfalama ve sõralama i şlemlerini aktif hale getirdik. gvUrunler.AllowSorting gvUrunler.AllowSorting = true; gvUrunler.AllowPaging = true; gvUrunler.PageSize gvUrunler.PageSize = 10; gvUrunler.DataSource gvUrunler.DataSource = dt; dt ; gvUrunler.DataBind();
} 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 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.
Resim: Sayfalama işlemi yapõldõğõ esnada hata al õ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 belirlem b elirlememiz emiz 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 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 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. 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.
// Sayfalama i şleminde; yani PageIndexChanging PageIndexChanging event'i tetiklendi ğ inde inde çal õşacak metot GridViewSelectEventArgs e ) void GridView1_SelectedIndexChanging(object sender, GridViewSelectEventArgs { gvUrunler.PageIndex = e.NewSelectedIndex; gvUrunler.DataBind(); } // Sõralama i şlemi yapõld õğ õnda; yani Sorting event'i tetiklendi ğ ğinde inde çal õşacak metot GridViewSortEventArgs e) void GridView1_Sorting(object sender, GridViewSortEventArgs { // İ lk lk sort i şlemi yap õld õğ õnda çal õşõr if (ViewState["siralananK (ViewState["siralananKolon"] olon"] == null) { ViewState.Add("siralananKol ViewState.Add("siralananKolon", on", e.SortExpression); e.SortExpression); ViewState.Add("siralamaYo ViewState.Add("siralamaYonu", nu", "ASC"); } else { // Ayn õ kolon 2. kez s õraland õğ õnda çal õşõr if (ViewState["siralananKol (ViewState["siralananKolon"].ToString() on"].ToString() == e.SortExpression) e.SortExpression) { if (ViewState["siralamaYonu"].ToStri (ViewState["siralamaYonu"].ToString() ng() == "ASC") ViewState["siralamaYonu" ViewState["siralamaYonu"]] = "DESC"; else ViewState["siralamaYonu" ViewState["siralamaYonu"]] = "ASC"; } // Farkl õ bir kolon sõraland õğ õnda çal õşõr else { ViewState["siralananKolon"] ViewState["siralananKolon"] = e.SortExpression; e.SortExpression; ViewState["siralamaYonu"] ViewState["siralamaYonu"] = "ASC"; } } // 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) görünümünü(DataView) de ğ i iş tiriyoruz DataTable dt = (DataTable)gvUrunler.DataSource; (DataTable)gvUrunler.DataSource; dt.DefaultView.Sort = ViewState["siralananKolon"].ToString() ViewState["siralananKolon"].ToString() + " " + ViewState["siralamaYonu"].ToString(); gvUrunler.DataBind(); }
Yukar õda yapõlan işlemlere biraz daha detaylõ şekilde bakalõm.
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 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) 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. gerekecektir. Son olarakta gridview gridview nesnesini DataBind DataBind metodu ile tekrar yükleyecek olursak artõk verilerimiz düzgün bir şekilde sõralanarak görüntülecektir. Böylece gridview kontrolüne programatik yollarla veri ba ğlamada sayfalama ve sõralama işlemlerini nasõl gerçekleştirebilece ğimizi görmüş olduk. Özellikle karmaşõk sorgulamalarda sorgulamalarda gridview kontrolüne bu şekilde veri bağlayabilir layabilir ve dolayõsõyla da sayfalama-sõralama işlemlerini ele almamõz gerekebilir. Ele aldõğõmõz işlemler özellikle bu tip durumlarda oldukça işinize yarayacaktõr.
ASP.NET 2.0 ile gelen yeni veri kontrollerinden 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, ralayabilmekte, hatta yine kod yazmadan otomatik güncelleme ve silme işlemlerini de gerçekleştirebilmekteyiz. tirebilmekteyiz. Bu kontrol ile ilgili olarak o larak programcõya düşen görev ise kontrolün varolmayan 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 u zantõlõ olarak bir metin dosyasõna nasõl dönüştürebileceğimizi göreceğiz. GridView veriyi tutuş şekli açõsõndan DataTable nesnesinde benzetilebilir. GridView'da saklanan kayõtlar satõrlar ve sütunlar halinde tutulmaktadõr. Gridview'deki satõrlar GridViewRow, sütunlarda DataControlField tipinden birer nesne olarak saklanõr. Satõrlara Rows kolleksiyonundan(collection), kolleksiyonundan(collection), sütunlara ise Colums kolleksiyonunda erişebilmekteyiz. Bir satõrda bulunan bir sütunun değerine elde etmek için ise GridViewRow nesnesinin Cells kolleksiyonunu kolleksiyonunu kullanarak ilgili hücredeki bilgilere erişebiliriz. Aslõnda ASP.NET'te dosya download işlemini biliyorsak, bu bilgiler bile bizim bir gridview içerisindeki kayõtlar õ metinsel bir dosyaya aktarmamõz için yeterli olacaktõr. Kolleksiyonu ve kolleksiyonda saklanan verinin tipini bildiğimize göre bir foreach döngüsü içerisinde bu değerlere erişebilmemiz mümkündür. Bir sayfaya ekleyeceğimiz GridView'a gvUrunler adõnõ verip, gerekli ayarlamalar õ yapõp bir SqlDataSource kontrolüne bağlayalõm. Yapacağõm örnekte AdventureWorks AdventureWorks veritabanõnda yer alan a lan Production.Product tablosunu kullanacağõm(Sorgu: SELECT ProductID, Name, Color, ListPrice, ModifiedDate FROM FRO M Production.Product Production.Product ). ). Sayfaya eklenen bir buton kontrolünün Click event'inde grid kontrolünün içerisindeki verilere a şağõdaki örnek kodlar ile erişebiliriz. Kodlara bakõlacak olursa; bir foreach döngüsü ile griddeki satõrlar içerisinde ad õm adõm ilerlenmiş ve elde edilen satõr õn Cells kolleksiyonundan 1 numaralõ indeksteki değeri istenilmiş(yani Name sütunu). protected void Button1_Click(object sender, EventArgs e) { Response.Write("GridView'daki ürünlerin isimleri:"); foreach (GridViewRow row in gvUrunler.Rows) Response.Write(row.Cells[1].Text + " "); }
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. protected void Button1_Click(object sender, EventArgs e) { Response.Write("GridView'daki ürünler:"); foreach (GridViewRow gvr in gvUrunler.Rows) { for(int i=0; i < gvUrunler.Columns.Count; i++) Response.Write(gvr.Cells[i].Text + " "); Response.Write(" "); } }
Şekil: Gridviewdaki o an bulunan bütün veriler getirildi
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ü 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 o laya farklõ yaklaşõmlar õmõz olabilir. Sadece o an gridde görüntülenen satõrlar õ dosyaya kaydetmek isteyebilece 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 UpdateDelete 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 RadioButtonList kontrolü ile sadece bu sayfadaki verileri kaydetme, ilk 50 veriyi kaydetme ve tüm t üm verileri kaydetme seçeneklerini ele alacağõz. Sayfamõzõn tasar õmõ ve kodlar õ aşağõdaki gibi olacaktõr.
SortExpression="ModifiedDate" SortExpression="ModifiedDate" /> " SelectCommand="SELECT SelectCommand="SELECT [ProductID], [Name], [ Name], [Color], [ListPrice], [ModifiedDate] [ModifiedDate] FROM [Production].[Product]" DeleteCommand="DELETE DeleteCommand="DELETE FROM [Production].[Product] WHERE [ProductID] = @ProductID" UpdateCommand="UPDATE UpdateCommand="UPDATE [Production].[Product] [Production].[Product] SET [Name] = @Name, [Color] = @Color, [ListPrice] = @ListPrice, [ModifiedDate] [ModifiedDate] = @ModifiedDate @ModifiedDate WHERE [ProductID [P roductID]] = @ProductID"> /> runat="server"> Sadece Value="0">Sadece bu kayõtlar Value="1">İlk 50 kayõtTüm kayõtlar Sayfanõn tasar õmõnõ ve gridviewa bağlanacak verinin ayarlanmasõndan sonra ad õm adõm yapõlacak işlemleri kodlamaya başlayalõm. Öncelikli olarak gridde bulunan Edit ve Delete butonlar õnõn oluşturulacak txt dosyasõnda bulunmasõnõ istemeyeceğimiz için bu link butonlar õnõ yazdõrma işleminde çõkarmamõz gerekecek. Update ve Delete gibi komut çalõştõran butonlar gridview içerisinde içerisinde CommandField olarak tutulduğu için gridviewdaki CommandField kõsmõnõ programatik olarak gridden çõkarmamõz yeterli olacaktõr. Bu işlemi gerçekleştirmek için GereksizKolonlariSil adõnda bir metot yazalõm. Bu işlemin ardõndan da kullanõcõnõn radiobuttonlistten işaretleyeceği seçeneğe göre gridden farkl õ sayõda veri okunacağõ için bu kõsmõ çözümleyelim. Burada; - Sadece bu kayõtlar seçene ğini seçilirse direkt olarak grid içerisindeki satõrlar õ okuma ve download işlemi yaptõrmamõz gerekecek. - İlk 50 kayõt seçeneği seçilirse grid kontrolünün PageSize özelliğini 50 yapmak gerekecek. Yine ilk 50 kaydõn getirilebilmesi için de PageIndex özelli ğinin 0 olarak ayarlanmasõ gerekecek. Ardõndan grid kontolünün kontolünün DataBind metodunu çağõracak olursak ilk sayfaya
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, 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 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. private void GereksizKolonlariSil() { // Eğer Select, Edit ve Delete gibi CommandFieldlar CommandFieldlar aktif ise bu butonlar õn bulunduğu sütunu gridden kaldõr õyoruz. for (int i = 0; i < gvUrunler.Columns.Count; gvUrunler.Columns.Count; i++) { if (gvUrunler.Columns[i] is CommandField) gvUrunler.Columns.RemoveAt(i); } } protected void Button1_Click(object sender, EventArgs e) { GereksizKolonlariSil(); // 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 (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 } Bu şekilde gridview kontrolünün içeriğini yazdõr õlacak hale geldik. Butona t õklandõğõnda postback işlemi gerçekleşeceği için gridview kontrolünü yeniden yeniden düzenliyoruz; fakat az sonraki yapõlacak işlemlerde postback sonrasõ dosya download edileceği için sayfa 58
yenilenmeyecektir, 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 içerisindeki verileri metinsel dosyaya kaydetme işlemini üstlenecek TextKaydet metodu bulunmaktadõr. protected void TextKaydet() { // string birleştirme işleminin daha performanslõ olmasõ için System.Text isim alanõ // altõnda yer alan StringBuilder ile string birleştirme işlemi yapacağõz StringBuilder sb = new StringBuilder(); // Öncelikli olarak gridviewdaki sütunlar õn başlõklar õnõ okuyor ve değişkenimize ekliyoruz DataControlField cell in gvUrunler.Columns) foreach (DataControlField { sb.Append(cell.HeaderText + " "); // HeaderT HeaderText ext property'si hücrenin başlõk bilgisini getirir } sb.Append(Environment.NewLine); // Yeni bir satõr açõyoruz // Artõk kayõtlar õ tek tek okuyup değişkenimize ekliyoruz foreach (GridViewRow gvr in gvUrunler.Rows) { for (int i = 0; i < gvUrunler.Columns.Count; i++) { // Eğer hücrede boş değer varsa karakterinin yazõlmasõnõ engellemek için kontrol yapõyoruz if (gvr.Cells[i].Text (gvr.Cells[i].Text == " " || gvr.Cells[i].Text == "") sb.Append(" - "); else sb.Append( gvr.Cells[i].Text + " "); } sb.Append(Environment.NewLine); // Satõr bittiğinde bir alt satõra geç } // 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(" Response.AddHeader("content-dispositi content-disposition", on", "attachment;filename=Urunler "attachment;filename=Urunler.txt"); .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.
Bir önceki makalemizde GridView nesnesinin satõr-sütun (row-column) ilişkisinin ne şekilde olduğuna, GridView kontrolünün içerisindeki kay õtlar õ nasõl okuyabileceğimize ve okunan satõrlar õ metinsel bir dosyaya nasõl aktarabileceğimize değinmiştik. Bu makalemizde de okunan verileri bir Excel dosyasõna nasõl aktarabileceğimizi inceleyeceğiz. İlk bakõşta ğ i DataTable veya SqlDataSource gibi bir veri aklõmõza şu gelebilir: "GridView'in içeri ğ kaynağ õndan geliyor. Zaten o nesneleri kullanarak veri aktarma i şlemini yürütebiliriz" . Evet, kesinlikle:) Fakat özellikle web sayfalar õnda GridView ile yap õlan raporlama işlemlerinde sayfayõ kullanan kişi yapmõş olduğu sõralamaya veya sayfalamaya göre o an görünen kayõtlar õ bir dökümana aktarmak ve kendi bilgisayar õna saklamak isteyebilir. Örneğin kullanõcõ gridview'da listelenen ürünleri fiyatõna göre sõralatõp gelen ilk 50 tane kaydõ bir Excel dökümanõna aktarmak isteyebilir. İşte bu noktada veriyi s õralanmõş, sayfalanmõş şekilde zaten hali hazõrda tutan gridviewden okuma ve aktarma işlemi yapmak programcõ ve kullanõcõ açõsõndan oldukça önemli bir i şlem olacaktõr. Ö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 içerisinde verileri çok daha farkl f arklõ 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: seçebiliriz: 1. GridView kontrolündeki kontrolündeki satõrlar õ direkt olarak Excel dosyasõna aktarmak 2. GridView kontrolündeki kontrolündeki satõrlar õ okuyarak Table nesnesine aktarmak ve ardõndan Table nesnesinin içeriğini Excel dosyasõna aktarmak 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 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 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 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. 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. protected void Button1_Click(object sender, EventArgs e) { // GridView'in footer k õsmõnõn Excel dosyas õnda görüntülenm gö rüntülenmesini esini istemiyors istemiyorsak ak PagerSettings'i saklamam õz gerekli gvUrunler.PagerSettings.Visible gvUrunler.PagerSettings.Visible = false;
GereksizKolonlariSil(); lk 50 kay õt if (rblSecim.SelectedIndex == 1) // İ lk { gvUrunler.PageIndex = 0; gvUrunler.PageSize = 50; } else if (rblSecim.SelectedIndex (rblSecim.SelectedIndex == 2) 2 ) // Tüm kay õtlar gvUrunler.AllowPaging = false; ikliklerin n geçerli olmas õ için verileri tekrar gvUrunler.DataBind(); // Yapõlan değ i i şiklikleri yüklüyoruz GridiExceleKaydet(); // Gridviewdeki kay õtlar õ direkt olarak Excel'e yazacak metot }
private void GereksizKolonlariSil() 62
{ // E ğ er Select, Edit ve Delete gibi CommandFieldlar CommandFieldlar aktif ise bu butonlar õn bulundu ğ u ğ er ğ u sütunu gridden ç õkar õyoruz for (int i = 0; i < gvUrunler.Columns.Count; gvUrunler.Columns.Count; i++) { if (gvUrunler.Columns[i] is CommandField) gvUrunler.Columns.RemoveAt(i); } }
Böylece gridview kontrolünün içeriğini dosyaya yazdõr õlacak şekle getirildi. Butona tõklandõğõnda postback işlemi gerçekleşeceği için gridview kontrolü yeniden düzenlenecek, ardõndan da GridiExceleKaydet metodunda okunan kayõtlar õ dosyaya aktaracağõz. Aşağõda bu metot ve yapõlan işlemlerin açõklamalar õ bulunmaktadõr. protected void GridiExceleKaydet() { // Olu şacak dosyaya gridview aynen aktar õlacağ õ için hücrelerin çevrelerinin çizilmesini sağ l lõ yoruz gvUrunler.GridLines gvUrunler.GridLines = GridLines.Both; // Gönderilecek cevaba gridin içeri ğ ini ini yazd õrmak için gvUrunler kontrolünü render etmek gerekli. Bu i şlemleri // StringWriter ve HtmlTextWriter Ht mlTextWriter nesnelerini ile yürütüyoruz. yürütüyoruz. StringWriter, System.IO isim alanõ alt õnda yer al õr StringWriter stringYaz = new StringWriter(); StringWriter(); HtmlTextWriter htw = new HtmlTextWriter(stringYaz); HtmlTextWriter(stringYaz); gvUrunler.RenderControl(htw); // İ stemciye stemciye gönderilecek cevab õ olu şturuyoruz turuyoruz.. Öncelikli olarak cevapta(res cevapta(response'da) ponse'da) şu ana kadar olu şan // bilgileri silip, cevab õn başl õk bilgisine gönderilecek dosya ile ilgili ilgili bilgileri ekliyoruz. Dosya tipini belirttikten // sonra yukar õda olu şturulan StringWriter StringWriter nesnesini nesnesini ToString metodu metodu ile cevaba yazd õr õyoruz Response.Clear(); Response.AddHeader("content-disposition", Response.AddHeader("content-disposition", "attachment;filename=Urunler.xls"); "attachment;filename=Urunler.xls"); Response.ContentType = "application/ms-excel"; "application/ms-excel"; Response.Write(stringYaz.ToString()); Response.End(); }
Bu işlemlerle birlikte gridview kontrolünün içeriğini Urunler.xls olarak bir Excel dosyas d osyasõ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 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 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. 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.
VerifyRenderingInServerForm(Control control) public override void VerifyRenderingInServerForm(Control { // Olu şan hata gvUrunler isimli kontrolün render edilmesi esnas õnda al õnd õğ õ için, render edilen // kontrolün gvUrunler olmad õğ õ durumda base class'taki metodunu ça ğ õr õyoruz if(control.ID != "gvUrunler") base.VerifyRenderingInServerForm(control); } Böylece gridviewin RenderControl metodu ile çözümlenmesi işleminde yaşanan sorunun üstesinden gelebileceğiz. Sayfayõ çalõştõrdõğõmõzda seçim işlemini yaparak kayõtlar õ dosyaya aktarabiliriz.
64
Şekil: Seçime göre olu şan Urunler.xls dosyamõz Bu şekilde 1. yolumuz olan gridviewden direkt okuma ve Excel'e yazma i şlemini gerçekleştirdik. Buradaki en büyük avantajõmõz satõr okuma işlemleriyle uğraşmadan sadece render edilme işlemi ile bu işlemi yürütebilmek olacaktõr. Dezavantajõmõz ise sayfamõzõn yapõsõ ile ilgili olan bir metodu override ederek gridview kontrolünün render edilmesini engellemek gibi bir i şlemle uğraşmamõz gerekeceğidir. Gridviewdeki kayõtlar õ Excel dosyasõna aktarmamõzõn bir diğer yolu ise System.Web.UI.WebControls isim alanõ altõnda yer alan Table isimli bir class'tan faydalanarak bu işlemi yürütmektir. Table class'õ aslõnda HTML
< table> etiketinin sunucu taraf õnda oluşturulmasõnõ sağlayan, içinde satõr ve hücreler bulundurabilen bulundurabilen nesne yap õsõ sunan bir kontroldür. Burada ise Table nesnesini Excel dosyasõndaki satõr ve sütunlar õ oluşturmasõ amacõyla kullanacağõz. Aşağõda, gridview içerisindeki sat õrlar õ Table nesnesine aktarma ve ardõndan da gridview yerine Table nesnesini render ederek içeri ğini dosyaya aktarma işlemlerini içeren TabloyuExceleKaydet metodu bulunmaktadõr. protected void TabloyuExceleKaydet() { // Yeni bir tablo olu şturuyoruz. Bu tablo griddeki sat õrlar õ içerisind içerisinde e bar õnd õracak. // Olu şan Excel dosyas õnda hücreler arasõnda çizgiler ekliyoruz Table tablo = new Table(); tablo.GridLines = GridLines.Both; // Tablonun ilk sat õr õ sütun ba şl õklar õ olacak tablo.Rows.Add(gvUrunler.HeaderRow);
65
// Gridview'daki sat õrlar õ döngü ile Rows kolleksi kolleksiyonundan yonundan al õyor ve tabloya ekliyoruz foreach (GridViewRow row in gvUrunler.Rows) { // GridViewRow class' õ TableRo TableRow w class' õndan kal õt õld õğ õ için Add metoduna parametre olarak verilebilir tablo.Rows.Add(row); } // Burada gridview yerine tablo nesnesini render ediyoruz StringWriter stringYaz = new StringWriter(); StringWriter(); HtmlTextWriter htw = new HtmlTextWriter(stringYaz); HtmlTextWriter(stringYaz); tablo.RenderControl(htw); // Render edilen bilgileri htw nesnesine yaz
Response.Clear(); Response.AddHeader(" Response.AddHeader("content-dispositi content-disposition", on", "attachment;filename=Urunler "attachment;filename=Urunler.xls"); .xls"); Response.ContentType = "application/ms-excel"; Response.Write(stringYaz.ToString()); Response.End(); } Butonun click eventinde çağõrdõğõmõz GridiExceleKaydet metodu yerine TabloyuExceleKaydet TabloyuExceleKaydet metodunu çağõracak olursak artõk griddeki veriler önce Table nesnesine, ardõndan Excel dosyasõna aktar õlacaktõr. Bu yolu seçtiğimizde VerifyRenderingInServerForm metodunu override etmemize gerek kalmayacaktõr. 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 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 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. inceliyoruz.
1. ASP.NET AJAX Entegrasyonu ASP.NET AJAX, ASP.NET ortamõnda hõzlõ ve kolay bir şekilde AJAX uygulamalar uygulamalar õ geliştirmemizi sağlayan ücretsiz bir AJAX framework'üdür. ASP.NET 2.0'õn ardõndan duyurulan ve bu y õlõn (2007) başõnda resmi sürümü çõkar õlan AJAX Extension'lar õ ASP.NET 3.5 ile mimariyle bütünle bütünleşik şekilde geliyor. Artõk temel sõnõf kütüphanelerimiz kütüphanelerimiz içerisinde AJAX kontrolleri ve tipleri t ipleri de bulunmaktad bulunmaktadõr. Bir başka deyişle AJAX web uygulamalar õ geliştirmek için ASP.NET'in sitesinden ASP.NET AJAX paketini indirmeye ve kurulum yapmaya gerek kalmayacak. .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 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 bulunmaktadõr. (ScriptManagerProxy (ScriptManagerProxy ve Timer kontrolleri nedendir bilinmez bu postere eklenmemiş ama aşağõda güncellediğim posterin ilgili kesitini görebilirsiniz.)
Şekil: System.Web.UI isim alanõna AJAX kontrolleri eklendi
2. LINQ (Language Integrated Query) .NET Framewrok 3.5 ile birlikte art õk web uygulamalar u ygulamalar õnda da Linq hayatõmõza girecek. Linq C# 3.0 ile birlikte geliyor ve dil ile bütünleşik olarak sorgulamalar yapõlabilmesini sağlõyor. Veritabanõnda SQL query'leri kullanarak nasõl tablolar üzerinde sorgulamalar yapõyor ve sorgu sonucunu elde edebiliyorsak, art õk C# veya VB.NET gibi bir dil ile de uygulama içerisindeki bir nesnenin içeri ği ile ilgili SQL sorgu cümlelerine benzer şekilde sorgulamalar gerçekleştirebileceğiz. Bir dizi, bir koleksiyon nesnesi, nesnesi, XML dosyadan alõnan veriler veya DataTable gibi veri ta şõyan bir nesne üzerinde Select, Where, Order By, Join... gibi tanõdõğõmõz ifadeleri if adeleri kullanarak sorgulamalar sorgulamalar gerçekleştirebiliyoruz. tirebiliyoruz. Aslõnda Linq böyle 3-4 cümle ile anlatõlacak kadar da basit bir yenilik değil. Aksine arka planda sadece Linq'i desteklemek için bile birçok önemli yenilik C# diline kazand õr õlõyor. Linq ile birlikte gelen var tipi, nesne ve koleksiyonlara koleksiyonlara ilk değer atõcõlar, extension metotlar õ ile varolan bir sõnõfa ek metotlar eklemek gibi birçok yeniliği de C# veya VB.NET gibi bir dil ile dolayõsõyla ASP.NET ile bütünleşik şekilde kullanabiliyoruz.. kullanabiliyoruz.. Linq ve gelen di ğer yeniliklerle ilgili olarak a şağõdaki blog yazõlar õnõ ve makaleleri okumanõzõ tavsiye ederim. - C# 3.0 Ne Getiriyor ve LINQ PROJESİ Nedir? - Bilinçsizce Türlendirilmiş Lokal Değişken (Implicitly Typed Local Variable) Variable):: var - Nesne ve Koleksiyonlara İlk Değer Atayõcõ (Object and Collecti Collection on Initializer) - Genişletme Metotlar õ (Extension Methods) - LINQ: Daha Fazla Sorgu
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 gö rüntüleme,, veri seçme-ekleme-güncelleme-silm seçme-ekleme-güncelleme-silme e gibi işlemleri yapabileceğimiz bir kontrol. İlk bakõşta GridView kontrolüne benzetebilece benzetebileceğimiz bu kontrolün GridView'den GridView'den üç temel farklõlõğõ bulunmaktadõr. Bildiğimiz gibi GridView ile veri seçmegü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 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 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. 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. bulabilirsiniz.
DataSourceID: Bağlanacak DataSource kontrolünün ID bilgisi EditIndex: Güncelleme işleminin yapõlacağõ kayõt numarasõ. Varsayõlan değeri -1'dir ve hiçbir kayõtõ güncelleme modunda açma anlamõna gelir GroupItemCount: Gruplanacak kayõt sayõsõnõ belirler. Bu sayõ tek satõrda kaç kayõt bulunacağõnõ belirler ve 1 dõşõnda bir değer verildiğinde GroupTemplate tanõmlamasõ da yapõlmasõ gerekecektir. InsertItemPosition: Insert şablonunun bulunacağõ yeri belirler. InsertItemPosition InsertItemPosition enum sabiti tipinden değer alõr ve alabileceği değerler None, FirstItem ve LastItem'dõr. ItemContainerID: Görüntülenecek verilerin bulunaca bulunacağõ HTML elementin ID bilgisini taşõr. LayoutTemplate, LayoutTemplate, ItemTemplate, ItemTemplate, AlternatingItemTemplate, AlternatingItemTemplate, SelectedItemTemplate, SelectedItemTemplate, InsertItemTemplate, InsertItemTemplate, EmptyDataTemplate, EmptyDataTemplate, EditItemTemplate, GroupTemplate gibi görünüm şablonlar õ içerisine yazõlacak uygun HTML elementleri ile verinin her türlü görünümünü belirleyebiliriz. belirleyebiliriz. Aşağõda ListView ile oluşturulmuş bir sayfanõn çõktõsõnõ görebilirsiniz.
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. ekillendirebilmekteyiz. ListView'in TemplateLayout şablonu içerisine eklenir. Temel olarak esnek sayfalama template hazõrlamamõzõ sağlayan bu kontrolde 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 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 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 kontrolümüzde bu amaca yönelik kullanõlabilecek bir kontroldür.
4. Web Servislerinde WCF Deste ği Web servisleri art õk .NET Framework 3.0 ile gelen WCF (Windows Communication Foundation) desteği ile geliştirilebiliyor. JSON kullan õlan AJAX uygulamalar õnda ve RSS kaynaklar õndan veri sağlanmasõ gibi işlemler artõk WCF ile daha da kolay şekilde
71
gerçekleştirilebilecek. tirilebilecek. Yine Visual V isual 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. 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.
ASP.NET 3.5 EXTENSIONS EX TENSIONS 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 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. 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. tirebiliriz. Asl A slõ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 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, DataTable, DataSet ve entity katmanõmõzdaki sõnõflar õn bulunduğu bileşendir. - View uygulamanõn arayüzlerinin arayüzlerinin bulunduğu bileşendir. Master sayfalar, aspx ve ascx gibi kullanõcõnõn görüntüleyece 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ülenec gö rüntülenecek ek nesnenin ne snenin render edilmesi sağlanabiliyor. 2. ASP.NET AJAX Taraf õndaki Geliştirmeler : Futures paketinden tanõdõğõmõz History kontrolü bu paketin içerisinde olacak. olacak. AJAX sayfalar õnda tarayõcõdaki ileri-geri gitme problemini çözecek olan bu kontrol asenkron postbackler esnasõnda sayfanõn URL kõsmõnõ değiştirerek tarayõcõnõn değişen sayfa içeriklerini geçmişine kaydetmesini sağlõyor.
72
3. Dinamik Veri (Dynamic Data) Deste De steği: Yine Futures paketinden tanõdõğõmõz bir özellik. DynamicAutoData, DynamicList, DynamicNavigator , DynamicRssLink gibi bazõ veri kontrolleri ile bir veritaban ve ritabanõ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 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 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 f ramework altõnda toplanõyor gibi. Artõk veri ile ilgili her türlü işlemi oluşturacağõmõz veya SqlMetal.ex S qlMetal.exe e 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/ http://asp.net/downloads/3.5-extensions/adresine 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 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. edilebilmektedir. Bu kontrollerden 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 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. isteyebiliriz. Böyle bir durumda akla gelen soru TreeView kontrolünü 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. Site haritasõnõn sitemap dosyasõnda saklanmasõnõn bazõ dezavantajlar õ olduğunu da söyleyebiliriz. söyleyebiliriz. Zira XML tabanlõ bir doküman olduğu için gerek yapõsõnõ çözümlemek gerekse güncellemeler yapmak sõkõntõ doğurabilmektedir. urabilmektedir. Özellikle kategori-alt kategori-alt kategori yapõsõ geniş olan ve sõklõkla güncellenen sitelerde (örne ğin alõşveriş sitelerinde) verileri XML dokümanõnda saklamak yerine veritabanõnda saklamak daha sõk tercih edilmektedir. Peki sitemizin haritasõnõ veritabanõndaki tablolarda saklõyorsak bu verileri TreeView kontrolünde nasõl görüntüleriz? Makalemizin ikinci kõsmõnda da bu sorunun çözümünü adõm adõm 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 o luş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. 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. 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("Post T reeNode("Postback back Link", "Deger1"); // Bir önceki link gibi çal õşõr. Linkin sol kõsmõnda son parametrede yer alan a lan resim görüntülenir TreeNode anaMenu2 = new TreeNode("Resimli Link", "Deger2", "menu.jpg"); // Oluşan link 4. parametrede 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 f akat geçerli bir resim adresi verilerek linkin solunda resim görüntülenebilir TreeNode anaMenu3 = new TreeNode("Sayf T reeNode("Sayfaya aya Link", "", "", "Sayfa.aspx", "_blank"); "_blank"); Bir TreeNode nesnesi ChildNodes koleksiyonunda kendi tipinden nesneler ta şõyabilir ve bunlarda o nesnenin alt linklerini olu şturur. Oluşan ana menü de TreeView kontrolünün Nodes koleksiyonuna eklenerek menü içerisinde görüntülenmesi sa ğlanõr. Aşağõda oluşturulan iki alt menü bir ana menüye bağlanmakta ve ana menüde TreeView kontrolüne bağlanmaktadõr.
Default.aspx
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", ""); // Alt düğümler ana menü nesnesine ekleniyor anaMenu1.ChildNodes.Add(altMenu1); anaMenu1.ChildNodes.Add(altMenu2); // Oluşan ana menü sayfadaki agacMenu agacMenu kontrolüne kontrolüne ekleniyor agacMenu.Nodes.Add(anaMenu1); Sayfa çalõştõr õldõğõnda oluşan basit menü aşağõdaki şekilde görülmektedir.
Resim: Programati P rogramatik k şekilde oluşturulan TreeView kontrolü Bu şekilde menülerin TreeView içerisinde programatik olarak nas õl yerleştirileceğini görmüş olduk. Dilerseniz XML dosyadan ve veritabanõnda getirilen verileri nasõl TreeView’a aktarabileceğimizi inceleyelim
Veri Kaynağõ Olarak XML Dosyalar õnõ Kullanmak Sitemap dosyalar õ ASP.NET 2.0 ile birlikte gelen yeni bir dosya tipidir. XML tabanlõ olan bu dosya SiteMapDataSource ile navigasyon kontrollerine veri kaynağõ oluşturmaktadõr. Bazõ durumlarda kendi hazõrladõğõmõz özel yapõdaki bir XML dosyasõndaki verileri de TreeView kontrolü ile kullanmak isteyebiliriz. Böyle bir durumda XML dosyasõnõ XmlDataSource kontrolü ile TreeView’a ba ğlamamõz gerekecektir. Tabii ki dosyamõzdaki yapõyõ çözümleyebilmesi için de TreeView kontrolünde baz õ özel ayarlamalar yapmamõz gerekir. Bir askeri birlikteki askerlerin listesini içeren XML dosyasõnõ TreeView kontrolüne yükleyelim. Öncelikli olarak işe bir XML dosyasõ oluşturarak başlayalõm.
Askerler.xml
76
Bu noktadan sonra XMLDataSource kontrolü kontrolü ile dosyayõ TreeView'a TreeView'a ba b ağlamamõz ve gerekli ayarlar õ yapmamõz gerekecektir. TreeView kontrolünün DataBindings koleksiyonuna eklenecek TreeNodeBinding nesneleri ile bu işlemi gerçekleştirebiliriz. tirebiliriz. Bu işlemi programatik yollarla gerçekleştirebileceğimiz gibi dekleratif şekilde de yapabiliriz. Aşağõdaki kodlarda sayfamõza eklenen TreeView ve XmlDataSource kontrolleri ile TreeView'in DataBindings koleksiyonuna eklenen TreeNodeBindings nesneleri görülmektedir.
Default.aspx deBinding> TreeNodeBinding tan õmlamalar õnda bulunan DataMember özelliği XML'den okunacak etiket ismini, TextField ise görüntülenecek verinin bulunduğu niteliği belirlemektedir. Sayfa çalõştõr õldõğõnda okunan verilerin TreeView'a hiyerar şik şekilde doldurulduğu görülecektir gö rülecektir.. TreeView kontrolünün önemli özelliklerinden biri de listelenen linklere resim eklenebilece ği gibi CheckBox gibi bir kontrolde eklenmesini sağlayabilmesidir. layabilmesidir. Yaptõğõmõz örnekte belirli bir bölükte bulunan askerlerden bazõlar õnõn seçilmesi ve sayfa postback edildiğinde seçili
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. 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
Resim: XML dosyasõnõ kaynak olarak kullanan TreeView'õn a) normal şekilde oluşturulmasõ, b) linklerinin CheckBox ile birlikte oluşturulmasõ 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. 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 protected void btnSec_Click(object sender, EventArgs e) { // En üstte tek node oldu ğ ğu için bu node'un içerisindeki k õsõmlar õ tek tek ele al õyoruz foreach(TreeNode foreach(TreeNode node in AskerListe.Nodes[0].ChildNodes) AskerListe.Nodes[0].ChildNodes) { Response.Write(node.Value + " kõsmõndaki askerler: "); askerler: "); // Her k õsõmda bulunan askerleri ele al õyoruz foreach(TreeNode foreach(TreeNode altNode in node.ChildNodes) { e if(altNode.Checked) // E ğ ğer r seçilmi ş ise Response.Write(" - " + altNode.Text + " "); } } }
Seçim işlemi yapõldõktan sonra aşağõdaki şekilde görüleceği gibi seçim listesini elde edebiliyoruz.
Resim: 1) Listeden seçim yap õlmasõ, 2) Seçilen S eçilen askerlerin listesinin listesinin ve ba ğlõ olduğu kõsõmlar õn elde edilmesi
Veri Kaynağõ Olarak Veritabanõ Kullanmak Geldik makalemizin belki de en can al õcõ kõsmõna! Zira veritabanõnda saklanan site haritalar õnõ TreeView veya Menu gibi kontrollere aktarabilmek biz programcõlar için oldukça
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 Ürünlerimizin bulunduğu ana kategorilerimiz kategorilerimiz olsun; Elektronik E lektronik 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.
Şekil: Kategoriler tablosu
Şekil: Alt Kategoriler tablosu
Şekil: Ürünler tablosu 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 ş Urunler şeklinde bir ilişkinin olduğu görülecektir. DataSet'e ekleyeceğimiz DataRelation nesneleri de bu düzende belirlenecektir.
Default.aspx.cs protected DataSet MenuListe() { OleDbConnection con = new OleDbConnection("Provider=Microsoft.Jet.OleDB.4.0; Data Source=C:\\Inetpub\\wwwroot\\TreeVi Source=C:\\Inetpub\\www root\\TreeView_test\\Veri ew_test\\Veriler.mdb"); ler.mdb");
80
OleDbDataAdapter OleDbDataAdapter daKat = new OleDbDataAdapter("Select OleDbDataAdapter("Select * From Kategoriler", con); OleDbDataAdapter daAltKat = new OleDbDataAdapter("Select * From AltKategoriler", con); OleDbDataAdapter daUrunler = new OleDbDataAdapter("Select * From Urunler", con); // Tablolardan gelen verileri DataSet içerisine tablolar halinde dolduruyoruz dolduruyoruz DataSet ds = new DataSet(); daKat.Fill(ds, daKat.Fill(ds, "Kategoriler"); daAltKat.Fill(ds, daAltKat.Fill(ds, "AltKategoriler"); daUrunler.Fill(ds, daUrunler.Fill(ds, "Urunler"); // Tablolar aras õnda ili şkili kolonlar üzerinden ili şkileri belirliyoruz ds.Relations.Add("Kat_AltKat", ds.Tables["Kategoriler"].Col ds.Tables["Kategoriler"].Columns["KategoriI umns["KategoriID"], D"], ds.Tables["AltKategoriler"].Colum ds.Tables["AltKategoriler"].Columns["KategoriID ns["KategoriID"]); "]); ds.Relations.Add("AltKat_Urun", ds.Tables["AltKategoriler"].Col ds.Tables["AltKategoriler"].Columns["AltKategori umns["AltKategoriID"], ID"], ds.Tables["Urunler"].Column ds.Tables["Urunler"].Columns["AltKategoriI s["AltKategoriID"]); D"]); return ds; }
Makalemizin ilk kõsõmlar õna dönecek olursak TreeView kontrolünün TreeNode nesnelerinde oluştuğundan bahsetmiştik. Programatik olarak TreeView'e düğümler (node) ekleyip, düğümler altõna da alt düğümler (child node) oluşturarak menüler elde edebilmiştik. Bu noktadan sonra yapacağõmõz işlem döngüler içerisinde önce kategorilere erişmek ve kategori için TreeNode nesneleri olu şturmak. Oluşan kategori düğümüne alt kategorileri, alt kategorilere de kendilerine ait ürünlerin eklenmesini sa ğlamamõz gerekiyor. Oluşan tüm kategori nesnelerini de TreeView'in TreeView'in Nodes koleksiyonuna ekleyecek olursak menümüzü oluşturabilece ğiz.
TreeNode anaMenu = new TreeNode(dr["Ad"].ToString(), TreeNode(dr["Ad"].ToString(), "", "", "Kategori.aspx?Id=" + dr["KategoriID"].ToString(), ""); // Alt kategorileri k ategorileri oku foreach(DataRow drAlt in dr.GetChildRows("Kat_AltKat")) dr.GetChildRows("Kat_AltKat")) { TreeNode altMenu = new TreeNode(drAlt["Ad"].ToString(), "", "", "AltKategori.aspx?Id=" "AltKategori.aspx?Id=" + drAlt["AltKategoriID"].ToString(), drAlt["AltKategoriID"].ToString(), ""); // Ürünleri oku foreach(DataRow drUrun in drAlt.GetChildRows("AltKat_Uru drAlt.GetChildRows("AltKat_Urun")) n")) { 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); } }
Sayfayõ çalõştõrdõğõmõzda veritabanõndaki 3 tablodan getirilen verilerin hiyerar şik şekilde TreeView kontrolüne yüklendiğini görebiliriz. Aşağõdaki resimde sayfamõzõn çõktõsõnõ görebilirsiniz.
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. tirilebiliyor. Burada bizim için en önemli noktalardan 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 nesnelere ait liste koleksiyonlar õnõ taşõyarak ta gerçekleştirebilirdik. Bu makalemizde TreeView kontrolünün nesneleri taşõyõş şekline değinerek XML veri kaynaklar õndan veya bir veritabanõnda okunan verileri TreeView kontrolüne nas õl aktarabileceğimizi inceledik. Sitemap dosyalar õ kullanmaksõzõn da TreeView kontrolünü etkin şekilde uygulamalar õmõzda kullanabiliriz. Burada anlatõlan bir çok konu asl õnda bir diğer navigasyon kontrolü olan Menu kontrolü için de geçerli olduğunu söyleyebiliriz.
83
Site Navigasyonu Hakkõnda Bilinmey Bilinme yenler 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 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.
Site Haritasõnõn Belirli K õsõmlar õnõ Görüntüleme Site navigasyonu işlemlerinde kulland õğõmõz sitemap dosyasõnõn belirli standartlar õ bulunmaktadõr. En dõşta sadece bir SiteMapNode düğümünün olmasõ, aynõ linki birden fazla kez kullanamamak (bu kõsõtlamayõ nasõl aşabileceğimizi bir sonraki ba şlõkta göreceğiz) gibi standartlar bazen kar şõmõza birer kõsõtlama olarak çõkmakta ve yapmak istediğimiz işlemleri engelleyebilmektedir. engelleyebilmektedir. Yine bazõ durumlarda içerisinde onlarca dü ğüm (node) bulunduran bir site haritasõnõn sadece belirli bir kõsmõnõ görüntülemek isteyebiliriz. SiteMapDataSource kontrolünün bazõ özelliklerini kullanarak site haritasõnõn belirli kõsõmlar õnõn görüntülenmemesi görüntülenmemesi veya sadece belirli k õsõmlar õndan sonraki düğümlerin görüntülenmesi gerçekleştirilebilir. Dilerseniz standart bir sitemap dosyasõ hazõrlayarak ne gibi işlemleri yapabileceğimizi inceleyelim.
Web.sitemap title="Makaleler"> Sitenin genelinde şablon olarak kullan õlacak olan bir master sayfaya SiteMapPath, TreeView ve SiteMapDataSource kontrollerini 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
Resim: Sitemap dosyasõndaki veriler SiteMapPath ve TreeView kontrolüne eklendi e klendi web.sitemap dosyasõnda oluşturulan site haritasõnda hiyerar şik olarak en üstte Anasayfa bulunmaktadõr. Bu link sayfamõzda da aynõ şekilde tutuluyor. Fakat TreeView kontrolünde anasayfa linkinin görülmesi çoğu zaman istenilmeyen bir durumdur. Özellikle SiteMapPath ile
85
birlikte TreeView kullanõldõğõnda zaten Anasayfa linki sürekli olarak SiteMapPath'de SiteMapPath'de yer alacağõ için TreeView'da en d õşta tüm node'lar õ kapsayan Anasayfa node'unu göstermek istemeyebiliriz. istemeyebiliriz. Fakat sitemap dosyasõnda da en dõşta bir b ir SiteMapNode bulundurmak 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?
SiteMapDataSource kontrolüne ait ShowStartingNode özelliği (property) bu işlemi gerçekleştirmemizi sağlar. bool tipinden de ğer alan bu özellik varsay õlan olarak true değerini taşõr ve başlangõç node'unun gösterilmesini sağlar. Eğer bu özelliğe false değeri atanõrsa sitemap dosyasõnõ veri kaynağõ olarak kullanan kontrolde en dõştaki node okunmaz. Aşağõda değişen kod kõsmõ ve sayfanõn yeni çõktõsõ görülmektedir. Sablon.master ... ...
Resim: ShowStartingNode özelliği false de ğeri olarak ayarland õğõnda en dõştaki node listelenmez Bu şekilde en dõştaki node'un görüntülenmesi engellendi ve artõk Anasayfa linki görüntülenmiyor. görüntülenmiyor. SiteMapPath SiteMapPath kontrolü SiteMapDataSource SiteMapDataSource kontrolüne bağõmlõ çalõşmadõğõ için bu değişiklikten etkilenmez ve Anasayfa A nasayfa linkini görüntüler. Bazõ durumlarda da site haritasõndaki içeriklerin belirli k õsmõnõ görüntülemek isteyebiliriz. isteyebiliriz. Örneğin yukar õ kullandõğõmõz senaryoda ziyaretçi Makaleler kategorisi içerisinde gezerse TreeView'da sadece Makaleler kategorisinin alt linklerini görüntülemek isteyebiliriz. isteyebiliriz. Sitemap S itemap
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.
- StartFromCurrentNode StartFromCurrentNode: O an bulunula bu lunulan n sayfanõn node ve alt node'lar õnõn getirilmesini sağlar. bool tipinde değer alõr ve true değeri aldõğõnda sadece bulunulan sayfanõn node ve alt node'lar õnõ getirir. Özellikle karmaşõk site haritalar õnda ziyaretçiye sadece o an ziyaret ettiği kategorinin alt kategorilerini görüntülemek görüntülemek istendiğinde kullanõlabilir. Örneğin kullanõcõ Makale.aspx sayfasõnda bulunduğunda TreeView veya Menu kontrolü sadece Makaleler kategorisindeki linkleri görüntüler. - StartingNodeUrl: Belirtilen adresin bulundu 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ülenm gö rüntülenmesi esi istenildiğinde bu özellik "Editorler.aspx" değerine ayarlanabilir. Aşağõdaki kod örneklerinde örneklerinde yukar õda bahsedilen özelliklerin kullan õmõ görülmektedir. Kodlar õn hemen altõnda ise sayfanõn çõktõsõ bulunmaktadõr.
Resim: StartFromCurrentNode true de ğeri aldõğõ için o an bulunulan kategori ve alt kategorileri getirildi
Sablon.master (StartingNodeUrl kullanõmõ)
87
StartingNodeUrl="Videolar.aspx" />
Resim: StartingNodeUrl özelliği Videolar.aspx değerini aldõğõ için sitemap dosyasõnda bu sayfa ve altõnda yer alan node'lar getirildi
Site Haritasõnda Aynõ Linki Birden Fazla Kullanmak Sitemap dosyasõndaki siteMapNode 'lar õn url bilgilerinin tekil (unique) değerler olmasõ gerekmektedir. Site haritasõ oluşturulurken XmlSiteMapProvider taraf õndan url bilgileri tekil değer olarak alõnõr ve birbirini tekrar eden url bilgilerinin olmasõna izin verilmez. Önceki örnekte kullandõğõmõz web.sitemap dosyasõndaki Makale.aspx url bilgisini Default.aspx Default.aspx bilgisi ile değiştirelim. Sayfayõ çalõştõrdõğõmõzda aşağõdaki gibi bir hata sayfas õ ile kar şõlaşõr õz.
Web.sitemap ...
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. tirebiliriz. Peki P eki varolan yap õyõ kullanarak bu işlemi nasõl gerçekleştirebiliriz? 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. gerekebilir. Bir diğer yol ise asõl sayfa adresinin sonuna geçersiz geçersiz QueryString'ler yazmak olacaktõr. Her ne kadar etkili etkili ve tavsiye t avsiye edilecek 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 ...
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
SiteMap Nesnesi ile Çal õşmak Sitemap dosyalar õnda taşõnan bilgileri uygulama içerisinden okuma olanağõmõz bulunmaktadõr. Sonuçta XML olarak taşõnan bu verileri programatik yollarla elde etme şansõmõz olacaktõr. .NET Framework Framework gibi güçlü bir altyap õya sahip ortamda bu dosyayõ XML olarak okuma işlemi yapmak yerine elbetteki daha kolay bir yolumuz da olacakt õr! SiteMap adõndaki nesne ile bu dosya içerisindeki içerisindeki belirli bilgileri kolay ve etkili şekilde okuyabilmekteyiz. Özellikle o an bulundu ğumuz sayfa ile ilgili bilgileri site haritasõ dosyasõndan okuyabilmek bizim için önemli olacaktõr. SiteMap.CurrentNode özelliği o an bulunulan sayfanõn siteMapNode düğümünün SiteMapNode sõnõf õ tipinden değerini getirecektir. Bu özellik üzerinden erişebileceğimiz önemli bilgileri a şağõda listesini gördüğünüz özelliklerden (property) elde edebiliriz e debiliriz..
Description:
Bulunulan sayfanõn description kõsmõndaki bilgi
Title:
Bulunulan sayfanõn title kõsmõndaki bilgi
Url:
Bulunulan sayfanõn url kõsmõndaki bilgisi
HasChildNodes:
Bulunulan sayfa node'unun altõnda alt node (child node) olup olmadõğõ bilgisi. bool değer getirir ve true alt node'lar õn olduğunu belirtir
ChildNodes:
Eğer alt node'lara sahip ise bu node'lar õn SiteMapNodeCollecti SiteMapNodeCollection on tipinden listesinin getirir
ParentNode:
Bulunulan sayfa node'unun node'unun üst kõsmõnda yer alan sayfa node'unun SiteMapNode tipinden değerini getirir
NextSibling:
Aynõ seviyede bir sonraki kõsõmda bulunulan sayfa node'unun
90
SiteMapNode tipinden değerini getirir
PreviousSibling:
Aynõ seviyede bir önceki k õsõmda bulunulan sayfa node'unun SiteMapNode tipinden değerini getirir
SiteMap nesnesini kullanabilmek için sayfamõzda SiteMapDataSource veya diğer ildir . Eğer o an görüntülenen site navigasyonu navigasyonu kontrollerinin kontrollerinin bulunmasõ zorunlu değ ildir görüntülenen sayfa projemizdeki web.sitemap dosyasõnda bulunuyor ise SiteMap.CurrentNode özelliği bize o sayfanõn SiteMapNode tipinden değerini otomatik olarak getirecektir. Özellikle sitemap dosyasõndaki title ve description nitelikleri sayfamõzda sõklõkla kullanabileceğimiz özellikler olabilir. Örneğin ADO.NET kategorisindeyken sayfamõzõn başlõk bilgisini title kõsmõndan alõp ADO.NET olarak belirlemek ve sayfanõn belirli bir k õsmõndaki bir etikete de description kõsmõndan alõnan bilgiyi yazdõrmak kulağa oldukça ho ş gelen kolaylõklar gibi geliyor. Aşağõda bu özelliklerin baz õlar õnõ kullanarak sayfamõzda değişiklikler yapõyoruz.
SiteMap.CurrentNode SiteMap.CurrentNode özelliği kullanõlarak sayfa hakk õndaki bilgileri elde ettik
Site Haritasõna Ek Bilgiler Ekleme Sitemap dosyasõnda saklanan standart sayfa bilgileri url, title ve description niteliklerinde tutulmaktadõr. Bu niteliklerde sayfa ile ilgili istenilen en temel bilgiler saklamaktad õr. Fakat bazõ durumlarda site haritasõ dosyasõnda bir sayfa ile ilgili farklõ bilgileri de saklamak isteyebiliriz. isteyebiliriz. Bu tip bilgileri elbetteki farklõ veri kaynaklar õndan (XML dosyasõ, veritabanõ gibi) elde ederek kullan õcõlara sunabiliriz. Fakat bir sayfanõn bazõ bilgilerini sitemap dosyasõndan, bazõ bilgilerini bilgilerini de farklõ bir kaynaktan elde etmek kötü bir pratik olacaktõr. Peki sayfa ile ilgili saklamak istediğimiz bu tip bilgileri yine sitemap dosyasõ içerisinde saklamamõz mümkün müdür? Sitemap dosyasõnõn yapõsõ buna uygun mudur ve saklanan bilgileri sayfa içerisinden içerisinden elde etmek için ekstra işlemler yapmak gerekir mi? Sitemap dosyalar õ içerisinde ek bilgileri kolay şekilde taşõyabilmektedir. yabilmektedir. Böyle bir durumda uygulama içerisinden 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, mlayabiliyorsak, bu bilgileri b ilgileri 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. 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. görülmektedir.
Web.sitemap ... title="Makaleler"> ... Her bir node içerisinde Editor="Uğur UMUTLUOĞLU" şeklinde nitelik tanõmlamalar õ yapmak yeterli olacaktõr. Gelelim sayfa içerisinden bu bilgiyi nas õl elde edebileceğimize. Makalemizin önceki kõsõmlar õnda bulunduğumuz sayfanõn varolan bilgilerini Sitemap nesnesinin CurrentNode özelliği üzerinden okuyabildiğimizi görmüştük. Örneğin title bilgisini SiteMap.CurrentNode.Title ifadesi ile elde edebilmiştik. Title ve diğer özellikler SiteMapNode sõnõf õ içerisinde daha önceden tanõmlõ olduklar õ için sõnõf õn nesne örneği üzerinden erişebiliriz. Fakat sonradan tanõmladõğõmõz Editor bilgisini b ilgisini özellik (property) üzerinden değil de CurrentNode özelliğinin indeksleyicisi (indexer) üzerinden erişebiliriz. Aşağõdaki tek satõrlõk ifade bu bilgiyi b ilgiyi sayfamõza eklediğimiz lblEditor adõndaki bir etikete aktarmamõzõ sağlayacakt õr.
Sablon.master.cs protected void Page_Load(object sender, EventArgs e) { ... lblEditor.Text = "Bölüm Editörü: " + SiteMap.CurrentNode["Editor"]; ... } Sayfayõ çalõştõrdõğõmõzda o an bulunduğumuz kategorinin siteMapNode düğümünden okunan Editor bilgisinin elde edildi ğini görebiliriz. SiteMap.CurrentNode özelliği o anki sayfanõn siteMapNode düğümünün nesne örneğini getirmekte ve içerisinde taşõnan Editor bilgisini de
93
indeksleyici üzerinden üzerinden SiteMap.CurrentNode["Editor"] şeklinde okuyabilmekteyiz. Bu şekilde sitemap dosyasõnda farklõ nitelikler tanõmlayõp sayfa içerisinden içerisinden kolay şekilde okunmasõnõ sağlayabiliriz. Aşağõda sayfamõzõn çõktõsõ görülmektedir.
Birden Fazla Sitemap Dosyas õ Kullanabilmek ASP.NET uygulamalar õnda bazõ durumlarda birden fazla site haritasõ dosyasõ kullanmak isteyebiliriz. Farklõ içerikleri olan linkleri ayr õ iki dosyada toplayarak sayfamõzõn farklõ kõsõmlar õnda görüntülemek görüntülemek kullanõcõlar õn site içerisinde gezinmelerini gezinmelerini kolaylaştõracaktõr. Fakat site navigasyon navigasyon kontrollerini kontrollerini SiteMapDataSource kontrolü ile beslediğimizde sadece bir tane sitemap dosyasõ kullanabilmekteyiz. kullanabilmekteyiz. Bu durumun sebebi ise site haritasõ sağlayõcõlar õnda (SiteMap Provider) sadece web.sitemap dosyasõ için bir tanõmlama yapõlmasõdõr. Web uygulamalar õnda kullandõğõmõz web.config dosyalar õ bildiğimiz gibi .NET Framework'ün kurulu olduğu dizinde bulunan baz õ konfigürasyon konfigürasyon dosyalar õndan kalõtõm yoluyla elde edilerek kullanõlõr. Yani bir sunucuda çalõşan tüm web uygulamalar õ bu dizindeki .config dosyalar õnda yapõlan ayarlara göre çalõşmaktadõr. Windows XP işletim sistemi ile .NET Framework 2.0 kurulu olan bir bilgisayarda bilgisayarda C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG dizininde bulunan web.config dosyasõna bakõlacak olunursa düğümünde sadece bir sağlayõcõ tanõmlamasõ olduğu görülür. Yine bu tanõmlamada göreceğimiz siteMapFile niteliği aslõnda SiteMapDataSource kontrolünün verileri hangi dosyadan okudu ğunun göstergesidir. Aslõnda buradaki tanõmlamalardan yola çõkarak uygulamadaki web.config dosyasõna birden fazla sağlayõcõ tanõmlamasõ yapõp farklõ isimdeki .sitemap dosyalar õnõn projemizde kullanõlabilmesini sağlayabiliriz. layabiliriz. Öncelikli olarak o larak web.config dosyamõza web2.sitemap isimli bir dosyayõ da kullanabilmemizi sağlayan tanõmlamayõ ekleyelim. düğümü içerisine açacağõmõz düğümüne ekleyeceğimiz kodlar aşağõda görülmektedi g örülmektedir. r.
web.config ...
94
name="SiteMapProvider2" siteMapFile="web2.sitemap" siteMapFile="web2.sitemap" Bu şekilde artõk uygulamamõzda web.sitemap dosyasõ dõşõnda web2.sitemap dosyasõnõ da kullanabiliriz. kullanabiliriz. Öncelikli olarak projemize web2.sitemap adõnda bir site haritasõ dosyasõ ekleyelim. Ardõndan da sayfamõza bir Menu kontrolü ile bir SiteMapDataSource kontrolü ekleyelim. SiteMapDataSource kontrolünün SiteMapProvider özelliği az önce web.config dosyasõna eklediğimiz SiteMapProvider2 sağlayõcõsõ olarak belirlenirse Menu kontrolüne web2.sitemap dosyasõndaki veriler aktar õlacaktõr. Aşağõda web2.sitemap ve Sablon.master S ablon.master dosyalar õna eklenen kodlar görülmektedir.
web.sitemap title="Anasayfa"> description="">
Sablon.master ... > ...
95
Sayfayõ çalõştõrdõğõmõzda daha önceden hazõrladõğõmõz TreeView kontrolünün SiteMapDataSource1 SiteMapDataSource1 kontrolü ile web.sitemap dosyasõndan, Menu kontrolünün ise SiteMapDataSource2 SiteMapDataSource2 kontrolü ile web2.sitemap dosyasõndan getirilen verilerle doldurulduğunu görebiliriz. A şağõda sayfamõzõn çõktõsõ bulunmaktadõr.
Resim: Birden fazla sitemap dosyasõndan alõnan veriler TreeView ve Menu kontrollerine yüklendi Bu makalemizde site navigasyon işlemlerinin bilinmeyen yönlerini incelemeye çal õştõk. ASP.NET 2.0 ile birlikte gelen sitemap dosyalar õ ve site navigasyon kontrolleri birçok işlemin kolay şekilde yapõlmasõnõ sağlamaktad õr. Bu yapõlar õ detaylõ şekilde bilmemiz durumunda kar şõmõza çõkabilecek farklõ senaryolar õ kolay şekilde çözebiliriz. çözebiliriz.
96
TreeView Kontrolüne Kullanõcõ İsteğine Göre Veri Ekleme 04 Mart 2008
TreeView kontrolü ASP.NET uygulamalar õnda site gezinme işlemlerinde sõklõkla kullanõlan kontrollerden biridir. Ağaç görünümünde linkler ve alt linkleri hiyerar şik biçimde listeleyen bu kontrol açõlõr kapanõr bir yapõ sunduğu için özellikle karmaşõk ve çok sayõdaki içerikleri içerikleri listelerken oldukça kullanõşlõ olmaktadõr. TreeView kontrolünün içeriğini sitemap dosyasõndan okuyabildiğimiz gibi veritabanõ vb. bir veri kaynağõndan da okuyabilmekteyiz. okuyabilmekteyiz. TreeView kontrolünün farklõ veri kaynaklar õyla kullanõmõ ile ilgili bilgi edinmek için daha önceden yazm õş olduğum makaleye bu linkten göz atabilirsiniz. Veritabanõndan getirilen bu veriler eğer çok fazla ise tüm verileri bir defada getirmek performans açõsõndan olumsuz olabilir. Kullanõcõnõn sadece görüntülemek istediği içerikleri yüklemek sayfanõn daha hõzlõ çalõşmasõnõ sağlayacakt õr. Bu konuyla ilgili olarak oldukça somut bir örnek üzerinde durabiliriz. Eminim ki hepimiz MSDN sitesini gezmişiz ve araştõrma yaparken sol kõsõmdaki menüyü kullanarak birçok konuya göz atmõşõzdõr. Eğer dikkat ettiyseniz buradaki ağaç görünümlü kontrolün tüm içeriği ilk başta yüklenmemektedir. yüklenmemektedir. Kullanõcõ bir linke tõkladõğõnda o konuya ait alt linkler bir veri kaynağõndan dinamik şekilde getirilerek yüklenir. Zira oldukça geniş konu ve alt konuyu saklayan bu menünün bir defada yüklenmesi sayfanõn ilk yüklenmesi esnasõnda oldukça uzun sürecektir. Çok sayõda içeriği bulunan veritabanlar õnda bu bilgileri TreeView kontrolüne kontrolüne yüklemek istediğimizde verilerin isteğe göre yüklenmesi bizim için önemli olabilmektedir. Yaz õmõzda bu işlemi nasõl gerçekleştirebileceğimizi inceliyor olaca ğõz. TreeView kontrolüne başlangõçta belirli verileri yüklemek ve bir linke tõklandõğõnda alt linklerini yükleme i şlemi bu kontrolün TreeNodePopulate olayõ (event) ile gerçekleşmektedir. TreeView kontrolü üzerinde yapõlacak işlemleri ve gerekli ayarlar õ makalenin ilerleyen kõsõmlar õnda göreceğiz. Bir örnek üzerinden konuyu incelemeye başlayalõm. Spor kulüpleri ile bilgileri sunan bir web portal õmõz olduğunu düşünelim. Avrupa ve dünya liglerindeki futbol kulüplerini ve her futbol kulübünde kulübünde bulunan oyuncular õ bir TreeView kontrolünde listelemek istiyoruz. Ziyaretçinin seçtiği futbolcu ile ilgili bilgileri ise sayfam õzda listeleyeceğiz. Veritabanõmõzda yaklaşõk 20 tane ligi saklayacak olursak, her ligde ortalama 18 futbol takõmõnõ ve her futbol takõmõnda ortalama 25 futbolcu olduğunu da düşünürsek TreeView kontrolüne 3 ayr õ tablodan yaklaşõk 9000 satõrlõk bilgiyi yüklememiz gerekecektir. Farklõ tablolardan bu kadar veriyi kontrole yüklemek elbetteki uzun zaman alacaktõr ve tüm t üm verilerin getirilmesi de böyle bir senaryoda gereksiz olacaktõr. Bu işlem yerine sayfa ilk yüklendiğinde sadece liglerin listesini getirilecek olursak, bir lige tõklandõğõnda o ligin futbol fu tbol kulüplerini, bir kulübe tõklandõğõnda da o kulübün oyuncular oyuncular õ listeye eklenecektir. Böylece her tõklamada istenilen verilerin getirilmesi işlemini gerçekleştirmek gerekecektir. Ziyaretçi sayfa ile etkileşime geçtiğinde veritabanõndan veriler getirileceği için çalõşma esnasõnda biraz yavaş işleyiş olsa da sayfa ilk çalõştõğõnda daha hõzlõ yüklenecektir. Microsoft Access'te oluşturacağõmõz bir veritabanõ üzerinden örneğimizi gerçekleştirelim. Bu veritabanõnda Ligler , Kulupler ve Oyuncular adõnda verilerin saklandõğõ tablolar õmõz olacaktõr. Aşağõdaki resimde bu tablolar õn bilgileri görülmektedir.
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 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 public partial class _Default _ Default : System.Web.UI.Page { string yol; protected void Page_Load(object sender, EventArgs e) { yol = Server.MapPath("~/App_Data") Server.MapPath("~/App_Data") + "/Spor.mdb"; "/Spor.mdb"; if(!IsPostBack) LigleriYukle(); } private void LigleriYukle () { OleDbConnection OleDbConnection con = new OleDbConnection("Provider=Microsoft.Jet.Ol OleDbConnection("Provider=Microsoft.Jet.OleDB.4.0; eDB.4.0; Data Source=" + yol); OleDbCommand cmd = new OleDbCommand("Select LigID, Ad From Ligler", con); con.Open(); OleDbDataReader dr = cmd.ExecuteReader(); while (dr.Read()) { TreeNode kategori = new TreeNode(dr["Ad"].ToString(), TreeNode(dr["Ad"].ToString(), dr["LigID"].ToString()); dr["LigID"].ToS tring()); kategori.PopulateOnDemand kategori.PopulateOnDem and = true; tvLig.Nodes.Add(kategori); } con.Close(); } protected void tvMenu_TreeNodePopulate(object sender, TreeNodeEventArgs e) { // Bu metot az sonra doldurulacak } }
99
Bağlanõlan veritabanõnnda çalõştõr õlan sorgu sonucu sadece ligler getirildi ve tvLig t vLig adõndaki TreeView kontrolüne veriler eklendi. Buradaki en önemli noktalardan no ktalardan bir tanesi de eklenen TreeNode nesnelerine ait PopulateOnDemand ("isteğe göre besle" diyebiliriz) diyebiliriz) özelli ğidir. bool tipinden değer alan bu özelliği true belirlememiz 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.
Resim: Sadece ligler TreeView kontrolüne eklendi Bir sonraki adõmda kullanõcõ herhangi bir linke t õklayarak o ligin alt õndaki kulüpleri listelemek isteyecektir. Bu noktada TreeNodePopulate TreeNodePopulate olayõ tetiklenecek ve code-behind sayfamõzda yazdõğõmõz tvMenu_TreeNodePopulate metodu çağr õlacaktõr. Bu metodun parametrelerine 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 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 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 TreeNodeEventArgs e) protected void tvMenu_TreeNodePopulate(object sender, TreeNodeEventArgs { if (e.Node.Depth == 0) // Lige t õklanmõş ise KulupleriYukle(e.Node); else if (e.Node.Depth == 1 ) // Kulübe t õklanmõş ise OyunculariYukle(e.Node); }
KulupleriYukle(TreeNode ligNode) private void KulupleriYukle(TreeNode { OleDbConnection OleDbConnection con = new OleDbConnection("Provider=Microsoft.Jet.Ol OleDbConnection("Provider=Microsoft.Jet.OleDB.4.0; eDB.4.0; Data Source=" + yol); OleDbCommand cmd = new OleDbCommand("Select KulupID, Ad From Kulupler Where LigID=@id", con); cmd.Parameters.AddWithValue("@id", ligNode.Value); con.Open(); OleDbDataReader dr = cmd.ExecuteReader(); while (dr.Read()) { TreeNode kategori = new TreeNode(dr["Ad"].ToString(), TreeNode(dr["Ad"].ToString(), dr["KulupID"].ToString()); kategori.PopulateOnDemand kategori.PopulateOnDemand = true; kategori.SelectAction kategori.SelectAction = TreeNodeSelectAction.Expand; TreeNodeSelectAction.Expand; ligNode.ChildNodes.Add(kategori); } con.Close(); }
OyunculariYukle(TreeNode kulupNode) private void OyunculariYukle(TreeNode { OleDbConnection OleDbConnection con = new OleDbConnection("Provider=Microsoft.Jet.Ol OleDbConnection("Provider=Microsoft.Jet.OleDB.4.0; eDB.4.0; Data Source=" + yol); OleDbCommand cmd = new OleDbCommand("Select OyuncuID, Ad From Oyuncular Where KulupID=@id", con); cmd.Parameters.AddWithValue("@id", kulupNode.Value); con.Open(); OleDbDataReader dr = cmd.ExecuteReader(); while (dr.Read()) {
101
string navigateUrl = "Default.aspx?OyuncuID=" "Default.aspx?OyuncuID=" + dr["OyuncuID"].ToString() dr["OyuncuID"].ToString();; TreeNode kategori = new TreeNode(dr["Ad"].ToString(), "", "", navigateUrl, ""); kulupNode.ChildNodes.Add(kategori); } con.Close(); } Görüldüğü gibi kulüplerin getirilmesi getirilmesi KulupleriYukle, oyuncular õn getirilmesi OyunculariYukle adõndaki iki metot ile gerçekleştiriliyor. tiriliyor. Her iki metoda da parametre olarak tõklanõlan TreeNode TreeNode nesnesi gönderiliyor. gönderiliyor. Value özelliğinden erişilen ID bilgisine göre alt node'lar õn kayõtlar õ getirilerek tõklanan TreeNode nesnesinin ChildNodes koleksiyonuna ekleniyor. OyunculariYukle metodunda TreeNode nesnesinin PopulateOnDemand ve SelectAction özelliklerine herhangi bir atama yapõlmadõğõnõ görülmektedir; çünkü oyuncular õn altõnda herhangi bir alt node yer almayacağõ için beslenmesine gerek yoktur. Bu metotla ilgili bir diğer farkta oyuncu ismine tõklandõğõnda sayfamõza QueryString ile oyuncunun ID bilgisi ta şõnacağõ için TreeNode nesnesinin farklõ şekilde oluşturulmasõdõr. Sayfayõ çalõştõrdõğõmõzda aşağõdaki gibi bir sonuç alabiliriz. alabiliriz.
Resim: Kullanõcõdan gelen isteklere göre TreeVi T reeView ew 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 tetiklenme tet iklenmesini sini de tvMenu_TreeNodePopulate metoduna bir
102
breakpoint ekleyerek görebiliriz.
Resim: "İspanya La Liga" linkine tõklandõğõnda breakpoint eklediğimiz noktada seçilen node'un bilgilerini görebiliriz Breakpoint'i kaldõrarak sayfanõn çalõşma şeklini tekrar gözlemleyelim. Liglere ve kulüplere tõklandõğõnda veritabanõndan verilerin getirilmesine rağmen sayfada herhangi bir postback işlemi olmadõğõnõ göreceğiz. Aslõnda TreeView kontrolü varsayõlan davranõş şekline göre TreeNodePopulate olayõ tetiklendiğinde callback tekniğini kullanarak sunucu ile asenkron şekilde iletişime geçmektedir. Böylece getirilen veriler veriler hem daha hõzlõ şekilde kontrole eklenmektedir, hem de postback işlemi gerçekleşmediği için sayfa kaybolmadan yenilenir. TreeView kontrolüne bu davranõşõ kazandõran PopulateNodesFromClient özelliğidir. bool tipinden değer alan bu özelliğin varsayõlan değeri true'dur ve node'lar õn istemci (client) taraf õnda asenkron şekilde güncellenmesini sağlar. Bu özellik false değerine atanõr ve sayfa tekrar çalõştõr õlõrsa liglere ve kulüplere tõklandõğõnda sayfada postback işleminin yapõldõğõ görülecektir. Son olarakta QueryString ile ta şõnan bilgileri alarak lblOyuncuBilgiler 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.
OyuncuBilgileriniGetir(string oyuncuID) private void OyuncuBilgileriniGetir(string { OleDbConnection con = new OleDbConnection("Provider=Microsoft.Jet.OleDB.4.0; Data Source=" + yol);
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() + " Doğum Tarihi: " + dr["DogumTarih"].ToStri dr["DogumTarih"].ToString() ng() + " Oynadõğõ Mevki: " + dr["Mevki"].ToString(); con.Close(); }
Resim: Seçilen oyuncunun bilgileri getirildi
ASP.NET AJAX Kontrolleri ile TreeView Kontrolüne Dinamik Veri Ekleme TreeView kontrolüne veri eklenirken kullan õcõyõ bilgilendirmek için işlem yapõldõğõ esnada bir metin görüntülemek istenilebilir. istenilebilir. Bu tip bir işlemi ASP.NET AJAX kontrolleri ile kolay şekilde gerçekleştirebiliriz. ScriptManager , UpdatePanel ve UpdateProgress kontrolü ile yap õlacak bu işlemde dikkat etmemiz gereken nokta TreeView TreeView kontrolünün PopulateNodesFromClient özelliğidir. Bu özelliğin true olmasõ durumunda TreeView callback yöntemiyle sunucuyla iletişime geçecek ve kulland õğõmõz AJAX kontrolleri etkin olmayacaktõr. Bundan dolayõ da UpdateProgress UpdateProgress kontrolü ile kullan õcõyõ haberdar edemeyiz. Eğer TreeView kontrolü UpdatePanel içerisinde at õlõrsa ve PopulateNodesFromClient özelliğine de false değeri atanõrsa, kontrol normal bir postback işlemi yapmak isteyecek fakat UpdatePanel'e bağlõ çalõştõğõ içinde kõsmi postback (partial postback) işlemi gerçekleşecektir.
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.
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.
ASP.NET ATLAS 29 Mart 2006 Not: Bu makale Microsoft’un ASP.NET AJAX’ õ duyurmas õndan önce yay õnlanmõşt õr.
ASP.NET ATLAS, ASP.NET AJAX’ õn release olmadan önceki ad õd õr ve bu makalede bahsedilen konular õn hemen hemen tamam õ ürünün tam sürümü için de geçerlidir.
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öndermed g öndermeden en (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 teknolojinin örneklerini sõkça görüyoruz. Bu sitelerde site lerde 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. 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 o larak duyurulmasõnõn hemen ardõndan ATLAS’õn beta sürümünü de duyurdu. ATLAS adõ verilen bu eklenti, ASP .NET . 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 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 g eliş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 nimetlerinden de faydalanmamõzõ sağladõ. ATLAS'õn genel yapõsõna bakacak olursak; ATLAS kullanõcõ taraf õndaki Framework ve Servisler ile sunucu taraf õnda yer alan Framework olmak üzere iki kõsõmdan oluşuyor. (ATLAS'õn genel mimarisini sşağõdaki resimden görebilirsiniz) Bu yap õ sayesinde Atlas .js dosyalar õndan oluşan Sunucu Script Kütüphaneleri ve Uygulama Servisleri kullan õcõ taraf õnda çalõşarak kontrollerdeki ve bileşenlerdeki verileri sunucu taraf õna gönderebiliyor ve aynõ zamanda server-controller aracõlõğõ sunucu taraf õnda çalõşan ASP .NET sayfalar õyla ve web servisleri ile haberle şebiliyor. Uygulamayõ geliştiriciler olarak ise bizler ASP .NET'e eklenen 108
ATLAS kontrolleri sayesinde AJAX'ta yapabildi 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.
Resim: ATLAS'õn Genel Mimari Yap õsõ Makalenin son kõsmõnda ASP .NET - ATLAS'a A TLAS'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 W eb 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. t eknoloji. 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 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. Kullanõmõna bakacak ba kacak olursak; buradaki en önemli özellik EnablePartialRendering EnablePartialRendering özelliğidir. Bu özellik sayesinde sayfamõzda oluşturacağõmõz kõsõmlar, tüm sayfa tekrar yüklenmeksizin parça halinde yüklenecektir. "Partial Page Rendering" (Türkçe olarak parçal õ sayfa düzenlemesi diyebiliriz) modelini sayfamõzda çalõşõr hale getirebilmemiz için bu özelliğin True olarak ayarlanmasõ gerekiyor, aksi durumda sayfamõz ATLAS'õn nimetlerind n imetlerinden en faydalanamayacaktõr. Yine kontrolü sayesinde sayfamõzõ bir web servisine bağlayabilir ve uygulamal u ygulamalarda arda sayfamõzõ bu web servisi ile konuşturabiliriz.
110
UpdatePanel Sadece kendi içerisindeki alan õn güncellenmesini sağlar. İçerisine eklenmiş olan HTML kodlar õ ve ASP .NET . NET kontrolleri dahil olmak üzere her şeyi, bir olay tetiklendi tet iklendiği anda ya da bir değişiklik olduğu anda tekrar güncellemektedir. UpdatePanel içerisinden güncellenen bir sayfa tamamen sunucu taraf t araf õna gönderilmez (post-back olmaz) ve bu olay esnasõnda UpdatePanel'in UpdatePanel'in dõşõndaki hiçbir alan güncellenmez. .... Güncellenmeyecek Güncellenmeyecek içerikler ..... runat="server"> .... Güncellenmeyecek Güncellenmeyecek içerikler ..... UpdatePanel alt elementi olan ile birlikte kullanõlmaktadõr. UpdatePanel'de güncellenecek olan kõsõm sadece içerisinde tutulmaktadõr. Yani değiştirilecek bilgilerimizin, kodlar õmõzõn ve kontrollerimizin kontrollerimizin tamamen bu elementin içerisinde tutulmasõ gerekmektedir. ise, UpdatePanel'in dõşar õsõnda bulunan bir kontrolün değerinin değişmesi ya da kontrolde bir olayõn gerçekleşmesi durumunda UpdatePanel'in güncellenmesini sağlar. Yukar õdaki kodlara bakacak olursak, UpdatePanel dõşõnda bulunan Button2 adlõ bir butonun Click olay õ UpdatePanel'e UpdatePanel'e trigger olarak eklenmiş. Yani Button2'ye tõkladõğõmõzda UpdatePanel UpdatePanel güncellenebilecek. Eğer Button2'nin Click olayõnõ UpdatePanel'e UpdatePanel'e eklemezsek, bu butona tõkladõğõmõzda tüm sayfa yeniden yüklenecektir. yüklenecektir. (Button2'yi 'in içerisine koymu ş olsayd õk, trigger eklememize gerek kalmayacakt ka lmayacakt õ ) Örnek bir uygulama yapacak olursak; - 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 ayarlamalar õn yapõlmõş olduğunu görebilirsiniz. - Uygulamaya geçecek olursak, Default.aspx dosyasõnõn en üst kõsmõna öncelikle bir
111
kontrolü ekleyelim ve bu kontrolün kont rolün EnablePartialRendering özelliğini True yapalõm. - Daha sonra sayfamõza bir kontrolü ekleyelim. in içerisine lblZaman ad õnda bir label ve Button1 adõnda bir buton ekleyelim. - Sayfamõzõn Page_Load olayõna lblZaman.Text = "Zaman: " + Date.Now() yazalõm. - UpdatePanel'imizin içerisindeki butonun Click olayõna yine aynõ kodu yazalõm: lblZaman.Text = "Zaman: " + Date.Now() - UpdatePanel'in dõşõna Button2 adõnda bir buton daha ekleyelim. Bu butonun Click olayõnõ UpdatePanel'in UpdatePanel'in içerisindeki alt elementine ControlEventTrigger ControlEventTrigger olarak ekleyelim. (Aşağõdaki örnekteki gibi)
/> - Uygulamamõzõ çalõştõrdõğõmõzda butonlar õmõza tõkladõğõmõzda tarayõcõmõzõn hareketlerine dikkat edecek olursak, progress barda (tarayõcõnõn sağ alt köşesinde) sayfanõn yüklendiğini gösteren mavi şeritin hiç çõkmadõğõnõ ve sayfamõzda değişen zaman bilgisi dõşõnda hiçbir hareketlilik veya değişiklik olmadõğõnõ göreceğiz. Basit bir örnek ile UpdatePanel'i 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 güncelleme i şlemi yapõldõğõnda ziyaretçiye güncellem g üncelleme e 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. yapabilirsiniz.
112
runat="server"> /> Bilgiler güncelleniyor..... Örnek koda bakacak olursak, o lursak, UpdateProgress UpdateProgress kontrolünün alt elementi olan ProgressTemplate'in ProgressTemplate'in içerisine yazmõş olduğumuz kodlar ziyaretçiye güncelleme yapõldõğõ bilgisini vermeye yöneliktir. Sayfa ilk yüklendiğinde ya da yükleme işlemleri bittiğinde bu kõsõm görünmez (display:none) Bu kõsõm sadece UpdatePanel'de bir güncelleme olayõ olduğunda, güncelleme işlemi bitene kadar sayfamõzda görüntülenir. görüntülenir.
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 güncellenmesini sağlayan kontroldür. Belirttiğimiz zaman aralõklar õnda sayfamõzdaki UpdatePanel'in UpdatePanel'in içerisindeki bilgileri güncellenmesini güncellenmesini sağlar. ID="TimeControl1">
Yukar õdaki kodlardan ilkine bakacak olursak, burada sayfamõza bir ATLAS TimerControl TimerControl kontrolü eklemiş bulunuyoruz. 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ü UpdateControl'ümüzü timer t imer 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 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 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 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 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 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.
Klasik Çalõşma Modeli Klasik model kullanõlan bir web sayfasõnda, istemci web tarayõcõsõndan aldõğõ isteği sunucuya gönderir(1) ve sunucu bu isteğe göre oluşturduğu içeriği tarayõcõya gönderir(2). Böylece web sayfasõ istemci taraf õndan görüntülenir. İstemci aynõ sayfa üzerinde yeni bir istekte bulunduğunda ise istek sunucuya tekrar gönderilir(3) ve üretilen içerik tamamen yenilenmiş bir sayfa olarak tarayõcõya gönderilir(4). Bu aslõnda bugüne kadar gördüğümüz, alõşõlagelmiş çalõşma modelidir. Bir sayfa üzerinden başka bir sayfaya veya içeriğe istekte bulunur ve PostBack işlemi ile sayfa tamamen yenilenir. (Aşağõdaki şekilde klasik çalõşma modeli anlatõlmõştõr.)
AJAX Çalõşma Modeli AJAX mimarisini kullanan bir web sayfasõnda ise ilk işlemler klasik çalõşma modeldeki gibi olur. Yani istemci isteğini sunucuya gönderir(1) ve oluşturulan içerik alõnarak tarayõcõ 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 a rka 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 tutulmayacak t utulmayacakttõr, kõsmi bir PostBack işlemi gerçekleşecektir ve sayfanõn tamamen yenilenmesine 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 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.
Dünü, bugünü, yar õnõ… AJAX’a bu kadar övgünün yeterli olduğunu düşünüyorum. AJAX’õn tarihçesine bakacak olursak aslõnda birçoğumuzun sandõğõ gibi AJAX’õn son 1-2 yõl içinde çõkan bir model olmadõğõnõ görüyoruz. AJAX’õ uygulamamõzõ sağlayan XMLHTTPRequest XMLHTTPRequest nesnesi ilk olarak Microsoft taraf õndan Internet Explorer 5.0’õn yapõsõna eklenmişti. Birçoğumuzun kullanmõş olduğu Outlook Web Access aracõ AJAX’õ kullanan ilk örneklerden biriydi. Ancak ilk zamanlarda XMLHTTPRequest XMLHTTPRequest nesnesinin sadece Internet Explorer’da Explorer’da bulunmasõ ve diğer tarayõcõlar õn bu nesneyi yap õsõnda bulundurmamas bulundurmamasõ nedeniyle AJAX neredeyse hiç kullanõlmamõştõ. Son zamanlarda zamanlarda ise popüler tüm tarayõcõlar artõk yapõlar õnda bu nesneyi bulundurmaya başladõlar. AJAX’a asõl popülaritesini kazand õran ise Google’õn son birkaç yõlda hazõrladõğõ uygulamalar oldu. Google Suggest, Suggest, Google Earth, Earth, Gmail gibi uygulamalar kullanõcõlar õ ve geliştiricilere yepyeni bir web dünyasõnõn haberlerini vermiş oldu. Yine PageFlakes,, Microsoft’un Start.com ve VirtualEarth uygulamalar õ son yõllarda AJAX’õ PageFlakes kullanan ve çok ses getiren sitelerden sadece birkaçõ. Şu an kullanõlan popüler tarayõcõlar õn neredeyse tamamõ (Internet Explorer 5.0+, Firefox 1.0+, Opera 8+, Safari 1.2 ve Netscape 7
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 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) 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 güncellenen alanlarda değişiklikler olmaktadõr.
XMLHTTPRequest Nesnesini İnceleyelim XMLHTTPRequest nesnesi JavaScript’in içerisinde bulunan bir yap õdõr. Bu nesne içerisindeki içerisindeki metotlar, eventhandler ve özellikler sayesinde bir web sayfasõnõn yüklendikten sonra asenkron şekilde sunucu ile haberleşmesini sağlamaktadõr. Bu işlemi yaparken kulland õğõ 2 temel metot vardõr. Bunlar open ve send metotlar õdõr. Yine asenkron haberleşmenin hangi safhada olduğunu, sunucudan bize bir bilgi dönüp dönmediğini kontrol edebilmemizi sağlayan bir olay ve bir özellik bulunmaktad bulunmaktadõr. Bunlar da onreadystatechange onreadystatechange eventhandler’õ ve readystate özelliği. Gelin isterseniz XMLHTTPRequest nesnesinin üyelerinin kullan õmõnõ ve AJAX modelini bir web sayfasõna nasõl uygulayabilece uygulayabileceğimizi daha iyi anlamak için ilk AJAX örneğimizi hazõrlayalõm. Öncelikle sayfamõzõn HTML içeriğini hazõrlayalõm. HTML
117
sayfamõzda içerisine bir tane span elementi ve tipi buton olan bir input elementi ekleyelim. n> Buradaki buton yapacağõmõz asenkron çağr õyõ tetikleyecek olan elementimizdir. Bu butona tõkladõğõmõzda az sonra yazacağõmõz ve adõ AsenkronCagriYap() olan JavaScript fonksiyonumuzu çağõr õp, çağr õ sonucunda dönecek olan bilgileride yine JavaScript içerisinden dinamik bir şekilde id bilgisi lblGuncelle olan span elementimizin içerisine yazdõracağõz. JavaScript’teki fonksiyonlar õmõzõ yazmadan önce isterseniz bu bölümün b ölümün başõnda anlattõğõmõz XMLHTTPRequest nesnesini nasõl oluşturacağõmõzõ ve bu nesnenin yapõsõnda bulunan üyelerini inceleyelim. 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.XMLHTT ActiveXObject(“Microsoft.XMLHTTP”) P”) ve XMLHTTPRequest() XMLHTTPRequest() ile nesne oluşturabiliriz. IE 6.0+ tarayõcõlar için aşağõdaki tanõmlama yapõlõr. var nesne = new ActiveXObject("Msxml2.XM ActiveXObject("Msxml2.XMLHTTP"); LHTTP"); IE 5.5 sürümleri için ise aşağõdaki tanõmlama yapõlõr. var nesne = new ActiveXObject("Microsoft.XMLH ActiveXObject("Microsoft.XMLHTTP"); TTP"); 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() NesneOlustur() { var nesne; try { nesne = new ActiveXObject("Msxml2.XMLHTTP"); ActiveXObject("Msxml2.XMLHTTP"); // IE 6.0+ tarayõcõlar için } catch(e) { try {
118
nesne = new ActiveXObjec Act iveXObject("Micr t("Microsoft.XMLHTTP"); osoft.XMLHTTP"); // IE 5.5 tarayõcõlar õ için } catch(e) { try { nesne = new XMLHTTPRequest(); 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; } Yukar õdaki JavaScript fonksiyonu bize istemcinin istemcinin kullandõğõ tarayõcõya göre oluşturacağõ XMLHTTPRequest XMLHTTPRequest nesnesini döndürecektir. Bu nesne üzerinden artõk asenkron işlemlere başlayabiliriz. open ve send metotlar õ sunucuya asenkron istekte bulunmamõzõ sağlamaktad õr. 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.) nesne.open(“GET”, nesne.open(“GET”, “sonuc.aspx”, true); 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 o larak gönderilecek veriyi taşõyabilir. Send metodunu parametresiz veya null parametresi ile de kullanabilmekteyiz. kullanabilmekteyiz.
nesne.send(); veya nesne.send(null); İ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 XMLHTTPRequest içerisinde bulunan onreadystatechange onreadystatechange eventhandler’ eventhandler’õ ve readystate özelliğini kullanmamõz gerekiyor.
119
onreadystatechange onreadystatechange eventhandler’ 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 onreadystatechange onreadystatechange olayõnõ atacağõmõz bir fonksiyon içerisinde readystate değerini kontrol edersek, readystate bize 4 değerini getirdiğinde artõk isteğimiz tamamlanmõş ve bize bir sonuç getirilmiş demektir. nesne.onreadystatechange nesne.onreadystatechange = function { if (nesne.readystate == 4) { // sonucu HTML’e yazdõr } } Artõk HTML kodumuzdaki buton içerisinden çağõracağõmõz AsenkronCagriYap() AsenkronCagriYap() fonksiyonunu oluşturabiliriz. function AsenkronCagriYap() AsenkronCagriYap() { var yeniNesne = NesneOlustur(); NesneOlustur(); // XMLHTTPRequest XMLHTTPRequest nesnemizi oluşturduk // Bulunacağõmõz isteği açõyor ve sunucuya gönderiyoruz. gönderiyoruz. İsteğimiz aynõ dizinde bulunan Ogrenciler.htm adresine, GET metodunu kullanarak gerçekleşiyor. yeniNesne.open("GET","O yeniNesne.open("GET","Ogrenciler.htm" grenciler.htm",true); ,true); yeniNesne.send(null); // Yeni bir fonksiyon f onksiyon yazmamõza gerek kalmadan onreadystatechange olayõnõ isimsiz bir fonksiyona bağlõyoruz yeniNesne.onreadystatech yeniNesne.onreadystatechange ange = function() { // Eğer readystate 4 değerine sahipse asenkron işlem bitmiş ve veriler getirilmiş demektir if(yeniNesne.readystate if(yeniNesne.readystate == 4) { // Getirilen veriyi HTML k õsmõndaki lblGuncelle içerisine dinamik bir şekilde yazdõr õyoruz document.getElementById('lblGun document.getElementById('lblGuncelle').innerH celle').innerHTML TML = yeniNesne.responseText; yeniNesne.responseText; } } }
120
Son olarak belirtmemiz gereken nokta ise document.getElementById('lbl document.getElementById('lblGuncelle'). Guncelle'). 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 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 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() 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 içerisine yazacaktõr. Yukar õdaki örneğimizde kullandõklar õmõz dõşõnda XMLHTTPRequest’in aşağõdaki üyeleri de bulunmaktadõ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", 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 ü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. Bu yazõmõzda AJAX A JAX modelini inceleyip web uygulamalar õmõzda nasõl kullanabileceğmizi ele aldõk. AJAX web üzerinde uygulama geliştiriciler için gerçekten köklü ve önemli bir geli ge lişme. ASP .NET geliştiricileri için hazõrlanan ve kullanõmõ giderek yaygõnlaşan ASP .NET AJAX aracõnõ kullanmak için AJAX’õ veya JavaScript’i iyi bilmemize gerek olmamas o lmamasõna rağmen temel olarak AJAX modelini modelini nasõl uygulayabileceğimizi öğrenmek bizler için oldukça yararlõ 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 projelerimizde kullanarak, daha persormanslõ ve zengin uygulamalar geliştirebiliyoruz. tirebiliyoruz. ASP.NET AS P.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 uygulamalar uygulamalar õnõn sunucuya taşõnmasõnda, klasik uygulamalar õn ASP.NET AJAX uygulamasõ haline getirilmesinde getirilmesinde ve bazõ ASP.NET kontrollerinin UpdatePanel içerisinde kullanõlmasõnda çõkabilecek sorunlar ve bu sorunlar halinde ne gibi i şlemler yapmamõz gerekeceğini aşağõda detaylõ şekilde ele alacağõz.
ASP.NET AJAX deste ği olmayan (AJAX Extension kurulu olmayan) bir sunucuda ASP.NET AJAX’ õ nasõl çalõştõrabilirim? ASP.NET AJAX ile ilgili belki de en sõk kar şõlaşõlan sorulardan biri de şu: “Kendi bilgisayar õmda ASP.NET AJAX projemi geliştirdim. Her şey gayet güzel çalõşõyordu. Fakat sitemin bulunduğu sunucuya dosyalar õ yüklediğimde ‘Configuration ‘Configuration Error’ vb. bazõ hatalar alõyorum ve sayfalar õmõ çalõştõramõyorum”. Bu hatanõn temel sebebi, sunucuda ASP.NET AJAX Extension v1.0’õn kurulu olmamasõdõr. ASP.NET AJAX’õn ATLAS sürümlerinde yapõlan bir projenin kullanacağõ assembly dosyalar õ projenin Bin dizinine at õlõyor ve assembly a ssembly 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. 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 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 AJAX 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. ge rekecektir.
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, ...System.Web.Extensions, Version=1.0.61025.0, Version=1.0.61025.0, tanõmlamalar õn type özelliği içerisinde ...System.Web.Extensions, Culture=neutral, PublicKeyToken=31bf3856ad364e PublicKeyToken=31bf3856ad364e35 35 ş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=31bf38 PublicKeyToken=31bf3856ad364e 56ad364e35 35 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.
web.config dosyasõnda gerekli değişikliklerin yapõlmasõ 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.
Daha önceden geli ştirilmiş ASP.NET 2.0 uygulamasõnda nasõl ASP.NET AJAX kullanabilirim? Daha önceden geli ştirilmiş bir ASP.NET 2.0 projesini AJAX’a geçirmek kar şõmõza çõkabilecek ihtiyaçlardan biridir. Böyle bir durumda yap õlmasõ gereken iki işlem var. Birincisi web.config web.config dosyasõ içerisindeki gerekli değişiklikleri yapmak, ikincisi ise uygulama içerisinde AJAX kullanõlacak sayfalara ScriptManager ve UpdatePanel gibi AJAX kontrollerin eklenmesi olacaktõ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 u ygulamanõza eklemek. Eğer klasik uygulamnõzdaki web.config dosyasõnda değişiklikler yaptõysanõz, ASP.NET AJAX projesindeki web.config’den - - kõsmõ içerisindeki - kõsmõ içerisindeki - - tem.web.extensions> - kõsõmlar õnõ uygulamanõzõn web.config dosyasõ içerisindeki içerisindeki uygun u ygun alanlara eklemeniz gerekecektir. Buradaki kõsõmlar õn hiyerar şik olarak belirli bir düzene sahip olmasõ gerekece ği için bazõ düzenlemeler yapmak gerekebilir. Örneğin düğümünün, kõsmõndaki ilk düğüm olmasõ zorunlu olacaktõr. Bu tip hatalar õ derleme zamanõnda veya ilk çalõştõrma anõnda alacağõmõz için kolayca düzeltebiliriz. düzeltebiliriz. Böylece uygulamanõzda ASP.NET AJAX ile ilgili ayarlamalar õ gerçekleştirmiş olacaksõnõz. - ASP.NET AJAX Extension’lar Extension’lar õnõ kullanmak istediğiniz sayfalara ScriptManager, ScriptManager, UpdatePanel, UpdateProgress gibi kontrolleri ekleyerek sayfalar õnõzda artõk AJAX’õ sorunsuz bir şekilde kullanabilirsiniz.
Daha önceden geli ştirdiğim bir ASP.NET 1.0 veya 1.1 uygulamasõnda ASP.NET AJAX’ õ kullanabilir miyim? ASP.NET AJAX Extension, ASP.NET’in sadece 2.0 versiyonu ile kullanõlabilir bir yap õ olduğu için, önceki ASP.NET sürümlerinde sürümlerinde ASP.NET AJAX’õn kullanõlmasõ mümkün değildir. 1.0 ve 1.1 sürümleri ile geliştirilmiş projelerde .NET Framework için haz õrlanmõş olan AJAX.NET isimli ücretsiz AJAX kütüphanesini kullanabilirsiniz. kullanabilirsiniz. (AJAX.NET için http://ajax.schwarzhttp://ajax.schwarzinteractive.de adresinden bilgi alabilirsiniz) alabilirsiniz)
ASP.NET AJAX uygulamalar õnda FileUpload ve WebParts kontrolleri kontr olleri gibi kontrolleri çal õştõramadõm? Sorun neden kaynaklanõyor? ASP.NET AJAX, ASP.NET kontrolleri ile uyumlu bir şekilde çalõşsa da desteklemediği bazõ kontroller de vardõr. Bu kontroller asenkron mimari ile uyumlu çalõşamayacağõ için, bir UpdatePanel içerisinde de düzgün şekilde kullanõlamayacaktõr. FileUpload, TreeView, Menu kontrolleri, Login kontrolleri ve Web Part kontrolleri AJAX uygulamalar õnda düzgün bir şekilde kullanõlamamaktad õr. Yine GridView ve DetailsView kontrolleri de bazõ durumlarda UpdatePanel içerisinde düzgün şekilde kullanõlamayacakt õr. GridView
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 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 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
veya etiketi ile oluşan bir alan) içerisine eklenen kontrollerin görüntülenmesini görüntülenmesini ve asenkron bir şekilde bu kontrollerin içeriklerinin güncellenmesini sağlar. ve kõsõmlar õ olmak üzere iki kõsõmdan oluşmaktadõr. kõsmõnda, UpdatePanel UpdatePanel içerisinde yer alacak a lacak 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. kõsmõnda ise UpdatePanel'in UpdatePanel'in çalõşmasõnõ; yani güncelleme işleminin gerçekleşmesini sağlayacak olaylar õn bağlanmasõ işlemi gerçekleştirilir. 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. runat="server"> UpdatePanel’in UpdatePanel’in ContentTemplate’i ContentTemplate’i içerisine bileşenleri eklemek, kõsmi güncelleme işleminin yapõlmasõ için yeterli olmayacakt o lmayacaktõr. UpdatePanel içerisindeki kõsmõn güncellenmesi için, sayfada bulunan herhangi bir kontrol üzerinde gerçekle şecek bir olayõn paneli tetiklemesi gerekecektir. Örneğin, bir butonun tõklanmasõ; yani Button kontrolünün Click olayõnõn gerçekleşmesi UpdatePanel’in güncellenmesini sağlayabilir. UpdatePanel, kendisini güncelleyecek olaya ba ğlanõr ve böylece olay gerçekleştiğinde UpdatePanel içerisi asenkron bir şekilde güncellenebilir. Burada UpdatePanel’in içerisini güncelleyecek kontrolün bulunacağõ konuma göre iki farklõ durum sözkonusu olacaktõr; kontrolün UpdatePanel UpdatePanel içerisinde veya dõşar õsõnda olmasõ. Gelin bu iki durumda UpdatePanel'in nas õl çalõştõğõnõ ele alalõm. Öncelikle File > New > Web Site menüsünden ASP.NET AJAX Enabled Web Site seçeneğini seçerek açtõğõmõz yeni projenin Default.aspx Default.aspx sayfasõna bir UpdatePanel UpdatePanel kontrolü ekleyelim.
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 a tama 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.
Resim: UpdatePanel içerisindeki kontrolün paneli tetiklemesi 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 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.
Durum-2: Kontrol UpdatePanel’in d õşõnda ise: Güncelleme işlemini yapacak kontrol bazõ durumlarda tasar õm gereği UpdatePanel’in dõşar õsõnda da bulunabilir. bulunabilir. Böyle bir durumda d urumda bu kontrolün paneli otomatik olarak güncelleyebilmesi güncelleyebilmesi mümkün olmayacaktõr. Kontrol ancak trigger olarak panele bağlanõrsa, kontrol üzerinde gerçekleşecek olay panelin içerisini güncelleyecektir. Bu durumda kontrolü UpdatePanel içerisinde bulunan kõsmõna AsyncPostBackTrigger trigger olarak
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 UpdatePanel’e eklemek gerekecektir. gerekecektir. runat="server">
width:200px">
Text="Label">
Resim: UpdatePanel d õşõndaki bir kontrolün paneli tetiklemesi 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 AsyncPostBackTrigger eklenmesi AsyncPostBackTrigger , panele asenkron postback işlemi yapmasõ istenilen kontrolün eklenmesi için kullanõlacak seçenektir. seçenektir. ControlID, paneli tetikleyecek kontrolün adõ, EventName ise bu kontrol üzerinde gerçekle şecek olaydõr. Bu şekilde UpdatePanel dõşõndaki bir kontrolün kontrolün paneli asenkron bir şekilde güncellemesi sağlanabilir. Eğer tasar õm gereği UpdatePanel içerisinde bulunan bir kontrolün panelin içerisinde de ğilde, sayfanõn tamamõnda postback işlemi gerçekleştirmesi istenirse, bu kontrolün panele PostBackTrigger olarak eklenmesi gerekecektir. gerekecektir.
Bir Sayfada Birden Fazla UpdatePanel Kullan õmõ Bir sayfa içerisinde bir tane UpdatePanel kullan õlabileceği gibi birden fazla UpdatePanel de kullanõlabilir. Böyle bir durumda da kar şõmõza bazõ kar õşõklõklar çõkabilecektir. Gelin şimdi de bir sayfa içerisinde içerisinde birden fazla f azla UpdatePanel bulundu bulunduğunda panellerin ne şekilde çalõşacağõnõ, birbirlerinin birbirlerinin güncellem g üncellemelerinden elerinden nas õl etkileneceklerini ele alalõm. Bu işlem için öncelikli olarak sayfamõza UpdatePanel2 adõnda ikinci bir panel ekleyelim. Bu panelin ContentTemplate’i ContentTemplate’i içerisine de aşağõda görüldüğü şekilde Label2 adõnda bir Label kontrolü ve Button2 adõnda bir Button kontrolü ekleyelim.
Default.aspx runat="server">
width:200px">
runat="server">
129
Label2 kontrolünün 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(); } Artõk UpdatePanel2 kontrolü içerisindeki Button2’ye tõklandõğõnda Label2 üzerine güncel zaman bilgisinin asenkron bir şekilde güncellenerek gelmesini bekliyoruz. Uygulamay õ çalõşõtõr õp değişiklikleri gözlemleyelim. Burada istenilenin d õşõnda bir durum gözünüze çarpacaktõr. Herhangi bir paneldeki butona t õklanõlmasõ durumunda her iki panelin de güncelleneceğini göreceksiniz.
Resim: Bir sayfada birden fazla UpdatePanel kullanõmõ 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. güncellenmektedir. UpdatePanel'lerin UpdatePanel'lerin bu şekilde çalõşmalar õnõ sağlayan UpdateMode özellikleridir. özellikleridir. Sayfamõza eklediğimiz bir UpdatePanel'in 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 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 tet iklenecektir.. Bu noktada UpdatePanel1'in UpdatePanel1'in UpdateMode özelliğini Conditional yapacak olursan õz, sayfayõ çalõştõrdõğõnõzda UpdatePanel1'in UpdatePanel1'in sadece kendi triggerlar õ taraf õndan tetiklenebilece 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. Aşağõdaki tabloda iki UpdatePanel'in UpdateMode özelliklerine göre ne şekilde tetiklenecekleri listelenmi listelenmiştir.
İç İçe UpdatePanel Kullan õmõ ASP.NET AJAX ile hazõrlanan bir sayfa içerisinde iç içe UpdatePanel'ler de kullanõlabilmektedir. labilmektedir. Hazõrlanan web sayfasõ içerisinde UpdatePanel sayfanõn büyük bir kõsmõnõ kaplõyor ve içerisinde çok sayõda kontrol bulunduruyorsa, bulunduruyorsa, içerisindeki tüm kontrollerin beraber güncellenmesinin dõşõnda bazõ kontrol gruplar õnõn da ayr õ olarak güncellenmesi istenilebilir. istenilebilir. Böyle bir durumda, ana UpdatePanel'in UpdatePanel'in ContentTemplate kõsmõnda yerleştirilecek ikinci bir UpdatePanel, dõştaki UpdatePanel ile uyumlu bir şekilde çalõşabilecektir. Aşağõdaki örnekte sayfaya eklenen bir UpdatePanel UpdatePanel içerisine ikinci bir UpdatePanel UpdatePanel eklenmiştir. Burada iç kõsõmdaki UpdatePanel'in dõştaki panelden ayr õ olarak çalõşabilmesi için dõştaki UpdatePanel'in UpdatePanel'in (UpdatePanel3) UpdateMode özelliği Conditional, içteki UpdatePanel'in UpdatePanel'in (UpdatePanel4) UpdateMode özelliği ise Always olarak tanõmlanmalõdõr.
Resim: Bir UpdatePanel içerisinde ba şka bir UpdatePanel kullan õlabilir. 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. güncellenecektir. Baz B azõ 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 u ygulama 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 t amamen güncellenmesine güncellenmesine gerek kalmadan, kalmadan, sadece belirli alanlar õnõ yenileyebilir yenileyebilir ve böylece daha hõzlõ çalõşan web sayfalar õ geliştirebiliriz. 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. getirilmektedir. Bu nedenle AJAX artõk biz web uygulama geliştiricileri için oldukça önemli hale gelmi ştir. AJAX ile geliştirilmiş popüler uygulamalara örnekler http://www.pageflakes.com http://local.live.com http://www.gmail.com http://www.netvibes.com AJAX temel olarak istemci-sunucu istemci-sunucu (client-server) arasõnda asenkron işlemler yürütülmesini sağladõğõ için, uygulamanõn en önemli kõsmõ belki de istemci taraf õnda çalõştõrmamõz gereken JavaScript kodlar õ olacaktõr. Zira istemciden sunucuya asenkron bir şekilde gidebilmek için istemci taraf õnda kodlar çalõştõrmak gerekecektir. Bir AJAX uygulamasõ geliştirebilmek için iyi seviyede JavaScript dili bilmemiz gerekir diyebiliriz. JavaScript dilini iyi bilmeyen kullanõcõlar için ise kolay bir şekilde AJAX uygulamalar õ geliştirebilmeleri için AJAX kod kütüphaneleri hazõrlanmõş ve geliştiricilerin kullan õmõna sunulmuştur. Microsoft ise ASP.NET programcõlar õnõn uygulamalar õnõ kolay bir şekilde AJAX destekli hale getirmeleri ge tirmeleri için ASP.NET AJAX adõ verilen ücretsiz bir kod kütüphanesi duyurmuştur. ASP.NET AJAX temel olarak istemci ve sunucu taraf õnda çalõştõr õlacak bileşenlerden oluşmakta ve tam anlamõyla sunucu taraflõ yürütülebilecek AJAX uygulamalar õ geliştirmemizi sağlamaktad õr. ASP.NET AJAX framework’ünün istemci taraf õnda gerekli JavaScript kod kütüphaneleri ve servisleri, sunucu taraf õnda ise .NET Framework Framework ve ASP.NET kontrolleri ile uyumlu bir şekilde çalõşmamõzõ sağlayan AJAX kontrolleri, sõnõf kütüphaneleri kütüphaneleri ve servisler bulunmaktad bulunmaktadõr. 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 a raçta bu kütüphaneyi kullanabilmek 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 AJAXEnabled Web Site şablonunu seçerek projemizi olu şturuyoruz. Ben projenin dili olarak C#’õ seçiyorum.
Resim: Visual Studio 2005’te yeni bir AJAX projesi açmak Böylece yeni bir ASP.NET AJAX projesi oluşturduk. ASP.NET AJAX Extensions kurulumunu 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 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 ScriptManagerProxy bu tip bir sayfada ScriptManager 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 ScriptM S criptManager anager 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 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 b ilgilerini saklamak saklamak için iller ve ilceler olmak üzere Microsoft Office Access’te iki tablo oluşturalõm.
Resim: Access’te Access’te oluşturduğumuz iller ve ilceler tablolar õ 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 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.
Resim: DropDownList Tasks T asks penceresinden gerekli gerekli i şlemleri yapõyoruz Açõlan pencereden adõm adõm ilerleyecek olursak; - 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 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’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 SQ L 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 içerisindeki bileşenler otomatik olarak asenkron güncellenebilir 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 UpdatePanel kontrolü ContentTemplate ve Triggers olmak üzere iki kõsõmdan oluşur. Oluşturduğumuz sayfanõn kodlar õna bakacak olursak DropDownList kontrollerinin UpdatePanel içerisindeki içerisindeki kõsmõna eklendiğini görebiliri g örebiliriz. z. UpdatePanel'de asenkron olarak güncellenecek kõsõmlar sadece ContentTemplate ContentTemplate içerisinde tutulmaktadõr. Triggers kõsmõnda ise UpdatePanel’in UpdatePanel’in içeriğinin asenkron olarak güncellenmesini güncellenmesini sağlayacak kontrollerin tanõmlamasõ yapõlõr. Örneğin bir Button’a tõklandõğõnda veya DropDownList’ten bir seçim yapõldõğõnda UpdatePanel’in içeriğinin güncellenmesi isteniliyorsa isteniliyorsa bu kontrollerin UpdatePanel’e UpdatePanel’e trigger (tetikleyici) olarak bağlanmasõ gerekir. runat="server"> 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. Böylece UpdatePanel kontrolümüzü nasõl kullanabileceğimizi incelemiş olduk. Dilerseniz uygulamamõzõ görsel olarak daha zengin hale getirelim. Örneğin iller menüsünden bir il seçtiğimizde ilçelerin güncellenmesi esnasõnda UpdateProgress kontrolü ile sayfan õn bir 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 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 ö zelliği 0 olarak belirleyelim ve kontrolün içerisine güncelleme işlemini belirten bir resim dosyasõ ve metin ifade ekleyelim. DisplayAfter="0">
Resim: UpdatePanel’in içeriği güncellendiği esnada UpdateProgress UpdateProgress kontrolü görüntülenir Eğer yapõlacak güncelleme işlemi zamana bağõmlõ olacaksa AJAX kontrollerinden kontrollerinden olan Timer ’i’i UpdatePanel’e ekleyerek panel içeriğinin belirli zaman aralõklar õyla güncellenmesini 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. güncellenir. Bu yazõmõzda Microsoft’un ASP.NET ASP. NET uygulamalar 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. inceleyebilirsiniz. Bir sonraki yazõmõzda görüşmek dileğiyle…
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 rencilerin isimlerinin ve 3 tane t ane 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 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.
Artõk Excel dosyasõ ADO.NET taraf õndan kullanõlabilecek formattadõr. Bu haliyle Excel dosyasõnõ bir Access veritabanõ dosyasõ gibi düşünebiliriz. Burada; NotTablosu tablo adõ, AdSoyad, Sõnav1, Sõnav2 ve Final ise alan adlar õdõr. Dosyayõ Notlar_1.xls olarak kaydedelim ve dosyayõ kapatalõm. (Zaten dosya açõkken uygulamamõzõ çalõştõr õrsak hata verecektir.) Burada dikkat etmemiz gereken önemli bir nokta var. İlk satõr õmõzda yer alan AdSoyad, Sinav1, Sinav2 ve Final bilgileri alan ad õ olarak algõlanacaktõr ve veritabanõna eklemeye çalõştõğõmõzda ilk satõr õmõzdaki bu bilgiler al õnmayacaktõr. Dosyadaki bilgileri SQL komutuyla filtreleyerek, istediğimiz satõrlar õ ve bilgileri çekebileceğiz. Örnek olarak “SELECT * FROM
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 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 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 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. ' Dosyaya bağlanmak için gerekli olan bağlantõ stringini Dim ConnStr As String = "Provider=Microsoft.Jet.OLED "Provider=Microsoft.Jet.OLEDB.4.0;Data B.4.0;Data Source=" & Server.MapPath("Notlar_1.xls") Server.MapPath("Notlar_1.xls") & ";" & "Extended Properties=Excel 8.0;" Dim Conn As New OleDbConnection(ConnStr) Conn.Open() Dim MyCommand As New OleDbCommand("SELECT * FROM NotTablosu", Conn) Dim da As New OleDbDataAdapter da.SelectCommand da.SelectCommand = MyCommand MyCommand da.Fill(dt) ' Verileri daha sonra da kullanabilmek için session içerisinde içerisinde tutuyoruz Session("Veriler") Session("Veriler") = dt ' Verinin görüntülenece görüntüleneceği DataGrid in DataTable a ba ğlanmasõ ve verinin yüklenmesi DataGrid1.DataSource DataGrid1.DataSource = dt.DefaultView DataGrid1.DataBind() Label1.Text Label1.Text = "Excel dosyasõndan veri alõndõ" 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 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 ConnStr As String St ring = "data source=.;persist security info=False;initial info=False;initial catalog=Deneme;user catalog=Deneme;user id=UserDeneme;pwd=123" id=UserDeneme;pwd=123" Dim Conn As New SqlConnection(ConnStr) Conn.Open() Dim sayi As Integer ' Session içerisinde tutulan verilerin alõnmasõ dt = Session("Veriler") Session("Veriler") For sayi = 0 To dt.Rows.Count dt.Rows.Count - 1 Dim SqlStr As String = "INSERT INTO Notlar (AdSoyad, (AdSoyad, Sinav1, Sinav2, Final) " & _ "VALUES ('" & dt.Rows(sayi)(0) & "', " & dt.Rows(sayi d t.Rows(sayi)(1) )(1) & ", " & dt.Rows(sayi)(2) & ", " & dt.Rows(sayi)(3) & ")" Dim MyCommand As New SqlCommand(SqlStr, Conn) Dim da As New SqlDataAdapter SqlDataAdapter da.SelectCommand da.SelectCommand = MyCommand MyCommand da.Fill(dt) Next Label1.Text Label1.Text = "Veriler veritabanõna yazõldõ" Conn.Close()
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. CREATE TABLE [dbo].[Notlar] ( [AdSoyad] [varchar] (50) NOT NULL , [Sinav1] [int] NULL , [Sinav2] [int] NULL , [Final] [int] NULL ) ON [PRIMARY]
Oluşturduğumuz bir Excel dosyasõndaki tanõmlanmõş verileri ADO.NET aracõlõğõyla alarak kullanõcõnõn görebileceği formda bir datagrid nesnesine yazdõrdõk. Daha sonra da yine bu verileri ADO.NET nesneleri aracõlõğõyla SQL Server’ S erver’daki daki tablomuza yazdõrdõk. Anlatmaya çalõştõğõm konuda bu özelliği basit yönüyle inceledik. inceledik. Buradaki örnek kodlardan yola çõkarak sizde uygulamalar õnõzda bir Excel dosyasõndaki verileri alõp üzerinde işlemler yapabilir ve varolan başka bir veritabanõ dosyasõna yazdõrabilirsiniz.
144
Datatable ile Sõralama ve Filtreleme İşlemleri 11 Temmuz 2007
Geliştirdiğimiz uygulamalarda veritabanõ ile ilgili işlemleri sõklõkla yapmaktayõz. Veritabanõna bağlanmak, verileri seçip uygulama ortamõnda aktarmak ve bu verileri uygulamayõ kullanacak kişilerin istediğine göre sunmak, programc p rogramcõ olarak bizlerin en rutin işlemlerinden biridir. Tabi ki bu tip işlemleri yaparken esas alacağõmõz kurallardan biri de uygulamanõn performanslõ bir şekilde çalõşmasõnõ sağlamakt õr. Bu yazõmõzda da veritabanõndan çektiğimiz verileri uygulama ortamõnda sakladõğõmõz DataTable nesnesi üzerinde verileri filtreleme ve s õralama işlemlerini yapmamõzõ sağlayan Find ve Select isimli iki metodu detayl õ bir şekilde irdeleyeceğiz. Dilerseniz şöyle bir senaryo ile konumuza giriş yapalõm. Veritabanõnda ürünlerimizin ürünlerimizin bulunduğu tablodan verileri getirerek uygulama içerisinde kullan õyoruz. Kullanõcõ, form üzerinde bulunan kontroller aracõlõğõyla aynõ veri üzerinde özel kriterler belirterek veri seçme işlemleri gerçekleştiriyor. (Sadece istenilen kriterdeki kayõtlar õ getir, istenilen kriterdeki verileri istenilen sõrada getir... gibi) Eğer kullanõcõ form üzerinde bu tip işlemleri sõklõkla yapacak ise, her seferinde veritabanõna bağlantõ açmak, sorgu çalõştõrmak ve sorgu sonuçlar õnõ uygulamaya aktarmak elbetteki hem uygulaman uygulamanõn performansõnõ azaltacaktõr, hem de veritabanõnda daha fazla işlem yapõlacağõ için sunucuda yavaşlõğa sebep olacaktõr. İşte böyle bir senaryoda tablodan istenilen tüm verileri alarak uygulamada (yani DataTable nesnesi içerisinde) saklamak, daha sonra da bu veriler üzerinde filtreleme ve s õralama işlemleri yapmak uygulamamõzõn performansõnõ olumlu yönde arttõracaktõr. ADO.NET içerisinde bu tip işlemleri yapmamõzõ sağlayan bazõ yapõlar mevcuttur. Bu yazõmõzda ise DataTable sõnõf õ içerisinde bulunan baz õ metotlar õ kullanarak bu işlemleri nasõl gerçekleştireceğimizi göreceğiz. Yine DataTable nesnesi içerisindeki verileri okuyarak, bu verilerin farklõ görünümlerini sunan sunan DataView isimli bir nesne ile de bu tip işlemler yapõlabilir. DataView nesnesini ilerleyen zamanlarda f õrsat olursa bir makale ile sizlere sunmaya çalõşacağõm. Dilerseniz DataTable sõnõf õ içerisinde yer alan bu metotlar õn kullanõmõnõ örnek bir uygulama ile inceleyelim. inceleyelim. Bunun için bir Windows Application açarak aşağõdaki şekilde bir form tasarlayalõm.
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:
Şekil: MS Access'te haz õrlayaca ğõmõz Urunler tablosu İ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; System.Collections.Generic; using System.ComponentModel; System.ComponentModel; using System.Data; using System.Drawing; System.Drawing; using System.Text; using System.Windows.Forms; System.Windows.Forms; using System.Data.OleD System.Data.OleDb; b; // Veritaban Veritabanõ işlemleri için gerekli isim alanõnõ ekliyoruz. namespace DataTable_SortFilter DataTable_SortFilter { public partial class Form1 : Form
146
{ // Connection, Connection, DataAdapter DataAdapter ve DataTable DataTable nesnelerini field olarak tanõmlõyoruz. OleDbConnection con; OleDbDataAdapter da; DataTable dtUrunler; public Form1() { InitializeComponent(); } private void Form1_Load(object Form1_Load(object sender, EventArgs E ventArgs e) { // Gerekli bağlantõ ve sorgu cümleleri ile nesneleri oluşturuyoruz. // DataAdapter'õn Fill metodu ile getirilen verileri DataTable nesnesine yüklüyoruz. yüklüyoruz. con = new OleDbConnection("Provider=M OleDbConnection("Provider=Microsoft.Jet.OleDb.4.0; icrosoft.Jet.OleDb.4.0; Data Source=Sirket.mdb"); da = new OleDbDataAdapter("SELECT * FROM Urunler", con); dtUrunler = new DataTable("Urunler"); da.Fill(dtUrunler); } private void btnDoldur_Click(object btnDoldur_Click(object sender, EventArgs e) { // btnDoldur isimli butona tõklandõğõnda dgvUrunler isimli gridimizi verilerle dolduruyoruz. dgvUrunler.DataSource dgvUrunler.DataSource = dtUrunler; dtUrunler; } } } DataTable nesnemizi verilerle doldurduk. Şimdi yavaş yavaş sõralama ve filtreleme işlemlerini nasõl gerçekleştirebileceğimize bakalõm.
Find metodu ile Sat õr (DataRow) Arama Bildiğiniz gibi, DataTable nesneleri veritabanõndaki tablolara oldukça benzer nesnelerdir. Tõpkõ tablolarda olduğu gibi DataTable DataTable nesnesinde tutulan sütunlardan (DataColumn) birini veya birden fazlasõnõ, DataTable'õn PrimaryKey property'si ile primary key (birincil anahtar) olarak tanõmlayabiliriz. Primary key olarak tanõmlanan sütunda taşõnan kayõtlar tek olmalõ, yani birbirini tekrar etmemelidir. Bu aşamadan sonra artõk Find metodunu kullanarak tablo içerisinde primary key sütundaki kayõtlar üzerinde arama yapõlabilir. Find metodu parametre olarak object tipinden bir değer alõr ki; bu değer primary key alanda taşõnan değerlerden biri olmalõdõr. dtUrunler adõndaki DataTable nesnemizin primary key sütunu int tipinden de ğer
147
alan UrunID sütunu olacaktõr. UrunID'si 5 olan bir kaydõn DataRow tipinden bilgilerine şu şekilde ulaşabiliriz.
DataRow satir = dtUrunler.Sort(5); // UrunID'si 5 olan kaydõn bilgilerini DataRow tipinden getirecektir. 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. private void btnFind_Click(object btnFind_Click(object sender, EventArgs e) { // Arama işlemlerini yapabilmek için DataTable nesnesinin Primary Key alan õnõ // belirlememi be lirlememizz gereklidir. dtUrunler nesnesinin nesnesinin PrimaryKey property'si DataColumn DataColumn tipinden // bir dizi isteyeceği için öncelikli olarak bu diziyi tan õmlõyoruz. Burada unique kayõt // saklayan herhangi bir alan tablonun Primary key'i olarak belirlenip Find metodu ile bu // alan üzerinde arama yapõlabilir. DataColumn[] DataColumn[] dcPK = { dtUrunler.Columns["UrunID dtUrunler.Columns["UrunID"] "] }; dtUrunler.PrimaryKey dtUrunler.PrimaryKey = dcPK; // 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); 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 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["UrunID"].ToString() + " - " + satir["Ad"].ToString() + " - " + satir["Fiyat"].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 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. // UrunID ve Ad sütunlar õnõ bir DataColumn dizisi içerisinde primary key olarak // tanõmlõyor ve dtUrunler tablomuzun tablomuzun PrimaryKey P rimaryKey property'sine property'sine set ediyoruz. DataColumn[] dcPK = { dtUrunler.Columns["UrunID"], dtUrunler.Columns["UrunID"], dtUrunler.Columns["Ad"] dtUrunler.Columns["Ad"] }; dtUrunler.PrimaryKey dtUrunler.PrimaryKey = dcPK; // Object tipindeki dizimizin 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.F dt Urunler.Rows.Find(urunI ind(urunID_Ad); D_Ad);
Select Metodu ile Filtreleme ve S õralama İşlemleri Find metodu primary key alan üzerinden tek bir sat õr ile bilgi getirir, yani bir nevi SELECT * FROM Urunler WHERE UrunID=5 gibi bir sorgu çal õştõrmamõzõ sağlar. Bazõ durumlarda durumlarda ise sadece bir kaydõn değilde belirli kriterlere uyan kayõtlar õn bulunmasõnõ isteyebiliriz.(SELECT isteyebiliriz.(SELECT * FROM Urunler WHERE Fiyat>1 AND Fiyat<2 gibi) Dikkat edecek olursan õz Find metodunda yapacağõmõz aramalar sadece primary key alanõ ile kõsõtlõ idi. Burada bahsettiğimiz sorguda ise sadece primary key alan üzerinden değil de, tüm alanlarla ilgili kriterler belirtme isteğinden söz ediyoruz. Yine verdiğimiz kriterler sonucunda getirilen kayõtlar õn belirli bir alana göre sõralanmasõnõ da isteyebiliriz. (SELECT * FROM Urunler WHERE Fiyat>1 AND
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 metodunun versiyonlar õnõ inceleyecek olursak;
public DataRow[] Select(); DataTable içerisindeki tüm satõrlar õ getirir. public DataRow[] Select(string filterExpression); DataTable içerisinden sadece filtrelenen kayõtlar õ getirir. public DataRow[] Select(string filterExpression, string sort); DataTable içerisinden sadece filtrelenen kayõtlar õ, belirtilen sõralamada getirir. public DataRow[] Select(string filterExpression, string sort, DataViewRowState recordStates); DataTable içerisinden DataRowViewState'i belirtilen kay õtlar içerisinden filtrelenen kayõtlar õ, belirtilen sõralamada getirir. Metot içerisinde kullanõlan parametreler ile ilgili olarak; - 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.
Added: Sadece eklenen kayõtlarda CurrentRows: Tabloda o an varolan kayõtlarda Deleted: Sadece silinen kayõtlarda ModifiedCurrent: Değişen kayõtlarda (o an varolan değerleri ile birlikte) ModifiedOriginal: Değişen kayõtlarda (orjinal değerleri ile birlikte) None: Hiçbir kayõtta OriginalRows: Orjinal kayõtlarda (silinen ve değişen kayõtlar dahil) Unchanged: Değişmeyen kayõtlarda Tablo: DataViewRowState enum tipinin alabileceği değerler ve anlamlar õ Select metodunun örnek kullanõmlar õnõ aşağõda bulabilirsiniz. bulabilirsiniz.
150
// Tablodaki tüm kayõtlar õ getirir. DataRow[] satirlar = dtUrunler.Select(); dtUrunler.Select(); // Tablodaki kayõtlarda UrunID bilgisi 5 ve 10 arasõnda olanlar õ getirir. DataRow[] satirlar = dtUrunler.Select("UrunID>5 dtUrunler.Select("UrunID>5 AND UrunID<10"); // Tablodaki kayõtlarda UrunID bilgisi 5 ve 10 arasõndaki kayõtlar õ Fiyat değerleri azalan şekilde getirir. DataRow[] satirlar = dtUrunler.Select("UrunID>5 dtUrunler.Select("UrunID>5 AND UrunID<10", "Fiyat DESC"); // Tabloda o an varolan kayõtlar içerisinde, UrunID bilgisi 5 ve 10 arasõndaki kayõtlar õ, Fiyat değerleri azalan şekilde getirir. DataRow[] satirlar = dtUrunler.Select("UrunID>5 dtUrunler.Select("UrunID>5 AND UrunID<10", "Fiyat DESC", DataViewRowState.CurrentRows); Yukar õdaki ifadelerin tamamõndan dönen sonuç DataRow dizisi şeklindedir. Dizi olarak gelen bu kayõtlar õ bir foreach döngüsü içerisinde 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. foreach (DataRow dr in satirlar) { label1.Text label1.Text += dr["UrunID"] + " - " + dr["Ad"] + " - " + dr["Fiyat"] + "\n"; } Uygulamamõzõn btnSelect butonuna tõklandõğõnda txtWhereCumle textbox'õndan, cmdOrderBy combobox'õndan ve cbDesc checkbox'õndan alacağõ değerlere göre filtrelenen ve sõralanan kayõtlar õ DataGridView kontrolüne aşağõdaki gibi doldurabiliriz. doldurabiliriz. private void btnSelect_Click(object btnSelect_Click(object sender, EventArgs e) { string whereIfade, orderByIfade; whereIfade whereIfade = txtWhereCumle.Text; txtWhereCumle.Text; // WHERE'den sonra gelecek gelecek ifade orderByIfade = cmbOrderBy.SelectedItem.To cmbOrderBy.SelectedItem.ToString(); String(); // ORDER BY'dan sonra gelecek ifade if (cbDesc.Checked) (cbDesc.Checked) orderByIfade += " DESC"; // Tersten sõralama yapõlacaksa ifademize DESC ekliyoruz DataRow[] satirlar = dtUrunler.Select(whereI dtUrunler.Select(whereIfade, fade, orderByIfade); // 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 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 çözebilecek şekilde dizayn edilmiştir. DataTable DataTable dtGecici dt Gecici = dtUrunler.Copy(); dtUrunler.Copy(); dtGecici.Clear(); foreach (DataRow dr in satirlar) { // satirlar sat irlar nesnesindeki nesnesindeki row'lar hala dtUrunler tablosuna ait olduğu için // ImportRow metodu ile satõrlar õ kopyalõyoruz dtGecici.ImportRow(dr); } dgvUrunler.DataSource dgvUrunler.DataSource = dtGecici; dtGecici; // Verileri gride yüklüyoruz. yüklüyoruz. } txtWhereCumle isimli textbox'a arama kriterlerimizi, kriterlerimizi, cmbOrderBy combobox'õna sõralanacak alanõn girişini yaparak, sõralamayõ tersten yapmak istiyorsak cbDesc checkbox'õnõ seçerek istenilen verileri grid içerisine doldurabiliriz. doldurabiliriz.
Şekil: Filtreleme ve S õralama işlemlerinin yapõlmasõ ve sonuçlar õn elde edilmesi Bu yazõmõzda DataTable üzerinde filtreleme ve s õralama işlemlerini gerçekleştirmemizi sağlayan Find ve Select metotlar õnõ derinlemesine derinlemesine incelemeye çal ça lõştõk. Veritabanõndan getirilen aynõ veriler üzerinde sõklõkla sorgulama yapacağõmõz durumlarda (özellikle raporlama, listeleme vb. işlemlerde) veritabanõna sürekli bağlanarak aynõ veriler üzerinde sorgu çalõştõrmak performans ve zaman açõsõndan olumsuz sonuçlar doğurabilir. Bu tip 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 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 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 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 S erver Single-Server Single-Server Deployment kurulumudur. Kurulum Windows Server 2003 - Standart Edition üzerinde yapõlmõştõr.
TEAM FOUNDATION SERVER KURULUMU (I) bölümünde anlatõlan aşamalar sunucu olarak kullanõlacak bilgisayard b ilgisayarda, a, TEAM EXPLORER KURULUMU (II) bölümündeki aşamalar ise Team Foundation Server'a bağlanarak, bu ortak alan üzerinde proje geli ştirecek bilgisayarlarda bilgisayarlarda gerçekleşmelidir. Team Foundation Server ile ilgili olarak daha detayl õ bilgileri daha önceden yazgelistir.com'da yayõnlanmõş olan şu makalelerden elde edebilirsiniz: Team Foundation Server Nasõl Kurulur 1 Team Foundation Server Nasõl Kurulur 2
I. Team Foundation Server Kurulumu Bu kuruluma kuruluma geçmeden önce, Windows W indows Update sitesinden son güncellemeler yapõlmalõdõr. (http://windowsupdate.microsoft.com http://windowsupdate.microsoft.com))
Not: Kurulum boyunca sõklõkla güncelleme işlemleri yapõlacaktõr. Bu nedenle kurulum esnasõnda internete bağlõ olmanõz gerekecektir. Güncelleme işlemleri, zorunlu olmamakla beraber, kurulumun doğru şekilde sonlanabilmesi ve TFS'õn (Team Foundation Foundation Server) düzgün şekilde çalõşabilmesi için tavsiye edilmektedir. Kuruluma geçmeden önce, sunucu olarak kullanacağõmõz (TFS kurulumu yapacağõmõz bilgisayar) sistem üzerinde gerekli kullanõcõlar õ oluşturmamõz gerekecektir. Bu kullanõcõlar, kurulum işlemi sõrasõnda ve kurulum sonrasõnda bazõ işlemleri yapabilmemiz için gerekli olacaktõr. Oluşturulacak kullanõcõlar ve özellikleri aşağõdaki gibi olacaktõr: - TFSSETUP: Kurulum işlemini yapacak olan kullanõcõdõr. Kullanõcõ olarak, Administrator grubunda yer almalõdõr. - TFSSERVICE: SharePoint Services ile ilgili işlemlerde kullanõlacak olan kullan õcõdõr. Güvenlik açõsõndan Administrator grubunda yer almamalõ ve Log on locally yetkisine sahip olmalõdõr. - TFSREPORTS: SQL Server Reporting Reporting Services taraf õndan kullanõlacak olan kullan õcõdõ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. Aşağõdaki kurulumlar yapõlõrken sisteme TFSSETUP kullanõcõsõ ile login olunmasõ gerekmektedir. Önemli başka bir husus ta; kurulumlar õ aşağõdaki sõraya göre yapmamõz, kurulumun başar õlõ bir şekilde bitmesi için gerekli olacaktõr. Şimdi adõm adõm kurulum işlemlerini yapmaya ba şlayalõm.
I.a. IIS Kurulumu - 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) seçilmemelidir) - Kurulum bittikten sonra http://windowsupdate.microsoft.com http://windowsupdate.microsoft.comadresinde adresinden n 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. I.b. SQL Server Kurulumu - 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 developmen de velopmentt 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. Management Tools dõşõndaki tüm bileşenlerde Feature * Client Components’in altõndan Management 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. 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. görüntülenir. Install seçeneğine tõklayarak kuruluma başlayõn.
I.c. SQL SERVER 2005 Hotfix Kurulumu - Bu kurulumdan kurulumdan önce SQL Server 2005 – Service Pack 1 ’in yüklenmesi sağlõklõ olacaktõr. http://go.microsoft.com/fwlink/?LinkId=65988adresinde http://go.microsoft.com/fwlink/?LinkId=65988 adresinden n SQL Server 2005 – Service Pack 1 ‘i yükleyin ve kurulumu yapõn. - Hotfix kurulumu için öncelikle SQL Server Configuration Manager ’i’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 AS2005KB914595-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 ’da SQL Server Browser ’õ Automatic konumda ve çalõşõr durumda olduğunu kontrol edin. Çalõşmõyorsa çalõşõr hale getirmeniz gerekmektedir. gerekmektedir. - SQL Server 2005 Network Configuration ’da Protocols for MSSQLServer ’a ’a tõklayarak TCP/IP‘nin enabled olduğuna emin olun.
I.d. .NET Framework 2.0 Hotfix Kurulumu - Team Foundation Server DVD’sinden KB913393 dizinindeki NDP20-KB913393-X86.exe dosyasõnõ çalõştõr õnõz. Bu şekilde .NET Framework 2.0 Hotfix kurulumunu da tamamlamõş olacaksõnõz.
I.e. SharePoint Services Kurulumu - SharePoint Services Service Pack 2 ile kurulumu yapmak için http://go.microsoft.com/fwlink/?linkid=55087adresindeki http://go.microsoft.com/fwlink/?linkid=55087 adresindeki dosyayõ indiriniz. - Kurulum dosyasõnõ çalõşõtõr õnõz ve Type of Installation sayfasõnda Server Farm seçeneğini seçiniz. Summary ekranõndan Install seçeneğine tõklayarak kurulumu ba şlatõnõz. - Kurulum tamamlandõğõnda Configure Administrative Virtual Server başlõğõnda bir web sayfasõ açõlacaktõr. Bu pencere çõktõğõnda üzerinde hiçbir değişiklik yapmadan kapatõnõz. (Bu
156
sayfa üzerinde hiçbir ayar değişikliliğinin yapõlmamasõ gerekmektedir. SharePoint üzerindeki ü zerindeki gerekli ayarlar õ daha sonradan Team Foundation Server yapacakt õr. Bu sayfanõn açõlmamasõ durumunda http://go.microsoft.com/fwlink/?LinkId=52668 http://go.microsoft.com/fwlink/?LinkId=52668adresini 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 http://windowsupdate.microsoft.com))
I.f. Team Foundation Server S erver Kurulumu - TFS kurulan sisteme TFSSETUP ile login olun. - TFS kurulum DVD’sini takõnõz ve açõlan autorun ekran õndan Install Team Foundation Server ve daha sonra da Single-Server Installation seçeneğini seçin. - Welcome ekranõnda Next’i, sonraki ekrandan I accept the terms of.... seçeneğini seçerek Next seçeneğine tõklayõn. - Kurulum bilgisayar õnõzõn donanõmsal ve yazõlõmsal gereksinimlerini kontrol edip eğer sorun varsa size bildirecektir. bildirecektir. Sorun olmamasõ durumunda Next’e tõklayarak devam edin. - Destination Folder ekranõnda görünen klasörü değiştirmeyin ve Next’i seçin. - Service Account penceresinde domain\TFSSERVICE ile login olun. - Reporting Account sayfasõnda domain\TFSREPORTS ile login olun. - SMTP ve e-posta bilgilerini doldurunuz doldurunuz ve Next’i seçerek kurulum ekranõna geçiniz. - Install’a tõklayarak kuruluma ba şlayõnõz. - Kurulum boyunca TFS sizden bilgisayar õnõzõ yeniden başlatmanõzõ isteyebilir. Böyle bir durumda bilgisayar õnõzõ yeniden başlatõnõz. Sisteme TFSSETUP ile login olmayõ unutmayõnõz! TFS kuruluma kald õğõ yerden devam edecektir.
I.g. Team Foundation Server Kurulumundan Sonra Yapõlacak İşlemler - 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 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. 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 vstfs şeklinde bir kõsõm var ise herhangi problem yok demektir.
II. Team Explorer Kurulumu
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 V isual 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 ku rulu 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: gerekecektir: - Microsoft Office Excel 2003 'ü Complete Install seçeneğini seçerek kurunuz. - Microsoft Office Project Professional 2003 'ü Complete Install seçeneğini seçerek kurunuz. - Windows Update sitesini ziyaret ederek gerekli güncellemeleri yükleyin. (Adres: http://windowsupdate.microsoft.com)) http://windowsupdate.microsoft.com - Office Update sitesini ziyaret ederek gerekli güncellemeleri yükleyin. (http://office.microsoft.com/officeupdate http://office.microsoft.com/officeupdate)) - Control Panel > Add/Remove Programs > Add/Remove Windows Components seçeneğinden Internet Explorer Enhanced Security Configuration (Internet Explorer Arttõr õlmõş Güvenlik Yapõlandõr õlmasõ) seçeneği eğer seçili ise seçimi Next’i seçin ve bu işlemi tamamlayõn. - Team Foundation Server kurulum DVD’sini Team Explorer kurulacak olan bilgisayara takõn ve çalõşan autorun ekranõndan Install Team Explorer ’õ seçin. Setup Wizard’da gerekli seçenekleri seçip Next ile ilerleyerek kurulumu tamamlayõnõz.
III. Visual Studio 2005’ten TFS'a Ba ğlanma Ve Takõm Projesi Oluşturma III.a. Visual Studio 2005'ten Team Foundation Server’a Bağlanma 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 çerçevesinde bir projeye p rojeye dahil olabilir olabilir veya yeni bir proje oluşturabilirsiniz.
III.b. Takõm Projesi Oluşturma 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. 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. Projeni P rojenin n 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.