AJAX Web Sitelerinde Tarayıcıda Geri/İleri Düğmesi Sorunu

0 dakikada yazıldı

10283 defa okundu

Düzenle

İ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.