ASP.NET'de ViewState
| Bu makalemizde ASP.NET sayfalarında dinamik verileri tutmaya
yarayan View State konusunu göreceğiz. |
Giriş
ASPiştiricilerinin iyi bildiği gibi, bir web sayfasında dinamikliği korumak oldukça güçtür. Mesela asp ile yapılmış bir data grid'imiz (veli listeleme tablosu) var. Kullanıcı önce listede 2. sayfaya bastı , daha sonra listeyi id kolonuna göre sıraladı. ASP'de data grid'in doğru çalışması için hem grid sayfasının, hemde grid sıralama kolonunun belli bir yerde tutulması lazımdır. Genelde ASP geliştiricileri bu tip bilgileri tutan bir mekanizma olmadığı için bu bilgileri session nesnesinde veya query string olarak adres satırında tutarlar. Bu da asp geliştiricilerinin dinamik verileri tutmak için onlarca satır kod yazmak zorunda bırakır. ASP.NET bu tür dinamik özellikleri tutmak için ve için view state ve post back mekanizmasını geliştirmiştir. View state ile sayfada bulunan dinamik veriler otomatik olarak view state'te saklanr ve sayfanın bir dahaki gösteriminde bu veriler view state'ten alınarak otomatik olarak sayfadaki dinamik veriler korunur. Bu kısa girişten sonra view state mekanizmasını detaylı olarak inceleyelim.View State
Önceki makalemde Post Back hakkında gerekli bilgiyi aldıysak şimdi Post Back'ın tamamlayıcısı olan view state'e geçebiliriz. View State aslynda asp.net sayfalarında bulunan gizli(hidden) bir alandır. Bu alanda asp.net sayfasındaki sunucu kontrolleri ve sayfalar ile ilgili dinamik özellikleri tutulur. View State ve postback bir elmanın iki yarısı gibi düşünebiliriz. view state sayesinde sayfa bir önceki sayfa gösterimde saklanan dinamik verilerin alynmasıyla sayfa kullanıcıya en son sunulan hale getirilir, post back sayesinde ise sayfada event handler (olay yakalayıcı) metodların çalışırılmasıyla sayfa istenilen son haline getirilir.View State ve post back mantığını tamamen kavramak için ilk önce asp.net sayfaları nasıl üretildiğini detayli olarak bilmemiz gerekir. Önceki makalemde IIS'den ASP.NET sayfalarına kadar olanki iş akışını anlatmıştım (IIS & ASP.NET Isbirligi). O makalemde bahsedildiği gibi her http handler sınıfında bir adet ProcessRequest metodu bulunmaktadır ve bu metod asıl http üretme işini üstlenmektedir. Asp.net sayfalaryda (Page sınıfını extend ettikleri için ) birer http handler'dır ve Page sınıfında ProcessRequest metodu bulunmaktadyr. Bu Page sınıfındaki ProcessRequest metodu bir biri ardına bir kaç metod çağırmaktadır. Bu metodlar sayesinde kullanıcıya html cevap döndürülür.
Daha önceki makalede bir miktar bahsedildiği gibi aspx sayfalarının sunumu için ilk önce Http handler Factory sınıfı çalışır. Bu sınıfın görevi o sayfa için otomatik olarak merge edilmiş sınıfı bulmaktır. Merge edilmiş sınıf aspx sayfalarında ön plan ASP.NET taglarının, arka plan kodlarıyla birleştirilip programlama dillerine çevrilmesidir. Programlama diline çevrilmiş dosya WINDOWS\Microsoft.NET\Framework\versiyon\Temporary ASP.NET Files\proje_ady\ klasöründe bulunur. Mesela Default.aspx dosyası için otomatik olarak üretilen sınıfın adı _Default'dır. Kullanıcıdan Default.aspx isteği geldiğinde Http Handler Factory bu klasördeki _Default sınıfını bulur. Daha sonra o sınıfı initialize eder (oluşturur) ve bu sınıfın ProcessRequest metodunu çalıştırır.
| şekil 1: ASPX sayfaları oluşum iş akış şeması. |
| Kod 1: BasitSayfa.aspx dosyası |
| şekil 2: Aspx sayfası kontrol ağacı. |
Ağaç yapısı oluştuktan sonra bu metodun içinde şekil 1 belirtildi?i gibi bazı metodlar sırasıyla çalıştırılır. Öncelikle Page sınıfının ve sayfadaki tüm sunucu kontrollerinin Init metodları çalıştırılır. Init metodunda sayfanın ve sunucu kontrollerinin Init olayını handle eden metodlar çalıştırılır. Bu aşamada kontrol ağacı oluşturulduğu için sunucu kontrollere Init metodlarında ulaşılabiliriz.
Init'den sonra eğer sayfa PostBack durumunda ise LoadViewState metodu çalışır. Eğer sayfa ilk açılıyor ise (yani postback durumunda değil ise) bu metod çalışmaz. Bu metodda VievState tutulduğu yerden (varsayılan olarak __VIEWSTATE gizli form alanında tutulur) okunur, daha sonra Page ve Page sınıfının altındaki ViewState değerlerine atanır. Ayrıca view state değerinin geçerliliği kontrol edilir. ( view state'nin kullanıcı tarafından değiştirilmesini önlemek için bazı mekanizmalar vardır. İlerleyen bölümde ayrıntılı olarak bahsedilecektir). Ayrıca alynan view state değişkenleri, kontrollerin özelliklerine atanır ve sayfa bu bölümün sonunda view state değerleri yüklendiğinden kullanıcıya en son gösterilen sayfa ile aynı görünümdedir.
Daha sonra aynı şekilde sayfa eğer PostBack durumunda ise LoadPostbackData metodu çalıştırılır. Bu bölümde postback yapılarak sunucuya gönderilen form alanlarına bakılır. Gönderilen form alanı ile aynı isimde bir sunucu kontrolü var ise bu sunucu kontrolünün LoadPostbackData() metodu çalıştırılır. Bu metod çalıştığında sunucu kontrolü kendi özellik değerlerini formdan gelen değer ile değiştirir.
Örnek vermek gerekirse sayfamızda <asp:TextBox runat="server" Text="isim" ID="txtIsim"/> ASPNET koduyla yazılmış bir Text Boxımız var. Text box'ın sayfa ilk açıldığında içinde yazan değer isim olacaktır. Kullanıcı bu değeri "süleyman" olarak değiştirip sunucuya gönderdiğinde ASP.NET ilk önce LoadPostbackData aşamasında sunucu kontrollerinde txtIsim adında bir kontrol olup - olmadığını kontrol edecek, olduğunu gördüğünde TextBox sınıfının LoadPostbackData() metodunu çalıştıracaktır. Bu metod çalıştığında TextBox formdan dönen "süleyman" değerini kendi Text özelliğine atayacaktır. Böylelikle html oluşturulduğunda kullanıcıya gönderilen sayfada TextBox'ın içinde "isim" yerine "süleyman" yazacaktır.
İPUCU:
LoadPostbackData() metodu IPostBackDataHandler sınıfının bir metodudur. Bu yüzden
DropDownList, TextBox gibi PostBack yapıldığında özelliklerini değiştirecek sunucu
kontrolleri bu sınıfı extend ederler. Ayrıca eğer kendi sunucu kontrolümüzü yazıyorsak
ve bu kontrolün değerlerini sayfadan gelen form alanına göre değiştirmesi gerekiyorsa
kontrol için yazdığımız sınıfta bu metodu overwrite(üzerine yazılması) etmemiz gerekmektedir.
DİKKAT:
Genel bir yanılgı olarak ViewState'in formda girilen değerleri tuttuğu zannedilir.
Yani form'a basıldığında dönen sayfadaki değerlerin aynı kalmasının sebebi
ViewState olduğu zannedilir. Fakat bu PostBack mekanizması tarafından yapılır. ViewState
form ile gönderilmeyen, ve dinamik olarak güncellenebilen değerleri tutar. Mesela
Label kontrolünün Text özelliği, bu özellik form ile döndürülmez. Bu değer View
State'te saklanır. İleride ayrıntısıyla ViewState'in hangi değerleri tuttuğu açıklanacaktır.
LoadPostBack evresinden sonra bizim bildiğimiz Load evresi gelir. Load evresinde Load hareketi için kayıt edilmiş event handler metodları çalıştırılır. (Sayfa için Page_Load adynda Load evresinde çalıştırılıcak metod otomatik olarak Visual Studio tarafından oluşturulur.)
Event bölümünde değişiklik ve tıklama için kayıt edilmiışmetodlar çalıştırılır. Mesela bir buton'un click olayı için yazılmış bir Button1_Click metodu varsa bu aşamada metod çalıştırılır.
DİKKAT:
Önce change metodları daha sonra kontrol tarafından çalıştırılan diğer event handler
metodları çalıştırılır. Change metodu textBox kontrolünde bulunan TextChange gibi
olayları yakalayan metodlardır. Yani bir değişkeni hem Change metodlarında ve hem
de Click metodlarında değiştirirseniz (tabiki her 2 metodun çalıştırılması için
uygun kullanıcı hareketleri yapılması lazım. Mesela hem Textbox yazısı değiştirilecek
hem de butona basılacak) Click için yazılmış metotdaki son değer işlenir.
Bütün event handler metodları çalıştırıldıktan sonra artık sayfa render (html koduna çavrilmesi) edilerek kullanıcıya gönderilmeye hazırdır. Fakat ASP.NET sayfayı render etmeden önce LoadViewState aşamasından sonra değiştirilen kontrol değişkenlerini (tabi bu değişkenlerin view state'te saklanması gerekmektedir) toplayarak view state'i oluşturur ve bunu bir alanda saklar. (varsayılan alan sayfadaki __VIEWSTATE gizli form alanıdır)
Son olarak sayfadaki tüm sunucu kontrolleri html'ye çevrilir (yani render edilir) ve sayfa kullanıcıya döndürülür.
ViewState Nasıl Çalışır?
Bu aşamaya kadar olan kısımda gördüğümüz ASP.NET sayfalarının nasyl oluştuğunu gördük. Biraz kafamız karışmış olabilir fakat view state'in nasıl çalıştığını anlamak için bu kısımları bilmek gerekmektedir. Ayrıca ilerde kendimize özel Page sınıfları ve sunucu kontrolleri yaptığımızda (Page ve WebControl sınıfını extend eden sınıflar) bu kısımları bilmek oldukça işimize yarayacaktır. Daha önceden belirttiğimiz gibi View State PostBack ile sunucuya gönderilemeyen değerileri tutmak için yapılmış bir mekanizmadır. Bir değerin view state'te tutulması için o değerin view state'de tutulacağının belirtilmesi gerekmektedir.| Kod 2: Label kontrolü Text Özelliği |
Daha açıklayıcı olması için bir örnek yapacak olursak; mesela sayfamızda bir Label kontrolü var. Ayrıca sayfamızda 2 tane button var. Butonlardan birisine basıldığında Label kontrolünün text özelliğini "butona basıldı" yapacak diğer butona basıldığında hiç bir şey yapılmayacak.
| Kod 3: viewState_deneme.aspx dosyası |
| Kod 4: viewState_deneme.aspx.cs dosyası |
| şekil 3: Senaryolara göre Label ve View State durumu. |
View State Büyüklüğü
Her güzel şeyin bir bedeli olduğu gibi ViewState'inde bir bedeli vardır. View State varsayılan olarak sayfada bulunan __VIEWSTATE gizli form alanına kaydediliyor. Buda istemeden sayfanın büyüklüğünü belli miktar attırıyor. Sayfadaki View State miktarını page directive kısmında trace="true" yazarak görebiliriz.| şekil 4: ASPX sayfası kontrol ağacı ve view state büyüklükleri. |
| Kod 5: gridViewStateOrnek.aspx dosyası |
| şekil 5: Grid view olan bie sayfada view state büyüklüğü. |
View State'i Büyüklüğünü Kontrol Altına Alma
Öncelikle iyi bir geliştirici sayfanın büyüklüğünü olabilecek en minimum seviyede tutması gerekmektedir. Çünkü büyük sayfalar kullanıcılara gösterilirken daha fazla zaman alır. Bahsettiğimiz gibi bazen ASP.NET'te view state büyüklüğü oldukça fazla olabilmektedir. Bunu kontrol altına almak için ASP.NET'te view state'i sunucu kontrolü bazlı veya sayfa bazlı disable(devre dışı alma) özelliği vardır. Bu işlemi ASP.NET sunucu kontrollerinde EnableViewState özelliğini false yaparak yapabiliyoruz.| şekil 6: EnableViewState=false yapıldığında view state büyüklüğü. |
View state disable etmenin yanında view state'i sayfadaki gizli bir alan yerine Session, dosya veya veritabanında tutabiliyoruz. Fakat bu güçlü web sunucuları için önerilen bir yöntemdir. Çünkü bu işlem web sunucularına ek yük getirmektedir. View state'in form alanına kayıt işlemi Page sınıfında bulunan SavePageStateToPersistenceMedium() metoduyla yapılmaktadır, ve view state'in form alanından okunması işlemi LoadPageStateFromPersistenceMedium() ile yapılmaktadır. Eğer view state'in saklanma yerini değiştirmek istiyorsak bu 2 metodu sayfada overwrite(üzerime yazmamız) etmemiz gerekmektedir.
Aspx sayfalarının kaynak koduna baktığımızda __VIEWSTATE gizli form alanında yazılan değer okunabilir bir yazı değildir. Bunun sebebi view state değerleri yazılmadan önce System.Web.UI.LosFormatter sınıfı tarafından serialize edilmektedir. Ayrıca view state form alanından okunurken aynı sınıf tarafından deserialize edilmektedir. Yapacağımız örnekte Page sınıfındaki SavePageStateToPersistenceMedium ve LoadPageStateFromPersistenceMedium metodlarını overwrite edeceğiz ve LosFormatter sınıfını kullanarak view state değerlerini Session içine kaydedeceğiz.
| Kod 6: ViewStateSessionKayit.aspx.cs dosyası |
| şekil 7: View State'i Session'a kaydedildiğinde view state büyüklüğü. |
DİKKAT:
Bu kodun çalışması için kullanıcı browser'ında cookies'in devre dışı bırakılmaması
gerekmektedir. Eğer devre dışı bırakılmışsa Session çalışmayacağı için view state
kullanılamaz. Bu tip durumların önüne geçmek için sayfada gizli bir form alanına
bir GUID (global unique id) koyulabilinir ve view state bu ad ile dosya sistemine
kaydedilebilinir. Fakat dosya sistemine kaydedilen dosyaların belli aralıklarla
silinmesi lazımdır. Aksi halde sistemin disk'i hızla dolabilir.
İPUCU:
Bu kodda view state'i biz sadece tek bir sayfa için Session'a kaydettik. Eğer tüm
sayfalarda biz view state'i Session'a kaydetmek istiyorsak Page sınıfını extend
eden bir sınıf oluşturmalıyız. Bu sınıfta LoadPageStateFromPersistenceMedium ve
SavePageStateToPersistenceMedium metodlarını yaptığımız şekilde overwrite etmeliyiz.Daha
sonra oluşturduğumuz sayfaların base sınıfı olarak yaptığımız sınıfı göstermeliyiz.
(Daha fazla ayrıntılı bilgi için Nesne Tabanlı Programlama hakkındaki makalelere
bakabilirsiniz).
View State Güvenliği:
Sayfada bulunan view state her ne kadar okunmaz bir formatta isede view state kullanıcılar tarafından biraz kod yazma ile veya internetten hazır yazılmış kod bularak parse edilebilinir.(içindeki veriler okunabilinir.) Aynı zamanda okunan view state'teki değerler değiştirilip tekrar LosFormatter ile deserialize edilebilinir. Örnek olarak GridView listeleme sunucu kontrolündeki veriler'in sayfa her açılışında veritabanına başlanmamak için ASP.NET tarafından otomatik olarak view state'te tutulduğundan bahsetmiştik. Eğer grid view üzerinde ürünler ve fiyatları yazıyorsa kullanıcı view state'teki fiyatları modifiye edip sayfayı postback yaptığında karşısına gelen sayfada fiyatları kendi değiştirdiği şekilde görecektir. Hele bir de sepete atma fonksiyonu fiyatları grid view'den okuyorsa kullanıcı istediği fiyattan ürünleri alabilecektir.Neyseki ASP.NET'te view state'lere Machine Authentication Check(MAC) denilen bir mekanizma ile view state'in kullanıcı tarafından değiştirilmesini engellemektedir. MAC ile sunucu kullanıcıya gönderdiği view state ile kullanıcıdan gelen view state ile aynı olup olmadığına bakıyor. (Bunu view state'in hash değerini view state'in sonuna ekleyerek yapıyor). Eğer view state kullanıcı tarafından değiştirilmiş ise sayfa hata döndürüyor. Varsayılan olarak MAC tüm sayfalarda devrededir. Eğer bunu gereksiz bulunuyorsa (çünkü bu işlemde biraz kaynak tüketir) ve sayfalarınızda önemli bir veri bulunmuyorsa sayfada EnableViewStateMac özelliğini false yaparak bu işlemi devre dışı bırakabiliriz.
MAC dışıda eğer view state'in kullanıcılar tarafından parse edilmesi istenmiyorsa view state encrypt (şifreleme) edilebilinir. Bu işlem web.config dosyasında bulunan tagının içerisine validation = "3DES" yazarak yapylabilinir. Ayrıca bu tag içerisinde şifrelemelerde kullanılan anahtarlarda belirtilebilinir. validationKey özelliği MAC için kullanılacak anahtarı, decryptionKey 3DES için kullanılacak anahtarı belirler. Eğer bu anahtarları belirtilmemisse ASP.NET otomatik olarak rastgele anahtarlar üretir. Eğer birden fazla web sunucusunda aynı uygulama çalışıyorsa bu değerleri sabitlemekte fayda vardır.
Sonuç
Bu makalemizde ASP.NET geliştiricilerin en çok takıldığı konulardan birisi olan view state konusunu işledik. View state sayfada bulunan sunucu kontrollerinin ve sayfanın kendisinin dinamik değişkenlerini tuttuşu bir veri depolama alanıdır ve aynı sayfa nın PostBack çağırılmasında bu dinamik verilerin sayfada gösterilmesini sağlar.Ayrıca bu makalede view state değerlerini sayfada bulunan gizli form alanı yerine Session veya dosyaya nasıl yazılacağından bahsedildi. Böylelikle sayfa boyutları önemli ölçüde azaltılabilinmektedir. Son olarak makalede view state ile akılda oluşabilinecek güvenlik ile ilgili bilgiler verildi.
Hiç yorum yok:
Yorum Gönder