Makale Özeti

AJAX teknikleri kullanılan web sitelerinde internet tarayıcılarının İleri ve Geri tuşlarının çalışması için özel ve farklı teknikler uygulamak gerekiyor. Bu makalemizde bu tekniklere hızlı bir göz attıktan sonra ASP.NET tarafında kullanabileceğimiz bağımsız bir sunucu kontrolü olan UpdateHistory kontrolünün kullanımını inceleyeceğiz.

Makale

İnternet tarayıcılarındaki Geri ve İleri düğmelerinin ne kadar çok kişi tarafından kullanıldığını ilk AJAX web projelerinin kullanıcılarına teslim edilmesi ile anladım. Neredeyse herkes bu düğmelerin çalışmamasından şikayetçiyi (Haklılardı). AJAX altyapısı üzerine kurduğumuz web sitelerinde performansı arttırmak amacıyla olabildiğince işlemleri AJAX tekniği ile yapmaya çalışıyoruz. Bu durumun iki sakıncası var; birincisi web sitesi içerisindeki farklı konumlar için farklı adresler oluşmuyor. Kullanıcı web sitemizde onlarca düğmeye tıklayarak iç kısımlarda biryerlere ulaşmış olabiliyor fakat sayfa hiç yenilenmediği için ulaştığı noktanın bir adresi (URL) olmuyor. İkinci sakıncası ise makalemin ana nedeni olan ve bir önceki nedenden kaynaklanan, tarayıcılardaki Geri ve İleri düğmelerinin çalışmaması. Sayfanın adresi değişmediği için hiçbir internet tarayıcı sayfanın içerisindeki değişiklikleri adres geçmişine eklemiyor ve bu nedenle geriye veya ileriye gidiş de mümkün olmuyor.

Peki ne yapabiliriz? İlk aşamada sayfanın adresini değiştirmek için sayfa içi çapalar (linkler) kullanabiliriz. Bu tarz linkleri aşağıdaki şekilde tanımlayabilirsiniz. Normal adresin sonuna bir # işareti ile eklenirler ve adresein bu kısmının değişmesi için sayfanın yenilenmesi gerekmez.

http://www.biradres.com/birdosya.aspx?ID=2#Capa

Güzel bir taktik olduğu kesin fakat maalesef yukarıdaki şekliyle yaratılan adresler Internet Explorer içerisinde sayfa geçmişine eklenmeyebiliyor (IE sürümüne bağlı). Bizim tüm tarayıcılarla uyumlu olmamız şart. Bu durumda Internet Explorer için farklı bir teknik kullanmamız gerekecek. Sayfanın içerisine gizli bir IFRAME (Satır içi çerçeve) ekleyerek IFRAME içerisindeki dosyanın adresini değiştirebiliriz. Bu durum Internet Explorer'da adres geçmişine yeni bir sayfay eklemek için yeterli olacaktır. Tek yapmamız gereken sayfamızı yenileyen AJAX komutlarının başına IFRAME adresini de değiştiren bir kod eklemek. Peki Geri veya İleri düğmelerine basıldığını nasıl anlayacağız? IFRAME içerisinde kullanacağımız adres gerçek bir sayfaya yönlenecek ve eğer tarayıcıdaki düğmeler ile bu sayfa değişmişse bir üst seviyedeki ana sayfaya JavaScript ile bir parametre gönderecek. Böylece ana sayfa AJAX teknikleri ile kendini eski haline çevirecek.

Merak etmeyin, biz bunları tek tek yapmayacağız. Onun yerine bu konuda işimizi çok kolaylaştıracak bir sunucu kontrolü kullanacağız. Bahsettiğim kontrolün adı UpdateHistory. Aşağıdaki adresten kontrol paketini indirebilirsiniz. Paket içerisinde yer alan nStuff.UpdateControls.dll dosyasını Toolbox içerisine ekleyerek projenizdeki herhangi bir sayfaya sürükle&bırak tekniği ile kontrolü ekleyebilirsiniz.

http://www.nikhilk.net/Content/Samples/UpdateControls.zip

Kontrolü sayfaya eklediğinizde aşağıdaki şekilde gözükecektir. Kontrol üzerinde yapmamız gereken hiçbir ayar yok.

<nStuff:UpdateHistory ID="UpdateHistory1" runat="server">
</nStuff:UpdateHistory>

Sayfa içerisinde ayrıca deneme amaçlı olarak bir UpdatePanel bulunduralım. UpdatePanel içerisine bir düğme ve bir de Label yerleştirelim. Düğmeye her tıklandığında Label içerisindeki sayısal değeri alıp üzerine bir ekleyip geri döndürsün. Böylece sürekli içeriği değişen bir UpdatePanel sahibi olmuş oluruz.

<asp:UpdatePanel ID="UpdatePanel1" runat="server">
  <ContentTemplate>
    <asp:Label ID="etiket" runat="server">0</asp:Label>
    <asp:Button ID="dugme" runat="server" OnClick="dugme_Click" Text="TIKLA" />
  </ContentTemplate>
</asp:UpdatePanel>

Yukarıdaki kod içerisinde düğmeye tıklandığında etiket adındaki Label içerisindeki değeri alarak bir arttıracağımızdan bahsetmiştik. Arttırma işlemini yaparken aslında sayfanın içeriği değiştiği için gerekli kaydın tarayıcıya ait sayfa geçmişi listesine de eklenmesini istiyoruz. Böylece İleri ve Geri düğmeleri ile site içerisinde gezebileceğiz. Bunun için aşağıdaki kodu yazıyor olacağız.

    Protected Sub dugme_Click(ByVal sender As Object, ByVal e As System.EventArgs)
        etiket.Text = CInt(etiket.Text) + 1
        UpdateHistory1.AddEntry(CInt(etiket.Text))
    End Sub

Yukarıdaki kodun ilk satırı bize yabancı değil. İkinci satıra baktığımızda ise UpdateHistory kontrolüne ait AddEntry metodunu kullandığımızı görüyoruz. Bu metoda vermiş olduğumuz tek parametre olan metin değeri sayfanın adresine, # işaretinden sonrasına ekleyecek. Tarayıcıda ileri veya geri düğmelerine basıldığında bizim sayfayı tekrar eski haline göre düzenlememiz için geriye yine bu veri döndürülecek. Veritabanına bağlı gerçek bir örnekte sayfada gösterilen veriyi bir veritabanı tablosundan Birincil Anahtar (Primary Key) değerini sorguyla göndererek aldığınızı düşünelim. Bu durumda AddEntry komutu ile adrese ekleyeceğimiz veri Primay Key'in ta kendisi olmalıdır. Böylece bir sonraki adımda göreceğimiz üzere sayfa kullanıcı tarafından ileri ve geri düğmeleri ile değiştirildiğinde adresin # işaretinden sonraki kısmına bakarak sayfaya kolaylıkla veri yerleştirebiliriz.

Son olarak gelelim kullanıcının ileri ve geri düğmelerini kullandığında sayfanın nasıl eski haline dönüştürüleceğine. Bu işlemi yapmak için UpdateHistory kontrolüne ait Navigate metodunu kullanacağız. Söz konusu metod bize hedef sayfanın EntryName değerini döndürüyor olacak.

Protected Sub UpdateHistory1_Navigate(ByVal sender As Object, ByVal e As nStuff.UpdateControls.HistoryEventArgs) Handles UpdateHistory1.Navigate
   If String.IsNullOrEmpty(e.EntryName) = False Then
      etiket.Text = e.EntryName
   Else
      etiket.Text = "0"
   End If
End Sub

Kodumuz içerisinde ilk olarak gelen parametrenin boş olup olmadığını kontrol ediyoruz. Eğer sayfa ilk defa açılıyorsa söz konusu parametre boş olacaktır. Bu durumda etiket adındaki Label içerisine 0 yazmamız yeterli. Eğer UpdateHistory tarafından bize döndürülen EntryName boş değilse kullanıcı bir şekilde Geri veya İleri düğmelerini kullanmış demektir. Kullanıcının hangi sayfaya gitmek istediğini EntryName değişkeni ile anlıyorum. Benim örneğimde bu veriyi direk etiket içerisine yazdırıyorum. Veritabanına bağlı gerçek bir örnekte siz geri dönen Primary Key verinize göre veritabanından gerekli içeriği çekerek sayfaya yerleştirebilirsiniz.

Son olarak projemin doğru çalışıp çalışmadığını kontrol etmek için UpdatePanel dışına da bir Label yerleştirerek sayfa açılışında mevcut saat bilgisini yazdırdım. Böylece sadece UpdatePanel içeriği mi yenileniyor yoksa tüm sayfa mı yenileniyor anlayabileceğim.

Son hali ile sayfanın HTML kodu aşağıdaki şekilde;

<%@ Page Language="VB" AutoEventWireup="true" CodeFile="Default.aspx.vb" Inherits="_Default" %>
<%@ Register Assembly="nStuff.UpdateControls" Namespace="nStuff.UpdateControls" TagPrefix="nStuff" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
        <ajaxToolkit:ToolkitScriptManager ID="ScriptManager1" runat="server" />
        <div>
            <nStuff:UpdateHistory ID="UpdateHistory1" runat="server">
            </nStuff:UpdateHistory>
            <asp:UpdatePanel ID="UpdatePanel1" runat="server">
                <ContentTemplate>
                    <asp:Label ID="etiket" runat="server">0</asp:Label>
                    <asp:Button ID="dugme" runat="server" OnClick="dugme_Click" Text="TIKLA" />
                </ContentTemplate>
            </asp:UpdatePanel>
            <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label></div>
    </form>
</body>
</html>

Sayfamızın Code-Behind kısmı da aşağıdaki gibi sonlandı.

Partial Class _Default
    Inherits System.Web.UI.Page
 
    Protected Sub dugme_Click(ByVal sender As Object, ByVal e As System.EventArgs)
        etiket.Text = CInt(etiket.Text) + 1
        UpdateHistory1.AddEntry(CInt(etiket.Text))
    End Sub
 
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Label1.Text = Date.Now.ToLongTimeString
    End Sub
 
    Protected Sub UpdateHistory1_Navigate(ByVal sender As Object, ByVal e As nStuff.UpdateControls.HistoryEventArgs) Handles UpdateHistory1.Navigate
        If String.IsNullOrEmpty(e.EntryName) = False Then
            etiket.Text = e.EntryName
        Else
            etiket.Text = "0"
        End If
    End Sub
End Class

Çözümümüz ile aslında sadece Geri ve İleri tuşları ile ilgili sorunu çözmedik. Ayrıca AJAX uygulamalarında her sayfanın ayrı adreslerinin olmaması sorununu da çözdük. Kopyala - Yapıştır tekniği ile adresler # işaretinden sonraki kısımları ile beraber taşındıklarında başka bir tarayıcıda denenmeleri durumda sayfa doğru konumda açılacaktır.

Hepinize kolay gelsin.

Daron Yöndem
MCPD, MCITP, MCTS, MCSD, MCAD
MCDBA, MCP, ACP, ICSD, IEL'03
http://daron.yondem.com