aspNet

Published on July 2016 | Categories: Documents | Downloads: 118 | Comments: 0 | Views: 2655
of 159
Download PDF   Embed   Report

Comments

Content

ASP.NET ASP.NET AJAX ADO.NET Makaleleri

Uğur UMUTLUOĞLU
www.umutlluogllu.com www.umut uog u.com http://umutlluogllu.bllogspot.com http://umut uog u.b ogspot.com [email protected] ugur.umut uog [email protected]

Son Güncelleme: 18 Mayõs 2008
Bu materyali istediğiniz şekilde dağõtabilir ve sitenizde yayõnlayabilirsiniz.

1

İçindekiler
Önsöz ................................................................................................................................... 3 ASP.NET............................................................................................................................... 4 ASP.NET Web Site Administration Tool ............................................................................ 5 HttpBrowserCapabilities ile Tarayõcõ Bilgilerine Ulaşmak ................................................... 8 AdRotator ile Reklam Yönetim Sistemi Geliştirmek.......................................................... 12 View State ile Durum Yönetimi ........................................................................................ 19 ASP.NET 2.0 - Sayfa Direktifleri (Page Directives) .......................................................... 29 ASP.NET 2.0 - Performans Yönetimindeki Yenilikler ....................................................... 38 GridView'e Programatik Veri Bağlamada Sayfalama ve Sõralama İşlemleri..................... 49 GridView Kayõtlarõnõ Okumak ve Metin Dosyasõna Aktarmak........................................... 54 GridView'deki Kayõtlarõ Excel Dosyasõna Aktarmak.......................................................... 61 ASP.NET 3.5 ile Gelen Yenilikler..................................................................................... 67 TreeView'da Veritabanõyla ve XML Dosyalarla Çalõşmak................................................. 74 Site Navigasyonu Hakkõnda Bilinmeyenler....................................................................... 84 TreeView Kontrolüne Kullanõcõ İsteğine Göre Veri Ekleme .............................................. 97 ASP.NET AJAX .................................................................................................................107 ASP.NET ATLAS............................................................................................................108 AJAX: Asenkron JavaScript ve XML ...............................................................................115 ASP.NET AJAX Uygulamalarõ ile İlgili Sorunlar ve Çözümleri .........................................122 AJAX Uygulamalarõnda UpdatePanel Kullanõmõ..............................................................126 ASP.NET AJAX’a Giriş ...................................................................................................133 Diğer Konular....................................................................................................................140 Excel Dosyasõndaki Bilgilere Ulaşmak ............................................................................141 Datatable ile Sõralama ve Filtreleme İşlemleri .................................................................145 Adõm Adõm Team Foundation Server Single-Server Kurulumu .......................................154

2

Önsöz
Bu e-kitapta ASP.NET, ASP.NET AJAX ve ADO.NET gibi .NET teknolojileri ile ilgili yazmõş olduğum makaleleri topluca bulabilirsiniz. Şimdilik üç ayrõ kategoride yer alan makaleler, İçindekiler kõsmõnda yazõm tarihlerine göre sõralanmõştõr. Yine her kategorinin başlangõcõnda, o kategoride yer alan makaleler ile ilgili anahtar kelimeler yer almaktadõr. Kitapta görmüş olduğunuz makalelerin çevrimiçi versiyonlarõnõ yazgelistir.com ve msakademik.net 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. Bu kitabõ sitenizden veya forumlardan paylaşabilirsiniz.

Uğur UMUTLUOĞLU

3

ASP.NET

Anahtar kelimeler
AdRotator Caching Performans ViewState

ASP.NET 2.0
Excel

ASP.NET 3.5

ASP.NET AJAX LINQ

GridView

HttpBrowserCapabilities

Sayfa Direktifleri

SqlCacheDependency

Site Navigasyonu SiteMap TreeView Veritabanõ Örnekleri
Xml

Website Administration Tool

4

ASP.NET Web Site Administration Tool
16 Mart 2006 Bu makalede sizlere Visual Studio 2005 ile gelen ve ASP .NET uygulamalarõnda kullanabileceğimiz yeniliklerden birisi olan Web Site Administration Tool'u anlatmaya çalõşacağõm. Web Site Administration Tool'un aslõnda bize çok büyük yenilikler getirmediğini, ancak uygulamamõzda yapacağõmõz bazõ işlemleri hõzlõ, pratik ve derli toplu yapmamõzõ sağlayan bir araç olduğunu söyleyerek başlayalõm. Bildiğiniz gibi ASP .NET ile birlikte gelen web.config dosyasõnda yaptõğõmõz ayarlarõ uygulamamõzõn genelinde kullanarak işimizi bir noktadan, daha az kod yazarak, hõzlõ ve güvenli bir şekilde yapabiliyorduk. web.config ile birlikte daha hõzlõ yaptõğõmõz bu işlemleri, Web Site Administration Tool ile hiç kod yazmadan, özel dizinlerde elle web.config dosyalarõ oluşturmadan çok daha hõzlõ bir şekilde yapabiliyoruz. Aslõnda bu aracõn temel mantõğõ da bu. Sizin web.config dosyalarõnda XML tabanlõ kodlarõ yazarak yapmanõz gereken ayarlarõ, bir web arayüzüyle kolay ve pratik bir şekilde yapmanõzõ sağlamak. Web Site Administration Tool'u açmadan önce önemli sayõlabilecek bir noktayõ belirtmek istiyorum. Solution Explorer'dan uygulamamõzõn içerisinde yer alan App_Data klasörüne bakacak olursak, bu klasörün altõnda herhangi bir dosya olmadõğõnõ göreceğiz. Tabii ki az sonra buraya bazõ dosyalar gelecek. Web Site Administration Tool'a Visual Studio 2005'e yeni eklenen bir menü olan Website menüsünün altõndaki ASP .NET Configuration'dan ulaşabildiğimiz gibi Solution Explorer penceresinin en sağõndaki ASP .NET Configuration kutucuğuna tõklayarakta ulaşabiliyoruz. ASP .NET Development Server aktif hale geliyor, tarayõcõmõzda yeni bir pencere açõlõyor ve resimdeki gibi bir sayfayla karşõlaşõyoruz.

Sayfadan yapabileceğimiz işlemlere özetle bakacak olursak; Security linkinden - Authentication modunu değiştirebilir

5

- Kullanõcõ oluşturabilir ve yönetebilir - Rol oluşturabilir ve yönetebilir - Kullanõcõlarõ rollerle ilişkilendirebilir - Rollerin dizinlere erişim haklarõnõ yönetebilirsiniz. Application linkinden - Uygulama genelinde kullanõlabilecek (web.config de tutulacak) değerleri oluşturabilir ve yönetebilir - Uygulamada e-posta göndermek için gerekli olan SMTP ayarlarõnõ yönetebilir - Hata sayfalarõ ayarlarõ yapõlabilir - Debugging ve tracing işlemleri ile ilgili ayarlarõ yapabilirsiniz. Provider linkinden - Uygulamanõzda kullanacağõnõz data sağlayõcõsõ ile ilgili ayarlarõ yapabilir - Membership ve role sağlayõcõlar için farklõ data sağlayõcõsõ belirleyebilirsiniz. Kullanõmõnda çok zorluk çekilmeyecek, basit ve kullanõşlõ bir araç. İsterseniz bu aracõ kullanarak sitemizde kullanõcõlar ve roller oluşturalõm, bunlarõ aralarõnda ilişkilendirelim ve rollerin dizine erişim haklarõnõ ayarlayõp web.config dosyalarõnda ne gibi değişiklikler olduğunu gözlemleyelim. 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 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 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. (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. <?xml version="1.0" encoding="utf-8"?> <configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0"> <system.web> <authorization> <allow roles="editor" /> <deny users="?" /> </authorization> </system.web> </configuration>

7

HttpBrowserCapabilities ile Tarayõcõ Bilgilerine Ulaşmak
25 Nisan 2007 Web sayfamõza bağlanan istemcilerin kullandõklarõ tarayõcõlarõn (web browser) tipi, versiyonu, eklentileri, özellikleri farklõ olabilmekte ve bu farklõlõklar bazõ durumlarda sorunlar oluşturabilmektedir. Örneğin bir tarayõcõda düzgün ve sorunsuz görüntülenen bir sayfa, başka bir tarayõcõda hatalõ olarak görüntülenebilmektedir. Bu noktada uygulama geliştirilirken tarayõcõ bazlõ olarak bazõ kontrollerin yapõlmasõ ve buna göre de istemciye uygun içeriklerin gönderilmesi gerekebilir. Bir web uygulamasõ geliştirilirken, bazõ durumlarda istemcinin tarayõcõsõ hakkõnda bilgiler elde etmek ve bu bilgiler doğrultusunda işlemler yapõlmak istenilebilir. ASP.NET web uygulamalarõnda bu tip işlemleri kolay bir şekilde yapmamõzõ sağlayan HttpBrowserCapabilities sõnõfõ bulunmaktadõr. HttpBrowserCapabilities sõnõfõndan oluşturacağõmõz bir nesne örneği ile sayfamõza bağlanan ziyaretçinin kullandõğõ tarayõcõ ile ilgili bilgilere erişebilir ve bu bilgilere göre farklõ sayfalara yönlendirme yapmak, farklõ içerikler görüntülemek gibi işlemler yapabiliriz. Yine sitemize bağlanan ziyaretçilerin tarayõcõlarõnõn istatistiklerini veritabanõnda tutmak için de bu sõnõfõ etkili bir şekilde kullanabiliriz. 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 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õ ActiveXControls Beta Browser İşlevi Tarayõcõnõn ActiveX desteği olup olmadõğõ hakkõnda bilgi verir. (bool tipinde değer döndürür) Tarayõcõnõn beta sürümü olup olmadõğõ hakkõnda bilgi verir. (bool tipinde değer döndürür) Varolan tarayõcõ bilgilerini verir. (string tipinde değer döndürür)

8

ClrVersion Cookies Crawler EcmaScriptVersion Frames IsMobileDevice JavaScript VBScript JScriptVersion Platform SupportsCallback Type Version Win16 Win32

İstemcide kurulu olan .NET Framework sürümünü getirir. (string değere dönüştürülerek kullanõlabilir) Tarayõcõnõn cookie desteği olup olmadõğõnõ verir. (bool tipinde değer döndürür) Bağlanan tarayõcõnõn crawler (Google, Yahoo gibi site indeksleyicileri) olup olmadõğõnõ verir. (bool tipinde değer döndürür) Tarayõcõnõn desteklediği ECMA script versiyonunu verir. (string değere dönüştürülerek kullanõlabilir) Tarayõcõnõn HTML frame desteği olup olmadõğõnõ verir. (bool tipinde değer döndürür) 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 ö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) Tarayõcõnõn desteklediği Jscript versiyonunu verir. (string değere dönüştürülerek kullanõlabilir) Ziyaretçinin bulunduğu platform ile ilgili bilgileri verir. (string tipinde değer döndürür) Tarayõcõnõn Client Script CallBack desteği olup olmadõğõnõ verir. (bool tipinde değer döndürür) Tarayõcõnõn ismini ve tipini verir. IE7 gibi. (string tipinde değer döndürür) Tarayõcõnõn versiyon numarasõnõ verir. (bool tipinde değer döndürür) İstemcinin Win16 tabanlõ bir bilgisayarda çalõşõp çalõşmadõğõnõ verir. (bool tipinde değer döndürür) İstemcinin Win32 tabanlõ bir bilgisayarda çalõşõp çalõşmadõğõnõ verir. (bool tipinde değer döndürür)

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 nesnesini // aynõ tipten değer getiren Request.Browser özelliği aracõlõğõyla oluşturmalõyõz. HttpBrowserCapabilities tarayici = Request.Browser; Response.Write("Tarayõcõ beta sürüm mü? : " + tarayici.Beta + "<br>"); Response.Write("Tarayõcõnõn cookie desteği var mõ? : " + tarayici.Cookies + "<br>");

9

Response.Write("Tarayõcõ mõbil bir cihazda mõ çalõşõyor? : " + tarayici.IsMobileDevice + "<br>"); Response.Write("Tarayõcõnõn Ecma script versiyon numarasõ : " + tarayici.EcmaScriptVersion + "<br>"); Response.Write("Tarayõcõnõn çalõştõğõ işletim sistemi : " + tarayici.Platform + "<br>"); Response.Write("Tarayõcõnõn tipi: " + tarayici.Type + "<br>"); } 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 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.

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 sõnõfõnõ kullanarak site ziyaretçilerinin tarayõcõlarõ ile ilgili istatistikleri tutabiliriz. Yine bu özellikleri kullanarak tarayõcõnõn tipine göre farklõ

10

içerikler sunabilir, farklõ sayfalara yönlendirme işlemleri yapabilir. Örneğin, sitemiz ziyaret edecek kullanõcõlarõn masaüstü bilgisayarlardaki tarayõcõlarõ kullanabilecekleri gibi, mobil bir bilgisayardan da erişebilecekleri olasõ bir durumdur. Mobil tarayõcõlar ise normal bir tarayõcõ kadar işlevsel olmadõklarõ için sayfalarõmõzdaki içeriklerin bazõlarõnõ görüntüleyemez veya hatalõ görüntüler. Böyle bir durum karşõsõnda mobil bir tarayõcõ için farklõ sayfalar tasarlamak ve gelen kullanõcõlarõ bu sayfalara yönlendirmek isteyebiliriz. Aşağõdaki gibi hazõrlanan bir projenin anasayfasõ içerisinde gerekli kontroller ve yönlendirmeler yapõlõrsa istenildiği gibi kullanõcõnõn doğru içeriğe erişmesi sağlanabilir. Yine kullanõcõnõn tarayõcõsõnõn Cookie, JavaScript gibi sitenin işleyişi açõsõndan önem taşõyan bileşenleri desteklememesi durumunda, site düzgün bir şekilde kullanõlamayacağõ için kullanõcõya bilgilendirici mesajlar verilebilir.

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 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. <?xml version="1.0" encoding="utf-8" ?> <Advertisements> <Ad> <AlternateText>NedirTV</AlternateText> <ImageUrl>images/nedirtv.jpg</ImageUrl> <NavigateUrl>http://www.nedirtv.com</NavigateUrl> <Impression>5</Impression> <Keyword>video</Keyword> </Ad> <Ad> <AlternateText>MS Akademik</AlternateText> <ImageUrl>images/msakademik.gif</ImageUrl> <NavigateUrl>http://www.msakademik.net</NavigateUrl> <Impression>3</Impression> <Keyword>makale</Keyword> </Ad> <Ad> <AlternateText>Yazgeliştir</AlternateText> <ImageUrl>images/yazgelistir.gif</ImageUrl> <NavigateUrl>http://www.yazgelistir.com</NavigateUrl> <Impression>5</Impression> <Keyword>makale</Keyword> </Ad> </Advertisements> Bu şekilde hazõrlanan bir XML dosyasõ AdRotator kontrolünün AdvertisementFile özelliğine dosya yolu belirtilerek bağlanõp kullanõlabilir. Dosyadaki her <ad> boğumu bir reklamõ tanõmlar. Buradaki <AlternateText> resmin alt metnini, <ImageUrl> resim dosyasõnõn yolunu ve adõnõ, <NavigateUrl> ise resme tõklandõğõnda hangi URL'ye gidileceğini belirler. XML

12

dosyasõ içerisinde tanõmlõ olan <Impression> boğumundaki değer ise, o reklamõn gösterilme sõklõğõnõ belirlemektedir. Bu sõklõk herhangi bir yüzdesel oran değil, diğer reklamlara göre ne kadar sõklõkta görüntüleneceğidir. (Örneğin Impression değeri 10 olan bir reklam, Impression değeri 5 olan bir reklama göre yaklaşõk 2 kat fazla gösterilecektir.) <Keyword> alanõnda ise o reklama ait anahtar kelime veya kelimelerin tanõmlamasõ yapõlõr. AdRotator kontrolünün KeywordFilter özelliğine verilecek anahtar kelime ile XML dosyasõndaki <Keyword> alanõndaki kelimenin eşleşmesi durumunda, reklamõn/reklamlarõn seçilmesi ve görüntülenmesi sağlanõr. Bu şekilde basit bir XML dosyasõna tanõmlanan reklam bilgileri ile site içerisinde kullanõlabilecek reklam dönüşüm sistemi oluşturabiliriz. XML ile AdRotator kullanõm oldukça pratik ve kolaydõr. Fakat burada bizleri kõsõtlayõcõ bazõ özellikler olduğu gibi, yine yapõlmasõnõ isteyebileceğimiz bazõ ek işlemleri de gerçekleştirmekte de bazõ sõkõntõlarla karşõlaşabiliriz. Reklamlarõ dinamik şekilde değiştirme işlemi gerçekleştirmek için her seferinde XML dosyasõnõ açõp değişiklikler yapmak, aslõnda bir programcõ için kõsõtlayõcõ bir unsurdur. Bu noktada reklamlarõ XML dosyasõnda saklamak yerine veritabanõnda tutmak, özellikle sõklõkla güncellenecek reklam bilgileri için programcõya veya site yöneticisine dinamik bir yapõ ve dolayõsõyle kolaylõk sağlayacaktõr. Yine reklamlarla ilgili olarak; bir reklamõn kaç kez görüntülendiği, o reklama kaç kez tõklandõğõ gibi istatistiklerin tutmakta böyle bir sistemde oldukça zengin bir işleyiş sunacaktõr. Yukarõda 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.

13

Resim: Reklamlar Tablosu Tablomuzdaki alanlarõ isimlendirirken AdRotator'a alanlarõ kolay bir şekilde tanõtabilmek için AlternateText, ImageUrl, NavigateUrl, Impression ve Keyword kõsõmlarõnõ XML dosyasõndaki aynõ isimlerle adlandõrmamõz gerekecektir. Bu şekilde tablo verileri AdRotator'a bağlandõğõnde alanlar otomatik olarak algõlanacaktõr. ID tablonun primary key'i, Link reklam URL'si, Durum reklamõn aktif olup olmadõğõ, Goruntuleme reklamõn görüntülenme sayõsõnõ ve Tiklama reklama kaç kez tõklanõldõğõ bilgilerini taşõyacak alanlardõr. Bu şekilde tasarladõğõmõz tablo içerisine artõk verilerimizi ekleyerek, AdRotator kontrolüne bu verileri nasõl bağlayabileceğimizi görelim.

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 bulunmaktadõr. protected void Page_Load(object sender, EventArgs e) { // Ornek isimli veritabanina baglanti cumlesi olusturuluyor. SqlConnection conn = new SqlConnection("data source=.; initial catalog=Ornek;

14

integrated security=true")) // Tablodan reklam bilgilerini getirecek sorgu cumlesi hazirlaniyor SqlCommand comm = new SqlCommand("SELECT AlternateText, ImageUrl, NavigateUrl, Impression FROM Reklamlar WHERE Durum='True'", conn); DataTable dt = new DataTable(); SqlDataAdapter da = new SqlDataAdapter(comm); da.Fill(dt); // DataTable nesnesine eklenen veriler, AdRotator'a veri kaynagi olarak gosteriliyor ve veriler yukleniyor AdRotator1.DataSource = dt; AdRotator1.DataBind(); }

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 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 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 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(object sender, AdCreatedEventArgs e) { SqlConnection conn = new SqlConnection("data source=.; initial catalog=Ornek; integrated security=true"); string id = e.NavigateUrl; // 15. karakterden sonraki deger bize reklamin ID degerini verecektir. reklam.aspx?ID=3 icerisinden 3 degeri gibi... id = id.Substring(15); // id degeri alinan reklamin bulundugu satirda Goruntuleme alanini 1 arttirarak guncelliyoruz SqlCommand comm = new SqlCommand("UPDATE Reklamlar SET Goruntuleme=Goruntuleme+1 WHERE ID=@ID", conn); comm.Parameters.AddWithValue("@ID", id); conn.Open(); comm.ExecuteNonQuery(); conn.Close(); } ! NOT: Buradaki id.SubString(15) ifadesi 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 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 sağlayacağõz. reklam.aspx.cs sayfasõnõn Page_Load metodu içerisinde öncelikli olarak 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"]; SqlConnection conn = new SqlConnection("data source=.; initial catalog=Ornek; integrated security=true"); // Reklamõn tõklanma sayõsõ güncelleniyor SqlCommand comm = new SqlCommand("UPDATE Reklamlar SET Tiklama=Tiklama+1 WHERE ID=@ID", conn); 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.AddWithValue("@ID", reklamID); conn.Open(); string url = selectComm.ExecuteScalar().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 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 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 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 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 bir sayfa içerisindeki kontrollerin değerleri, sayfa post edildiğinde kaybolurdu ve tekrar elde etmek için ekstra işlemler yapmamõz gerekirdi. ASP.NET'e geçiş yaptõğõmõz ilk zamanlarda en çok dikkatimizi çeken durumlardan birisi de bir formu post ettiğimizde form üzerindeki verilerin kaybolmamasõydõ. İşte ASP.NET uygulamalarõnda bizi bu sõkõntõdan kurtaran ve post işleminden sonra da verilerin form üzerinde saklanmasõnõ sağlayan View State nesnesidir. Dilerseniz View State nesnesinin uygulamalarda bize ne gibi bir kolaylõk sağladõğõnõ daha net bir şekilde görebilmek için şu basit örneği gerçekleştirelim. Açtõğõmõz bir sayfaya iki tane Label kontrolü ve iki tane Button kontrolü ekleyelim. Label kontrollerinden bir tanesinin EnableViewState özelliğini true, diğerinin ise bu özelliğini false olarak ayarlayalõm. (EnableViewState özelliği bir kontrolün özelliklerinin ViewState içerisinde taşõnõp taşõnmamasõ durumunu belirler. Makalemizin ilerleyen kõsõmlarõnda EnableViewState özelliğini tekrar inceliyor olacağõz.) Butonlardan bir tanesinin Click eventi içerisine aşağõdaki ifadeleri ekleyelim. Diğer butonda ise herhangi bir değişiklik yapmayacağõz, sadece postback yapmak amaçlõ kullanacağõz. 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 sadece formda bulunan input elementleri değil, GridView, DetailsView ve Calendar diğer ASP.NET sunucu kontrollerinin özellikleri de 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 nesnesinin içeriği Görüldüğü gibi bilgiler HTML kodlarõ içerisinde __VIEWSTATE adõ verilen hidden bir input elementi bulunmaktadõr. Bir ASP.NET sayfasõnda varsayõlan olarak her zaman __VIEWSTATE değeri saklanmaktadõr. Base64 formatõ kullanarak şifrelenen veriler sayfa içerisinde saklanõr ve sayfanõn postback ile tekrar yüklenmesi durumunda gerekli bilgiler çözümlenerek sayfa içerisinde kullanõlõr. Yukarõdaki resimde seçili olarak tutulan View State değerine dikkat edelim. Adõm-2: Sayfamõzdaki button'un Text özelliğini Click, label'õn Text özelliğini de Hello olarak değiştirelim. Sayfayõ çalõştõrdõktan sonra tekrar HTML kodlarõ içerisindeki __VIEWSTATE değerini kontrol edelim.

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. Bunun sebebi şu anda View State içerisinde sadece sayfamõzdaki kontrollerin hiyerarşik olarak diziliminin tutulmasõ ve bizim Design aşamasõnda yapmõş olduğumuz değişikliklerin tutulmamasõdõr . Yani kontrolün özelliklerinde belirlediğimiz atamalar direkt olarak HTML kodlarõ içerisinde <input type="submit" name="Button1" value="Click" ... şeklinde tutulacağõ için bu bilgilerin __VIEWSTATE'e yazõlmasõna gerek yoktur. Zaten View State'in en temel kullanõm amaçlarõndan biri de Design aşamasõnda belirlenen kontrol özelliklerini saklamasõ değil, form üzerinde Postback işlemi yapõldõktan sonra değişen kontrol değerlerinin taşõnmasõnõ ve sayfa tekrar yüklendiğinde bu verilerin kaybolmamasõnõ sağlamaktõr. Dilerseniz son cümlede bahsettiğimiz olayõ Adõm-3'te görelim. Adõm-3: Aşağõdaki kod örneğinde görüldüğü gibi, Button'un Click olayõ (event) gerçekleştiğinde lblIcerik'in Text özelliğini ASP.NET olarak değiştirelim. Sayfayõ çalõştõrdõktan sonra buttona tõklayarak Click eventini gerçekleştirelim ve Postback ile sayfayõ tekrar elde edelim. Yeniden oluşan sayfanõn kodlarõna bakacak olursak aşağõdaki gibi __VIEWSTATE'in içeriğinin değiştiğini görebiliriz. protected void Button1_Click(object sender, EventArgs e) { lblIcerik.Text = "ASP.NET"; }

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 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 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 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. 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 küçültmüş olsamda, __VIEWSTATE'in oldukça fazla yer kapladõğõ aşina bir şekilde görünmektedir. Yine sayfanõn HTML kodlarõnõ ayrõ bir dosyaya, __VIEWSTATE içerisindeki metinsel kõsmõ da farklõ bir dosyada kaydedip aralarõndaki farkõ kõyaslayacak olursak __VIEWSTATE değerinin sayfa içerisinde oldukça fazla yer kapladõğõnõ göreceksiniz. Örneğin benim hazõrladõğõm bu örnekte sayfanõn tamamõ 6.66 KB, sadece

23

__VIEWSTATE içerisindeki değer ise 2.85 KB yer kaplamaktadõr. Yani View State'de saklanan veri, boyut olarak sayfanõn neredeyse yarõsõnõ kaplamaktadõr. Burada oluşturulan View State değeri her Postback işlemi gerçekleştiğinde sunucuya gönderileceği ve her sayfa oluşumunda da istemciye getirileceği için sürekli olarak sunucu-istemci arasõnda fazladan veri transferi söz konusu olacaktõr. İşte bu noktada uygulamayõ geliştiren kişi olarak bize önemli bir performans ayarlamasõ görevi düşmektedir. GridView vb. bir kontrolün View State içerisinde saklanmasõ, sayfanõn düzgün bir biçimde çalõşmasõ için gerekli midir, yoksa gereksiz midir? Bir başka söylemle; sayfa, Postback olduğunda önceki halinde bulunan verileri hatõrlamaya ihtiyacõ var mõdõr, yok mudur? Eğer cevabõmõz "Hayõr, bu sayfanõn tekrar oluşturulmasõ esnasõnda, önceki halindeki GridView vb. bir nesnenin verisinin taşõnmasõna gerek yok" ise, bu noktada sayfanõn sunucu-istemci arasõnda daha hõzlõ şekilde çalõşabilmesi bu değerlerin View State içerisinde saklanmasõnõ engellememiz gerekmektedir. ASP.NET sunucu kontrollerinin tamamõnda EnableViewState adõnda bir özellik bulunmaktadõr. Bu özellik kontrolün postback işlemi sonucunda değişen değerlerinin View State içerisinde saklanõp saklanmayacağõnõ belirler. bool tipinden bir değer alabilen EnableViewState özelliğinin varsayõlan değeri true'dur. EnableViewState değerinin true olmasõ, kontrolün özelliklerinin View State içerisinde saklanõr, false olmasõ durumunda ise saklanmaz. Eğer bir kontrolün özelliklerinin View State içerisinde taşõnmasõnõ istemiyorsanõz, o kontrolün EnableViewState özelliğini false olarak ayarlamanõz gerekecektir. Aşağõdaki örnek kod parçasõnda bir GridView kontrolünün EnableViewState özelliğinin kapatõlmõştõr. <asp:GridView ID="GridView1" runat="server" EnableViewState="False"></asp:GridView>

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 özelliğini kapatma işlemini kontrolün EnableViewState özelliği üzerinden gerçekleştirebileceğimiz gibi, bir sayfa içerisindeki tüm kontrollerin ViewState özelliğini de sayfamõzõn Page direktifi 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. <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" EnableViewState="false" %>

25

protected void Page_Load(object sender, EventArgs e) { 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. 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. Indeksleyiciler aracõlõğõyla içerisinde key-value çiftleri taşõ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. 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"]; DataTable dtTest = (DataTable)ViewState["tablo"]; Görüldüğü gibi, ViewState içerisinde sakladõğõmõz değerler object tipinde saklanacağõ için sayfa içerisinde bu verilere erişirken gerekli dönüşüm (cast) işlemlerini de gerçekleştirmek gerekecektir. ViewState içerisinden saklanan bir değeri çõkarmak için Remove metodu, programatik yollarla eklenen tüm verileri çõkarmak ise Clear metodu kullanõlabilir. Aşağõda bu iki metodun kullanõmõ gösterilmiştir. ViewState.Remove("tablo"); // tablo isimli nesne 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 de çok kolay olacaktõr. (Internette ViewState Decoder şeklinde bir arama yapacak olursanõz ViewState değerlerini çözümleyen çok sayõda araç ile karşõlaşabilirsiniz.) Eğer ViewState içerisinde gizli bir bir güvenlik açõğõna sebebiyet verebilir. Bundan dolayõ ViewState'in şifrelenmiş bir şekilde veri saklamasõna güvenerek, bir kullanõcõ veya site için güvenlik sorununa yol açabilecek verileri taşõmamalõyõz. Peki ViewState'de şifrelenerek taşõnan bu verileri biraz daha güvenli bir biçimde saklamak mümkün olabilir mi? MAC (Machine Authentication Check) adõ verilen bir yapõ aracõlõğõyla ViewState nesnesinin kullanõcõ tarafõndan değiştirilip değiştirilmediği ASP.NET sayfasõ tarafõndan algõlanabilmekte ve kullanõcõya hata gönderilebilmektedir. Bir ASP.NET sayfasõnõn MAC mekanizmasõ bu tip güvenlik nedenleriyle varsayõlan olarak açõk tutulmakta ve sayfa postback işlemine tabi tutulduğunda sunucu tarafõnda sayfanõn asõl ViewState değeri ile o an kendisine gelen ViewState değerlerini karşõlaştõrõp eğer farklõlõk varsa; yani ViewState nesnesi değiştirilmiş ise kullanõcõya hata gönderilecektir. Bu ayarõn açõk bõrakõlmasõ bahsettiğimiz gibi güvenlik açõsõndan gereklidir. Fakat bu durumda sayfa üzerinde postback işlemi yapõldõğõnda sunucu tarafõnda ekstra kontrol işlemleri yapõlacağõnõ ve performans açõsõndan bazõ kayõplarõmõz olacağõnõ da unutmamak gerekir. Eğer sayfada ViewState'de taşõnan değerlerin kullanõcõ tarafõndan değiştirilmesinin güvenlik açõsõndan bir sakõncasõ yok ise, bu özelliği kapatmak isteyebiliriz. Sayfa bazõnda bu özelliği kapatmak istiyorsak Page direktifini, site genelinde kapatmak istiyorsak web.config dosyasõnõ kullanabiliriz. Aşağõdaki örneklerde sadece bir sayfa içerisinde ve web.config dosyasõ içerisinde eklenecek kodlar görülmektedir. <%@ Page Language="C#" AutoEventWireup="true" EnableViewStateMac="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<system.web> ..... ..... <pages enableViewStateMac="false"></pages>

27

..... </system.web> Bu yazõmõzda, durum 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 - Sayfa Direktifleri (Page Directives)
26 Ağustos 2007 Sayfa direktifleri, ASP.NET uygulamalarõ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 direktifleri 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õ 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 beri tüm sayfalarda kullanõlmaktadõr. ASP.NET 2.0 ile birlikte gelen bazõ yeni dosya tipleri (Master Sayfalar gibi) ve çalõşma mekanizmalarõ (CrossPage Postback gibi) ile birlikte, yeni sayfa direktifleri de ASP.NET'in yapõsõna eklenmiştir. Bu makalemizde bir sayfada kullanõlabilecek tüm direktifleri detaylõ bir şekilde ele alõyor olacağõz. Aşağõdaki listede ASP.NET sayfalarõnda kullanõlabilecek sayfa direktiflerinin listesi bulunmaktadõr. 1. Page 2. Assembly 3. Control 4. Implements 5. Import 6. Master 7. MasterType 8. OutputCache 9. PreviousPageType 10. Reference 11. Register Aslõnda listenin ilk sõrasõnda gördüğümüz Page direktifi bize oldukça tanõdõk gelecektir. Zira her .aspx uzantõlõ sayfanõn HTML kodlarõnõn en üst kõsmõnda bulunan Page direktifi üzerinde değişiklik yapmasak dahi ne amaçla kullanõldõğõnõ az-çok bilmekteyiz. Page direktifinin kullanõmõnõ şöyle bir bakacak olursak; <% @Page ...... %> şeklinde bir tanõmlamaya sahip olduğunu görürüz. Aslõnda bu tanõmlama tüm sayfa direktifleri için geçerli bir tanõmlama şeklidir. Yukarõdaki listede gördüğünüz 11 sayfa direktifi <% @DirektifAdõ şeklinde başlar, devamõnda gerekli niteliklerine (attribute) atamalar yapõlarak ayarlamalar yapõlõr ve %> ifadesi ile de direktifin sonlandõrõldõğõ derleyiciye bildirilir. Burada görülen <% %> ifadeleri asp söz diziminde, sunucu tarafõnda çalõştõrõlacak etiket anlamõna gelmekte, @ işareti ise çalõştõrõlacak ifadenin bir sayfa direftifi ifadesi olduğunu belirtir. Direktif içerisinde ise gerekli tanõmlamalar NitelikAdõ="Değeri" şeklinde yapõlacaktõr.

29

Dilerseniz sayfa direktiflerinin kullanõmõnõ, gerekli ve önemli nitelikleri ile birlikte tek tek ele alalõm.

1. Page Direktifi
Page direktifi ASP.NET sayfalarõnda kullanõlan en temel ve önemli direktiftir. İçerisinde yapõlan tanõmlamalar ile bulunduğu sayfanõn derleyici tarafõndan nasõl, ne şekilde ele alõnacağõnõ ve hangi özelliklerle birlikte derlenip çalõştõrõlacağõnõ belirler. Page direktifi zorunlu olmamakla birlikte, tüm .aspx sayfalarõnda bulunmaktadõr. Page direktifi ile birlikte kullanõlacak önemli nitelikler (attribute) aşağõda bulunmaktadõr. - Async: Sayfanõn asenkron şekilde çalõşmasõnõ belirler. true değeri alõrsa sayfa asenkron şekilde çalõşabilir hale gelir, false değer aldõğõnda senkron şekilde çalõşõr. - AutoEventWireup: Sayfanõn yaşam döngüsü içerisinde olaylarõ (event) için tanõmlanmõş olan metot isimlerinin kullanõlõp kullanõlmayacağõnõ belirler. Eğer true değeri alõrsa Page_Init, Page_Load, Page_PreRender gibi önceden tanõmlanmõş metot isimleri olaylara bağlanarak kullanõlõr. Eğer false değeri alõrsa kullanõcõ kendisi olaylara farklõ metot isimleri bağlayabilir. Varsayõlan değeri true'dur. - CodeFile: Sayfanõn code-behind dosyasõnõ belirler. Yani aspx sayfasõ çalõştõrõldõğõnda hangi kod sayfasõ ile birlikte derleneceği bu nitelik ile belirlenir. Default.asp.cs gibi. - Culture: Sayfanõn para birimi, tarih ve ölçü birimleri gibi kültür (culture) bilgilerinin hangi dile göre getirileceğini belirler. - UICulture: Sayfanõn görsel arayüzündeki dile göre değişebilen içeriklerin sayfa oluşturulduğunda hangi dil kullanõlarak üretileceğini belirler. - EnableTheming: Site genelinde tema ayarlamalarõ açõk ise, temalandõrma işleminin sayfaya uygulanõp uygulanmayacağõnõ belirler. Eğer web.config'den uygulama için bir tema ayarlamasõ yapõlmõş ise ve bu nitelik true değerini taşõrsa tema sayfaya uygulanõr, false değerini taşõrsa tema sayfaya uygulanmaz. - EnableViewState: Sayfa içerisindeki kontrollerin PostBack işlemi sonucunda değişen özelliklerinin ViewState nesnesi içerisinde taşõnõp taşõnmayacağõnõ belirler. true değeri alõrsa sayfadaki bütün kontrollerin özellikleri ViewState'de taşõnõr, false değeri alõrsa taşõnmaz. Varsayõlan değeri true'dur. - ErrorPage: Sayfada hata oluşmasõ durumunda, sayfanõn hangi hata sayfasõna yönlendirileceğini belirler. - Inherits: Sayfanõn compile işlemi yapõlõrken hangi sõnõftan (class) kalõtõlacağõnõ ve hangi sõnõfõn örnekleneceğini belirler. Varsayõlan olarak sayfanõn code-behind dosyasõnda yazõlan sõnõf adõ, yani dosya ile aynõ ismi taşõyan sõnõf adõ bu değere atanõr. Default2.aspx sayfasõnda Default2 gibi. - Language: Sayfanõn hangi .NET destekli dil ile yazõldõğõnõ belirler. C# dilinde yazõlmõş ise C#, VB.NET dilinde yazõlmõş ise VB gibi. - MasterPageFile: Sayfa eğer bir master sayfadan türetilmiş ise, türetilen master sayfanõn adõ atanõr. SiteMaster.master isimli master sayfadan türetilen sayfa için SiteMaster.master bilgisini taşõr. - MaintainScrollPositionOnPostback: Sayfanõn PostBack işlemi sonucunda yenilenmesi durumunda, sayfanõn otomatik olarak kullanõcõnõn son olarak konumlandõğõ yere getirilmesi işlemini yapar. Yani kullanõcõ scroll bar ile sayfayõ aşağõya doğru hareket ettirip, ardõndan da sayfayõ yenilerse, yenileme işlemi sonrasõnda tarayõcõ sayfanõn en üstüne değil de

30

kullanõcõnõn son olarak kaldõğõ kõsma konumlanõr. true değeri alõrsa burada bahsedildiği gibi davranõr. false değeri almasõ durumunda ise yenileme işlemi sonunda sayfanõn en üstüne gelinir. - Theme: Sayfanõn App_Themes klasöründe oluşturulmuş site şemalarõndan birini uygulamasõnõ sağlar. - Title: Sayfanõn tarayõcõdaki başlõk bilgisini belirler. - Trace: Sayfada trace (izleme) işlemlerinin yapõlõp yapõlmayacağõnõ belirler. Varsayõlan değeri false'dur ve trace işlemi yapõlmaz. true değeri atandõğõnda sayfada trace işlemi yapõlõr. - ValidateRequest: Sayfadaki bilgilerin sunucuya gönderilmesi esnasõnda, form içerisinde taşõnan bilgilerde güvenlik açõsõndan sorun çõkarabilecek içerikler var ise (örneğin kullanõcõ bir TextBox içerisinde <span> <b> <script>....</script> gibi ifadeler yazdõysa) sayfanõn hata vermesini ve bilgilerin gönderiminin iptal edilmesini sağlar. Güvenlik açõsõndan önemli bir niteliktir. Varsayõlan değeri true'dur ve yukarõda bahsedildiği gibi bir işlem gerçekleşirse işlemi iptal eder ve hata verir. false ise tehlikeli bir içerik bulunsa bile gönderilen bilgileri kabul edecektir. Aşağõdaki kod örnekğinde bir ASP.NET sayfasõna uygulanabilecek Page direktifi görülmektedir. <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" Culture="tr-TR" UICulture="tr-TR" EnableViewState="false" ErrorPage="Hata.aspx" %>

Yukarõdaki örnekte sayfanõn C# dili ile kodlandõğõ, sayfa olaylarõnõn varsayõlan metotlara bağlandõğõ, sayfanõn C# kodlarõnõn Default.aspx.cs dosyasõnda bulunduğu, sayfanõn _Default adõnda bir sõnõftan türetildiği, sayfanõn kültür (culture) bilgisinin tr-TR yani Türkçe dili olduğu, sayfa içerisindeki kontrollerin değerlerinin ViewState içerisinde saklanmayacağõ ve sayfada bir hata oluşursa sayfanõn otomatik olarak Hata.aspx isimli sayfaya yönlendirileceği belirtilmiştir.

2. Assembly Direktifi
İlgili sayfaya kullanõcõnõn oluşturmuş olduğu bir assembly'nin eklenmesini sağlar. Böylece sayfa içerisinde ilgili assembly'de bulunan tipler (class, struct gibi) kullanabilmektedir. web.config dosyasõ içerisinde <assembly> düğümüne add etiketi ile uygulamaya assembly ekleme işleminin sayfa bazõnda yapõlmasõnõ sağlar. Assembly direktifinin alabileceği iki nitelik vardõr: - 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.

31

<%@ Assembly Name="AssemblyIsmi" %> Assembly direktifinin iki niteliği de aynõ işlemi yapmakta ve bir Assembly direktifi içerisinde aynõ anda bunlardan sadece bir tanesi kullanõlabilmektedir.

3.Control Direktifi
Bir user control'ünün (kullanõcõ kontrolü) özelliklerinin belirlenmesini sağlar. Böylece ASP.NET'in bu user control'ünü ne şekilde ele alacağõ ve nasõl derleyeceği belirlenir. Bildiğiniz gibi user control'ler ascx uzantõsõ ile saklanan, içerisinde ASP.NET kontrolleri ve HTML kodlarõ bulundurabilen ve ASP.NET web sayfalarõnõn belirli parçalarõnõ oluşturan dosya tipleridir. Bir aspx sayfasõ içerisindeki Page direktifi ile ascx kontrolünde kullanõlan Control direktifinin hemen hemen aynõ işlevleri olduğunu söyleyebiliriz. Control direktifi sadece user control'lerinde kullanõlabilmektedir. Control direktifinin nitelikleri, Page direktifinin niteliklerine göre az sayõda olmakla beraber, niteliklerin kullanõmõ ve yaptõklarõ işlemler hemen hemen aynõdõr. Yukarõda, Page direktifi kõsmõndaki niteliklere ve açõklamalarõna göz atmak, Control direktifinin kullanõmõ ile ilgili bize yeterli bilgi verecektir. Aşağõda Control direktifinin bir user control'ünde kullanõmõ ile ilgili bir örnek yer almaktadõr. <%@ Control Language="C#" AutoEventWireup="true" CodeFile="Login.ascx.cs" Inherits="Login" 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 uygulanabilir. Implements direktifi sadece Interface niteliğini kullanmaktadõr. - Interface: Sayfaya uygulanacak .NET 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. <%@ Implements Interface="System.Web.UI.IValidator" %>

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 belirtilmesi gerekir. Aşağõdaki örnekte Import direktifi ile bir sayfaya namespace eklemeleri yapõlmõştõr. <%@ Import Namespace="System.Data.SqlClient" %> <%@ Import Namespace="KendiIsimAlanim" %>

6. Master Direktifi
Bir Master page'in özelliklerinin belirlenmesini sağlayan direktiftir. Page direktifi web form sayfalarõnda(aspx), Control direktifi user control'lerde(ascx) olduğu gibi, Master direktifi de master page'lerin ASP.NET derleyicisi tarafõndan ne şekilde ele alõnacağõnõ belirler. Kullanõlan nitelikler ve niteliklerin kullanõm amaçlarõ Page ve Control direktifleri ile hemen hemen aynõdõr. Bu nitelikler için Page direktifi kõsmõndaki nitelik açõklamalarõna göz atabilirsiniz. Aşağõda bir master page dosyasõnda kullanõlabilecek Master direktifi görülmektedir. <%@ Master Language="C#" AutoEventWireup="true" CodeFile="SiteSablonu.master.cs" Inherits="SiteSablonu" %>

7. MasterType Direktifi
Master page'den türetilen bir ASP.NET sayfasõndaki Page.Master property'si MasterPage tipinden bir değer döndürmekte ve böylece master page ile ilgili işlemler yapõlabilmektedir. Bazõ durumlarda master page sõnõfõ içerisinde tanõmlanmõş özel bir property (özellik) veya metoda Page.Master özelliği ile direkt olarak erişilmek istenilebilir. Böyle bir durumda Page.Master özelliğini ilgili master page'in tipine cast (dönüştürme) işlemi yapmak gerekecektir. İlgili sayfadan master page'in nesne örneğine cast işlemi yapõlmadan erişilmek istenilirse, bu sayfaya MasterType direktifi eklenmesi gerekecektir. MasterType direktifi içerisinde tanõmlanan master page'in otomatik olarak Page.Master özelliğinin geri dönüş tipi olmasõnõ sağlar ve böylece master page'deki özel property veya metoda direkt olarak erişme işlemi gerçekleştirilebilir. Aşağõda MasterType direktifinin alabileceği nitelikler ve bu niteliklerin açõklamalarõ yer almaktadõr. - TypeName: Content page'de Master özelliğinin geri dönüş tipi olmasõ istenilen master page'in tip adõnõ alõr. - VirtualPath: Content page'de Master özelliğinin geri dönüş tipi olmasõ istenilen master page dosyasõnõn dosya yolunu ve ismini alõr. Örnekteki MasterType direktifi, content page içerisindeki Master özelliğinin geri dönüş tipinin SiteSablonu.master isimli master page dosyasõ olduğunu belirler.

33

<%@ MasterType VirtualPath="~/SiteSablonu.master" %>

Resim-1: MasterType direktifi eklenilmediğinde Page.Master property'si MasterPage nesne örneğini getirir ve master page'deki üyelere erişmek için cast işlemi gerekir

Resim-2: MasterType direktifi eklendiğinde artõk Page.Master property'si master page'in nesne örneğini getirir

Resim-3: Master property'si master page'in nesne örneğini getirdiği için content page'den direkt olarak master page üyelerine erişebiliriz

8. OutputCache Direktifi
ASP.NET uygulamalarõnda sayfanõn çõktõsõnõ önbelleğe alma işlemlerinde (Caching) kullanõlan direktiftir. Sayfaya OutputCache direktifini eklediğimizde ve gerekli nitelikleri tanõmladõğõmõzda, sayfanõn HTML çõktõsõ bellekte saklanõr, sayfa belirli bir süre boyunca tekrar çalõştõrõlmaz ve bellekten okunur. OutputCache direktifi ile yapõlan önbellekleme işlemleri sayfanõn daha hõzlõ şekilde istemciye gönderilmesini sağlar. - 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ğõ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 ve None'dir. - NoStore: Sayfanõn header (başlõk) bilgilerinde "no cache" bilgisinin gönderilip gönderilmeyeceğini belirler. - SqlDependency: Sayfanõn SQL Server veritabanõndaki bir tablonun değişimine bağõmlõ olarak önbelleklenmesi durumunda kullanõlacak niteliktir. Bu özelliğe değer atayabilmek için, web.config dosyasõndaki caching düğümünde bulunan sqlCacheDependency içerisine bir veritabanõ tanõmlamasõ yapõlmalõdõr. - VaryByControl: Sayfadaki bir kontrolün değişimine göre önbellekleme işleminin yapõlmasõnõ sağlar. Değer olarak önbellekleme işleminin yapõlmasõnõ sağlayacak kontrolün ID değerini almalõdõr. - VaryByCustom: Farklõ değerlere ve kriterlere göre önbellekleme işlemlerinin yapõlmasõ durumunda kullanõlacak niteliktir. Bu niteliğin alacağõ değerin yakalanõp ele alõnabilmesi için Global.asax dosyasõ içerisindeki GetVaryByCustomString isimli metodun ezilmesi (override edilmesi) gerekmektedir. - VaryByHeader: Sayfanõn HTML kõsmõnda yer alan header (başlõk) bilgilerine göre önbellekleme işlemlerinin yapõlmasõnõ sağlar. - VaryByParam: Sayfanõn Url'den gelen QueryString parametrelerine göre önbelleğe alõnõp alõnmayacağõnõ belirler. Varsayõlan değeri None'dir ve parametreleri dikkate almaksõzõn sayfanõn belleğe alõnmasõnõ sağlar. QueryString'deki herhangi bir parametrenin adõnõ alarakta bu değere göre sayfanõn farklõ kopyalarõnõn önbellekleğe alõnabilmesini sağlar. Bu niteliğin her OutputCache direktifi içerisinde yazõlmasõ zorunludur. Aşağõda bir sayfanõn HTML çõktõsõnõ QueryString bilgisine bakmaksõnõz 30 saniye süre ile istemcinin bilgisayarõnda önbelleğe atan OutputCache direktifi bulunmaktadõr. <%@ OutputCache Duration="30" Location="Client" VaryByParam="None" %>

9. PreviousPageType Direktifi
Cross-Page PostBack işlemlerinde hedef sayfaya gelinen kaynak sayfanõn nesne örneğini elde etmek için kullanõlan direktiftir. Normal koşullarda sayfanõn code-behind kõsmõnda elde ettiğimiz PreviousPage nesnesi Page tipinden nesne örneği döndürmektedir. Eğer PreviousPage nesnesin üzerinden önceki sayfanõn nesne örneğini elde etmek istiyorsak sayfa içerisine PreviousPageType direktifi eklemek gerekecektir. PreviousPageType direktifinin alabileceği nitelikler ve açõklamalarõ aşağõdadõr. - 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 PreviousPageType direktifi eklendiği sayfada PreviousPage nesnesinin Source.aspx sayfasõnõn nesne örneğini dönmesini sağlar. <%@ PreviousPageType VirtualPath="~/Source.aspx" %>

35

Dilerseniz PreviousPageType direktifinin sayfaya ne gibi bir etkisi olduğunu daha iyi anlayabilmek için aşağõdaki resimleri inceleyelim. Resim-4'te PreviousPageType direktifi eklenmemiş bir sayfada PreviousPage nesnesinin geri dönüş tipinin Page class'õ olduğunu görebilirsiniz. Resim-5'te ise sayfaya PreviousPageType direktifi eklendiğinde sayfanõn PreviousPage nesnesinin Source.aspx sayfasõnõn nesne örneğinin döndürdüğü görülmektedir. Böylece artõk PreviousPage'den önceki sayfanõn nesne örneğine ulaşõlabilir ve önceki sayfanõn class'õ içerisinde metot, property gibi üyeler çağrõlabilir.

Resim-4: PreviousPageType direktifi eklenmemiş bir sayfada 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 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. Aşağõda Register direktifi ile kullanõlabilecek 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 kullanõmõ için aşağõdaki kod örneklerine bakmakta fayda var) Aşağõdaki Register direktifi ile sayfaya LoginKontrolum adõndaki bir user control'ü eklenmiştir. Böylece sayfaya TagName ve TagPrefix bilgileri ile ilgili dosyadaki user control eklenebilir. <%@ Register Src="Login.ascx" TagName="LoginKontrolum" TagPrefix="myControls" %>

<myControls:LoginKontrolum ID="LoginKontrolum1" runat="server" />

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. En temel performans bakõmõ tekniklerimiz olan OutputCache ile sayfa çõktõsõnõ, Cache nesnesi ile de sayfa içerisindeki bir nesneyi belirli bir süre bellekte saklayabilmekte ve sonraki erişimlerde sayfanõn çok daha hõzlõ bir şekilde çalõşabilmesini sağlayabilmekteyiz. ASP.NET 2.0 ile birlikte birçok alanda gelen yenilikler arasõnda performans yönetimi konusunda da bazõ yeni teknikler ve kullanõm kolaylõklarõ getirilmiştir. Bu yazõmõzda da ASP.NET 2.0 ile birlikte gelen bu yenilikleri inceliyor olacağõz. ASP.NET 2.0 ile gelen yenilikleri şu başlõklar altõnda 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. Sayfa veya user control içerisine ekleyeceğimiz <%@ OutputCache ... %> direktifi ile sayfanõn önbelleğe alõnma şeklini belirleyebiliyorduk. ASP.NET 2.0 ile birlikte gelen Cache Profilleri ile birlikte sayfalarõmõzda ortak olarak kullanabileceğimiz OutputCache ayarlamalarõnõ artõk web.config içerisinde düzenli bir şekilde saklayabilmekte ve sayfa içerisinde OutputCache direktifinin bu profillerden birini kullanabilmesini sağlayabilmekteyiz. Dilerseniz önce OutputCache direktifini sayfa içerisinde nasõl kullanabiliyorduk bir hatõrlayalõm. Aşağõdaki kod parçasõnõ bir .aspx sayfasõndaki Page direktifinin alt kõsmõna ekleyecek olursak; sayfa QueryString bilgisini dikkate almaksõzõn 60 saniye süre ile önbelleğe alõnacaktõr. <%@ OutputCache Duration="60" VaryByParam="None" %>

38

Cache profillerin bize ne gibi bir noktada fayda sağladõğõnõ görebilmek için şöyle bir senaryo üzerinde duralõm. Varsayalõm ki uygulamamõz çok sayõda sayfadan oluşuyor ve bu sayfalarõn bir grubunu farklõ şekilde, diğer grubunu farklõ şekilde önbelleğe alma işlemini gerçekleştirmek istiyoruz. Şöyle ki; 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" %> ifadesini, Grup 2 sayfalarõna da <%@ OutputCache Duration="300" VaryByParam="UrunID" %> ifadelerini eklememiz gerekecekti. Varsayalõm ki belirli bir süre sonra Grup 1'deki sayfalarõn çok uzun süre ile önbellekte tutulduğunu ve kullanõcõnõn güncel bilgiye erişemediğini gördük. Yine Grup 2'deki sayfalarõnda sadece UrunID QueryString bilgilesine göre değil de, UrunID ve Renk QueryString bilgilerine göre önbellekte saklanmasõnõ istiyoruz; yani sayfalardaki OutputCache direktiflerini değiştirme ihtiyacõmõz var. Bu durum yukarõdaki 12-13 tane sayfanõn tek tek açõlarak kod kõsõmlarõnda değişiklik yapõlmasõ anlamõna geliyor. Sayfa sayõsõnõn 30-40 olduğunu düşünürsek durum biraz daha vahim hale geliyor:) İşte bu noktada gruplanan iki OutputCache niteliğini web.config içerisinde saklayacak ve sayfalarõmõzda da web.config'deki bu ayarlarõ kullanacak olursak artõk bilgileri tek bir noktada toplamõş ve dolayõsõyla da bu değişiklikleri de çok basit bir şekilde sayfalara uygulamõş olacağõz. Peki Cache profillerini web.config içerisinde ne şekilde saklayacağõz. Aşağõdaki kod parçalarõ ile birlikte web uygulamasõna CacheProfil_A ve CacheProfil_B adõnda iki tane Cache profili eklemiş oluyoruz. <system.web> ..... ..... <caching> <outputCacheSettings> <outputCacheProfiles> <add name="CacheProfil_A" duration="600" varyByParam="None" /> <add name="CacheProfil_B" duration="300" varyByControl="UrunID"/> </outputCacheProfiles> </outputCacheSettings> </caching> </system.web> 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 bir user-control (ascx) dosyasõ ekleyerek sadece bu alanõn HTML çõktõsõnõ önbelleğe saklayabiliyor ve sayfanõn diğer alanlarõnõn dinamik oluşmasõnõ sağlayabiliyorduk. Fakat sayfanõn tamamõnõ önbellekten getirilirken sadece belirli bir alanõnõ dinamik oluşturma işlemini gerçekleştiremiyorduk. ASP.NET 2.0 ile birlikte gelen yeniliklerle birlikte artõk bu tip bir önbellekleme işlemini de gerçekleştirebilmekteyiz.

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. 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 "<b>" + DateTime.Now.ToLongTimeString() + "</b>"; } Yazacağõmõz metot dinamik içeriğimizi oluşturacak; yani HTML kodlarõmõzõ bize getirecek bir metot olmalõdõr. Bundan dolayõ metodumuzun geri dönüş tipi string'dir ve return edilen HTML kodlarõ dinamik içeriğimizi oluşturacaktõr. Bu sayfamõza bir istek geldiğinde sayfa içeriği (dinamik alan dõşõndaki içerikler) önbellekten getirilecektir; yani sayfamõzõn tekrar çalõştõrõlmasõna, dolayõsõyla da nesne örneğini oluşturulmasõna gerek yoktur. Bundan dolayõ static bir metot yazacak olursak uygulamamõz sayfanõn nesne örneğine ihtiyaç duymadan bu metodu çağõrabilecektir. Metodumuz HttpResponseSubstitutionCallback delegate'inin işaretleyebileceği bir metot olmak zorunda olduğu için burada bir de HttpContext tipinden bir metot parametresine ihtiyacõmõz vardõr. Bu parametre gelen istek ile ilgili bilgilerin taşõnmasõnõ sağlar fakat pek kullanmaz. Böylece yazõlacak metodun detaylarõnõ irdelemiş olduk. Peki metodu nasõl çağõracağõz. Aşağõdaki kodlarda görüldüğü gibi bir sayfa tasarlayalõm. ...... <%@ OutputCache Duration="30" VaryByParam="none" %> ...... ...... <form id="form1" runat="server"> <div> Önbellekten gelen zaman: <%= DateTime.Now.ToLongTimeString() %> <br /><br /> Dinamik zaman: <% Response.WriteSubstitution(new HttpResponseSubstitutionCallback(DinamikIcerik)); %> </div> </form> .....

41

Resim: Post-Cache Substitution yolunu kullandõğõmõzda sadece belirli bir alanõn dinamik oluşmasõnõ sağlayabiliriz. 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 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 sayfaya nasõl uygulanabileceğini görebiliriz. ...... <%@ OutputCache Duration="30" VaryByParam="none" %> ...... ...... <form id="form1" runat="server"> <div> Önbellekten gelen zaman: <%= DateTime.Now.ToLongTimeString() %> <br /><br /> Dinamik zaman: <asp:Substitution ID="Substitution1" runat="server" MethodName="DinamikIcerik" /> </div> </form> ..... Görüldüğü gibi Substitution kontrolünin 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 ise önbellekten getirilecektir.

3. SqlCacheDependency ile Veritabanõndaki Değişikliklere Göre Veri Önbellekleme
ASP.NET 2.0'dan önceki 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. Yine bu sõnõf aracõlõğõyla veritabanõnda bir tablodaki değişimlere bağõmlõ kalarak önbellekleme işlemleri yapõlabilmekteydi. Fakat bu işlemleri yapabilmek için gerek vertiabanõnda oluşturulacak 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 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 çok detaylõ bir mevzu olduğu için başlõ başõna bir makale olarak ele almakta fayda olabilir. Biz burada olabildiğince kõsa bir şekilde bu mekanizmayõ incelemeye ve uygulamalarda nasõl kullanabileceğimizi göreceğiz. Öncelikli olarak SqlCacheDependency'nin uygulama ve veritabanõ tarafõndaki bileşenlerini inceleyelim. Veritabanõndaki bir tablonun değişimine göre önbellekleme işlemleri yapabilmek için mutlaka veritabanõ ile bütünleşik şekilde çalõşmak, yani veritabanõ içerisinde bazõ nesneleri kullanmak gerekecektir. Burada esas alõnacak durum verilerin asõl getirildiği tablonun verilerini kontrol etmek yerine bizim aracõ bir tablo üzerinden asõl verilerin saklandõğõ tablonun kontrolünü yapmaktõr. Zira verilerin saklandõğõ tablomuzda binlerce kayõt bile olabilir. Böyle bir tablonun değişip değişmediğini trigger'lar aracõlõğõyla başka bir tabloya aktarmak ve kontrollerin bu tablo üzerinden gerçekleştirmek çok daha hõzlõ olacaktõr. Uygulama içerisinde kullanacağõmõz SqlCacheDependency tipindeki nesnemiz tablonun değişip değişmediğini belirli aralõklarla veritabanõndan kontrolünü yapacak ve eğer tabloda değişiklik olmuşsa Cache'de saklanacak verinin değiştirilmesini sağlayacak. Bu işleyişi daha iyi anlamak için aşağõdaki şekil üzerinden konuşmaya devam edelim.

43

Resim: SqlCacheDependency mekanizmasõnõn çalõşma şekli 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 (notification table) bakacak ve değişim yoksa Cache'de saklanan veri aynen kullanõlacaktõr. Eğer 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 uygulamaya güncel verilerin aktarõlmasõnõ sağlayacaktõr. Bir projede SqlCacheDependency tekniğini uygulamak biraz zor bir yoldur. Gelin adõm adõm bu işlemi nasõl gerçekleştirebileceğimize bakalõm. Adõm-1 SQL Server'da ilgili notification table, trigger ve stored procedure'larõn kurulmasõ gereklidir. aspnet_regsql.exe aracõ ile bu işlemi kolay bir şekilde gerçekleştirebileceğiz. aspnet_regsql.exe .NET Framework SDK v2.0 ile birlikte gelen araçlardan biridir. SDK Command Prompt'ta yazõlacak komutlarla önce ilgili tablonun bulunduğu veritabanõna ilgili notification table, trigger ve stored procedure'larõn kurulmasõ gerekecektir. Başlat > Programlar > Microsoft .NET Framework SDK v2.0 > SDK Command Prompt seçeneğinden komut satõrõnõ açtõktan sonra aşağõdaki resimlerde görülen komutlarõ yazarak bu işlemi gerçekleştirelim. Not: Komutlarda yazõlan parametrelerden -S localhost: localhost isimli sunucu

44

-E: Windows Authentication ile bağlan -d AdventureWorks -ed: AdventureWorks veritabanõnõ aktif hale getir -t Urunler -et: Urunler isimli tabloyu aktif hale getir anlamõna gelmektedir. Farklõ durumlarda kullanõlabilecek parametreler için Command Prompt'ta aspnet_regsql -? komutunu yazarak yardõm alabilirsiniz.

Resim: 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 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 eklemek, ardõndan da SqlCacheDependency tanõmlamasõnõ yapmak gerekecektir. Aşağõdaki kodlarda yapõlmasõ gereken tanõmlamalar görülmektedir.

45

Resim: web.config dosyasõna connectionString ekleme ve SqlCacheDependency ayarlamalarõnõ yapmak <system.web> düğümü içerisine eklenen <sqlCacheDependency> 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ğinin ne kadar sürede bir kontrol edileceğini belirler. (3000 değeri 3 saniye anlamõna gelir) <databases> alt düğümünde ise hangi veritabanlarõnõn kaydedileceği belirlenir. <add> 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 <connectionStrings> 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 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 tipinden saklanacak verinin dosya veya veritabanõna bağõmlõ kalmasõnõ sağlayan nesnemiz olacaktõr. Bizim üçüncü parametre olarak kullanacağõmõz CacheDependency sõnõfõndan kalõtõlan SqlCacheDependency sõnõfõndan bir nesne olacaktõr. İsterseniz şöyle bir senaryo üzerinden SqlCacheDependency nesnesinin kullanõmõna bakalõm. Bir sayfada bulunan GridView 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 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 // değişim olursa nesne bellekten kaldõrõlõr; yani null olur. Böylece if bloğu çalõşõr // ve güncel veriler tekrar alõnõp Cache'e aktarõlabilir. if (Cache["veriler"] == null) { string baglanti = "data source=.; initial catalog=AdventureWorks; integrated security=true"; string sorgu = "SELECT * FROM Urunler"; SqlDataAdapter da = new SqlDataAdapter(sorgu, baglanti); DataTable dt = new DataTable(); da.Fill(dt); // SqlCacheDependency nesnesini oluşturuyoruz. İlk parametre web.config'de tanõmlanan // SqlCacheDependency database'i. İkinci parametre ise veritabanõnda kontrol edilecek // olan tablonun adõ olacaktõr. SqlCacheDependency tabloyaBaglan = new SqlCacheDependency("advConnDepend", "Urunler"); // dt isimli DataTable nesnesini Cache'e atõyoruz. İlk parametremiz Cache nesnesinin adõ, // ikinci parametre Cache'de saklanacak nesne; yani DataTable nesnesi, üçücü parametre // ise tabloyaBaglan isimli SqlCacheDependency nesnesi olacaktõr. Artõk Cache'de saklanan // veri Urunler tablosundaki değişimlere bağõmlõ olacaktõr. Değişim olmadõğõ sürece // değerler şu an oluşturulan nesneden alõnacaktõr. Tabloda değişim olduğunda bu kod bloğu // tekrar çalõşacağõ için Cache'de saklanan verileri güncellenmesi otomatikmen gerçekleşir. Cache.Insert("veriler", dt, tabloyaBaglan); } // GridView kontrolünün DataSource değeri Cache'den getiriliyor. Gelen değer object tipinde olduğu // için DataTable'a cast işlemi gerçekleştiriyoruz. GridView1.DataSource = (DataTable)Cache["veriler"]; 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. Bu yeni ASP.NET kontrollerinin önbellekleme işlemlerini kolay bir şekilde gerçekleştirmemizi sağlayan özelliklerinden biri de önbellekteki verilerle çalõşabilmesidir.. EnableCaching özelliğinin true olarak ayarlanmasõ ve CacheDuration özelliğinin saniye cinsinden bir değere atanmasõ durumunda bağlanan veriler belirli bir süre boyunca önbelleğe alõnacak ve buradan okunacaktõr. Yine SqlCacheDependency özelliği ile bir SqlDataSource veri kaynağõnõn SQL Server'daki tablonun değişim durumuna göre önbellekte saklanmasõ sağlanabilmektedir. Aşağõdaki örnek kodlarda SqlDataSource kontrolünün SqlCacheDependency özelliği ile veriyi önbellekte saklayabilmesi sağlanmaktadõr. Burada SqlCacheDependency özelliğinin aldõğõ değer advConnDepend:Urunler şeklindedir. advConnDepend web.config dosyasõnda tanõmlanan SqlCacheDependecy veritabanõnõn adõ, Urunler ise tablonun adõdõr. <asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:advConn %>" SelectCommand="SELECT * FROM [Urunler]" EnableCaching="true" SqlCacheDependency="advConnDepend:Urunler"> </asp:SqlDataSource>

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 veri saklama işlemlerinde kullanabiliriz. Böylece sadece dosya ve klasör değişimlerine bağõmlõ olmaksõzõn, kendi özel durumlarõmõza göre sõnõfõmõzõ düzenleyip Cache'de saklanacak verilerin bağõmlõlõk durumlarõnõ belirleyebiliriz.

48

GridView'e Programatik Veri Bağlamada Sayfalama ve Sõralama İşlemleri
31 Ekim 2007
Gridview kontrolü ile web uygulamalarõnda kompleks veri işlemlerini dahi çok kolay bir şekilde gerçekleştirebildiğimizi eminim ki çoğumuz oldukça iyi biliyoruz. Özellikle tasarõm aşamasõnda Visual Studio 2005 arayüzünün sunduğu olanaklar ile (Wizard'lar, properties penceresi, vb.) neredeyse kod yazmadan dahi bu işlemleri yürütebilmekteyiz. Fakat profesyonel bir uygulama geliştirirken gridview kontrolünü bu araçlarõ kullanmadan programatik yollarla kullanma ihtiyacõmõz olabilir. Böyle bir durumda da klasik alõşkanlõklarõmõz DataTable ve DataSet nesneleri ile çalõşmamõz gerekecektir. Tabii ki bu tip nesnelerle gridview kontrolüne programatik olarak veri bağlama işlemleri az önce bahsettiğimiz araçlarla yapõlan işlemlere göre biraz daha uzun ve zor olacaktõr. Bu makalede gridviewe programatik olarak veri bağlama işlemlerinde verileri sayfalama ve sõralama işlemlerini ne şekilde yürütebileceğimizi ele alacağõz. 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 ve AllowSorting ö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 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. Default.aspx <form id="form1" runat="server"> <asp:GridView ID="gvUrunler" runat="server"> </asp:GridView> </form> Default.aspx.cs protected void Page_Load(object sender, EventArgs e) {

49

SqlConnection conn = new SqlConnection("data source=.; database=AdventureWorks; integrated security=true"); SqlCommand cmd = new SqlCommand("Select ProductID,Name,Color From Production.Product Where ListPrice > 1500", conn); SqlDataAdapter da = new SqlDataAdapter(cmd); DataTable dt = new DataTable(); da.Fill(dt); // GridView kontrolünün özelliklerini ve veri bağlama işlemlerini gerçekleştiriyoruz. // Sayfalama ve sõralama işlemlerini aktif hale getirdik. gvUrunler.AllowSorting = true; gvUrunler.AllowPaging = true; gvUrunler.PageSize = 10; gvUrunler.DataSource = 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 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 belirlememiz gerektiğidir. Aldõğõmõz hatalar "The GridView 'gvUrunler' fired event XXX which wasn't handled." şeklindeydi ki XXX kõsmõndaki kelimeler de aslõnda ilgili event'lerin isimleridir. Burada bahsedilen hata gridview ile ilgili daha önceden ele alõnmamõş belirli bir event'in fõrlatõlmasõdõr. Zira gridview birçok işlemde olduğu gibi sayfalama ve sõralama işlemlerinde de arka planda ilgili eventleri gerçekleştirmektedir. Bizim programcõ olarak burada ilgili eventleri yakalayacak olan metotlarõ oluşturmamõz ve kodlamamõz gerekecektir. Sayfalama işlemi için ele alõnacak event PageIndexChanging, sõralama işlemlerinde ise Sorting'dir. Öncelikli olarak gerekli delegate'ler aracõlõğõyla bu eventleri birer metoda bağlõyor ve metotlarõn içerisini dolduruyoruz. Aşağõdaki kodlarda bu işlemlerin ne şekilde yapõldõğõ görülmektedir. Burada ilgili metotlara aktarõlan ikinci event parametresi bizim açõmõzdan oldukça önemlidir. Zira sayfalama esnasõnda çalõşacak GridView1_SelectedIndexChanging metodundaki GridViewSelectEventArgs tipindeki e parametresi ve sõralama işlemi esnasõnda çalõşacak olan GridView1_Sorting metodundaki GridViewSortEventArgs tipinden e parametresi buradaki eventler gerçekleşirken önemli bilgileri taşõmaktadõr. Default.aspx.cs protected void Page_Load(object sender, EventArgs e) { ........ gvUrunler.AllowSorting = true; gvUrunler.AllowPaging = true; gvUrunler.PageSize = 10; // Sayfalama ve sõralama event'lerini metotlara bağlõyoruz gvUrunler.PageIndexChanging += new GridViewPageEventHandler(gvUrunler_PageIndexChanging); gvUrunler.Sorting += new GridViewSortEventHandler(gvUrunler_Sorting); gvUrunler.DataSource = dt; gvUrunler.DataBind(); }

51

// Sayfalama işleminde; yani PageIndexChanging event'i tetiklendiğinde çalõşacak metot void GridView1_SelectedIndexChanging(object sender, GridViewSelectEventArgs e) { gvUrunler.PageIndex = e.NewSelectedIndex; gvUrunler.DataBind(); } // Sõralama işlemi yapõldõğõnda; yani Sorting event'i tetiklendiğinde çalõşacak metot void GridView1_Sorting(object sender, GridViewSortEventArgs e) { // İlk sort işlemi yapõldõğõnda çalõşõr if (ViewState["siralananKolon"] == null) { ViewState.Add("siralananKolon", e.SortExpression); ViewState.Add("siralamaYonu", "ASC"); } else { // Aynõ kolon 2. kez sõralandõğõnda çalõşõr if (ViewState["siralananKolon"].ToString() == e.SortExpression) { if (ViewState["siralamaYonu"].ToString() == "ASC") ViewState["siralamaYonu"] = "DESC"; else ViewState["siralamaYonu"] = "ASC"; } // Farklõ bir kolon sõralandõğõnda çalõşõr else { ViewState["siralananKolon"] = e.SortExpression; 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) değiştiriyoruz DataTable dt = (DataTable)gvUrunler.DataSource; dt.DefaultView.Sort = 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 elde edebiliyoruz. Sorting eventinde, yani sõralama işleminde ise iki bilgiye ihtiyacõmõz olacaktõr; birincisi sõralama yapõlacak kolonun adõ, ikincisi ise sõralamanõn yönü (Ascending, Descending). Yine metotla birlikte gelen e parametresi bize önemli bilgileri taşõmaktadõr. Fakat e parametresi sõralanacak kolonun adõnõ doğru olarak getirse bile sõralama yönünü her defasõnda Ascending olarak getirecektir. Bundan dolayõ ihtiyacõmõz olan iki değerden birisine erişebilmek için ekstra çaba sarfetmemiz gerekecek. Burada sõralama işlemi yapõlan kolona bir kez tõklanõrsa sõralama işlemini Ascending(ASC), ardõndan bir kez daha aynõ kolona tõklanõrsa da Descending(DESC) yapmamõz gerekecektir. Özetle, her zaman bir kolona ilk tõklandõğõnda ASC, ikinci tõklamada DESC, üçüncü tõklamada ASC... şeklinde devam edecektir. Yine sayfa postback işlemini yaptõğõnda bir önceki sõralama işleminin yönünü bilmemiz ve değiştirmemiz gerekecektir. Bu nedenle ViewState nesnesi içerisinde bu değeri saklayarak her postback işleminde o anki sõralanacak kolonun durumuna göre sõralama yönünü değiştirmemiz gerekecek. Örneğin Name kolonunu ilk sõralamamda SQL cümlesinin sonuna Name ASC, Name kolonuna ikinci kez tõklandõğõnda Name DESC şeklinde bir sõralama yapmamõz gerekecek. Bu esnada eğer ki Color sütununa tõklanõrsa Color ASC şeklinde işleme devam etmemiz gerekecektir. Bu durumlarõ ele alabilmemiz için gerekli koşullarõ bu metot içerisinde oluşturuyoruz. Son işlem olarakta DataTable nesnesindeki verileri tekrar sõralayarak gridviewe yeniden bağlamamõz gerekecektir. Gridviewin DataSource özelliğinden object tipinde elde ettiğimiz nesneyi önce DataTable tipine cast ediyoruz. Ardõndan da datatable'õn görünümünü DataView nesnesi olarak elde etmemizi sağlayan DefaultView özelliğine ait Sort özelliğine de sõralama cümlemizi belirmemiz gerekecektir. Son olarakta gridview nesnesini DataBind metodu ile tekrar yükleyecek olursak artõk verilerimiz düzgün bir şekilde sõralanarak görüntülecektir. 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 gridview kontrolüne bu şekilde veri bağ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.

53

GridView Kayõtlarõnõ Okumak ve Metin Dosyasõna Aktarmak
01 Kasõm 2007 ASP.NET 2.0 ile gelen yeni veri kontrollerinden GridView web uygulamalarõnda kullandõğõmõz en zengin veri kontrolüdür. Bir programcõnõn birçok ihtiyacõnõ karşõlayabilecek gelişmiş özelliklere sahip olan bu kontrolle tek satõr kod yazmadan dahi veriye bağlanabilmekte, getirilen verileri sayfalayõp sõralayabilmekte, hatta yine kod yazmadan otomatik güncelleme ve silme işlemlerini de gerçekleştirebilmekteyiz. Bu kontrol ile ilgili olarak programcõya düşen görev ise kontrolün varolmayan özelliklerini çalõştõrabilecek işlemleri yapmak kalõyor. Bu işlemlerden birisi de GridView'deki verilerin farklõ bir ortama aktarõlmasõ olacaktõr. Farklõ ortamdan kastõmõz farklõ bir tabloya, farklõ bir nesneye veya bir dosyaya olabilir. Bu makalemizde GridView kontrolünde bulunan verilere programatik yollarla nasõl erişebileceğimize ve bu verileri txt uzantõlõ olarak bir metin dosyasõna nasõl dönüştürebileceğimizi göreceğiz. 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), 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 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 veritabanõnda yer alan Production.Product tablosunu kullanacağõm(Sorgu: SELECT ProductID, Name, Color, ListPrice, ModifiedDate FROM 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 + "<br>"); }

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("<br>"); } }

Ş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ü sayfalandõrõlmõş şekilde kullanõyorsak ve birden fazla sayfada veriler tutuluyorsa yukarõdaki kodlar çalõştõrõldõğõnda sadece o an üretilen sayfada grid içerisine hangi satõrlar geliyorsa o satõrlarõn bilgilerine erişebiliriz. Eğer amacõmõz griddeki bilgileri bir dosyaya aktarmak ise olaya farklõ yaklaşõmlarõmõz olabilir. Sadece o an gridde görüntülenen satõrlarõ dosyaya kaydetmek isteyebileceğimiz gibi, belirli sayõdaki satõrõ veya gride bağlanan tüm kayõtlarõda dosyaya kaydetmek isteyebiliriz. Dilerseniz gridviewdaki kayõtlarõ metinsel bir dosyaya kaydetme işlemini gerçekleştiren ve bu üç farklõ durumu gözönüne alan küçük bir uygulama yazalõm. Sayfaya ekleyeceğimiz gridview kontrolünü bir SqlDataSuorce kontrolüne bağlayalõm. Sorgu olarak yukarõdaki sorguyu aynen kullanabiliriz. Yine Update,Delete işlemleri içinde gerekli sorgularõ oluşturalõm. Burada her ne kadar Update-Delete işlemi yapmayacak olsakta gride eklenecek 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 kontrolü ile sadece bu sayfadaki verileri kaydetme, ilk 50 veriyi kaydetme ve tüm verileri kaydetme seçeneklerini ele alacağõz. Sayfamõzõn tasarõmõ ve kodlarõ aşağõdaki gibi olacaktõr.

Şekil: Oluşturduğumuz sayfanõn Design kõsmõ <asp:GridView ID="gvUrunler" runat="server" AllowPaging="True" AutoGenerateColumns="False" DataKeyNames="ProductID" DataSourceID="SqlDataSource1" PageSize="5"> <Columns> <asp:BoundField DataField="ProductID" HeaderText="ProductID" InsertVisible="False" ReadOnly="True" SortExpression="ProductID" /> <asp:BoundField DataField="Name" HeaderText="Name" SortExpression="Name" /> <asp:BoundField DataField="Color" HeaderText="Color" SortExpression="Color" /> <asp:BoundField DataField="ListPrice" HeaderText="ListPrice" SortExpression="ListPrice" /> <asp:BoundField DataField="ModifiedDate" HeaderText="ModifiedDate"

56

SortExpression="ModifiedDate" /> </Columns> </asp:GridView> <asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:AdventureWorksConnectionString %>" SelectCommand="SELECT [ProductID], [Name], [Color], [ListPrice], [ModifiedDate] FROM [Production].[Product]" DeleteCommand="DELETE FROM [Production].[Product] WHERE [ProductID] = @ProductID" UpdateCommand="UPDATE [Production].[Product] SET [Name] = @Name, [Color] = @Color, [ListPrice] = @ListPrice, [ModifiedDate] = @ModifiedDate WHERE [ProductID] = @ProductID"> <DeleteParameters> <asp:Parameter Name="ProductID" Type="Int32" /> </DeleteParameters> <UpdateParameters> <asp:Parameter Name="Name" Type="String" /> <asp:Parameter Name="Color" Type="String" /> <asp:Parameter Name="ListPrice" Type="Decimal" /> <asp:Parameter Name="ModifiedDate" Type="DateTime" /> <asp:Parameter Name="ProductID" Type="Int32" /> </UpdateParameters> </asp:SqlDataSource> <asp:RadioButtonList ID="rblSecim" runat="server"> <asp:ListItem Value="0">Sadece bu kayõtlar</asp:ListItem> <asp:ListItem Value="1">İlk 50 kayõt</asp:ListItem> <asp:ListItem Value="2">Tüm kayõtlar</asp:ListItem> </asp:RadioButtonList> <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Kayõtlarõ Kaydet" Width="153px" /> 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 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 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, dolayõsõyla da download işleminde tüm kayõtlar dosyaya yazdõrõlabilecek. Sayfaya eklediğimiz butonun click eventine aşağõdaki kodlar eklendiğinde grid kontrolündeki verileri istenilen şekilde download işlemine hazõrlamõş oluruz. Kodlarõn en alt kõsmõnda da az sonra yazacağõmõz ve metinsel dosyaya kaydetme işlemini üstlenecek olan metodu çağõrõyoruz. private void GereksizKolonlariSil() { // Eğer Select, Edit ve Delete gibi CommandFieldlar aktif ise bu butonlarõn bulunduğu sütunu gridden kaldõrõyoruz. for (int i = 0; i < 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 == 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 düzenliyoruz; fakat az sonraki yapõlacak işlemlerde postback sonrasõ dosya download edileceği için sayfa

58

yenilenmeyecektir, dolayõsõyla da bizim design kõsmõnda yaptõğõmõz ayarlamalar geçerli kalacaktõr. Aşağõdaki kodlarda da grid içerisindeki verileri metinsel dosyaya kaydetme işlemini üstlenecek TextKaydet metodu bulunmaktadõr. 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 foreach (DataControlField cell in gvUrunler.Columns) { sb.Append(cell.HeaderText + " "); // HeaderText 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 &nbsp; karakterinin yazõlmasõnõ engellemek için kontrol yapõyoruz if (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("content-disposition", "attachment;filename=Urunler.txt"); Response.ContentType = "application/vnd.text"; Response.Write(sb.ToString()); Response.End(); }

59

Şekil: Sayfayõ çalõştõrdõğõmõzda işaretlediğimiz seçeneğe göre txt uzantõlõ dosyayõ bilgisayarõmõza indirebiliriz Böylece gridview içerisindeki kayõtlarõ okuma işlemini gerçekleştirerek alõnan bilgileri txt uzantõlõ olarak metinsel bir dosya içerisinde sunmuş olduk. Özellikle basit anlamda kullanõcõ arayüzlerinde yapõlan listeleme ve raporlama işlemlerinde işimizi görebilecek tarzda küçük bir web uygulamasõ geliştirmiş olduk. Benzer yollarla okunan verileri başka bir kaynağa (farklõ bir sunucudaki tabloya veya bir Excel dosyasõna gibi) aktarabiliriz.

60

GridView'deki Kayõtlarõ Excel Dosyasõna Aktarmak
02 Kasõm 2007 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 aklõmõza şu gelebilir: "GridView'in içeriği DataTable veya SqlDataSource gibi bir veri 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 verileri çok daha farklõ bir formatta tutan bir dosya tipi. İşin en güzel ve kolay tarafõ şu ki; kullanacağõmõz gridview nesnesi içerisindeki kayõtlarõ çok fazla işlem yapmamõza gerek kalmadan kolay bir şekilde Excel dosyasõna aktarabileceğiz. Bu işlemi yaparken iki farklõ yolu seçebiliriz: 1. GridView kontrolündeki satõrlarõ direkt olarak Excel dosyasõna aktarmak 2. GridView 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 satõrlarõnõ Excel dosyasõna nasõl aktaracağõmõza bakalõm. Sayfamõza bir gridview kontrolü, bir radiobuttonlist kontrolü ve buton kontrolü ekleyerek sayfamõzõ tasarlayalõm. Aşağõda sayfamõzõn görünümü bulunmaktadõr.

61

Şekil: Kullanacağõmõz sayfanõn tasarõmõ ve kontrol isimleri RadioButtonList'ten yapõlan seçim işlemine göre farklõ şekilde verileri Excel'e aktarmamõz gerekecek. Yine gridviewde Edit-Delete-Select gibi command butonlarõ içeren bir kõsõm olursa bu kõsmõ dosyaya yazdõrmak istemeyebiliriz. Bu işlem için GereksizKolonlariSil adõnda bir metot oluşturup, gridview kontrolünün dosyaya yazõlmaya hazõr hale getirilmesi işlemini aşağõdaki kodlarda görüldüğü gibi butonun click eventinde gerçekleştiriyoruz. Yapõlan işlemlerle ilgili bilgiler yorum satõrlarõnda bulunmaktadõr. protected void Button1_Click(object sender, EventArgs e) { // GridView'in footer kõsmõnõn Excel dosyasõnda görüntülenmesini istemiyorsak PagerSettings'i saklamamõz gerekli gvUrunler.PagerSettings.Visible = false; GereksizKolonlariSil(); if (rblSecim.SelectedIndex == 1) // İlk 50 kayõt { gvUrunler.PageIndex = 0; gvUrunler.PageSize = 50; } else if (rblSecim.SelectedIndex == 2) // Tüm kayõtlar gvUrunler.AllowPaging = false; gvUrunler.DataBind(); // Yapõlan değişikliklerin geçerli olmasõ için verileri tekrar 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 aktif ise bu butonlarõn bulunduğu sütunu gridden çõkarõyoruz for (int i = 0; i < gvUrunler.Columns.Count; i++) { if (gvUrunler.Columns[i] is CommandField) gvUrunler.Columns.RemoveAt(i); } } 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õyoruz gvUrunler.GridLines = GridLines.Both; // Gönderilecek cevaba gridin içeriğini yazdõrmak için gvUrunler kontrolünü render etmek gerekli. Bu işlemleri // StringWriter ve HtmlTextWriter nesnelerini ile yürütüyoruz. StringWriter, System.IO isim alanõ altõnda yer alõr StringWriter stringYaz = new StringWriter(); HtmlTextWriter htw = new HtmlTextWriter(stringYaz); gvUrunler.RenderControl(htw); // İstemciye gönderilecek cevabõ oluşturuyoruz. Öncelikli olarak cevapta(response'da) şu ana kadar oluşan // bilgileri silip, cevabõn başlõk bilgisine gönderilecek dosya ile ilgili bilgileri ekliyoruz. Dosya tipini belirttikten // sonra yukarõda oluşturulan StringWriter nesnesini ToString metodu ile cevaba yazdõrõyoruz Response.Clear(); Response.AddHeader("content-disposition", "attachment;filename=Urunler.xls"); Response.ContentType = "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õna yazdõrabiliriz. Fakat sayfayõ çalõştõrõp dosyaya aktarma işlemini yaptõğõmõz esnada bir hata almamõz gerekecektir. Zira yukarõda gvUrunler isimli gridviewõn RenderControl metodunu çalõştõrmamõz çalõşma zamanõ esnasõnda HttpException istisnasõna sebep olacaktõr.

63

Şekil: gvUrunler'in RenderControl metodunu kullanarak yaptõğõmõz işlem başarõsõz olacak ve çalõşma zamanõnda HttpException istisnasõ alacağõz Buradaki hatanõn sebebi ASP.NET sayfasõnõn yapõsõ itibariyle çalõşma zamanõ esnasõnda içerisinde bulunan bir kontrolü RenderControl metodu ile çözümlememize izin vermemesidir. Bu hatayõ düzeltebilmek için Page class'õ içerisinde virtual olarak tanõmlanmõş olan VerifyRenderingInServerForm isimli metodu ezmek(override işlemi) gerekecektir. Bu işlemi Visual Studio 2005 editöründe gerçekleştirdiğimizde metodun gövdesinde otomatik olarak base class'taki metodu çağõran base.VerifyRenderingInServerForm(control); ifadesi bulunacaktõr. Bu metot parametre olarak Control tipinden nesneler almaktadõr ki; bu nesneler sayfamõz içerisinde bulunan runat="server" tanõmlamasõ içeren sunucu kontrollerimizdir. Bizim burada yapmamõz gereken işlem metot içerisinde gelen kontrole bakmak ve eğer gridview kontrolü ise bu metodun çağrõlmasõnõ engellemek olacaktõr. Aşağõdaki kodlarda bu işlemi nasõl yapacağõmõz görülmektedir. public override void VerifyRenderingInServerForm(Control 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 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çerisinde 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 kolleksiyonundan alõyor ve tabloya ekliyoruz foreach (GridViewRow row in gvUrunler.Rows) { // GridViewRow class'õ TableRow class'õndan kalõtõldõğõ için Add metoduna parametre olarak verilebilir tablo.Rows.Add(row); } // Burada gridview yerine tablo nesnesini render ediyoruz StringWriter stringYaz = new StringWriter(); HtmlTextWriter htw = new HtmlTextWriter(stringYaz); tablo.RenderControl(htw); // Render edilen bilgileri htw nesnesine yaz Response.Clear(); Response.AddHeader("content-disposition", "attachment;filename=Urunler.xls"); Response.ContentType = "application/ms-excel"; Response.Write(stringYaz.ToString()); Response.End(); } Butonun click eventinde çağõrdõğõmõz GridiExceleKaydet metodu yerine 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 3.5 sürümüne geçişte bu denli büyük ve köklü yeniliklerimiz olmayacak. Fakat AJAX ve Linq temelli olarak ta iki köklü yeniliğin geldiğini de belirtmekte fayda var. Bir diğer konu da ASP.NET 3.5'in ardõndan yakõnda resmen duyurulmasõ beklenen ASP.NET 3.5 Extension paketi. (Belki de yazõyõ okuduğunuzda bu paket resmen duyrulmuş olacaktõr) ASP.NET MVC (Model View Controller) Framework, yeni AJAX ve veri kontrolleri ile SilverLight kontrollerinin ekleneceği bu paketinde mimariye dahil olmasõyla birlikte aslõnda daha da önemli yeniliklerin bizi beklediğini söyleyebiliriz. Makalemizin son kõsmõnda bu paket ile ilgili de önemli bilgileri sizlerle paylaşmaya çalõşacağõm. ASP.NET 3.5 ile gelen en önemli ve köklü iki yenilik AJAX Extension entegrasyonu ve Linq desteğidir. Aslõnda Linq C# 3.0 ile birlikte gelen bir yenilik ve platformdaki tüm uygulamalarda kullanabileceğimiz gibi ASP.NET uygulamalarõnda da kullanabileceğiz. Aşağõdaki başlõklarda gelen yenilikleri inceliyoruz.

1. ASP.NET AJAX Entegrasyonu
ASP.NET AJAX, ASP.NET ortamõnda hõzlõ ve kolay bir şekilde AJAX 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şik şekilde geliyor. Artõk temel sõnõf kütüphanelerimiz içerisinde AJAX kontrolleri ve tipleri de 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 System.Web.UI isim alanõna eklenmiş durumda. Aşağõda Microsoft'un sunduğu .NET Framework 3.5 isim alanlarõ ve sõnõflarõ posterinden System.Web.UI kesiti bulunmaktadõr. (ScriptManagerProxy ve Timer kontrolleri nedendir bilinmez bu postere eklenmemiş ama aşağõda güncellediğim posterin ilgili kesitini görebilirsiniz.)

Ş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õ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, 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 kullanarak sorgulamalar gerçekleş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 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.. 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): var - Nesne ve Koleksiyonlara İlk Değer Atayõcõ (Object and Collection 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, veri seçme-ekleme-güncelleme-silme gibi işlemleri yapabileceğimiz bir kontrol. İlk bakõşta GridView kontrolüne benzetebileceğimiz bu kontrolün GridView'den üç temel farklõlõğõ bulunmaktadõr. Bildiğimiz gibi GridView ile veri seç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 çözebilirken, DataList'te olduğu gibi de arka planda HTML kodlarõnõ kullanarak kontrolün görünümünü çok kolay şekilde istediğimiz gibi değiştirebiliyoruz. ToolBox'ta Data Controls kõsmõnda yer alan bu kontrolü basit bir şekilde nasõl kullanabileceğimizi görelim. Bu örnekte ListView'i bir SqlDataSource kontrolü ile SQL Server veritabanõndaki bir tabloya bağlõyoruz. Bu kõsõm aslõnda önceki veri kontrollerinde olduğu gibi, fakat bağlama işleminin ardõndan verilerin nasõl görüntüleceğini belirlememiz gerekecektir. ListView'in sağ üst köşesindeki Smart-tag ikonuna tõklayarak açõlan pencereden Configure ListView linkini seçiyoruz. Açõlan pencereden verilerin nasõl listeleneceğini, stil ayarlarõnõ ve veri ekleme, güncelleme, silme, sayfalama işlemlerini aktif hale getirip getiremeceğimizi belirliyoruz. Aşağõdaki resimde karşõmõza çõkacak pencere ve yapabileceğimiz seçimler görünmektedir.

69

Resim: ListView'in "Configure ListView" penceresinden yapõlacak seçimler ve açõklamalarõ Aslõnda yukarõdaki resimde ilk ilgimizi çekecek durumlardan birisi verileri artõk yan yana da dizebildiğimiz olabilir. ListView tõpkõ DataList kontrolü gibi arka planda HTML kodlarõ ile özelleştirilebildiği için artõk görüntülenecek verileri esnek şekilde kullanõcõlara görüntületebiliriz. Bu şekilde yine görsel kõsõmdan yapacağõmõz işlemlerle veriye çok kolay erişebiliriz. ListView ile ilgili olarak kullanabileceğimiz bazõ önemli özellikler (property) ve açõklamalarõnõ aşağõda bulabilirsiniz. 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 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ğõ HTML elementin ID bilgisini taşõr. LayoutTemplate, ItemTemplate, AlternatingItemTemplate, SelectedItemTemplate, InsertItemTemplate, 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. 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. ListView'in TemplateLayout şablonu içerisine eklenir. Temel olarak esnek sayfalama template hazõrlamamõzõ sağlayan bu kontrolde ToolBox'õn Data Controls grubunda yer alõyor. İki farklõ görünüm şekli bulunan bu kontrole eğer istenilirse TextBox, DropDownList gibi kontroller eklenerek özelleştirebiliriz. Örneğin toplam 20 sayfadan oluşan verilerimizde bir TextBox'a 15 yazarak 15 numaralõ sayfaya gidilmesini sağlayabiliriz. Burada akla gelen sorulardan birisi şu olabilir DataPager gibi etkin sayfalama işlemleri yapabilen bu kontrolü sadece ListView kontrolü ile birlikte kullanõlabiliyor.

- LinqDataSourceaSource
LinQ ile yapõlan sorgu sonuçlarõnõ veri kontrollerine bağlanmasõnõ sağlayan kontroldür. Aslõnda bu kontrolle birlikte .NET Framework 3.5 ve Visual Studio 2008 ile gelen yeni bir dosya tipinden bahsetmekte fayda olacaktõr: yeni bir dosya eklerken karşõnõza LINQ to SQL Classes tipi olarak gelen DataBase Markup Language (dbml) dosyalarõ. Gelişmiş bir projedeki en büyük ihtiyaçlarõmõzdan birisi de veritabanõndaki tablolarõn class olarak karşõlõklarõnõ uygulamamõzda oluşturmak olacaktõr. Aslõnda entity katmanõ oluşturarak daha kolay şekilde veri ile çalõşmaktan bahsediyoruz. dbml dosyalarõ veritabanõndaki bir tablonun tüm özelliklerini taşõyan class'õnõ oluşturmamõzõ sağlar. DataContext tipindeki nesneler üzerinde Linq sorgularõ çalõştõrabiliriz. LinqDataSource kontrolümüzde bu amaca yönelik kullanõlabilecek bir kontroldür.

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. Yine Visual Studio 2008'de yeni bir web projesi oluştururken WCF Service proje şablonu, projemize yeni bir dosya eklerken WCF Service dosyasõ (.svc) karşõmõza çõkan yeniliklerden bazõlarõ. ASP.NET 3.5 ile birlite gelen temel yenilikler bunlar. Gözümüze biraz az gelmiş olabilir ama Microsoft geçtiğimiz günlerde çõkardõğõ ASP.NET 3.5 Extensions paketi ile artõk ASP.NET 3.5'i daha da güçlü hale getirdi. Bu yeni paket ile gelen yeni kontroller ve MVC Framework ile artõk daha güçlü ve zengin web uygulamalarõ geliştirebiliyor olacağõz. Aşağõdaki kõsa yazõda ASP.NET 3.5 Extensions paketini tanõmaya çalõşõyoruz.

ASP.NET 3.5 EXTENSIONS
Aslõnda Microsoft bunun bir benzerini ASP.NET 2.0'õn ardõndan ASP.NET AJAX Extension'õ duyurarak yapmõştõ. Şimdi de benzeri bir strateji ile geliyorlar. AJAX ancak 3.5 sürümünde mimariyle bütünleşti, belki 3.5 Extensions ile gelen yenilikler de ASP.NET 4.0 (böyle bir sürüm olur mu bilinmez) ile bütünleşik gelecektir. Aslõnda ASP.NET 3.5 Extensions içerisinde daha önceden duyurulan ASP.NET Futures paketindeki kontroller ile ASP.NET MVC Framework'ün olduğunu söylesek pek te yanlõş olmaz. Aşağõda bizleri bekleyen yenilikleri hakkõnda kõsa bilgileri bulabilirsiniz. 1. ASP.NET MVC Framework: MVC yani Model View Controller. MVC mimarisi aslõnda daha önceden de duyulan bir tasarõm deseniydi (design pattern) programlama dünyasõnda. Bu yaklaşõmdaki temel mantõk bir web projesini üç temel parçaya bölmek ve yapõlacak işleri bu parçalar üzerinden yürütmektir. Hazõrladõğõmõz projelerde sõklõkla kullandõğõmõz uygulamayõ iş katmanõ ile veri katmanõ olarak ayrõ parçalara bölmeyi buradaki yaklaşõm ile benzeştirebiliriz. Aslõnda temel amaç uygulamayõ işe yarar belirli amaçlarõ olan parçalara bölmek ve bir parçanõn değişiminden diğer parçalarõn etkilenmesini engellemektir. MVC uygulamanõn Model, View ve Controller olarak üçe ayrõlmasõnõ benimseyen bir tasarõm desenidir. - Model veri ve durum bilgilerini taşõr. Burasõ DataTable, DataSet ve entity katmanõmõzdaki sõnõflarõn bulunduğu bileşendir. - View uygulamanõn arayüzlerinin bulunduğu bileşendir. Master sayfalar, aspx ve ascx gibi kullanõcõnõn görüntüleyeceği dosyalar bu kõsõmda yer alõr. - Controller ise arayüzler arasõndaki etkileşimi sağlayan, veri nesneleri üzerinde değişiklik yapõlmasõnõ sağlayan bileşenlerdir. Örneğin, Controller katmanõndaki sõnõflar aracõlõğõyla etkin URL Mapping işlemi yaparak artõk tarayõcõ üzerinden sayfalara istek yapmak yerine nesnelere istekte bulunabiliyoruz. Yani URL üzerinden tarayõcõda görüntülenecek nesnenin render edilmesi sağlanabiliyor. 2. ASP.NET AJAX Tarafõndaki Geliştirmeler: Futures paketinden tanõdõğõmõz History kontrolü bu paketin içerisinde 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ği: Yine Futures paketinden tanõdõğõmõz bir özellik. DynamicAutoData, DynamicList, DynamicNavigator, DynamicRssLink gibi bazõ veri kontrolleri ile bir veritabanõnda yapacağõmõz Select, Insert, Update, Delete gibi işlemleri neredeyse kod yazmadan gerçekleştirebilmemizi sağlõyor. .NET Framework 3.5 ile gelen Database Markup Language (dbml) dosyalarõ ile dinamik veri kontrollerini birlikte düşününce ve üstüne MVC Framework'ü de katõnca bu yeniliklerin MVC'nin Model katmanõnõ oluşturacağõnõ söyleyebiliriz. 4. SilverLight Desteği: SilverLight artõk ASP.NET ile giderek bütünleşiyor. Tahminen yine Futures paketindeki Media ve XAML kontrollerinin ekleneceği bu pakette ASP.NET ile SilverLight'õn entegrasyonunun daha da kolaylaşacak. Yani daha interaktif daha zengin içerikli sayfalar geliyor. 5. ADO.NET Veri Servisleri (Data Services): ADO.NET Entity Framework adõ verilen bu pakette ASP.NET 3.5 Extensions ile birlikte duyurulacak. Object Relation Mapping (ORM) desteği ile daha da güçlenen .NET Framework 3.5'teki veri işlemleri aslõnda bu framework altõnda toplanõyor gibi. Artõk veri ile ilgili her türlü işlemi oluşturacağõmõz veya SqlMetal.exe aracõ ile oluşturulacak class'lar ile gerçekleştireceğiz gibi. ASP.NET 3.5 Futures paketiyle ilgili daha detaylõ bilgi edinmek, bilgisayarõnõza yüklemek ve kullanmak için http://asp.net/downloads/3.5-extensions/ adresine göz atabilirsiniz.

73

TreeView'da Veritabanõyla ve XML Dosyalarla Çalõşmak
05 Şubat 2008 ASP.NET 2.0 ile birlikte gelen site navigasyonu kontrolleri ile site haritalarõnõn kullanõcõlara dinamik menülerle görüntülenmesi sağlanabilmekte ve daha profesyonel görünümler elde edilebilmektedir. Bu kontrollerden biri olan TreeView’da ağaç görünümünde menüler oluşturmamõzõ sağlamaktadõr. Genellikle proje içerisinde XML tabanlõ oluşturulan bir .sitemap dosyasõ ile birlikte kullanõlõr. Sitemap dosyalarõ gerek oluşturulmasõ gerekse site navigasyon kontrolleri ile kolay ve uyumlu çalõşmasõ açõsõndan biz yazõlõm geliştiricilere büyük kolaylõklar sağlamaktadõr. Sitemap dosyasõ belirli standartlar dahilinde yazõlmakta ve genellikle site içerisindeki linklerin hiyerarşik yapõsõnõ saklamaktadõr. TreeView kontrolü site haritasõnõ taşõmak amacõyla kullanõlabileceği gibi farklõ içerikleri de ilişkisel şekilde kullanõcõlara sunulmasõnõ da sağlayabilecek bir yapõya sahiptir. Örneğin kendi hazõrladõğõmõz XML dokümanõndaki verilerin süzülerek üst düğüm – alt düğüm ilişkisi ile bu kontrole yüklenmesini isteyebiliriz. Böyle bir durumda akla gelen soru TreeView kontrolünü farklõ yapõdaki XML dosyalarõ ile nasõl konuşturabileceğimizdir. Makalemizin ilk kõsmõnda bu sorunun çözümünü inceleyeceğiz. Site haritasõnõn sitemap dosyasõnda saklanmasõnõn bazõ dezavantajlarõ olduğunu da 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. Özellikle 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şturulmasõnõ sağlar. Aslõnda sayfa çalõştõrõldõğõnda TreeView’da görünen tüm linkler birer TreeNode nesnesidir. TreeNode nesnesi de kendi içerisindeki ChildNodes koleksiyonu içerisinde yine kendi tipinden yani TreeNode nesneleri taşõyabildiği için iç içe linkler oluşturulabilmektedir. Sitemap dosyasõnõ TreeView kontrolüne kaynak olarak gösterdiğimizde kullanõlan SiteMapDataSource kontrolünün yapmõş olduğu işlem .sitemap dosyasõnõn içerisindeki yapõyõ çözümlemek ve bunlarõ TreeNode nesneleri olarak TreeView kontrolüne bağlamaktõr. Aşağõdaki şekil TreeView kontrolüne bağlanan TreeNode’larõn yapõsõnõ simgelemektedir.

74

Şekil: TreeView kontrolüne eklenen TreeNode nesnelerinin hiyerarşik yapõsõ TreeNode sõnõfõnõn (class) yapõcõ metotlarõ (constructor) aracõlõğõ ile farklõ şekilde nesneler oluşturulabilir. Burada oluşturulan nesneler TreeView kontrolündeki linkler olacağõ için sayfa yüklendiğinde LinkButton veya HyperLink olarak getirilecektir. Dolayõsõyla oluşturulan link ya aynõ sayfa üzerinde postback işlemi yapacak ya da başka bir sayfaya link verecektir. Aşağõda bir TreeNode nesnesinin farklõ oluşturulma şekilleri bulunmaktadõr. // Oluşan linkin metnini ilk parametre belirler. Bu linke tõklandõğõnda Deger1 değeri ile postback işlemi yapar TreeNode anaMenu1 = new TreeNode("Postback Link", "Deger1"); // Bir önceki link gibi çalõşõr. Linkin sol kõsmõnda son parametrede yer alan resim görüntülenir TreeNode anaMenu2 = new TreeNode("Resimli Link", "Deger2", "menu.jpg"); // Oluşan link 4. parametrede belirlenen sayfaya gider. Son parametre ise hedef sayfanõn açõlma şeklini belirler (“_blank” yeni bir pencerede açõlmasõnõ sağlar). 3. parametre burada boş bõrakõlmõştõr fakat geçerli bir resim adresi verilerek linkin solunda resim görüntülenebilir TreeNode anaMenu3 = new TreeNode("Sayfaya Link", "", "", "Sayfa.aspx", "_blank"); 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 <form id="form1" method="post" runat="server"> <asp:TreeView ID="agacMenu" runat="server" /> </form> Default.aspx.cs // Ana düğüm oluşturuluyor TreeNode anaMenu1 = new TreeNode("Ana menü - 1", "", "", "AnaMenu1.aspx", "");

75

// Alt düğümleri oluşturmasõ için iki TreeNode nesnesi oluşturuluyor TreeNode altMenu1 = new TreeNode("Alt menü - 1", "", "", "AltMenu1.aspx", ""); TreeNode altMenu2 = new TreeNode("Alt menü - 2", "", "", "AltMenu2.aspx", ""); // Alt düğümler ana menü nesnesine ekleniyor anaMenu1.ChildNodes.Add(altMenu1); anaMenu1.ChildNodes.Add(altMenu2); // Oluşan ana menü sayfadaki agacMenu 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: Programatik ş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 <?xml version="1.0" encoding="windows-1254" ?> <KarargahDestekGrubu> <Birim Ad="Karargah Bölüğü"> <Asker Id="109" Ad="Ahmet YÜKSEL" /> <Asker Id="186" Ad="Metin DİLEK" /> <Asker Id="214" Ad="Umut NACAK" />

76

<Asker Id="304" Ad="Onb. Eyüp ERDEM" /> <Asker Id="319" Ad="Çvş. Uğur UMUTLUOĞLU" /> <Asker Id="341" Ad="Çvş. Muhammet KURT" /> </Birim> <Birim Ad="Muhafõz Bölüğü"> <Asker Id="177" Ad="Bahadõr ARSLAN" /> <Asker Id="192" Ad="Emrah USLU" /> <Asker Id="265" Ad="Çvş. Burak BATUR" /> <Asker Id="329" Ad="Onb. Osman ÇOKAKOĞLU" /> </Birim> <Birim Ad="Lojistik Destek"> <Asker Id="155" Ad="Onb. Bülent SÖZGE" /> <Asker Id="281" Ad="Çvş. Özgür ALTUNTAŞ" /> <Asker Id="299" Ad="Burak Selim ŞENYURT" /> </Birim> </KarargahDestekGrubu> Bu noktadan sonra XMLDataSource kontrolü ile dosyayõ TreeView'a bağlamamõz ve gerekli ayarlarõ yapmamõz gerekecektir. TreeView kontrolünün DataBindings koleksiyonuna eklenecek TreeNodeBinding nesneleri ile bu işlemi gerçekleş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 <asp:TreeView ID="AskerListe" runat="server" DataSourceID="XmlDSAskerListe"> <DataBindings> <asp:TreeNodeBinding DataMember="KarargahDestekGrubu" Text="Karargah Destek Grubu"></asp:TreeNodeBinding> <asp:TreeNodeBinding DataMember="Birim" TextField="Ad"></asp:TreeNodeBinding> <asp:TreeNodeBinding DataMember="Asker" TextField="Ad" ValueField="Id"></asp:TreeNodeBinding> </DataBindings> </asp:TreeView> <asp:XmlDataSource ID="XmlDSAskerListe" Runat="server" DataFile="Askerler.xml" /> 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. TreeView kontrolünün önemli özelliklerinden biri de listelenen linklere resim eklenebileceği gibi CheckBox gibi bir kontrolde eklenmesini sağ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. 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 <asp:TreeNodeBinding DataMember="Asker" TextField="Ad" ValueField="Id" ShowCheckBox="true"></asp:TreeNodeBinding>

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. Ö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 <asp:Button ID="btnSec" runat="server" Text="Çarşõ İznine Çõkacak Askerleri Seç" OnClick="btnSec_Click" />

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 node in AskerListe.Nodes[0].ChildNodes) { Response.Write(node.Value + " kõsmõndaki askerler:<br>"); // Her kõsõmda bulunan askerleri ele alõyoruz foreach(TreeNode altNode in node.ChildNodes) { if(altNode.Checked) // Eğer seçilmiş ise Response.Write(" - " + altNode.Text + "<br>"); } } }

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 askerlerin 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 bulunduğu ana kategorilerimiz olsun; Elektronik Eşya, Bilgisayar gibi... Yine bu ana kategorilerin altõnda da ürünlerimizi ayrõştõrmak için alt kategorilerimiz olsun; Bilgisayar kategorisinin altõnda Dizüstü Bilgisayar ve Masaüstü Bilgisayar gibi... Bu kategorilere aitte ürünlerimiz olsun. Yani 3 tane ana tablomuz içerisinde bu bilgiler saklansõn: Kategoriler, AltKategoriler ve Urunler. Aşağõdaki şekillerde örnekte kullanacağõm tablolarõn alan isimleri ve veri tipleri bulunmaktadõr.

Ş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 ş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\\TreeView_test\\Veriler.mdb");

80

OleDbDataAdapter daKat = new OleDbDataAdapter("Select * From Kategoriler", con); OleDbDataAdapter daAltKat = new OleDbDataAdapter("Select * From AltKategoriler", con); OleDbDataAdapter daUrunler = new OleDbDataAdapter("Select * From Urunler", con); // Tablolardan gelen verileri DataSet içerisine tablolar halinde dolduruyoruz DataSet ds = new DataSet(); daKat.Fill(ds, "Kategoriler"); daAltKat.Fill(ds, "AltKategoriler"); daUrunler.Fill(ds, "Urunler"); // Tablolar arasõnda ilişkili kolonlar üzerinden ilişkileri belirliyoruz ds.Relations.Add("Kat_AltKat", ds.Tables["Kategoriler"].Columns["KategoriID"], ds.Tables["AltKategoriler"].Columns["KategoriID"]); ds.Relations.Add("AltKat_Urun", ds.Tables["AltKategoriler"].Columns["AltKategoriID"], ds.Tables["Urunler"].Columns["AltKategoriID"]); 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 Nodes koleksiyonuna ekleyecek olursak menümüzü oluşturabileceğiz. Default.aspx <form id="form1" method="post" runat="server"> <asp:TreeView ID="tvMenu" runat="server" /> </form>

Default.aspx.cs private void Page_Load(object sender, EventArgs e) { DataSet dsMenu = MenuListe(); // Kategorileri oku foreach(DataRow dr in dsMenu.Tables["Kategoriler"].Rows)

81

{ TreeNode anaMenu = new TreeNode(dr["Ad"].ToString(), "", "", "Kategori.aspx?Id=" + dr["KategoriID"].ToString(), ""); // Alt kategorileri oku foreach(DataRow drAlt in dr.GetChildRows("Kat_AltKat")) { TreeNode altMenu = new TreeNode(drAlt["Ad"].ToString(), "", "", "AltKategori.aspx?Id=" + drAlt["AltKategoriID"].ToString(), ""); // Ürünleri oku foreach(DataRow drUrun in drAlt.GetChildRows("AltKat_Urun")) { TreeNode urunMenu = new TreeNode(drUrun["Ad"].ToString(), "", "", "Urun.aspx?Id=" + drUrun["UrunId"].ToString(), ""); altMenu.ChildNodes.Add(urunMenu); } anaMenu.ChildNodes.Add(altMenu); } tvMenu.Nodes.Add(anaMenu); } }

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. Burada bizim için en önemli noktalardan biri tabii ki veritabanõnda saklanan kayõtlarõn tablolarda ilişkisel bir şekilde saklanmasõdõr. Bu tip bir işlemi yukarõdaki şekilde gerçekleştirebileceğimiz gibi kendi Kategori, AltKategori ve Urun sõnõflarõmõzõ oluşturup her bir sõnõf içerisinde bir alt birimindeki nesnelere ait liste koleksiyonlarõnõ taşõyarak ta gerçekleştirebilirdik. 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 Bilinmeyenler
01 Mart 2008 ASP.NET 2.0 ile birlikte gelen site navigasyonu yapõsõ ve kontrolleri ziyaretçilerin site içerisinde kolay şekilde gezinmelerini sağlayacak menüler oluşturabilmemizi sağlamaktadõr. Projelerimizde pratik şekilde kullanabileceğimiz bu yapõlar birçok ihtiyacõmõzõ karşõlayacak özelliklere sahiptir. Fakat bazen kendi özel durumlarõmõza göre bu kontrolleri değiştirmek veya varolan yapõya ek nitelikler kazandõrmak isteyebiliriz. Aslõnda site navigasyonu hakkõnda birçoğumuzun bilmediği özellikler belki de bizim projelerdeki bu tip ihtiyaçlarõmõzõ karşõlayabilecektir. İşte bu makalede ASP.NET'te site navigasyonu hakkõnda bilinmeyen yönleri keşfetmeye çalõşacağõz. Aşağõda beş başlõkta bu konularõn detaylarõnõ inceleyoruz.

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. 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 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 <?xml version="1.0" encoding="windows-1254" ?> <siteMap> <siteMapNode url="Default.aspx" title="Anasayfa"> <siteMapNode url="Makale.aspx" title="Makaleler"> <siteMapNode url="Aspnet.aspx" title="ASP.NET" description="ASP.NET konusunda makaleler" /> <siteMapNode url="Adonet.aspx" title="ADO.NET" description="ADO.NET konusunda makaleler" /> <siteMapNode url="Cs.aspx" title="C#" description="C# konusunda makaleler" /> <siteMapNode url="SqlServer.aspx" title="SQL Server" description="SQL Server ile ilgili makaleler" /> </siteMapNode> <siteMapNode url="Videolar.aspx" title="Videolar" description="Teknik içerikli videolar"> <siteMapNode url="KonuAnlatimi.aspx" title="Konu Anlatõmõ" description=".NET içerikli görsel videolar" /> <siteMapNode url="Webiner.aspx" title="Webiner" description="Web seminerlerinin

84

videolarõ" /> </siteMapNode> <siteMapNode url="Forum.aspx" title="Forum" /> <siteMapNode url="Iletisim.aspx" title="İletişim" /> </siteMapNode> </siteMap> Sitenin genelinde şablon olarak kullanõlacak olan bir master sayfaya SiteMapPath, TreeView ve SiteMapDataSource kontrollerini ekleyerek sitemap dosyasõndan getirilen verileri sayfamõza yükleyelim. Sayfayõ çalõştõrõp sonucunu görerek neler yapabileceğimiz üzerinde yazõmõza devam edelim. Aşağõda sayfamõzõn kodlarõ ve çõktõsõ bulunmaktadõr. Sablon.master <form id="form1" method="post" runat="server"> <asp:SiteMapPath ID="SiteMapPath1" runat="server" /><br><br> <asp:TreeView ID="TreeView1" runat="server" DataSourceID="SiteMapDataSource1" /> <asp:SiteMapDataSource ID="SiteMapDataSource1" runat="server" /> </form>

Resim: Sitemap dosyasõndaki veriler SiteMapPath ve TreeView kontrolüne eklendi 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 yer alacağõ için TreeView'da en dõşta tüm node'larõ kapsayan Anasayfa node'unu göstermek istemeyebiliriz. Fakat sitemap dosyasõnda da en dõşta bir SiteMapNode bulundurmak gibi bir zorunluluğumuz olduğunu da belirtmiştik; yani web.sitemap'te bu linki bulundurmak zorunludur. Peki TreeView'dan bu linki nasõl kaldõrabiliriz? 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 ... <asp:SiteMapDataSource ID="SiteMapDataSource1" runat="server" ShowStartingNode="false" /> ...

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. SiteMapPath kontrolü SiteMapDataSource kontrolüne bağõmlõ çalõşmadõğõ için bu değişiklikten etkilenmez ve Anasayfa linkini görüntüler. Bazõ durumlarda da site haritasõndaki içeriklerin belirli kõsmõnõ görüntülemek 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. Sitemap

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: O an bulunulan 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 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ğu node'u ve alt node'larõnõ getirir. Değer olarak string tipinden sayfanõn adurl bilgisini almaktadõr. Belirli sayfalarda sadece belirli bir kategorinin ve alt kategorilerinin görüntülenmesi istenildiğinde kullanõlabilir. Örneğin sitede editör olan bir kişi siteye giriş yaptõğõnda menü kõsmõnda sadece Editorler.aspx sayfasõ ve bu sayfanõn altõnda kalan sayfalarõn görüntülenmesi istenildiğinde bu özellik "Editorler.aspx" değerine ayarlanabilir. Aşağõdaki kod örneklerinde yukarõda bahsedilen özelliklerin kullanõmõ görülmektedir. Kodlarõn hemen altõnda ise sayfanõn çõktõsõ bulunmaktadõr. Sablon.master (StartFromCurrentNode kullanõmõ) <asp:SiteMapDataSource ID="SiteMapDataSource1" runat="server" StartFromCurrentNode="true" />

Resim: StartFromCurrentNode true değeri aldõğõ için o an bulunulan kategori ve alt kategorileri getirildi

Sablon.master (StartingNodeUrl kullanõmõ) <asp:SiteMapDataSource ID="SiteMapDataSource1" runat="server"

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 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 <siteMap> <siteMapNode url="Default.aspx" title="Anasayfa"> <siteMapNode url="Default.aspx" title="Makaleler"> ...

88

Resim: Sitemap dosyasõnda aynõ URL bilgisini taşõyan iki node bulunduğu için hata oluştu Görüldüğü gibi web.sitemap dosyasõnda birden fazla URL kullanõmõna izin verilmez. Fakat bazõ durumlarda site haritasõnda aynõ linki birden kez fazla kullanma ihtiyacõ hissedebiliriz. Böyle bir durumda maalesef aynõ linkleri kullanma şansõmõz olmayacaktõr. Ancak kendi özel SiteMapProvider'larõmõzõ oluşturarak bu tip bir işlemi gerçekleştirebiliriz. Peki varolan yapõyõ kullanarak bu işlemi nasõl gerçekleştirebiliriz? Bu işlem için iki yol seçilebilir. Bunlardan ilki URL ReWriting ile farklõ url'leri aynõ sayfaya yönlendirme yapmak olabilir, fakat bu pek etkili bir yöntem olmayacaktõr. Zira aynõ linki 3-4 yerde kullanmak için farklõ URL ReWriting tanõmlamalarõ yapmak gerekebilir. Bir diğer yol ise asõl sayfa adresinin sonuna geçersiz QueryString'ler yazmak olacaktõr. Her ne kadar etkili ve tavsiye edilecek bir yol olmasa da böyle bir durumda kullanõlabilecek en kolay çözüm bu olacaktõr. Örneğin aynõ sayfayõ üç farklõ yerde kullanmak istersek Sayfa.aspx, Sayfa.aspx?1 ve Sayfa.aspx?2 gibi üç farklõ url kullanõp aynõ sayfaya link verebiliriz. Aşağõda web.sitemap dosyasõndaki url'lerin değiştirildiği ve sayfanõn düzgün şekilde çalõştõğõ görülebilir. Web.sitemap <siteMap> <siteMapNode url="Default.aspx" title="Anasayfa"> <siteMapNode url="Default.aspx?1" title="Makaleler"> ...

89

Resim: Sitemap dosyasõnda aynõ olan URL bilgilerinin sonuna geçersiz QueryString'ler eklendiğinde farklõ anahtar değerleri taşõndõğõ için aynõ sayfalar link verilebilir

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 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 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. Description: Title: Url: HasChildNodes: ChildNodes: ParentNode: NextSibling: Bulunulan sayfanõn description kõsmõndaki bilgi Bulunulan sayfanõn title kõsmõndaki bilgi Bulunulan sayfanõn url kõsmõndaki bilgisi 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 Eğer alt node'lara sahip ise bu node'larõn SiteMapNodeCollection tipinden listesinin getirir Bulunulan sayfa node'unun üst kõsmõnda yer alan sayfa node'unun SiteMapNode tipinden değerini getirir 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 site navigasyonu kontrollerinin bulunmasõ zorunlu değildir. Eğer o an 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. Sablon.master ... <br><asp:Label ID="lblSayfaBilgi" runat="server" ForeColor="Red"/> <br><asp:HyperLink ID="hlOnceki" runat="server" ForeColor="Blue"/> <asp:HyperLink ID="hlSonraki" runat="server" ForeColor="Blue"/> ... Sablon.master.cs protected void Page_Load(object sender, EventArgs e) { this.Title = SiteMap.CurrentNode.Title; if(!String.IsNullOrEmpty(SiteMap.CurrentNode.Description)) lblSayfaBilgi.Text = "<br>Bu sayfada " + SiteMap.CurrentNode.Description + " bulabilirsiniz.";

if(SiteMap.CurrentNode.PreviousSibling != null) { hlOnceki.Text = SiteMap.CurrentNode.PreviousSibling.Title + " <<"; hlOnceki.NavigateUrl = SiteMap.CurrentNode.PreviousSibling.Url; } if(SiteMap.CurrentNode.NextSibling != null) { hlSonraki.Text = ">> " + SiteMap.CurrentNode.NextSibling.Title;

91

hlSonraki.NavigateUrl = SiteMap.CurrentNode.NextSibling.Url; } }

SiteMap.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. 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 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 elde etmek için ekstra işlemler yapmak gerekir mi? Sitemap dosyalarõ içerisinde ek bilgileri kolay şekilde taşõyabilmektedir. Böyle bir durumda uygulama içerisinden bu bilgilere ulaşmak ise beklediğimizden daha kolay olacaktõr. Ek bilgileri saklamak için daha önceden bir yerlerde (SiteMap sağlayõcõsõ gibi) tanõmlama yapmaya gerek yoktur. Nasõl ki bir sayfanõn url bilgisini siteMapNode içerisinde tanõmlayabiliyorsak, bu bilgileri de aynõ şekilde tanõmlayabiliriz. Sayfa içerisinden okuma işlemini ise biraz farklõ bir yoldan ama oldukça basit bir şekilde gerçekleştirilebilir. Dilerseniz daha önceki örneklerde kullandõğõmõz sitemap dosyamõz üzerinde bir örnek yaparak bu

92

işlemleri nasõl gerçekleştirebileceğimizi görelim. Sitemizdeki kategorilerin her birisinde bulunacak editör bilgilerini sitemap dosyasõnda ilgili sayfanõn node'unda saklayõp, ziyaretçi bir kategoriyi gezdiğinde ilgili kategorinin editörünü sayfada görüntüleyeceğiz. Öncelikli olarak sitemap dosyasõndaki her bir kategori node'una Editor adõnda bir nitelik tanõmlõyor ve ilgili editörlerin isimlerini belirtiyoruz. Aşağõda web.sitemap dosyamõzõn bir kõsmõnda yapõlan değişiklikler görülmektedir. Web.sitemap ... <siteMapNode url="Makale.aspx" title="Makaleler"> <siteMapNode url="Aspnet.aspx" title="ASP.NET" description="ASP.NET konusunda makaleler" Editor="Uğur UMUTLUOĞLU" /> <siteMapNode url="Adonet.aspx" title="ADO.NET" description="ADO.NET konusunda makaleler" Editor="Burak BATUR" /> <siteMapNode url="Cs.aspx" title="C#" description="C# konusunda makaleler" Editor="Emrah USLU" /> <siteMapNode url="SqlServer.aspx" title="SQL Server" description="SQL Server ile ilgili makaleler" Editor="Bülent SÖZGE" /> </siteMapNode> ... 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 özellik (property) üzerinden değil de CurrentNode özelliğinin indeksleyicisi (indexer) üzerinden erişebiliriz. Aşağõdaki tek satõrlõk ifade bu bilgiyi 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 SiteMap.CurrentNode["Editor"] şeklinde okuyabilmekteyiz. Bu şekilde sitemap dosyasõnda farklõ nitelikler tanõmlayõp sayfa içerisinden kolay şekilde okunmasõnõ sağlayabiliriz. Aşağõda sayfamõzõn çõktõsõ görülmektedir.

Resim: web.sitemap dosyasõndan okunan Editor bilgisi sayfada 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 kullanõcõlarõn site içerisinde gezinmelerini kolaylaştõracaktõr. Fakat site navigasyon kontrollerini SiteMapDataSource kontrolü ile beslediğimizde sadece bir tane sitemap dosyasõ 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 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 C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG dizininde bulunan web.config dosyasõna bakõlacak olunursa <siteMap> 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. Öncelikli olarak web.config dosyamõza web2.sitemap isimli bir dosyayõ da kullanabilmemizi sağlayan tanõmlamayõ ekleyelim. <system.web> düğümü içerisine açacağõmõz <siteMap> düğümüne ekleyeceğimiz kodlar aşağõda görülmektedir. web.config <system.web> ... <siteMap> <providers>

94

<add name="SiteMapProvider2" siteMapFile="web2.sitemap" type="System.Web.XmlSiteMapProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/> </providers> </siteMap> </system.web> Bu şekilde artõk uygulamamõzda web.sitemap dosyasõ dõşõnda web2.sitemap dosyasõnõ da 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 dosyalarõna eklenen kodlar görülmektedir. web.sitemap <?xml version="1.0" encoding="windows-1254" ?> <siteMap> <siteMapNode url="Default.aspx" title="Anasayfa"> <siteMapNode url="" title="Üyelik İşlemleri"> <siteMapNode url="SifreDegistir.aspx" title="Şifre Değiştir" description="" /> <siteMapNode url="Profil.aspx" title="Profil Bilgileri" description="" /> </siteMapNode> <siteMapNode url="Haberler.aspx" title="Haberler" description=""> <siteMapNode url="YazilimHaberleri.aspx" title="Yazõlõm Dünyasõndan Haberler" description="" /> <siteMapNode url="SeminerHaberleri.aspx" title="Seminer Haberleri" description="" /> <siteMapNode url="Duyurular.aspx" title="Duyurular" description="" /> </siteMapNode> <siteMapNode url="KitapOneri.aspx" title="Kitap Önerileri" /> </siteMapNode> </siteMap>

Sablon.master ... <asp:Menu ID="Menu1" runat="server" DataSourceID="SiteMapDataSource2" FontNames="Verdana" Font-Size="12px"></asp:Menu> <asp:SiteMapDataSource ID="SiteMapDataSource2" runat="server" ShowStartingNode="False" SiteMapProvider="SiteMapProvider2" /> ...

95

Sayfayõ çalõştõrdõğõmõzda daha önceden hazõrladõğõmõz TreeView kontrolünün SiteMapDataSource1 kontrolü ile web.sitemap dosyasõndan, Menu kontrolünün ise SiteMapDataSource2 kontrolü ile web2.sitemap dosyasõndan getirilen verilerle doldurulduğunu görebiliriz. Aşağõda sayfamõzõn çõktõsõ bulunmaktadõr.

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.

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 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. 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. 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 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 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 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 kulüplerini, bir kulübe tõklandõğõnda da o kulübün 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 <form id="form1" runat="server"> <div> <table border="0" cellpadding="4" style="width: 100%"> <tr> <td width="250"> <asp:TreeView ID="tvLig" runat="server" ExpandDepth="0" OnTreeNodePopulate="tvMenu_TreeNodePopulate" ImageSet="Simple"> <NodeStyle Font-Names="Tahoma" Font-Size="10pt" ForeColor="Black" HorizontalPadding="0px" NodeSpacing="0px" VerticalPadding="0px" /> </asp:TreeView> </td> <td valign="top">

98

<asp:Label ID="lblOyuncuBilgiler" runat="server"></asp:Label> </td> </tr> </table> </div> </form> TreeView kontrolü ilk yüklendiğinde sadece en üst seviyedeki node'lar gelecektir. Sayfamõzõn code-behind dosyasõnda yazacağõmõz kodlarla TreeView'a liglerin yüklenmesini sağlõyoruz. Default.aspx.cs public partial class _Default : System.Web.UI.Page { string yol; protected void Page_Load(object sender, EventArgs e) { yol = Server.MapPath("~/App_Data") + "/Spor.mdb"; if(!IsPostBack) LigleriYukle(); } private void LigleriYukle() { OleDbConnection con = new OleDbConnection("Provider=Microsoft.Jet.OleDB.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(), dr["LigID"].ToString()); kategori.PopulateOnDemand = 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 adõndaki TreeView kontrolüne veriler eklendi. Buradaki en önemli noktalardan bir tanesi de eklenen TreeNode nesnelerine ait PopulateOnDemand ("isteğe göre besle" diyebiliriz) özelliğidir. bool tipinden değer alan bu özelliği true belirlememiz durumunda eklenen ligler istek geldikçe alt node'larõnõ getirecektir. Oluşturulan lig node'larõna text olarak Ad, value olarak LigID değerlerini atayõp PopulateOnDemand özelliğine true değerini verdikten sonra tvLig adõndaki TreeView kontrolüne ekledik. Sayfanõn sorunsuz şekilde çalõşmasõ için TreeNodePopulate olayõnõ bağladõğõmõz tvMenu_TreeNodePopulate metodunu şimdilik içi boş bir şekilde tanõmladõk. Sayfa çalõştõrõldõğõnda sadece liglerin TreeView'a eklendiğini göreceğiz.

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 olayõ tetiklenecek ve code-behind sayfamõzda yazdõğõmõz tvMenu_TreeNodePopulate metodu çağrõlacaktõr. Bu metodun parametrelerine bakacak olursak ikinci parametrenin TreeNodeEventArgs tipinden e adõnda bir nesne olduğunu görürüz. e nesnesine ait Node özelliği tõklanõlan node'un nesne örneğini getirecektir. Örneğin Türkiye Süper Lig'e tõklanmasõ durumunda bu node'un nesne örneğine TreeNode tipinden erişebiliriz. Lige ait kulüpleri veritabanõndan çekerek ChildNodes koleksiyonuna eklememiz durumunda artõk kulüpler ligin alt node'larõ olarak eklenecektir. Bir sonraki adõmda da bir kulübe tõklandõğõnda oyuncular listeleneceği için burada tõklanõlan linkin lig mi olduğu yoksa kulüp mü olduğunun ayõrt edilmesi gerekecektir. Eğer bir lige tõklanmõşsa Kulupler tablosundan, bir kulübe tõklanmõşsa da Oyuncular tablosundan veriler getirilecektir. TreeNode nesnesine ait Depth özelliği elde edilen node'un hiyerarşik olarak hangi derinlikte olduğunu belirtmektedir. Ligler TreeView'da 0. derinlikte, kulüpler ise 1. derinliktedir. Bu durumu da göze alarak aşağõdaki şekilde sayfamõzõn kodlarõna eklemeler yapõyoruz.

100

Default.aspx.cs protected void tvMenu_TreeNodePopulate(object sender, TreeNodeEventArgs e) { 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); } private void KulupleriYukle(TreeNode ligNode) { OleDbConnection con = new OleDbConnection("Provider=Microsoft.Jet.OleDB.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(), dr["KulupID"].ToString()); kategori.PopulateOnDemand = true; kategori.SelectAction = TreeNodeSelectAction.Expand; ligNode.ChildNodes.Add(kategori); } con.Close(); } private void OyunculariYukle(TreeNode kulupNode) { OleDbConnection con = new OleDbConnection("Provider=Microsoft.Jet.OleDB.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=" + dr["OyuncuID"].ToString(); TreeNode kategori = new TreeNode(dr["Ad"].ToString(), "", "", navigateUrl, ""); kulupNode.ChildNodes.Add(kategori); } con.Close(); } Görüldüğü gibi kulüplerin getirilmesi KulupleriYukle, oyuncularõn getirilmesi OyunculariYukle adõndaki iki metot ile gerçekleştiriliyor. Her iki metoda da parametre olarak tõklanõlan TreeNode nesnesi 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.

Resim: Kullanõcõdan gelen isteklere göre TreeView içeriği dinamik şekilde dolduruldu Tüm verilerin bir defada gelmediğini görebilmek için sayfa götürülendikten sonra Kaynağõ Görüntüle seçeneğinden sayfanõn HTML kodlarõ kontrol edilebilir. Yine linklere tõklandõğõnda TreeNodePopulate olayõnõn tetiklenmesini de tvMenu_TreeNodePopulate metoduna bir

102

breakpoint ekleyerek görebiliriz.

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 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 etiketine yazdõrabiliriz. Bu işlemi Page_Load metodu içerisinde gerçekleştiriyoruz. Aşağõda sayfaya eklenen kodlar ve sayfanõn çõktõsõ yer almaktadõr. Default.aspx.cs protected void Page_Load(object sender, EventArgs e) { ... if (Request.QueryString["OyuncuID"] != null) OyuncuBilgileriniGetir(Request.QueryString["OyuncuID"].ToString()); } private void OyuncuBilgileriniGetir(string oyuncuID) { 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() + "<br>Doğum Tarihi: " + dr["DogumTarih"].ToString() + "<br>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. 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 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 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. Default.aspx ... <asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager> <asp:UpdatePanel ID="UpdatePanel1" runat="server"> <ContentTemplate> <asp:TreeView ID="tvLig" runat="server" OnTreeNodePopulate="tvMenu_TreeNodePopulate" ImageSet="Simple" ExpandDepth="0" PopulateNodesFromClient="False"> <NodeStyle Font-Names="Tahoma" Font-Size="10pt" ForeColor="Black" HorizontalPadding="0px" NodeSpacing="0px" VerticalPadding="0px" /> </asp:TreeView> </ContentTemplate> </asp:UpdatePanel> <asp:UpdateProgress ID="UpdateProgress1" runat="server" DisplayAfter="0"> <ProgressTemplate> Veriler yükleniyor. Bekleyiniz... </ProgressTemplate> </asp:UpdateProgress> ...

105

Resim: Dinamik yükleme işleminin UpdatePanel ve UpdateProgress ile gerçekleştirilmesi TreeView kontrolüne dinamik veri ekleme işlemini ASP.NET AJAX kontrolleri ile gerçekleştirmeyi de görmüş olduk. Bu makalemizde TreeView kontrolüne kullanõcõdan gelen isteklere göre dinamik şekilde veri ekleme işlemini inceledik. Özellikle çok sayõda node'lardan oluşan yapõlarda TreeView kontrolünün içeriğini dinamik şekilde oluşturmak uygulamanõn performansõ açõsõndan oldukça önemli olabilmektedir.

106

ASP.NET AJAX
Anahtar kelimeler
AJAX Mimarisi

ASP.NET AJAX Mimarisi
ScriptManagerProxy XMLHTTPRequest

Atlas

JavaScript

ScriptManager UpdateProgress

Timer

UpdatePanel

107

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öndermeden (postback atmadan) ya da yeni bir URL çağõrmadan sadece sayfamõzõn gerekli olan kõsmõnda değişiklikler yapabiliyorduk. Son zamanlarda www.start.com, www.virtualearth.com ve Google Suggest gibi birçok sitede bu teknolojinin örneklerini sõkça görüyoruz. Bu sitelerde ortak olan nokta, sayfalarõn çoğunun server tarafõna tamamen gönderilmeden, sadece güncellenecek olan kõsmõnõn server tarafõndan gelen bilgi ile yenilenmesidir. Bu teknolojiyi ASP .NET ile geliştirdiğimiz sayfalara kolay şekilde entegre edebileceğimiz bir teknoloji var mõ diye sorarsanõz, cevabõ; artõk evet:) Microsoft’un Visual Studio 2005 ve ASP .NET 2.0 ile gelen yeni vizyonunda artõk yazõlõm geliştirme kõsmõnda programcõnõn yükünün olabildiğince azaltõlmasõ, hazõrlanan projenin daha etkili ve daha hõzlõ şekilde geliştirilmesi amaçlanõyordu. İşte bu doğrultuda ASP .NET ekibi, ASP .NET 2.0’õn resmi olarak duyurulmasõnõn hemen ardõndan ATLAS’õn beta sürümünü de duyurdu. ATLAS adõ verilen bu eklenti, ASP .NET 2.0 Web Uygulamalarõnda AJAX teknolojisini çok kolay bir şekilde ve neredeyse hiç kod yazmaksõzõn kullanõlabilir hale getirdi. Web 2.0 sürümünün dillerden düşmediği son zamanlarda web dünyasõna yeni bir heyecan ve soluk getiren AJAX teknolojisi, ASP .NET - ATLAS sayesinde artõk çok kolay şekilde uygulamalara eklenebilir oldu. AJAX web uygulama geliştiriciler için çok önemli ve heyecan verici bir gelişme olmasõna rağmen getirdiği bazõ sõnõrlamalarõ ve zorluklarõ da vardõ. Tarayõcõ tipine göre farklõ DOM objeleri tanõmlamak, uygulamayõ geliştirebilmek için ileri sayõlabilecek düzeyde JavaScript kodu yazmak gibi... ATLAS bu kõsõtlamalarõ ve zorluklarõ ortadan kaldõrdõğõ gibi, aynõ zamanda nesne tabanlõ bir ortam olan .NET Framework'ün nimetlerinden de faydalanmamõzõ sağladõ. 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ğ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 nasõl ulaşabileceğimizi ve nasõl kurup kullanabileceğimizi anlatmaya çalõşacağõm. Daha önceden de bahsettiğim gibi ATLAS şu an hala geliştirme aşamasõnda olan ve tam sürüm olarak henüz piyasaya sürülmemiş olan bir ürün. Ürünü geliştiren ekip genellikle her ay içerisinde yenilenmiş sürümünü ATLAS'õn resmi sitesi olan http://atlas.asp.net adresinden ücretsiz olarak download edilebilir halde duyuruyorlar. Yine bu adresten bu ürün ile ilgili bir çok demo videoya ve yazõlõ kaynağa ulaşabilirsiniz. Download bölümünden ATLAS Setup linkinden ASP.NET “Atlas” March Community Technology Preview (CTP) dosyasõnõ ücretsiz olarak indirip bilgisayarõnõza kurabilirsiniz. Visual Basic .NET ve C# .NET dilleri ile uygulama geliştirmenizi sağlayan bu kurulumu tamamladõktan sonra, Visual Studio 2005'te yeni bir Web Site Projesi açacak olursanõz, önceki ekranlardan farklõ olarak My Templates'in altõnda Atlas Web Site adõnda bir template olduğunu göreceksiniz. Bu seçeneği seçerek yeni bir ATLAS uygulamasõ açabilir, kontroller ve uygulama üzerinde ekli olarak gelen dosyalar sayesinde sayfalarõnõzda ATLAS'õ kullanabilirsiniz.

109

Resim: Atlas Web Site Template'in seçilmesi ATLAS önümüzdeki günlerde adõndan daha çok bahsedilecek, üzerinde durulmasõ gereken ve önümüzdeki yõllarda uygulamalarõmõzda sõk sõk kullanacağõmõz çok yeni bir teknoloji. Umarõm bu yeni teknolojiyi genel olarak sizlere iyi ve anlaşõlõr bir şekilde aktarabilmişimdir. ATLAS'õn en son çõkan sürümünde (şu an için Mart ayõnda çõkan sürümü) birkaç yeni kontrol daha eklendi. Bu yazõda ATLAS kontrollerinden en çok kullanõlanlarõ olan ScriptManager, UpdatePanel, UpdateProgress ve TimerControl kontrollerine göz atacağõz.

ScriptManager
Sayfalarõmõzda ATLAS'õ kullanmamõzõ sağlayan ve her sayfaya mutlaka eklenmesi gereken kontroldür. Sayfamõzdaki ATLAS kontrollerinin doğru olarak çalõştõrõlabilmesi için bu kontrolümüzü sayfamõzõn en üst kõsmõna eklemiş olmamõz gerekmektedir. <atlas:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="True" > Kullanõmõna bakacak olursak; buradaki en önemli özellik 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 nimetlerinden faydalanamayacaktõr. Yine <atlas:ScriptManager> kontrolü sayesinde sayfamõzõ bir web servisine bağlayabilir ve uygulamalarda sayfamõzõ bu web servisi ile konuşturabiliriz. <atlas:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="True" > <Services> <atlas:ServiceReference path="MyWebService.asmx" type="text/javascript" />

110

</Services> </atlas:ScriptManager>

UpdatePanel
Sadece kendi içerisindeki alanõn güncellenmesini sağlar. İçerisine eklenmiş olan HTML kodlarõ ve ASP .NET kontrolleri dahil olmak üzere herşeyi, bir olay tetiklendiği anda ya da bir değişiklik olduğu anda tekrar güncellemektedir. UpdatePanel içerisinden güncellenen bir sayfa tamamen sunucu tarafõna gönderilmez (post-back olmaz) ve bu olay esnasõnda UpdatePanel'in dõşõndaki hiçbir alan güncellenmez. .... Güncellenmeyecek içerikler ..... <atlas:UpdatePanel ID="UpdatePanel1" runat="server"> <ContentTemplate> <asp:Label ID="lblZaman" runat="server"></asp:Label> </ContentTemplate> <Triggers> <atlas:ControlEventTrigger ControlID="Button2" EventName="Click" /> </Triggers> </atlas:UpdatePanel> .... Güncellenmeyecek içerikler ..... UpdatePanel alt elementi olan <ContentTemplate> ile birlikte kullanõlmaktadõr. UpdatePanel'de güncellenecek olan kõsõm sadece <ContentTemplate> içerisinde tutulmaktadõr. Yani değiştirilecek bilgilerimizin, kodlarõmõzõn ve kontrollerimizin tamamen bu elementin içerisinde tutulmasõ gerekmektedir. <Triggers> 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 trigger olarak eklenmiş. Yani Button2'ye tõkladõğõmõzda UpdatePanel güncellenebilecek. Eğer Button2'nin Click olayõnõ UpdatePanel'e eklemezsek, bu butona tõkladõğõmõzda tüm sayfa yeniden yüklenecektir. (Button2'yi <ContentTemplate> 'in içerisine koymuş olsaydõk, trigger eklememize gerek kalmayacaktõ ) Ö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õn yapõlmõş olduğunu görebilirsiniz. - Uygulamaya geçecek olursak, Default.aspx dosyasõnõn en üst kõsmõna öncelikle bir

111

<atlas:ScriptManager> kontrolü ekleyelim ve bu kontrolün EnablePartialRendering özelliğini True yapalõm. - Daha sonra sayfamõza bir <atlas:UpdatePanel> kontrolü ekleyelim. <ContentTemplate> 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 içerisindeki <Triggers> alt elementine ControlEventTrigger olarak ekleyelim. (Aşağõdaki örnekteki gibi) <atlas:UpdatePanel ID="UpdatePanel1" runat="server"> <ContentTemplate> <asp:Label ID="lblZaman" runat="server"></asp:Label><br /> <asp:Button ID="Button1" runat="server" Text="Zamanõ Güncelle" /> </ContentTemplate> <Triggers> <atlas:ControlEventTrigger ControlID="Button2" EventName="Click" /> </Triggers> </atlas:UpdatePanel> - 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 anladõğõmõzõ umuyorum. UpdatePanel'in içerisine farklõ kontroller (Calendar, Gridview, vb.) ekleyerek sayfanõn çalõşmasõnõ tekrar gözlemleyebilirsiniz.

UpdateProgress
Bu kontrol ise UpdatePanel'de güncelleme işlemi yapõldõğõnda ziyaretçiye güncelleme işleminin yapõldõğõnõ gösteren kontroldür. Örneğin bir güncelleme işlemi yapõldõğõnda "Yükleniyor" "Güncelleniyor" şeklinde bir yazõnõn ya da benzer bir resim dosyasõnõn görünmesini istiyorsanõz bu kontrol sayesinde bu işlemi yapabilirsiniz.

112

<atlas:UpdateProgress ID="UpdateProgress1" runat="server"> <ProgressTemplate> <img src="images/indicator.gif" /><br /> Bilgiler güncelleniyor.....<br /> </ProgressTemplate> </atlas:UpdateProgress> Örnek koda bakacak olursak, UpdateProgress kontrolünün alt elementi olan 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.

TimerControl
TimerControl adõndan ve konumuzun gidişatõndan da tahmin edebileceğimiz üzere, sayfamõzõn post-back atmaksõzõn, belirli aralõklarla UpdatePanel kontrolündeki bilgilerin güncellenmesini sağlayan kontroldür. Belirttiğimiz zaman aralõklarõnda sayfamõzdaki UpdatePanel'in içerisindeki bilgileri güncellenmesini sağlar. <atlas:TimerControl runat="server" Interval="5000" ID="TimeControl1">

<Triggers> <atlas:ControlEventTrigger ControlID="Button2" EventName="Click" /> <atlas:ControlEventTrigger ControlID="TimerControl1" EventName="Tick" /> </Triggers> Yukarõdaki kodlardan ilkine bakacak olursak, burada sayfamõza bir ATLAS TimerControl kontrolü eklemiş bulunuyoruz. Interval değeri ile Timer'õmõzõn ne kadar sürede bir tetikleneceğini belirtiyoruz. Interval="5000" tanõmlamasõndaki 5000 aslõnda 5 saniyeye eşit. Yani her saniye için değerimizi 1000 değer arttõrmamõz gerekecek. Bu sayede UpdateControl'ümüzü timer aracalõğõ ile tetikleyebiliyoruz. Yalnõz az önce de bahsetmiş olduğum gibi, UpdateControl'ün dõşarõdaki bir değişiklikle güncellenmesi için UpdatePanel kontrolümüze trigger eklememiz gerekiyordu. Burada da Timer kontrolümüz için UpdatePanel'imizin <Triggers> elementine gerekli kodlarõ eklememiz gerekecek. (Alt

113

kõsõmdaki kodlardan görebilirsiniz.) Buradaki EventName değerine dikkat edecek olursak Tick değerini görüyoruz. Tick TimerControl1 kontrolümüzün bir eventi. Buradaki örnekte Timer kontrolümüzün her 5 saniyede bir Tick eventi çalõşacak ve UpdatePanel'imizdeki değerler tüm sayfa post-back olmadan, ya da biz buton vb. bir kontrole müdahale etmeden güncellenecektir.

114

AJAX: Asenkron JavaScript ve XML
18 Ocak 2007 Son zamanlarda özellikle web programcõlõğõ ile ilgilenenlerin sõklõkla duyduğu bir terim AJAX. Microsoft’un tam sürümünü çõkarmaya hazõrlandõğõ ve yeni nesil web sayfalarõnda sõklõkla kullanacağõmõz ASP .NET AJAX’a geçiş yapmadan önce AJAX adõ verilen uygulama geliştirme yaklaşõmõnõ ele almamõz, temellerini öğrenmemiz iyi olacaktõr. Peki nedir AJAX? Bizlere nasõl bir teknoloji ve ne gibi yenilikler sunuyor? AJAX aslõnda yeni bir programlama dili ya da programlama aracõ değildir. Daha önceden de var olan bazõ teknolojileri kullanarak bize nasõl uygulama geliştireceğimizi gösteren yeni bir programlama modelidir. AJAX yani Asenkron JAvascript ve XML, temel olarak JavaScript dilindeki XMLHTTPRequest nesnesini kullanarak web sayfalarõ üzerinde asenkron bir şekilde veri iletişimini sağlayan programlama modelidir. Yani bir web sayfasõ yüklendikten sonra, aynõ sayfa üzerinde iken arka tarafta sunucu ile iletişime geçmeyi ve veri transferi yapmamõza olanak sağlar. Dilerseniz bu kõsmõ biraz daha açmak için klasik modelde programlanan bir web sayfasõnõn ve AJAX modelinde programlanan bir web sayfasõnõn nasõl çalõştõğõnõ inceleyelim.

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 planda asenkron bir şekilde sunucuya istekte bulunur(3). Sunucudan alõnan bilgi yine asenkron bir şekilde getirilir ve gelen yeni içerik ile birlikte sayfamõzda ilgili kõsõmlar güncellenir(4). Bu sayede yeni bir istek durumunda web sayfamõz sadece güncelleyeceğimiz verileri alacaktõr. Sayfa tamamen PostBack işlemi tabi tutulmayacaktõr, kõsmi bir PostBack işlemi gerçekleşecektir ve sayfanõn tamamen yenilenmesine gerek kalmayacaktõr. Bu işlem süresinde sayfa tamamen PostBack edilmeyeceği için farklõ bir sayfa beklemesi olmayacak ve aynõ sayfa üzerinde kalõnacaktõr. (Aşağõdaki şekilde AJAX çalõşma modeli anlatõlmõştõr.)

İki çalõşma modelini ele alõrsak AJAX bizlere klasik çalõşma modeline göre daha hõzlõ ve verimli bir çalõşma ortamõ sunmaktadõr. İstemciye sadece sayfanõn güncelleyeceğimiz kõsmõnõ getirildiğimiz için daha küçük veri parçalarõnõn transfer edilmesiyle sunucu ve istemci arasõndaki trafik azalmakta ve sayfalar daha hõzlõ bir şekilde yenilenmektir. Yine sayfamõzõ ziyaret eden kullanõcõlar aynõ sayfa üzerinde kalacaklarõ için site ile etkileşimleri artacaktõr. Bu sayede artõk web uygulamalarõ masaüstü uygulamalarõn sağladõğõ hõza ve zenginliğe giderek yaklaşmaktadõr.

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 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 nesnesinin sadece Internet Explorer’da bulunmasõ ve diğer tarayõcõlarõn bu nesneyi yapõsõnda bulundurmamasõ nedeniyle AJAX neredeyse hiç kullanõlmamõştõ. Son 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, Google 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’õ 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 nesnesini kullanõr. XMLHTTPRequest web tarayõcõsõ üzerinde bulunan bir bileşendir. JavaScript dilindeki XMLHTTPRequest nesnesi aracõlõğõ ile bu bileşeni kullanabilmekteyiz. Bu nesne sayfa yüklendikten sonra istemci ve sunucunun asenkron şekilde haberleşmesini sağlar. İstemci tarafõndaki web tarayõcõsõ, sunucudan asenkron şekilde veri isteğinde bulunur.(Request) Sunucu tarafõnda ise alõnan isteğe göre bir çõktõ üretilir ve veriler yine asenkron şekilde istemcinin web tarayõcõsõna gönderilir.(Response) Alõnan veriler DOM(Document Object Model) ve Javascript sayesinde dinamik bir şekilde sayfaya yüklenmesi sağlanõr. Bu esnada sayfada kõsmi PostBack işlemi olmakta ve yapõlan işlemler sayfanõn arka tarafõnda yapõlmaktadõr. İşlem süresince tarayõcõdaki sayfa aynen kalmakta ve sadece güncellenen alanlarda değişiklikler olmaktadõr.

XMLHTTPRequest Nesnesini İnceleyelim
XMLHTTPRequest nesnesi JavaScript’in içerisinde bulunan bir yapõdõr. Bu nesne 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õr. Bunlar da onreadystatechange eventhandler’õ ve readystate özelliği. Gelin isterseniz XMLHTTPRequest nesnesinin üyelerinin kullanõmõnõ ve AJAX modelini bir web sayfasõna nasõl 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 <body> içerisine bir tane span elementi ve tipi buton olan bir input elementi ekleyelim. <span id="lblGuncelle"></span> <input type="button" value="Güncelle" onclick="AsenkronCagriYap()" /> 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 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.XMLHTTP”) ve 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.XMLHTTP"); IE 5.5 sürümleri için ise aşağõdaki tanõmlama yapõlõr. var nesne = new ActiveXObject("Microsoft.XMLHTTP"); Mozilla, Opera, Safari gibi tarayõcõlar için ise aşağõdaki tanõmlama yapõlõr. var nesne = new XMLHTTPRequest(); Buradan şöyle bir sonuç çõkõyor. İstemci tarafõnda farklõ tarayõcõlar olabileceği için bizim bu ihtimali düşünüp yazacağõmõz fonksiyonda yukarõdaki tüm ihtimalleri denemeliyiz. Bunun için JavaScript içerisinde try-catch bloklarõ yazarak tarayõcõya göre yeni bir nesne oluşturmalõyõz. (Aşağõdaki kod üzerinde çok fazla dõrmaya gerek yok. Zira buradaki try-catch yapõsõ C# .NET ve VB .NET’teki yapõyla hemen hemen aynõdõr.) function NesneOlustur() { var nesne; try { nesne = new ActiveXObject("Msxml2.XMLHTTP"); // IE 6.0+ tarayõcõlar için } catch(e) { try {

118

nesne = new ActiveXObject("Microsoft.XMLHTTP"); // IE 5.5 tarayõcõlarõ için } catch(e) { try { nesne = new XMLHTTPRequest(); // Firefox, Opera 8.0+ ve Safari tarayõcõlarõ için } catch(e) { alert("Tarayõcõnõz AJAX'õ desteklemiyor!!!"); return null; } } } return nesne; } Yukarõdaki JavaScript fonksiyonu bize istemcinin kullandõğõ tarayõcõya göre oluşturacağõ 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”, “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 gönderilecek veriyi taşõyabilir. Send metodunu parametresiz veya null parametresi ile de 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 içerisinde bulunan onreadystatechange eventhandler’õ ve readystate özelliğini kullanmamõz gerekiyor.

119

onreadystatechange eventhandler’õ sunucuya istekte bulunduktan sonraki durum değişikliklerini yakalar. Burada bahsettiğimiz durumlar ise 5 tanedir ve bu durumlarõ readystate özelliğini kullanarak elde edebiliriz. Bu durumlar; 0 = İstek hazõrlanmadõ 1 = İstek hazõrlandõ 2 = İstek gönderildi 3 = İstek değerlendiriliyor ve sonuç bekleniyor 4 = İstek tamamlandõ ve sonuç geldi 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 = function { if (nesne.readystate == 4) { // sonucu HTML’e yazdõr } } Artõk HTML kodumuzdaki buton içerisinden çağõracağõmõz AsenkronCagriYap() fonksiyonunu oluşturabiliriz. function AsenkronCagriYap() { var yeniNesne = NesneOlustur(); // XMLHTTPRequest nesnemizi oluşturduk // Bulunacağõmõz isteği açõyor ve sunucuya gönderiyoruz. İsteğimiz aynõ dizinde bulunan Ogrenciler.htm adresine, GET metodunu kullanarak gerçekleşiyor. yeniNesne.open("GET","Ogrenciler.htm",true); yeniNesne.send(null); // Yeni bir fonksiyon yazmamõza gerek kalmadan onreadystatechange olayõnõ isimsiz bir fonksiyona bağlõyoruz yeniNesne.onreadystatechange = function() { // Eğer readystate 4 değerine sahipse asenkron işlem bitmiş ve veriler getirilmiş demektir if(yeniNesne.readystate == 4) { // Getirilen veriyi HTML kõsmõndaki lblGuncelle içerisine dinamik bir şekilde yazdõrõyoruz document.getElementById('lblGuncelle').innerHTML = yeniNesne.responseText; } } }

120

Son olarak belirtmemiz gereken nokta ise document.getElementById('lblGuncelle'). innerHTML şeklinde HTML kõsmõndaki lblGuncelle span elementine ulaşõyor ve bu elementin içerisine istek sonucunda gelecek olan bilgiyi yazdõrõyoruz. yeniNesne.responseText ise Text formatõnda gelecek olan veriyi almamõzõ sağşõyor. (responseXML ise DOM’a uygun XML formatõnda gelen veriyi almamõzõ sağlar) Sayfamõzõ çalõştõracak olursak sadece butonu bulunan bir sayfamõz olacak. Burada span elementi ile belirttiğimiz boş bir alan daha var. Uygulamamõzõn doğru çalõşõp çalõşmadõğõnõ görebilmemiz için sayfamõzõn bulunduğu dizine Ogranciler.htm adõnda bir dosya oluşturmamõz gerekiyor. Bu dosyanõn içerisine örnek olmasõ açõsõndan birkaç satõrlõk yazõ ekleyebiliriz. Sayfamõzda bulunan butona tõkladõğõmõzda butonun onclick olayõ çalõşacak ve AsenkronCagriYap() isimli JavaScript fonksiyonumuz çağõrõlacaktõr. Bu fonksiyon asenkron çağrõ işlemini gerçekleştirecek ve getirilen bilgiyi lblGuncelle adõnõ verdiğimiz span elementinin içerisine yazacaktõr. 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", "value") = Gönderilen başlõk bilgisine istenilen değeri atar.

Özellikler:
status = Sunucudan dönen cevabõn numarasal kodudur. Örneğin 404 kodu “Not Found” yani istekte bulunduğumuz sayfa bulunamadõ anlamõna gelir. 200 ise “OK” değeri dönderir ve işlemin tamamlandõğõnõ belirtir. statusText = status özelliğinin metin karşõlõğõnõ verir. Son kõsõmda belirtilen metot ve özellikler üzerinde fazla durmamõza gerek olmadõğõnõ düşünüyorum. AJAX’õ kullanarak asenkron veri alõş-verişini yapabilmek için örneğimizde kullandõğõmõz open ve send metotlarõ, onreadystatechange eventhandler’õ ile readystate özelliği bizim için yeterli olacaktõr. Bu yazõmõzda AJAX 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ş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õna rağmen temel olarak AJAX 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 kullanarak, daha persormanslõ ve zengin uygulamalar geliştirebiliyoruz. ASP.NET AJAX uygulamalarõ geliştirirken elbetteki bazõ durumlarda sõkõntõlar, sorunlar yaşanabilecektir. Bu yazõda bu nitelikteki bazõ sorunlarõ ve hatalarõ ele alarak bu durumlarda ne gibi çõkõş yollarõna başvurabileceğimize değineceğiz. ASP.NET AJAX uygulamalarõnõn sunucuya taşõnmasõnda, klasik uygulamalarõn ASP.NET AJAX uygulamasõ haline 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 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 dosyalarõ ile birlikte taşõnan proje, bulunduğu tüm bilgisayarda sorunsuz bir şekilde çalõşabiliyordu. ASP.NET AJAX v1.0 ile artõk bir AJAX projesinin kullanacağõ assembly dosyalarõ GAC(Global Assembly Cache) içerisine atõldõğõ için, projeye referans dosyasõ olarak eklemeler yapõlmõyor ve projeniz GAC’daki dosyalarõ kullanõyor. Bu nedenle hazõrlamõş olduğunuz bir ASP.NET AJAX projesinin sunucuda veya başka bir bilgisayarda çalõşabilmesi için, o bilgisayara ASP.NET AJAX Extension 1.0’õn kurulu olmasõ gerekecektir. Sunucuda AJAX projelerini çalõştõramama gibi bir durumda yapõlmasõ gereken işlemler, projenize gerekli dll dosyalarõnõ eklemek ve web.config dosyasõnda bazõ değişiklikleri yapmak olacaktõr. - Öncelikli olarak projenize gerekli dll dosyalarõnõ eklemeniz gerekecektir. ASP.NET AJAX dosyalarõnõn kullandõğõ assembly dosyalarõ System.Web.Extension ve System.Web.Extension.Design dll dosyalarõdõr. Bu dosyalarõ AJAX Extension kurulu bilgisayarõnõzdaki C:\Program Files\Microsoft ASP.NET\ASP.NET 2.0 AJAX Extensions\v1.0.61025 dizininde bulabilirsiniz. Projenize Bin isimli bir dizin oluşturmanõz ve dll dosyalarõnõ bu dizine eklemeniz gerekecektir.

122

- Daha sonra uygulamanõzdaki web.config dosyasõnda bazõ değişiklikler yapmanõz gerekecek. web.config içerisindeki tanõmlamalarõ dikkatli şekilde inceleyecek olursanõz, tanõmlamalarõn type özelliği içerisinde ...System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35 şeklinde ifadeler bulunur. Bu ifadeler yapõlacak olan işlemlerde kullanõlacak assembly dosyasõnõn GAC içerisinden okunacağõnõ belirten ifadelerdir. web.config’deki bu ifadelerde yer alan Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35 kõsõmlarõnõ çõkarmanõz gerekecektir. Aşağõdaki şekilde değişiklik yapõlacak alanlar gri zemin üzerinde gösterilmiştir. Web.config içerisindeki bu alanlar ve aynõ tanõmlamalarõn geçtiği diğer alanlarda değişiklik yapmak gerekecektir.

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 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õza eklemek. Eğer klasik uygulamnõzdaki web.config dosyasõnda değişiklikler yaptõysanõz, ASP.NET AJAX projesindeki web.config’den - <configSections></configSections> - <pages></pages> kõsmõ içerisindeki <controls></controls> - <compilation></compilation> kõsmõ içerisindeki <assemblies></assemblies> - <httpHandlers></httpHandlers> - <httpModules></httpModules> - <system.web.extensions></system.web.extensions> - <system.webServer></system.webServer> kõsõmlarõnõ uygulamanõzõn web.config dosyasõ içerisindeki uygun 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 <configSections> düğümünün, <configuration> 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. Böylece uygulamanõzda ASP.NET AJAX ile ilgili ayarlamalarõ gerçekleştirmiş olacaksõnõz. - ASP.NET AJAX Extension’larõnõ kullanmak istediğiniz sayfalara 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 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. (AJAX.NET için http://ajax.schwarzinteractive.de adresinden bilgi alabilirsiniz)

ASP.NET AJAX uygulamalarõnda FileUpload ve WebParts kontrolleri 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õnda, bir web sayfasõ içerisinde kõsõmlar oluşturulmasõnõ ve bu kõsõmlarõn asenkron şekilde güncellenmesini sağlayan kontroldür. ASP.NET AJAX uygulamalarõnda, bir sayfa PostBack işlemine tabi tutulmadan, sadece UpdatePanel içerisi güncellenebilir. Bu şekilde web sayfalarõ daha hõzlõ çalõşõr hale geldiği gibi, sunucu ile istemci arasõndaki veri trafiği de önemli derecede azalõr. UpdatePanel kontrolü, sayfa içerisinde bir alan oluşturarak, (HTML kõsmõnda <div> veya <span> etiketi ile oluşan bir alan) içerisine eklenen kontrollerin görüntülenmesini ve asenkron bir şekilde bu kontrollerin içeriklerinin güncellenmesini sağlar. <ContentTemplate></ContentTemplate> ve <Triggers></Triggers> kõsõmlarõ olmak üzere iki kõsõmdan oluşmaktadõr. <ContentTemplate> kõsmõnda, UpdatePanel içerisinde yer alacak içerikler bulunur.(ASP.NET kontrolleri, HTML kontrolleri, resim dosyalarõ, metinler vb.) Sadece bu kõsõmda yer alan bileşenler, kõsmi güncelleme işleminden etkilenir. <Triggers> kõsmõnda ise UpdatePanel'in çalõşmasõnõ; yani güncelleme işleminin gerçekleşmesini sağlayacak olaylarõn bağlanmasõ işlemi gerçekleştirilir. (Bir Button kontrolünün Click olayõ veya DropDownList kontrolünün SelectedIndexChanged olayõ gibi durumlarõn panele bağlanmasõ) ContentTemplate ve Triggers kõsõmlarõ UpdatePanel içerisinde şu şekilde kullanõlmaktadõr. <asp:UpdatePanel ID="updatePanel1" runat="server"> <ContentTemplate> <!-- Buraya gerekli içerikler eklenecek --> </ContentTemplate> <Triggers> <!-- Bu kõsõmda UpdatePanel'e olaylar bağlanõr --> </Triggers> </asp:UpdatePanel> UpdatePanel’in ContentTemplate’i içerisine bileşenleri eklemek, kõsmi güncelleme işleminin yapõlmasõ için yeterli olmayacaktõ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 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 sayfasõna bir 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 yapmasak dahi, UpdatePanel içerisinde yer alan Button gibi bir kontrole tõklandõğõnda panelin içerisindeki veriler güncellenecektir. Default.aspx ve Default.aspx.cs dosyalarõnda aşağõ değişiklikleri yapõp, uygulamayõ çalõştõralõm.

Default.aspx <asp:UpdatePanel ID="UpdatePanel1" runat="server"> <ContentTemplate> <asp:Label ID="Label1" runat="server" Text=""></asp:Label> <br /> <asp:Button ID="Button1" runat="server" Text="Button" /> </ContentTemplate> </asp:UpdatePanel> Default.aspx.cs protected void Page_Load(object sender, EventArgs e) { Label1.Text = DateTime.Now.ToLongTimeString(); }

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 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. Böyle bir durumda bu kontrolün paneli otomatik olarak 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 <Triggers> 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 eklemek gerekecektir. <asp:UpdatePanel ID="UpdatePanel1" runat="server"> <ContentTemplate> <table style="background-color:#DDDDDD; width:200px"> <tr> <td> <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label> <br /> <asp:Button ID="Button1" runat="server" Text="Button" /> </td> </tr> </table> </ContentTemplate> <Triggers> <asp:AsyncPostBackTrigger ControlID="btnDisari" EventName="Click" /> </Triggers> </asp:UpdatePanel> <br /><br /> <asp:Button ID="btnDisari" runat="server" Text="Panel dõşõndan güncelle" />

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 eklenmesi AsyncPostBackTrigger, panele asenkron postback işlemi yapmasõ istenilen kontrolün eklenmesi için kullanõlacak 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 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.

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 birden fazla UpdatePanel bulunduğunda panellerin ne şekilde çalõşacağõnõ, birbirlerinin güncellemelerinden 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 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 <asp:UpdatePanel ID="UpdatePanel2" runat="server"> <ContentTemplate> <table style="background-color:#B5DDDD; width:200px"> <tr><td> <asp:Label ID="Label2" runat="server"></asp:Label> <br /> <asp:Button ID="Button2" runat="server" Text="Button-2" /> </td></tr> </table> </ContentTemplate> </asp:UpdatePanel>

129

Label2 kontrolünün de asenkron şekilde güncellenmesi için Default.aspx.cs dosyasõndaki Page_Load kõsmõnõ şu şekilde değiştirelim: Default.aspx.cs protected void Page_Load(object sender, EventArgs e) { Label1.Text = DateTime.Now.ToLongTimeString(); Label2.Text = DateTime.Now.ToLongTimeString(); } 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. UpdatePanel'lerin bu şekilde çalõşmalarõnõ sağlayan UpdateMode özellikleridir. Sayfamõza eklediğimiz bir UpdatePanel'in UpdateMode özelliği varsayõlan olarak Always değerini taşõmaktadõr. UpdateMode özelliğinin Always olmasõ durumunda sayfa içerisindeki herhangi bir UpdatePanel'in tetiklenmesi panelinde tetiklenmesini sağlayacaktõr. Eğer UpdateMode özelliği Conditional değerini alõrsa, panel sadece kendi triggerlarõ aracõlõğõyla tetiklenecektir. Bu noktada UpdatePanel1'in UpdateMode özelliğini Conditional yapacak olursanõz, sayfayõ çalõştõrdõğõnõzda UpdatePanel1'in sadece kendi triggerlarõ tarafõndan tetiklenebileceğini göreceksiniz. Fakat UpdatePanel2'nin UpdateMode özelliği hala Always olduğu için UpdatePanel1'deki bir güncelleme, UpdatePanel2'yi de tetikleyecektir. Aşağõdaki tabloda iki UpdatePanel'in UpdateMode özelliklerine göre ne şekilde tetiklenecekleri listelenmiştir.

130

UpdatePanel1'in UpdateMode özelliği Always

UpdatePanel2'in UpdateMode özelliği Always

UpdatePanel1 triggerõ tetiklenirse Her iki panelde güncellenir. Her iki panelde güncellenir. UpdatePanel1 güncellenir, UpdatePanel2 güncellenmez. UpdatePanel1 güncellenir, UpdatePanel2 güncellenmez.

UpdatePanel2 triggerõ tetiklenirse Her iki panelde güncellenir. UpdatePanel2 güncellenir, UpdatePanel1 güncellenmez. Her iki panelde güncellenir. UpdatePanel2 güncellenir, UpdatePanel1 güncellenmez.

Conditional

Always

Always

Conditional

Conditional

Conditional

İç İçe UpdatePanel Kullanõmõ
ASP.NET AJAX ile hazõrlanan bir sayfa içerisinde iç içe UpdatePanel'ler de kullanõ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, içerisindeki tüm kontrollerin beraber güncellenmesinin dõşõnda bazõ kontrol gruplarõnõn da ayrõ olarak güncellenmesi istenilebilir. Böyle bir durumda, ana 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 içerisine ikinci bir UpdatePanel eklenmiştir. Burada iç kõsõmdaki UpdatePanel'in dõştaki panelden ayrõ olarak çalõşabilmesi için dõştaki UpdatePanel'in (UpdatePanel3) UpdateMode özelliği Conditional, içteki UpdatePanel'in (UpdatePanel4) UpdateMode özelliği ise Always olarak tanõmlanmalõdõr. Default.aspx <asp:UpdatePanel ID="UpdatePanel3" runat="server" UpdateMode="Conditional"> <ContentTemplate> <table style="width: 300px; background-color: #9999ff"> <tr><td> <asp:Label ID="lblDisKisim" runat="server"></asp:Label><br /> <asp:Button ID="Button3" runat="server" Text="Ana Panel" /><br /> <br /> <asp:UpdatePanel ID="UpdatePanel4" runat="server"> <ContentTemplate> <table style="width: 200px; background-color: #99ccff"> <tr><td>

131

<br /> <asp:Label ID="lblIcKisim" runat="server"></asp:Label><br /> <asp:Button ID="Button4" runat="server" Text="İç Panel" /> </td></tr> </table> </ContentTemplate> </asp:UpdatePanel> </td></tr> </table> </ContentTemplate> </asp:UpdatePanel> Default.aspx.cs protected void Page_Load(object sender, EventArgs e) { Label1.Text = DateTime.Now.ToLongTimeString(); Label2.Text = DateTime.Now.ToLongTimeString(); lblDisKisim.Text = DateTime.Now.ToLongTimeString(); lblIcKisim.Text = DateTime.Now.ToLongTimeString(); }

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. Bazõ durumlarda, özellikle sayfanõn tasarõmõ gereği bir UpdatePanel içerisinde başka bir UpdatePanel kullanõlmasõ durumu ile karşõlaşabiliriz.

132

ASP.NET AJAX’a Giriş
09 Eylül 2007 Merhabalar. Bu yazõmõzda web dünyasõnda son yõllara damgasõnõ vuran AJAX uygulama tekniğini kõsaca ele alõp Microsoft’un ASP.NET uygulama geliştiricilere ücretsiz olarak sunmuş olduğu ASP.NET AJAX isimli ücretsiz AJAX kod kütüphanesini uygulamalarõmõzda nasõl kullanabileceğimizi inceleyeceğiz. AJAX; yani Asenkron JavaScript ve XML adõ verilen uygulama modelini kullanarak istemci ile sunucu arasõnda asenkron şekilde işlemler yapabilmekteyiz. Temel olarak bu işlemler JavaScript dilini kullanarak tarayõcõnõn yapõsõndaki XmlHttpRequest bileşeni üzerinden yürütülmektedir. Böylece web sayfalarõnõn tamamen güncellenmesine gerek kalmadan, sadece belirli alanlarõnõ yenileyebilir ve böylece daha hõzlõ çalõşan web sayfalarõ geliştirebiliriz. Burada bahsettiğimiz işlem aslõnda web dünyasõnda devrim niteliğinde bir yenilikti. Google ve Microsoft gibi şirketlerin gerçekleştirdiği projelerle son iki yõl içerisinde giderek duyulan AJAX ismi, artõk günümüz web projelerinin vazgeçilmez bir parçasõ olmuştur. Yeni yapõlan birçok web projesi AJAX destekli olarak geliştirildiği gibi, eski web projelerinin birçoğu da AJAX destekli hale getirilmektedir. Bu nedenle AJAX artõk biz web uygulama geliştiricileri için oldukça önemli hale gelmiştir. 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 (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 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 ve ASP.NET kontrolleri ile uyumlu bir şekilde çalõşmamõzõ sağlayan AJAX kontrolleri, sõnõf kütüphaneleri ve servisler 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 bu kütüphaneyi kullanabilmek

133

için ASP.NET AJAX’õn resmi web sitesinden 1.3 MB’lõk küçük bir dosyayõ bilgisayarõmõza indirmek ve kurulum gerçekleştirmek gerekecektir. http://www.asp.net/ajax/downloads/ adresindeki Download ASP.NET Extensions v1.0 linkinden indireceğimiz dosyayõ bilgisayarõmõza kurduğumuzda Visual Studio 2005’e gerekli proje şablonu ve AJAX kontrolleri eklenecektir. Böylece artõk yeni bir AJAX web projesi oluşturabileceğiz. Dilerseniz artõk böyle bir projeyi nasõl geliştirebileceğimize bakalõm. Bu örneği Visual Studio 2005 uygulama arayüzünde geliştireceğim. Yeni bir proje açmak için File > New > Web Site seçeneğini seçiyoruz. Açõlan pencereden ASP.NET 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 gerçekleştirdiğimizde Visual Studio 2005 Toolbox’õna AJAX Extensions isminde yeni bir kontrol grubu açõlõr ve buraya AJAX uygulamalarõna özel beş tane kontrol eklenir: ScriptManager, UpdatePanel, UpdateProgress, Timer ve ScriptManagerProxy. Bu kontrollerin görevlerine kõsaca inceleyelim.

134

Resim: Visual Studio 2005 Toolbox’õna eklenen AJAX Extensions kontrolleri

ScriptManager:
Sayfanõn AJAX destekli çalõşmasõnõ sağlayan en temel kontroldür. İstemci için gerekli JavaScript kodlarõnõn üretilmesi ve sayfadaki diğer AJAX kontrollerinin uyumlu bir şekilde çalõşmasõnõ sağlar. Diğer AJAX kontrollerini kullanabilmek için sayfamõzda mutlaka bir tane ScriptManager kontrolü bulunmalõdõr.

UpdatePanel:
Sayfa içerisinde asenkron şekilde güncellenebilir alanlar oluşturulmasõnõ sağlayan kontroldür. Böylece sayfada sadece bu alanlarõn içeriğinin asenkron şekilde güncellenerek sayfanõn daha hõzlõ çalõşmasõ sağlanabilir.

UpdateProgress:
Asenkron güncelleme işlemi gerçekleşirken kullanõcõyõ güncelleme işleminden haberdar edebilmek için kullanabileceğimiz kontroldür. Kontrolün içeriği sadece güncelleme yapõldõğõnda sayfada görüntülenir, güncelleme işlemi bittiğinde ise kaybolur.

Timer:
UpdatePanel kontrolünün içeriği kullanõcõnõn isteği ile güncellenebileceği gibi bazõ durumlarda belirli zaman aralõklarõyla da güncellenebilir. Timer kontrolü ile UpdatePanel içeriğinin belirli zaman aralõklarõnda güncellenmesi sağlanabilir.

ScriptManagerProxy:
Bazõ durumlarda bir master sayfanõn (master page) içerik sayfasõnda ScriptManager kontrolü kullanma ihtiyacõ olabilir. Eğer master sayfada ScriptManager var ise, içerik sayfasõna ikinci bir ScriptManager kontrolü eklemek soruna yol açacaktõr. İşte böyle bir durumda içerik sayfasõna ScriptManager yerine ScriptManagerProxy kontrolü ekleyerek işlemleri yürütebiliriz. ScriptManagerProxy bu tip bir sayfada ScriptManager kontrolüne servis ve script ekleme işlemlerini gerçekleştirir. Projeyi açtõğõmõzda dikkatimizi çeken ilk şeylerden birisi aspx sayfamõzdaki ScriptManager kontrolü olacaktõr. Hali hazõrda gelen ScriptManager kontrolü dõşõnda sayfamõza UpdatePanel kontrolünü de ekleyecek olursak asenkron işlemler yürütebiliriz. Web sayfalarõnda gezinirken çoğumuz bir kayõt formundan il bilgisini seçtiğimizde sayfanõn yenilenmeden ile ait ilçeleri listelediğini görmüşüzdür. Dilerseniz bu şekilde bir uygulamayõ

135

gerçekleştirmeye çalõşalõm. İl ve ilçe bilgilerini saklamak için iller ve ilceler olmak üzere Microsoft Office Access’te iki tablo oluşturalõm.

Resim: 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 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 penceresinden 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 il_kod ve il_ad alanlarõnõ seçelim ve Next diyelim. Ardõndan da Finish butonuna tõklayõp ana menümüze dönelim. - Ana ekrandan ise ikinci açõlõr menüde il_ad, üçüncü açõlõr menüde ise il_kod seçeneklerini aktif yapalõm. Böylece ilk açõlõr menü kontrolüne illeri bağlamõş olduk. Şimdi yapõlacak işlem ise ilçeler açõlõr menüsüne seçilen ilin ilçelerini getirebilmek. ddlIlceler kontrolü için de yukarõdaki ilk iki adõmõ aynen gerçekleştirdikten sonra; - Karşõmõza çõkan pencereden ilceler tablosunu seçelim. Sütunlar listesinden ise sadece ilce_kod ve ilce_ad sütunlarõnõ seçelim. - Aynõ pencerede sağ kõsõmda bulunan WHERE butonuna tõklayalõm. Açõlan pencerede Column kõsmõndan ilce_il_kod, Operator kõsmõndan =, Source kõsmõndan Control’ü

136

seçelim. Sağ kõsõmdaki ControlID kõsmõndan ise ddlIller’i seçelim. Sağ kõsõmda yer alan Add butonu ile yaptõğõmõz seçimleri parametre olarak SQL cümlemize ekleyelim ve OK butonuna tõklayalõm. - Son ekranda Finish’i seçip ana ekranõmõza dönelim. Burada da ikinci açõlõr menüden ilce_ad sütununu, üçüncü açõlõr menüden ilce_kod sütununu seçelim ve OK diyelim.

Resim: İlçeler menüsüne seçilen ilin ilçelerinin getirilebilmesi için SQL cümlemize gerekli parametre ekleme işlemini gerçekleştiriyoruz Artõk sayfamõz yenilenmeden iller seçeneğinden seçilen şehre ait ilçeleri diğer menümüze ekleyecektir. Hiç JavaScript kodu yazmadan nasõl oldu bu iş diyecek olursanõz burada ASP.NET AJAX’õn ne denli önemli bir araç olduğunu görüyoruz. Normal bir web sayfasõnda kullandõğõmõz içeriklerimizi UpdatePanel içerisine ekleyecek olursak artõk panel içerisindeki bileşenler otomatik olarak asenkron güncellenebilir hale gelecektir. Artõk sayfamõzõ çalõştõrõp sonuçlarõ görelim.

137

Resim: İl menüsünden seçilen ile ait ilçeler sayfanõn yenilenmesine gerek kalmadan alttaki menüye doldurulur 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 <ContentTemplate> kõsmõna eklendiğini görebiliriz. UpdatePanel'de asenkron olarak güncellenecek kõsõmlar sadece ContentTemplate içerisinde tutulmaktadõr. Triggers kõsmõnda ise UpdatePanel’in içeriğinin asenkron olarak 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 bu kontrollerin UpdatePanel’e trigger (tetikleyici) olarak bağlanmasõ gerekir. <asp:UpdatePanel ID="UpdatePanel1" runat="server"> <ContentTemplate> <!-- Buraya güncellenecek içerikler gelecek... --> </ContentTemplate> <Triggers> <asp:AsyncPostBackTrigger ControlID="Button1" EventName="Click" /> </Triggers> </asp:UpdatePanel> 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 işlemi başladõğõnda bu kontrolün içeriği görünür hale gelir ve güncelleme işlemi bittiğinde ise kaybolur. Sayfaya eklediğimiz UpdateProgress kontrolünün DisplayAfter özelliği güncelleme işleminden kaç milisaniye sonra UpdateProgress’in görüntüleneceğini belirler. Bu özelliği 0 olarak belirleyelim ve kontrolün içerisine güncelleme işlemini belirten bir resim dosyasõ ve metin ifade ekleyelim. <asp:UpdateProgress ID="UpdateProgress1" runat="server" DisplayAfter="0"> <ProgressTemplate> <div style="background-color: #ff3333; color:White; font-size:14px; width:120px"> <img src="yukleniyor.gif" /><br /> <b>Yükleniyor...</b> </div> </ProgressTemplate> </asp:UpdateProgress> Sayfayõ çalõştõrõp il menüsünden farklõ illeri seçecek olursak UpdateProgress’in çalõşma şeklini gözlemleyebiliriz.

Resim: UpdatePanel’in içeriği güncellendiği esnada UpdateProgress kontrolü görüntülenir Eğer yapõlacak güncelleme işlemi zamana bağõmlõ olacaksa AJAX kontrollerinden olan Timer’i UpdatePanel’e ekleyerek panel içeriğinin belirli zaman aralõklarõyla güncellenmesini sağlayabiliriz. Timer kontrolünün Interval özelliği kaç milisaniyede bir panelin güncelleneceğini belirler. Örneğin Interval özelliği 30000 olursa panel içeriği 30 saniyede bir otomatik olarak güncellenir. Bu yazõmõzda Microsoft’un ASP.NET uygulamalarõnda hõzlõ ve çok kolay bir şekilde AJAX’õ uygulamamõzõ sağlayan ASP.NET AJAX isimli kütüphanesi ile nasõl uygulama geliştirebileceğimizi gördük. ASP.NET AJAX ile ilgili olarak www.nedirtv.com sitesindeki ASP.NET AJAX isimli videolarõ inceleyebilirsiniz. Bir sonraki yazõmõzda görüşmek dileğiyle…

139

Diğer Konular
Anahtar kelimeler DataRow

DataTable

Excel

Filtreleme

OleDb

Sõralama

Team Foundation Server

140

Excel Dosyasõndaki Bilgilere Ulaşmak
27 Kasõm 2005

Bildiğimiz gibi MS Excel, .xls tipi dosyalarda verileri saklamamõzõ ve bu veriler üzerinde işlemler yapabilmemizi sağlamaktadõr. Peki bu verilere .NET ortamõnda nasõl ulaşabiliriz? Bu aşamaya geçmeden, öncelikle bu işlemi yapabilmemiz için Excel’de dosyamõzõ ne şekilde hazõrlamamõz gerektiğini anlatacağõm. Hazõrlayacağõm örnekte bir sõnõftaki öğrencilerin isimlerinin ve 3 tane sõnav notlarõnõn bilgilerini Excel dosyamõzda tutalõm. Açtõğõmõz Excel dosyasõnda 4 adet sütunumuz olsun. “AdSoyad”, “Sinav1”, “Sinav2” ve “Final” sütunlarõ. Daha sonra bu sütunlarõn altlarõnõ gerekli bilgilerle dolduralõm.

Bilgilerin olduğu alanõ seçerek bu alana bir ad veriyoruz, böylece seçili alanõmõz tanõmlõ bir hale geliyor. Bunun için Ekle > Ad > Tanõmla menüsünü seçiyoruz ve buradan bu alana vereceğimiz ismi yazõp (Bu uygulamada ben NotTablosu adõnõ verdim) önce “Ekle” diyor ve daha sonra eklenen bu isim seçili iken “Tamam” diyoruz.

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õ oluşturuyorum. Uygulamamõzdaki WebFrom1.aspx dosyasõna bir buton ve 1 datagrid nesnesi ekliyorum. Butona tõkladõğõmda Excel dosyasõndaki veriler alõnarak datagride yüklenecek. Uygulamanõn kodlarõna gelince; öncelikle veritabanõ ile ilgili işlemler için System.Data.OleDb (Excel dosyasõna bağlanmamõz için gerekli) ve System.Data.SqlClient isim alanlarõnõ uygulama kodlarõnõn başlangõcõna ekleyip butonun Click Event’ ine aşağõdaki kodlarõ yazõyoruz. ' Dosyaya bağlanmak için gerekli olan bağlantõ stringini Dim ConnStr As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & 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 = MyCommand da.Fill(dt) ' Verileri daha sonra da kullanabilmek için session içerisinde tutuyoruz Session("Veriler") = dt ' Verinin görüntüleneceği DataGrid in DataTable a bağlanmasõ ve verinin yüklenmesi DataGrid1.DataSource = dt.DefaultView DataGrid1.DataBind() 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 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 = "data source=.;persist security info=False;initial catalog=Deneme;user 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") For sayi = 0 To dt.Rows.Count - 1 Dim SqlStr As String = "INSERT INTO Notlar (AdSoyad, Sinav1, Sinav2, Final) " & _ "VALUES ('" & dt.Rows(sayi)(0) & "', " & dt.Rows(sayi)(1) & ", " & dt.Rows(sayi)(2) & ", " & dt.Rows(sayi)(3) & ")" Dim MyCommand As New SqlCommand(SqlStr, Conn) Dim da As New SqlDataAdapter da.SelectCommand = MyCommand da.Fill(dt) Next 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’daki tablomuza yazdõrdõk. Anlatmaya çalõştõğõm konuda bu özelliği basit yönüyle 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õ 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 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õ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 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. 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; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Data.OleDb; // Veritabanõ işlemleri için gerekli isim alanõnõ ekliyoruz. namespace DataTable_SortFilter { public partial class Form1 : Form

146

{ // Connection, DataAdapter ve DataTable nesnelerini field olarak tanõmlõyoruz. OleDbConnection con; OleDbDataAdapter da; DataTable dtUrunler; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { // Gerekli bağlantõ ve sorgu cümleleri ile nesneleri oluşturuyoruz. // DataAdapter'õn Fill metodu ile getirilen verileri DataTable nesnesine yüklüyoruz. con = new OleDbConnection("Provider=Microsoft.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 sender, EventArgs e) { // btnDoldur isimli butona tõklandõğõnda dgvUrunler isimli gridimizi verilerle dolduruyoruz. dgvUrunler.DataSource = 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 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 sender, EventArgs e) { // Arama işlemlerini yapabilmek için DataTable nesnesinin Primary Key alanõnõ // belirlememiz gereklidir. dtUrunler nesnesinin PrimaryKey property'si 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[] dcPK = { dtUrunler.Columns["UrunID"] }; 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); // Kullanõcõdan ID değerini aldõk. Rows kolleksiyonunun Find metodu parametre olarak // verilen değeri satõrlar içerisinde arar ve bulduğu satõrõ DataRow tipinde geriye // döndürür. Böylece satir isimli DataRow nesnemizin indekleyicileri ([]) aracõlõğõyla // sütun isimlerini vererek kaydõn bilgilerine ulaşabiliriz. DataRow satir = dtUrunler.Rows.Find(urunID); string satirBilgileri = satir["UrunID"].ToString() + " - " + satir["Ad"].ToString() + " - " + satir["Fiyat"].ToString() + " YTL"; MessageBox.Show(satirBilgileri, urunID + " ID'li ürünün bilgileri"); } catch (Exception ex) { MessageBox.Show("Satõr bulunamadõ!"); } } Uygulamayõ çalõştõrdõğõmõzda gridi doldurup varolan bir kaydõn UrunID bilgisini txtID isimli textboxa yazõp butona tõklatõrsak o ürün ile ilgili UrunID, Ad ve Fiyat gibi bilgileri mesaj kutusu içerisinde görebiliriz.

148

Şekil: Find metodu ile ID bilgisi verilen kaydõn bilgilerine ulaşmak Böylece Find metodunu kullanarak primary key sütunumuzdaki bir bilgiye göre ilgili kaydõn değerlerine nasõl ulaşabileceğimizi görmüş olduk. Find metodunun kullanõmõnõ inceleyecek olursak bir de aşõrõ yüklenmiş halinin olduğunu görebiliriz. Metodun ikinci versiyonu ise object tipinden bir dizi ister. Eğer tablomuzun primary key alanõnõ birden fazla sütun oluşturuyorsa, Find metodunun bu versiyonunu kullanarak birden fazla kriter belirterek arama işlemi yapabiliriz. Örneğin dtUrunler tablomuzun primary key alanõnõn sadece UrunID sütunundan değilde, UrunID ve Ad sütunlarõnõn birleşiminden oluştuğunu varsayalõm. Böyle bir durumda arama kriterini sadece UrunID alanõ üzerinden değil, hem UrunID hem de Ad alanõ üzerinden verebiliriz. Aslõnda Find(object key) versiyonu primary key alan üzerinden WHERE UrunID=5 gibi bir arama yaparken, Find(object[] keys) versiyonu ise UrunID ve Ad sütunlarõnõn primary key olduğu bir durumda WHERE UrunID=5 AND Ad='Çikolata-Fõndõklõ' şeklinde bir arama yaparak sonucu getirir. Find metonun aşõrõ yüklenmiş halinin kullanõmõnõ aşağõdaki örnekte görebilirsiniz. // UrunID ve Ad sütunlarõnõ bir DataColumn dizisi içerisinde primary key olarak // tanõmlõyor ve dtUrunler tablomuzun PrimaryKey property'sine set ediyoruz. DataColumn[] dcPK = { dtUrunler.Columns["UrunID"], dtUrunler.Columns["Ad"] }; dtUrunler.PrimaryKey = dcPK; // Object tipindeki dizimizin ilk değer UrunID, ikinci değeri Ad sütunu için. object[] urunID_Ad = {5, "Çikolata-Fõndõklõ"}; DataRow satir = dtUrunler.Rows.Find(urunID_Ad);

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 ise sadece bir kaydõn değilde belirli kriterlere uyan kayõtlarõn bulunmasõnõ 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 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.

150

// Tablodaki tüm kayõtlarõ getirir. DataRow[] satirlar = dtUrunler.Select(); // Tablodaki kayõtlarda UrunID bilgisi 5 ve 10 arasõnda olanlarõ getirir. DataRow[] satirlar = 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 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 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 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 += 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. private void btnSelect_Click(object sender, EventArgs e) { string whereIfade, orderByIfade; whereIfade = txtWhereCumle.Text; // WHERE'den sonra gelecek ifade orderByIfade = cmbOrderBy.SelectedItem.ToString(); // ORDER BY'dan sonra gelecek ifade if (cbDesc.Checked) orderByIfade += " DESC"; // Tersten sõralama yapõlacaksa ifademize DESC ekliyoruz DataRow[] satirlar = dtUrunler.Select(whereIfade, 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 tablosu ile aynõ yapõya sahip oluyor.

151

// Fakat bize sadece o an seçilen veriler gerekli(satirlar dizisi). Bu nedenle de // dtGecici'deki row'larõ Clear metodu ile siliyoruz. Select metodunun kullanõmõnda // benzer durumlarda sõkõntõ çõkabilmektedir. Burada ele almadõğõmõz DataView nesnesi // bu problemleri çözebilecek şekilde dizayn edilmiştir. DataTable dtGecici = dtUrunler.Copy(); dtGecici.Clear(); foreach (DataRow dr in satirlar) { // satirlar nesnesindeki row'lar hala dtUrunler tablosuna ait olduğu için // ImportRow metodu ile satõrlarõ kopyalõyoruz dtGecici.ImportRow(dr); } dgvUrunler.DataSource = dtGecici; // Verileri gride yüklüyoruz. } txtWhereCumle isimli textbox'a arama 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.

Ş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 incelemeye çalõş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 uygulamaya yansõmayacağõnõ da unutmamamõz gerekir.

153

Adõm Adõm Team Foundation Server Single-Server Kurulumu
07 Mart 2007 Bu yazõda Team Foundation Server kullanabilmemiz için gerekli olan araçlarõn kurulumunu adõm adõm inceleyeceğiz. Yine Visual Studio 2005 üzerinde takõm projesi oluşturup bu projede çalõşabilmek için gerekli olan Team Explorer kurulumunu ve Visual Studio 2005'te yeni bir takõm projesini nasõl oluşturabileceğimizi göreceğiz. Bu dökümanda anlatõlan kurulum Team Foundation Server Single-Server Deployment kurulumudur. Kurulum Windows Server 2003 - Standart Edition üzerinde yapõlmõştõr. TEAM FOUNDATION SERVER KURULUMU (I) bölümünde anlatõlan aşamalar sunucu olarak kullanõlacak bilgisayarda, 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 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 geçmeden önce, Windows Update sitesinden son güncellemeler yapõlmalõdõr. (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 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 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) - Kurulum bittikten sonra http://windowsupdate.microsoft.com adresinden son güncellemeleri yapõn. Not: IIS krulumunu, benzer şekilde Control Panel > Add/Remove Programs kõsmõndaki Windows Components seçeneğinden de gerçekleştirebilirsiniz. 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 development tools - Components to Install penceresindeki Advanced seçeneğinden açõlan penceredeki ağaç yapõsõnõ açõnõz ve; * Database Services’in altõndaki Replication’a tõklayõn. Buradan Entire feature will be unavailable seçeneğini seçiniz. * Client Components’in altõndan Management Tools dõşõndaki tüm bileşenlerde Feature will be unavailable seçeneğini seçiniz. * Documentation, Samples, and Sample Databases’in altõndaki SQL Server Books Online seçeneğinden Feature will be unavailable seçeneğini seçiniz.

155

- Instance penceresinden Default Instance seçin. (Kurulumun başarõlõ bir şekilde yapõlabilmesi için Default Instance seçilmelidir. Named Instance'õn seçilmesi durumunda TFS kurulumu başarõsõz olacaktõr.) - Service Account ekranõndan Use the built-in System Account’u seçip listeden Local System’i seçin. - Start services at the end of the setup seçeneğinden tüm servisleri seçin. - Authentication Mode kõsmõndan Windows Authentication seçeneğini seçin. - Collocation Settings kõsmõndan dili Latin1_General seçin ve aşağõdaki kõsõmdan Accent– sensetive seçeneğini seçin. - Report Server Installation Options penceresinde Install the default configuration’õ seçin. - Error and Usage Report Settings penceresindeki iki seçeneği isteğinize göre seçebilirsiniz. - Son aşamada yapõlacak olan kurulumun özeti görüntülenir. Install seçeneğine tõklayarak kuruluma başlayõn. I.c. SQL SERVER 2005 Hotfix Kurulumu - Bu kurulumdan önce SQL Server 2005 – Service Pack 1’in yüklenmesi sağlõklõ olacaktõr. http://go.microsoft.com/fwlink/?LinkId=65988 adresinden SQL Server 2005 – Service Pack 1 ‘i yükleyin ve kurulumu yapõn. - Hotfix kurulumu için öncelikle SQL Server Configuration Manager’i açõn ve SQL Server 2005 Services’in altõndaki SQL Server Browser’õ Stop seçeneğinden durdurunuz. - Team Foundation Server DVD'si içerisindeki SQLServerKB klasörünü açõn ve 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 SQL Server Browser’õ Automatic konumda ve çalõşõr durumda olduğunu kontrol edin. Çalõşmõyorsa çalõşõr hale getirmeniz gerekmektedir. - SQL Server 2005 Network Configuration’da Protocols for MSSQLServer’a tõklayarak TCP/IP‘nin enabled olduğuna emin olun. 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=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 gerekli ayarlarõ daha sonradan Team Foundation Server yapacaktõr. Bu sayfanõn açõlmamasõ durumunda http://go.microsoft.com/fwlink/?LinkId=52668 adresini ziyaret ederek sorunun olasõ sebebini ve çözümünü araştõrõnõz.) Team Foundation Server kurulumuna geçmeden önce yapõlan kurulumlar ile ilgili güncelleme işlemlerinin yapõlabilmesi için Windows Update sitesini ziyaret ediniz ve varsa gerekli güncelleme işlemlerini yapõnõz. (Adres: http://windowsupdate.microsoft.com) I.f. Team Foundation Server 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. 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 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 Encryption Keys seçeneğine tõklayõnõz. Gelen ekrandan Backup’a tõklayõnõz. Çõkan ekrana bir şifre ile şifrenin tutulacağõ dosyanõn kaydedileceği yeri ve dosya adõnõ belirleyiniz. (Bu işlem Reporting Services Encryption Key’in yedeklenmesi amacõyla yapõlmaktadõr. Zorunlu bir işlem değildir.) - Internet Explorer’da adres kõsmõna http://localhost:8080/services/v1.0/Registration.asmx adresini yazõn ve açõlan sayfadan GetRegistrationEntries linkine tõklayõn. Açõlan sayfadaki Invoke butonuna tõklayõnõz. (Metin kutusuna herhangi bir değer girmenize gerek yok.) Karşõnõza gelen XML metinde <Type>vstfs</Type> şeklinde bir kõsõm var ise herhangi problem yok demektir.

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 Studio 2005 ile TFS sunucusuna bağlanabilmek için gerekli olan Team Explorer'õn kurulumunu göreceğiz. Bu kurulum TFS'e bağlanacak bilgisayarlara yapõlacaktõr. TFS kurulu olan makinada da Visual Studio 2005 kullanõlacaksa, aynõ şekilde bu makinaya da kurulumu gerçekleştirebiliriz. Kurulum için şu adõmlarõ takip etmemiz gerekecektir: - 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) - Office Update sitesini ziyaret ederek gerekli güncellemeleri yükleyin. (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 bir projeye dahil 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. MSF for CMMI, CMMI proje süreçlerini takip edebilmek için kullanõlabilecek bir şablon olduğu için küçük ve orta büyüklüklerdeki projelerde pek tercih edilmez. MSF for Agile veya kendi oluşturduğunuz proje şablonlarõ yeterli olacaktõr. Proje şablonu seçildikten sonra. sõradaki ekranda eğer proje ile ilgili açõklamalar varsa yazõn ve Next’i tõklayõn. Projenin kaynak kodlarõnõn tutulacağõ yeri seçin. Ekrana, oluşturacağõnõz proje ile ilgili bilgiler getirilir. Son kõsõmda Finish’e tõklayarak projeyi oluşturun.

159

Sponsor Documents

Or use your account on DocShare.tips

Hide

Forgot your password?

Or register your new account on DocShare.tips

Hide

Lost your password? Please enter your email address. You will receive a link to create a new password.

Back to log-in

Close