Bu yazıda son 1 yılda adından sıkça bahsettiren AJAX teknolojisi hakkında bilgi vermeye çalışacağım.
AJAX (Asynchronious Javascript And XML) 'ı bir internet sayfasının asenkron (yani sayfanın genel işleyişini durdurmadan) harici bir internet sayfasına kaynak olarak başvurması olarak tanımlayabiliriz. Tarayıcımızda açık olan bir sayfa, XMLHttpRequest adı verilen bir parçacık yardımıyla asenkron olarak başka bir web sayfasını çağırır. Çağırılan web sayfası ise geriye bir XML sayfası döndürür ve biz de bu XML dosyasını Javascript komutlarıyla parse ederek (yani XML dosyası içerisinden verileri çekerek) elde ettiğimiz verileri yine Javascript komutlarıyla açık olan web sayfasında uygun gördüğümüz yerlere yerleştiririz.
Peki neden AJAX? Neden ASP.NET 2.0 ın çok gelişmiş GridView gibi özelliklerini kullanmıyoruz da herşeyi elle programlamamız gereken bir işe bulaşıyoruz? Cevabı çok basit: Dinamik bir kullanıcı arayüzü, kasılmayan bir internet bağlantısı ve sunucuyu yormayan ve sunucunun aynı çalışmayla daha fazla isteğe cevap verebilmesini sağlamak.
Klasik bir ASP.NET sayfasında yaptığınız her istekte size bir sayfa gönderilir. Bu birçoğunuza pek önemli değil gibi gelse de bir tarafa dikkatinizi çekmek istiyorum: Her gelen web sayfasında değişmeyen birçok bölüm (menü, başlık, vs.) yeniden gönderilir ve daha önemlisi bu kısımların da sunucu tarafında derlenerek yollanmasıdır. Kısacası bu sistemde tüm yükü sunucu çekmektedir. İstemci sadece sayfa isteğinde bulunur ve gelen sayfayı kullanıcıya gösterir. Peki AJAX'ta bu sistem nasıl işlemekte? AJAX'ta ASP.NET sayfalarını bir xml sağlayıcısı olarak kullanıyoruz. Sayfaya istek geldiğinde, sayfa url'sindeki querystringleri kullanarak kendisi için gerekli olan verileri alır, işler ve sonuçta geriye verinin düzgün olarak formatlanmış hali olan xml sayfasını döndürür. Dikkat ederseniz burada verileri ekranda göstermeyi sağlayan hiçbir ASP.NET kontrolünü (GridView gibi) kullanmadık. Peki biz bu verileri nasıl göstereceğiz? Burada client tarafında programlama yapabileceğimiz Javascript devreye giriyor. Dönen xml dosyalarının düğümlerinde (node) hareket ederek verileri sistemli bir şekilde elde ediyor, dahs sonra bunları sayfada önceden belirlediğimiz yerlere yerleştiriyoruz. Göründüğü gibi sunucunun yapmış olduğu veriyi sayfaya yerleştirme işlemini biz istemciye bırakarak sunucuyu büyük bir yükten kurtardık. Ayrıca dönen değer salt veri olduğu için sunucunun bant genişliği problemini de azaltmış ve daha fazla isteğe cevap verebilecek hale getirmiş olduk.
Peki AJAX programlaması yapmak için neler gereklidir? Bir server-side programlama dilini (tercihen C#) en azından basit bir web sayfası yapacak kadar bilmek, biraz xml ve biraz da Javascript bilgisi yeterlidir.
Bunların dışında bazı konular hakkında ben biraz bilgi versem iyi olur kanaatindeyim: Bir web sayfası için istek yaptığınızda karşı taraftan gelen cevapta size gönderilen sayfanın içerik tipi (Content-Type) gönderilir. Normal şartlarda bu değer text/html dir. Ama bizim sunucudan istediğimiz şey bir XML sayfası olduğundan Content-Type'ı text/xml olarak değiştirmemiz gerekmektedir.
İsterseniz konunun daha rahat anlaşılabilmesi için bir örnek üzerinde devam edelim:
İlk örneğimizde (herzaman tüm kitaplardaki ilk örnek olduğu için) bir Merhaba Dünya uygulaması geliştirelim.
Adım 1. Visual Studio 2005'te yeni bir web sitesi yaratalım, Location olarak File System, Language olarak C# seçili olsun.
Adım 2. Solution Explorer'dan projemize yeni bir aspx sayfası ekleyelim:
Adım 3. Şimdi işin ilk adımı olarak veri sağlayıcımızı yani aspx sayfasını yazacağız.
Adım 3.1. İlk olarak sayfamız kendisine bir AJAX isteği geldiğinde gelen verileri işler. Ama örneğimiz bir Merhaba Dünya uygulaması olduğundan sadece geriye ufak bir xml dosyası göndermekle yetineceğiz. Öncelikle istemciye vereceğimiz cevabı aspx sayfamıza otomatik olarak yerleştirilmiş xhtml kodlarından arındırmamız gerekiyor. Daha sonra ise cevabımızın içerik tipini belirledikten sonra buffer özelliğini kapatmamız gerekiyor. Tarayıcılar, sayfaları önbelleklerine aldıklarında o sayfada değişiklik olmadığı sürece istemciye hep önbellekteki sayfayı gösterirler, aksini belirtmediğiniz takdirde. İşte bu aksi durumu 3. satırdaki kod ile sağlıyoruz. AJAX dinamik bir yapı ve dinamik olarak veri alımı zorunlu olduğu için buffer kontrolü işimize gelmez.
Response.Clear(); //Cevabı Temizle
Response.ContentType = "text/xml"; //Cevabın tipini belirle
Response.Expires = 0; //Buffer kontrolünü devre dışı bırak
Adım 3.2. Artık xml dosyamızı oluşturmaya başlayabiliriz: Öncelikle ihtiyacımız olan nesneleri kullanabilmek için sayfanın en üstüne şu satırı eklememiz gerekmekte:
using System.Xml;
Daha sonra ise bir XMLTextWriter tanımlayarak yeni bir dökümana başlamamız gerekmektedir. Bu tanımlamada dikkat edilmesi gereken iki parametre var: Birisi Response.OutputStream (cevabımızın Stream hali, bkz CSharpNedir.com - Streamler), bir diğeri ise System.Text.Encoding.GetEncoding("windows-1254") (Türkçe karakter desteklemesi için gerekli olan dil kodlaması) dır.
XmlTextWriter yaz = new XmlTextWriter(Response.OutputStream, System.Text.Encoding.GetEncoding("windows-1254"));
yaz.WriteStartDocument();
Daha sonra xml dosyamızın root elementini tanımlayacağız:
yaz.WriteStartElement("Basla");
Şimdi Merhaba Dünya yazısını yazmanın vakti geldi:
yaz.WriteString("Merhaba Dünya");
Başladığımız elementi ve dökümanı sırasıyla kapatalım. Unutmayın, xml çok katı kuralları olan bir dildir ve html ile aynı tabandan gelmesine rağmen aynı toleransı tanımaz. Bu yüzden açtığınız her elementi ters sırayla kapatmak zorundasınız.
yaz.WriteEndElement();
yaz.WriteEndDocument();
Daha sonra ise XMLTextWriter'ımızı ve cevabımızı bitireceğiz:
yaz.Close();
Response.End();
XML dosyamızın görüntüsü şu şekilde olacaktır:
Adım 4. Artık veri sağlayıcımız hazır olduğuna göre XML dosyamızı parse etme işlemine başlayabiliriz. Öncelikle projemize bir html sayfası ve bir Javascript dosyası ekliyoruz:
Daha sonra ise XMLHttpRequest nesnemizi aşağıdaki fonksiyon yardımıyla oluşturuyoruz:
function getXMLHttpRequest(){
var httpRequest = null;
try { httpRequest = new ActiveXObject("Msxml2.XMLHTTP");
}catch(e) {
try { httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
} catch(e) { httpRequest = null;}
}
if (!httpRequest && typeof XMLHttpRequest != "undefined")
httpRequest = new XMLHttpRequest();
return httpRequest;
}
Bu kod sayesinde XMLHttpRequest nesnemizin hem Internet Explorer'da hem de Firefox gibi Gecko tabanlı tarayıcılarda düzgün çalışmasını sağlıyoruz. Daha sonra ise parse işlemine geçmeden önce ufak bir işlem için bir fonksiyon tanımlamamız gerekmekte: Whitespace temizleme. Bir xml veya html belgesinde ifade edilemeyen bazı karakterler bulunur. Bunlar enter, tab gibi karakterlerdir ve maalesef bunları temizlemediğimiz takdirde bazı tarayıcılar bunları da element olarak kabul etmektedirler. Aşağıdaki kod bloğuyla bu işi de halletmekteyiz:
function removeWhitespace(xml)
{
var loopIndex;
for (loopIndex = 0; loopIndex <>
{
var currentNode = xml.childNodes[loopIndex];
if (currentNode.nodeType == 1)
{
removeWhitespace(currentNode);
}
if (((/^\s+$/.test(currentNode.nodeValue))) && (currentNode.nodeType == 3))
{
xml.removeChild(xml.childNodes[loopIndex--]);
}
}
}
Daha sonra hem IE de hem Firefox'ta verileri sorunsuz parse etmek için ufak bir fonksiyonumuz daha var:
function myNodeValue(myXmlText){
return (myXmlText.textContent|| myXmlText.innerText || myXmlText.text);
}
Ve geldik en önemli yere: XMLHttpRequest.onreadystatechange! Bu önemli olay, bize birçok kolaylık tanımakta. Bir XMLHttpRequest yollandığında XMLHttpRequest.readyState değeri verinin o anki durumuna göre değişik değerler alır:
0 = Hazır Değil
1 = Yükleniyor
2 = Yüklendi
3 = İnceleniyor
4 = Tamamlandı
Bizim için burada önemli olan değer 4. Çünkü biz verimiz tam olarak yüklendiğinde parse işlemine başlayacağız. Ayrıca HTTP protokolünün status değerlerini de kontrol etmemiz gerekmekte. Bunlara fazla değinmeyeceğim. Sadece kodlarını yazacağım:
200 - OK
404 - Sayfa Bulunamadı
403 - Yetkisiz Giriş Talebi
500 - Sayfa Hatası
Bunlardan da ihtiyacımız olan değer 200, çünkü bizim verimizi aldığımızdan emin olmamız gerekiyor. Aşağıda standart bir parser çağırıcı fonksiyonun şablonunu bulunmakta.
function AJAXOrnek()
{
var xmlRequest = getXMLHttpRequest();
xmlRequest.onreadystatechange = function()
{
if(xmlRequest.readyState == 4){
if(xmlRequest.status == 200){
var doc=xmlRequest.responseXML.documentElement;
removeWhitespace(doc);
MyParser(doc); //Burada verimizi parse edecek fonksiyonumuzu çağıracağız
}
else{
alert("Data erişiminde hata!"+xmlRequest.status );
}
}
}
xmlRequest.open("POST", "ajax.aspx", true);
xmlRequest.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8");
xmlRequest.send(null);
}
Artık parser fonksiyonumuz olan MyParser'ı yazmaya başlıyoruz:
function MyParser(doc)
{
var mesaj = myNodeValue(doc.childNodes[0]);
alert(mesaj);
}
Fonksiyonumuz gelen xml verimizin root elementi olan taglarına childNodes değeri ile eriştikten sonra myNodeValue fonksiyonuyla içeriğini bir alertbox'a basmakta. Eğer daha karmaşık bir xml dosyası hazırladıysanız ve içiçe taglarınız varsa, childNodes'u kullanarak hepsine ulaşabilirsiniz. Bu özelliği aynı bir dizideki gibi kullanıyoruz.
En son olarak ajaxornek.htm'i de aşağıdaki şekilde yapılandırdıktan sonra test işlemine başlayabilirsiniz:
Sonuç olarak aşağıdaki gibi bir görüntü elde etmeniz gerekmekte:
Umarım işinize yarar. Teşekkürler.
Yazar: Harun Yiğit LEGOZ