16 Şubat 2009 Pazartesi

State Management - 1

Selam herkese. Aslında kafamı dağıtmaktan başka bir şey yapmadığım bu blogda, makale yayınlamak istemiyordum ancak bloga fazla ilgi gösteremeyince bari yazdıklarımı buraya da taşıyayım dedim :) Geçenlerde biri kendi yazısı gibi göstermiş bu Durum Yönetimi serimi. Okunması, paylaşılması hoş bir şey aa uğraşınızı kendi uğraşı gibi göstermesi cidden saygısızca olmuş. Neyse uyardım zaten kendisini. İyi okumalar, siyah zeminde gözleriniz daha iyi okuyacaktır. :D
----

Merhaba arkadaşlar. Bir makalemiz ile daha birlikteyiz.
Bu makalemizin konusu: State Management, yani Durum Yönetimi. Peki nedir bu Durum Yönetimi dediğimiz şey?
Siz web ortamında birer istemcisiniz(client). Siz bir web sayfasına girdiğinizde onu sunucudan istemiş oluyorsunuz. Bunu HTTP protokolü ile yaparsınız. HTTP inetinfo.exe'ye sizin çağırdığınız sayfayı söyler. Inetinfo.exe de uzantıya bakar. Uzantı aspx ise aspnet_isapi.dll'e gider ve sayfayı hazırlamasını söyler, aspnet_isapi.dll de aspnet_wp.exe'ye gider. Tüm bu işlemlerden sonra size bir cevap(response) döner. Ancak yine HTTP protokolü aracılığıyla(HTTPResponse). HTTP'nin önemini herhalde kavramışsınızdır. Ancak HTTP'nin öyle bir özelliği var ki bizleri durum yönetimi kavramına yönlendirmekte. HTTP stateless'tır. Yani önceki durumlar hakkında bilgisi yok, hiç birşeyin durumunu tutmaz. Hatırlarsanız ASP.Net server-side bir yaklaşımdı, yani değişken vs. gibi değerlerini sunucuda oluşturuyordu. ASP.NET'te bir sayfa sunucuda render edildikten sonra, yani HTML'e çevrildikten sonra, kullanıcıya gönderilir ve sunucu belleğinden silinir. Yani eski değerlere tekrar erişme gibi bir durum mümkün olmuyor. Dolayısıyla birazdan inceleyeceğimiz kavramlar ile sayfanın durumunu tutabileceğiz(yani verileri kalıcı olarak saklayabileceğiz).
En çok karşılaşacağınız 5 tanesini inceleyeceğiz.
1. ViewState
2. Cookie
3. QueryString
4. Application State
5. Session State
Yukarıdakilerden ilk 3 tanesi, bilgileri kullanıcının bilgisayarında saklamalarından mütevellit "Client-Based State Manegement" olarak isimlendirilirler. Diğer iki tanesi de bilgileri sunucuda sakladığından, "Server-Based State Management" şeklinde bilinirler.
İsterseniz bu kavramların neler olduklarını inceleyelim.
ViewState: Sayfa postback olduğunda değişen kontrol değerlerinin taşınmasını, bunların kaybolmamasını sağlar(ki hepsinin mantığı aynı sayılır). Yukarıda da değinildiği üzere bilgileri client tarafında tutuyor. Bir örnekle açıklayalım: Diyelim ki 4 tane button var. 1 milyon kişi sayfaya bağlanmış. Herkes farklı bir düğmeye basar. Biz 1. düğmeye bastık. Sonra da gidip 2. düğmeye bastık. Ancak sayfaya daha önce de 1. düğmeye bastığımızı söylemeliyiz. Evet arkadaşlar, işte tüm bu bilgileri sayfa içinde tutarız. Buradaki kilit nokta bilgilerin sayfa içinde tutulduğudur. Dolayısıyla sayfa sunucuya gidip gelirken bunları taşır. Buradan çıkarılacak önemli sonuç nedir? Sayfanızda viewstate kullanacaksanız çok büyük verileri viewstate ile tutmamalısınız. Aksi taktirde büyük performans kayıpları yaşayabilirsiniz.
ViewState'i ASP.NET otomatik olarak kontrol ediyor. Aslına bakarsanız biz pek karışmıyoruz. Ancak gerekli durumlarda müdahele ederiz. Örneğin sık sık güncellenen bir veriniz varsa bu yapıyı kullanmamanız daha iyidir.
Sayfanın kaynağını görüntülediğinizde hidden diye bir alan görebilirsiniz. gibi bir satır görürsünüz. Değeri Base64 formatında string olarak sakladığı için anlamsız gelen bazı karakterler görmektesiniz. Yalnız burada bir ayrımın altını çizeyim. Bazı yerlerde şifreli diye ifadeler geçiyor. Bu değer şifrelenmemiştir, kodlanmıştır sadece. Zaten encoded diye geçiyor, encrypt diye değil.
ViewState ile ilgili diğer önemli nokta da, ViewState'in her sayfaya özel olmasıdır. Bir sayfa diğer sayfanın viewstate'ini bilemez.
Bir diğer önemli husus da ViewState'in sayfa üzerinde yer alan kontrollerin sırasını, dizimini tutmasıdır. Bunu gözlemlemenin en güzel yolu hidden alanına bakmaktır. Visual Studio'yu açın ve design ekranına sırayla bir button, bir textbox, bir label ve bir hyperlink koyun. Bunları çalıştırın ve sayfanın kaynağına bakın.

Şimdi de bu kontrollere bazı değişiklikler yapalım ve çalıştırıp tekrar kaynağı görüntüleyelim.

Gördüğünüz gibi değer değişmedi. Her ikisinde de value aynıdır. Bizim design kısmında yaptığımız değişikler ViewState'te tutulmaz. Takdir edersiniz ki, bu tür değişiklikler zaten source içerisinde tutulmakta olduğundan bunları saklamanın da pek bir mantığı yoktur.
Şimdi biraz kafa karıştırıcı detaya girelim. ViewState başlığının ilk cümlesini tekrar buraya taşıyorum: " Sayfa postback olduğunda değişen kontrol değerlerinin taşınmasını, bunların kaybolmamasını sağlar". Postback olduğunda değişen kontrol değerlerinden bahsetmişiz. Şimdi sayfanın postback olmasını sağlayalım. Mesela buttona tıklayalım. ButtonClick eventinin içine istediğiniz kodu yazabilirsiniz. Önemli olan sayfamızı postback ettirmektir.

Gördüğünüz gibi value değişti. Yani, postback sonucunda kontrollerin değişen özellikleri de ViewState'te tutulmaktadır. Ancak msdn'de belirtildiği üzere tüm kontrollerde bu geçerli olmuyormuş. Detaylı bilgi için : http://msdn.microsoft.com/en-us/library/ms972976.aspx

ViewState varsayılan olarak aktiftir. Sayfanızın source kısmında EnableViewState özelliğini ayarlayabilirsiniz. <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" EnableViewState="false" %> derseniz, sayfada ViewState kullanımını engellemiş olursunuz. Bunu sayfa genelinde değil de kontrol bazında da ayarlayabilirsiniz.


şeklinde. Bu şekilde yapmanın olumlu yanı sayfanın yükünü azaltmaktır. Böylelikle ViewState'in tutacağı değer küçülür. Ancak ViewStae'i sıkıştıradabilirsiniz. Bu konu hakkında bağlantıyı incelerseniz daha iyi fikir sahibi olacaksınız: http://www.codeproject.com/KB/viewstate/ViewStateCompression.aspx

ViewState, HashTable mantığında çalışır. Yani anahtar,veri çifti vardır. Anahtar ile veri çekilir. Object türünde veriler tutar. Ancak alışılan yöntemle, yani indekslerle değil de, anahtar vasıtasıyla verilere erişiyor. İndekste verilere tek tek bakarsınız ancak HashTable yapısında direkt olarak "şu anahtara sahip olan veriyi getir" diyorsunuz. Dolayısıyla çok daha hızlıdır. Örneğin:
ViewState["gurkan"]=1986;
şeklinde bir ifade kullanırsanız, gurkan anahtarına sahip bir veriye 1986 değerini atamış olursunuz. Her anahtar bir veriye verilmelidir. Var olan bir key'i tekrar vermek isterseniz Exception alırsınız.
Aynı şekilde:
int deger=(int)ViewState["gurkan"];
diyerek de ViewState'deki değeri bir değişkene atayabilirsiniz.

Şimdi de ViewState'in nasıl daha güvenilir bir hale getirilebileceğini inceleyelim. Daha önce de değindiğim üzere ViewState kodlanmıştı, şifrelenmemişti. Şifrelenmesini de az sonra ele alacağız ancak öncelikle kodlanmasından bahsedelim. Bu kodlamanın(Base64) uzunluğu hep 4'ün katları şeklindedir. Eğer 4'ün katı değilse, sonuna 4'ün katı olana kadar = konur. Bizim örneklerimizde de dikkat ettiyseniz sonunda = vardı, ViewState'in value'sunda. ASCII ile ilşkili bir kodlamadır ancak fazla detayına inmeyeceğim. Bu kodlama, değerlerin direkt görülebilmesini engeller. Bu yönü güzel çünkü ileride inceleyeceğimiz bazı nesnelerde direkt kullanıcının görebileceği şekilde değerler vardır. Ancak sık sık tekrarladığımız üzere bu bir şifreleme değildir ve encode edilmiş her şey, pek tabidir ki decode edilebilmektedir(Lojik devrelerdeki mantık aynen bunda da geçerlidir). Dolayısıyla pek de güvenli bir şey değildir. Eğer önemli bilgiler taşıyacaksak bu büyük bir risktir.
Daha önce Hash Fonksiyonlarını kullanan olduysa, orada Message Authentication Codes vardı. Mesajın içeriğinin yolda değiştirilmediğini ve belli bir kaynaktan çıktığını doğrulamaya yarıyordu. Hemen hemen aynı yapı burada da var: MAC. Sunucudaki ViewState değeri ile kullanıcıya gelen ViewState değerini karşılaştırıp, değişiklik yapılıp yapılmadığını kontrol eder. Eğer değişiklik varsa uyarır. Tüm bu işlemler yine otomatik olarak yapılmakta. Eğer siz gidip de EnableViewStateMac="false" demezseniz tabi. :) (EnableViewState'teki gibi yazdığınız yeri siz seçersiniz.)
Artık nasıl şifreleme yapılacağına değinme vakti geldi sanırım. Öncelikle, şifrelemek için EnableViewStateMac="true" olmalıdır. Ardından machine.config dosyanıza gibi bir ifade ile şifreleme yapabilirsiniz. Ancak şifrelemeler de %100 güvenlik anlamına gelmiyor şimdilik. Örnek olarak kullandığımız 3DES algoritması, simetrik bir algoritmadır. Dolayısıyla şifreleme için ve şifreyi çözme için aynı anahtar kullanılır. Dolayısıyla bu da güvenlik açığıdır. Herhalde tam anlamıyla güvenlikten söz edebilmek için bir kaç yıl daha bekleyeceğiz ki Quantum Kriptografi iyice gelişsin. :)
Arkadaşlar, makaleyi çok fazla uzatıp da okunurluğunu düşürmek istemiyorum. O yüzden bu yazıyı burada sonlandırıyorum. Bir sonraki makalede kaldığımız yerden devam edeceğiz.
Hoşça kalın..

Gürkan Alkan
İstanbul Üniversitesi Bilgisayar Mühendisliği

Not: Son 1 ayda e-postaların ulaşımında sorunlar yaşanıyordu ancak sorun tamamen çözülmüştür. Bilginize.
Referanslar: http://aspalliance.com/articleViewer.aspx?aId=135&pId=
http://msdn.microsoft.com/en-us/library/ms972976.aspx

Hiç yorum yok: