Çok kısa diğer makaleleri hatırlatacak olursak: 1. makalede State Management kavramını ve ViewState nesnesini; 2. makalede ise Cookie nesnesini incelemiştik. Şimdi de sırada QueryStrings var.
16 Şubat 2009 Pazartesi
State Management - 3
Merhaba herkese. State Management makale dizimizin 3 bölümü ile birlikteyiz.
Çok kısa diğer makaleleri hatırlatacak olursak: 1. makalede State Management kavramını ve ViewState nesnesini; 2. makalede ise Cookie nesnesini incelemiştik. Şimdi de sırada QueryStrings var.
Query String dediğimiz şey, aslında çoğumuzun sürekli karşılaştığı bir nesnedir. Query Stringler, URL'lerin sonunda gördüğümüz bilgilerdir. URL'nin sonunda ne var, hangisi query string? Somut bir örnekle bu konuyu daha yakından inceleyelim.
Server.Transfer kullanımındaki bir diğer farklılık, bu yöntemle server'ın kaynaklarının korunmasıdır. Bu yöntemle tek bir request ile işlerinizi yapabilmektesiniz. Response.Redirect kullanırken iki request yapıyorduk. Dolayısıyla Server.Transfer kullanmak server'ın performansı arttırdığı gibi, uygulamamızı da hızlandıracaktır. Ancak buradaki önemli nokta, Server.Transfer'deki transfer olayı aynı site içerisinde çalışmaktadır. Farklı bir alan için Response.Redirect kullanmak durumundasınız.
Çok kısa diğer makaleleri hatırlatacak olursak: 1. makalede State Management kavramını ve ViewState nesnesini; 2. makalede ise Cookie nesnesini incelemiştik. Şimdi de sırada QueryStrings var.
Query String dediğimiz şey, aslında çoğumuzun sürekli karşılaştığı bir nesnedir. Query Stringler, URL'lerin sonunda gördüğümüz bilgilerdir. URL'nin sonunda ne var, hangisi query string? Somut bir örnekle bu konuyu daha yakından inceleyelim.
Server.Transfer kullanımındaki bir diğer farklılık, bu yöntemle server'ın kaynaklarının korunmasıdır. Bu yöntemle tek bir request ile işlerinizi yapabilmektesiniz. Response.Redirect kullanırken iki request yapıyorduk. Dolayısıyla Server.Transfer kullanmak server'ın performansı arttırdığı gibi, uygulamamızı da hızlandıracaktır. Ancak buradaki önemli nokta, Server.Transfer'deki transfer olayı aynı site içerisinde çalışmaktadır. Farklı bir alan için Response.Redirect kullanmak durumundasınız.
State Management - 2
Merhaba bir kez daha herkese. State Management konulu makalemizin ikinci bölümü ile kaldığımız yerden devam edeceğiz.
İlk bölümde State Management'ın ne demek olduğunu, neden ihtiyaç duyulduğunu incelemiş, ViewState konusunu ele almıştık. Şimdi ise diğer nesnelerimize değineceğiz. Cookie ile başlayalım isterseniz.
Cookies: Cookie, kelime anlamı olarak çerez. :) Nedir bu cookieler? Cookieler, kullanıcılar hakkında bilgileri saklayan zararsız dosyalardır. Server tarafından kullanıcının bilgisayarına gönderilir. Aslında bu en basit haliyle böyle. Birazdan tüm detaylarına gireceğiz. Ancak bu kavramı anlamanız için somut bir kaç örnek vermek istiyorum.
Örneğin bir bir foruma üyesiniz. Foruma en son ne zaman geldiğiniz, siz yokken hangi mesajlar atılmış cookie ile görülebilir. Cookie'den geliş tarihiniz bulunur ve uygun işlem yapılır. Başka bir örnek verelim. E-Posta hesaplarında "Beni Hatırla" seçeneği var. Beni Hatırla seçeneğini aktifleştirirseniz, o da örneğin cookie yardımıyla sizi tanır. Arkadaşlar dikkatinizi çekerim, bu verdiğim örneklerde cookie kullanımı çok yaygın demiyorum. Sadece cookie ile de olur diyorum. Mesela online alışverişteki alışveriş sepeti uygulaması. Siz siteden çıksanız da sepetiniz bir sonraki açılışta hala orada durur. Cookie ile bunu yapmak pek akıllıca değil(sebebini makaleyi okudukça anlayacaksınız), genelde de yapılmaz ama mantığını anlamanız açısından size fikir verecektir.
Cookie hakkında kafanızda bir şeyler canlandıysa şayet şimdi bir adım öteye gidip, genel yapısını inceleyelim. Kullanıcı herhangi bir siteye girdi diyelim. Sizin sitenize girmiş olsun. Siz, sitenizden ona cookie'yi atarsınız(Response ile atabilirsiniz, çünkü hatırlarsanız ASP.Net'te server'dan dönen cevap response idi, bu yüzden cookie'yi yazarken response nesnesinden yardım alabiliriz.). Farzı misal kullanıcı sitenize tekrar girmeye karar verdi.URL'yi girdiği zaman, kullanıcının tarayıcısı(IE, Mozilla, Opera, Chrome vs.) da sitenize cookie'yi atar. Yani sizin kullanıcının bilgisayarına attığınız cookieyi, kullanıcının tarayıcısı yardımıyla geri alırsınız(Request ile alabilirsiniz, yine hatırlarsanız ASP.Net't client'tan giden istek Request idi, bu yüzden cookie'yi aldığımızda request nesnesinden yardım alabiliriz.). Yalnız tarayıcı URL ile ilgili cookie varsa, bulursa atar. Yoksa, atamaz. Böylelikle siz, sitenize gelen kullanıcı ile ilgili bazı bilgileri edinmiş olursunuz.
Kullanıcının siteden hangi sayfayı istediği normalde önemli değildir. Aslında önemli olduğu durumlar var ancak buna da makalemizin ilerleyen satırlarında değineceğiz. Standart olarak, cookie siteniz ile ilşkilidir, sitenizdeki bir sayfa ile değil(İsterseniz farklı ilişkiler de yaratabilirsiniz. Birazdan birlikte yaratacağız zaten.).
Çoğu tarayıcılar 4096 byte'a kadar cookie destekler. Bu küçük limit yüzünden, cookielerde küçük veriler saklamak uygundur. Tarayıcılar, bir siteden kullanıcının ne kadar cookie alacağını da belirlerler. Bir çok tarayıcı site başına 20 cookie'ye izin veriyor. Eğer siteniz daha fazlasını gönderirse eski cookieler sırasıyla silinmiş olur. Ancak bir kısım tarayıcılar da genel bir limit belirliyor, ki genelde 300 cookie oluyor bu limit, site bazında değil de tüm sitelerden gelen cookie sayısına göre saklıyorlar.
Cookie sınırlandırmalarında en büyük sorun ise kullanıcının tarayıcı ayarlarından cookie alımını engellemesidir. Gerçi bazı yazılımcılar, cookie'yi reddediyorsa siteme girmesin, de diyebilmekte. ? Dolayısıyla yararlı da olsa uygulamalarınız cookielere bağımlı olmamalıdır. Alternatif yollarınız mutlaka olmalıdır. Veyahut diğer yöntemlerle verilerini taşıyıp, saklarsınız. Kritik verilerde cookie kullanmamanız gerektiğini de herhalde fark etmişsinizdir. Bu konuya birazdan tekrar gireceğim. Tarayıcı ayarlarında yapılacak değişiklikler her zaman güçlük yaratır dedik. Bu sorunu aşabilmenin bir yolu da sitenizde P3P(Platform for Privacy Preferences Project) tanımlamaktır. Bu sayede, tarayıcılarında belli policy ayarları yapmış kullanıcılar, policy ihlallerinde derhal uyarılır ve siteye girmeyebilirler. Bu durumu sağladığınızda tarayıcılar sitenizden cookie alımı yapabilirler.
Cookie Yazma
İsterseniz şimdi cookie yazma olayına geçelim. Cookieler, kullanıcıların tarayıcılarına (yukarıda bahsettiğim sebeplerden dolayı) HttpResponse nesnesi ile yollanırlar, ki bu nesnenin de Cookies adında bir koleksiyonu vardır. HttpResponse nesnesine Page sınıfımızın(yani sayfamızın), Response property'si ile ulaşabiliriz. Sitenizden, kullanıcının harddiskinde depolanmak üzere, tarayıcıya gönderilen her cookie'yi Cookies koleksiyonuna eklemelisiniz.
Cookie yaratınca bir Name ve Value vermelisiniz. Mantıksal olarak anlamanız için ViewState'te bahsettiğim(State Management-1 Makalesi) HashTable yapısı gibi düşüneblirsiniz. Cookie'nin de "Name"i unique(eşsiz,tek) olmalı. Bu sayede direkt o isme tekabül eden değeri de bulabiliriz. Siz kazara aynı isimde 2 cookie yaratırsanız, birini diğerinin üstüne yazar. Bunlardan başka Cookie'nin yaşam süresini de belirleyebilirsiniz(expiration date and time). Mesela bir cookie'nin expiration date'ini 10 gün olarak ayarlarsanız, kullanıcı 10 gün boyunca o siteye girmezse cookie silinir. Kullanıcının siteye son girişinden itibaren 10 gün dikkate alınır çünkü. Şimdi diyebilirsiniz cookie'nin ömrünü uzun tutarım diye ama bunun da %100 garantisi yok çünkü kullanıcının canı sıkılır ve gider tüm cookieleri siler. :) Bu yüzden cookielerde öenmli şeyler taşınmamalı demiştik yukarıda.
Eğer cookie'nin expiration time'ını ayarlamazsanız, cookie yaratılır fakat kullanıcının bilgisayarında saklanmaz. Daha sonra göreceğimiz Session gibi varlığını sürdürür. Kullanıcı tarayıcısını kapatırsa cookie de gider. Bu yüzden expiration time'ını ayarlamayı unutmamalısınız. Ancak bu şekilde kullanılabilecek cookieler de işe yarayabilir; ya da kullanıcının bilgisyaraına cookie yazmayı güvenli bulmayabilirsiniz. Bu durumlarda Expiration Time değerine girmez ve kalıcı olmayan cookieler yaratırsınız. Örneğin ortak kullanılan bir bilgisayarınız vardır, girdiğiniz sitelerin cookiesini istemeyebilirsiniz.
Cookieleri eklemenin yollarından iki tanesine bakalım şimdi:
Response.Cookies["userName"].Value = "gurkan";
Response.Cookies["userName"].Expires = DateTime.Now.AddDays(1);
Yukarıdaki yol ile Cookilere direkt değer verebilirsiniz. Cookieler, NameObjectCollectionBase'den türedikleri için bu şekilde değer verilebilirler. UserName adında bir cookie yaratılıyor ve ona değer olarak gurkan veriliyor. Eğer o siteye 1 gün içinde tekrar girmezseniz cookie siliniyor.
HttpCookie cerez = new HttpCookie("lastVisit");
cerez.Value = DateTime.Now.ToString();
cerez.Expires = DateTime.Now.AddDays(1);
Response.Cookies.Add(cerez);
Yukarıdaki yol ile de cookie'yi yaratmak için HttpCookie sınıfını kullandık. Bu şekilde kullanmak için constructor içinde cookie adını belirtmek zorundayız. Dikkat edilmesi gereken nokta: tüm cookie değerleri string olmak zorundadır. Expiration ise DateTime türünde olmalıdır.
Birden Fazla Değeri Olan Cookie Olur mu?
Yukarıdaki örneklerde de gördüğünüz üzere her cookie'de bir değer sakladık. Ancak bir cookie'de birden fazla name-value çifti saklayabilirsiniz. Name-Value çiftleri subkeys olarak adlandırılırlar. Örneğin; "username" ve"lastvisit" adında 2 farklı cookie saklamak yerine, "userInfo" adında tek bir cookie yaratabiliriz. "username" ve"lastvisit" adında da subkey'leri olur.
Subkey kullanmanın birçok sebebi olabilir. Öncelikle birbiriyle ilişkili bilgileri tek bir cookie'ye koymak gayet güzel bir düşüncedir. Bunun dışında mesela hepsine birden expiration süresini atayabilirsiniz (Tersten düşünürsek, eğer hepsine farklı farklı süreler atayacaksak, ayrı ayrı cookieler kullanmak daha mantıklıdır). Ayrıca tarayıcıların limitlendirmelerini de bir nebze olsun aşabiliriz bu yolla.
Subkeys ile cookie yaratmak için yine 2 yolu da görelim:
Response.Cookies["userInfo"]["userName"] = "gurkan";
Response.Cookies["userInfo"]["lastVisit"] = DateTime.Now.ToString();
Response.Cookies["userInfo"].Expires = DateTime.Now.AddDays(1);
Yukarıdaki örnekte önceki örnektekilerin aynısı yapılıyor ama gördüğünüz gibi userinfo'nun alt anahtarları olarak kullandık username ve lastvisit'i.
HttpCookie cerez = new HttpCookie("userInfo");
cerez.Values["userName"] = "gurkan";
cerez.Values["lastVisit"] = DateTime.Now.ToString();
cerez.Expires = DateTime.Now.AddDays(1);
Response.Cookies.Add(cerez);
Yukarıdaki örnekte bir önceki örnekle aynı işi HttpCookie nesnesi yardımıyla yapmakta.
Cookie Faaliyet Alanları
Daha önce bahsettiğimiz bir konuya geri dönelim. Normalde tüm siteler kullanıcılarına cookie'yi atarlar. Kullanıcı da bu siteye request gönderirse, bu cookiler server'a gider. Siteye geri dönmüş olur. Yani başka bir deyişle: o sitedeki tüm sayfalar cookie'leri alır. Cookielerin faaliyet alanlarını 2 yolla ayarlayabilirsiniz.
1) Server'da bir klasöre erişim hakkı verirsiniz.
2) Domainlerin faaliyetlerini belirlersiniz.
Şimdi bu iki yaklaşımı da inceleyelim.
Server'da bir klasöre erişim hakkı vermek: Server'da bir klasör açarsınız ve cookie'leri alabilecek sayfaları o klasör altında tanımlarsınız. Bunu da Cookie'nin Path property'si ile ayarlarsınız.
HttpCookie cerez = new HttpCookie("AppCookie");
cerez.Value = "written " + DateTime.Now.ToString();
cerez.Expires = DateTime.Now.AddDays(1);
cerez.Path = "/Application1";
Response.Cookies.Add(cerez);
Buradaki Path, root'un altında fiziksel bir yol olabileceği gibi virtual path de olabilir. Yukarıdaki örnekte, Application1 klasörü içindeki tüm sayfalar cookielere erişebilmekte. Örneğin: www.gurkanalkan.com/Application1/... içindekiler cookileri alır. Ancak: www.gurkanalkan.com ya da www.gurkanalkan.com/Application2/... içindekiler cookilere erişemez.
(Yukarıdaki örneği diğer yol ile de yapabilirdik.)
Bazı tarayıcılarda path, büyük-küçük harfe karşı duyarlıdır. Buna dikkat edilmesi gerekir.
Domaine Scope Vermek: Bunda da domaininize göre erişim hakkı verirsiniz. Cookie'nin Domain property'si ile ayarlanır.
Response.Cookies["domain"].Value = DateTime.Now.ToString();
Response.Cookies["domain"].Expires = DateTime.Now.AddDays(1);
Response.Cookies["domain"].Domain = "support.gurkanalkan.com";
Yukarıdaki örnekte, cookielere sadece support.gurkanalkan.com subdomaini erişebilir. Diğer domainlerden erişilebilemez.
Son satırı:
Response.Cookies["domain"].Domain = "gurkanalkan.com";
şeklinde değiştirirseniz, tüm subdomainlerden erişilebilir bir hale gelmiş olur. Örneğin; "support.gurkanalkan.com", " forum.gurkanalkan.com", "thisishalloween.gurkanalkan.com" gibi tüm alt domainler erişir.
Cookie Okuma
Cookieleri HttpRequest nesnesi ile okuruz. Page sınıfımızın(sayfamız tabi ki) Request nesnesi ile de ulaşabiliriz o nesneye. Daha önce bu işlemin nasıl olduğuna değindiğim için direkt olarak kod üzerinde göstereceğim.
if(Request.Cookies["userName"] != null)
Label1.Text = Server.HtmlEncode(Request.Cookies["userName"].Value);
Yukarıdaki örnekte yine direkt işlem yapılmış. Eğer username isminde bir cookie varsa, bunun değerini label1'e yazdırıyor. HtmlEncode metodu da parametresindeki metni eğer html kodları varsa, değiştirerek komut olarak görünmemesini sağlar.
if(Request.Cookies["userName"] != null)
{
HttpCookie cerez= Request.Cookies["userName"];
Label1.Text = Server.HtmlEncode(cerez.Value);
}
Yukarıda da aynı işlemi diğer yolla yaptık.
Burada dikkat edilmesi gekeren, cookieyi okumadan önce, o cookienin var olduğundan emin olmaktır. Eğer bunu kontrol etmezsek ve okumaya çalıştığımız cookie yoksa(mesela anahtarını[ismini] yanlış yazmışızdır.) NullReferenceException alırız.
HtmlEncode ile de encode yaparak, kötü niyetli kullanıcıların cookie üzerinde oynama yapmamalarını sağlıyoruz.
Farklı tarayıcılar cookieleri farklı şekillerde saklarlar. Aynı makinadaki farklı tarayıcılar bile birbirlerinin cookielerini okuyamazlar. Örneğin IE'nin sakladığı cookielere Mozilla'dan erişemezsin.
Subkey'i olan bir cookiden okuma yapalım.
if(Request.Cookies["userInfo"] != null)
{
Label1.Text =
Server.HtmlEncode(Request.Cookies["userInfo"]["userName"]);
Label2.Text =
Server.HtmlEncode(Request.Cookies["userInfo"]["lastVisit"]);
}
Gördüğünüz gibi yine önce böyle bir cookienin var olup olmadığına bakıyoruz. Daha sonra da cookie yazma konusunda da gördüğümüz yöntemi kullanarak bu sefer okuma yapıyoruz.
"lastvisit"i daha önce DateTime türünde kullanmıştık. Ancak cookieler string değer tuttuklarından yukarıdaki gibi kullanılmış.
DateTime dt;
dt = DateTime.Parse(Request.Cookies["userInfo"]["lastVisit"]);
şeklinde de değiştirebiliriz.
Daha önce de bahsettiğim gibi subkey'ler NameValueCollection idi. Yani bir koleksiyon. Dolayısıyla bu koleksiyondan subkeyi farklı bir şekilde de alabiliriz. (Name'inden value'sini ayırırız)
if(Request.Cookies["userInfo"] != null)
{
System.Collections.Specialized.NameValueCollection
UserInfoCookieCollection;
UserInfoCookieCollection = Request.Cookies["userInfo"].Values;
Label1.Text =
Server.HtmlEncode(UserInfoCookieCollection["userName"]);
Label2.Text =
Server.HtmlEncode(UserInfoCookieCollection["lastVisit"]);
}
"Expiration Date"i Değiştirmek
Tarayıcıların cookieleri yönetmekten sorumlu olduğunu söylemiştik(Server ile cookile alışverişi, bilgisayara yerleştirmesine izin vermes, vermemesi, limitlendirmeleri). Cookienin expiration time ve date'i de tarayıcya bu konularda yardım eder(saklanmaları, silinmeleri vs.). Dolayısıyla siz cookienin Name ve Value'suna erişip okuyabilirken, expiration Time ve Date'ini okuyamazsınız.
Tarayıcı, server'a cookie'yi yollarken, expiration bilgisini göndermez(sıfır değeri döndürür). Eğer cookienin expiration date'i ile ilgili şüpheleriz varsa cookie'yi değiştirebilirsiniz. (Birazdan cookie değiştirme konusuna da değineceğiz.)
Cookie Koleksiyonunu Okumak
Bazen sayfanızda geçerli olan tüm cookieleri okumak durumunda kalabilirsiniz. Aşağıdaki kod örneği de bu durumlar içindir.
System.Text.StringBuilder output = new System.Text.StringBuilder();
HttpCookie cerez;
for(int i=0; i
{
cerez = Request.Cookies[i];
output.Append("Cookie name = " + Server.HtmlEncode(cerez.Name)
+ "
");
output.Append("Cookie value = " + Server.HtmlEncode(cerez.Value)
+ "
");
}
Label1.Text = output.ToString();
Yukarıdaki örneğin bir problemi var. Eğer cookielerin subkeyleri varsa, subkeyler tek bir name/value stringi şeklinde görünecektir.
Subkey'in olup olmadığını anlamak için HasKeys property'si kullanılır. Eğer varsa; subkey koleksiyonunu, ayrı ayrı subkey name ve value'ları şeklinde okuyabilirsiniz. Subkey value'larını Values koleksiyonundan indeks ile direkt okuyabilirsiniz.Value'ların isimlerine de Values koleksiyonunun AllKeys property'si ile okuyabilirsiniz. Bu size bir string dizisi dönecektir. Aynı şekilde Name'leri Keys property'si ile de okuyabilirsiniz. Bu da size bir string dizisi döner. Ancak aralarında bir fark var. AllKeys ile isimler siteye ilk erişimden sonra cachelenir(önbellekleme) . Keys ile isimler siteye her erişimde tekrar tekrar bulunur. Bu yüzden şartlara göre her ikisini de kullanmak avantajlı olabilir.
Şimdi bir önceki örneği subkey durumunu kontrol edecek şekilde değiştirelim.
System.Text.StringBuilder output = new System.Text.StringBuilder();
HttpCookie cerez;
string subkeyName,subkeyValue;
for(int i=0; i
{
cerez = Request.Cookies[i];
output.Append("Name = " + cerez.Name + "
");
if(cerez.HasKeys)
{
for(int j=0; j
{
subkeyName = Server.HtmlEncode(cerez.Values.AllKeys[j]);
subkeyValue = Server.HtmlEncode(cerez.Values[j]);
output.Append("Subkey name = " + subkeyName + "
");
output.Append("Subkey value = " + subkeyValue +
"
");
}
}
else
{
output.Append("Value = " + Server.HtmlEncode(cerez.Value) +
"
");
}
}
Label1.Text = output.ToString();
Yukarıdaki kodu NameValueCollection nesnesi yardımıyla da yapabilirdik.
System.Text.StringBuilder output = new System.Text.StringBuilder();
HttpCookie cerez;
string subkeyName,subkeyValue;
for(int i=0; i
{
cerez = Request.Cookies[i];
output.Append("Name = " + cerez.Name + "
");
if (cerez.HasKeys)
{
System.Collections.Specialized.NameValueCollection CookieValues =
cerez.Values;
string[] CookieValueNames = CookieValues.AllKeys;
for (int j = 0; j <>
{
subkeyName = Server.HtmlEncode(CookieValueNames[j]);
subkeyValue = Server.HtmlEncode(CookieValues[j]);
output.Append("Subkey name = " + subkeyName + "
");
output.Append("Subkey value = " + subkeyValue +
"
");
}
}
else
{
output.Append("Value = " + Server.HtmlEncode(cerez.Value) +
"
");
}
}
Label1.Text = output.ToString();
Cookieleri Değiştirme ve Silme
Bir cookieyi direkt değiştiremezsiniz. Bunun yerine, yeni bir değer verip tekrar cookieyi yaratırsınız ve onu tarayıcıya gönderirsiniz. Eskisinin üzerine yazdırmış olursunuz.
Aşağıda da örnek olarak ziyaretçi sayısını tutan bir kod mevcuttur.
int sayac;
if (Request.Cookies["counter"] == null)
sayac = 0;
else
{
sayac = int.Parse(Request.Cookies["counter"].Value);
}
sayac++;
Response.Cookies["counter"].Value = sayac.ToString();
Response.Cookies["counter"].Expires = DateTime.Now.AddDays(1);
Silme işlemine geçelim isterseniz. Silme de bir nevi değiştirme işlemidir. Cookieyi sizin direkt silmeniz mümkün değil çünkü cookie kullanıcının bilgisayarında saklı. Cookieyi siz değil, kullanıcının tarayıcısı silecek. Ama bunu siz sağlayacaksınız. Silmek istediğiniz cookie ile aynı isimde bir cookie oluşturun; ama expiration time'ını geçmiş bir tarih olarak ayarlayın. Bunu gönderin. Tarayıcı da bunu diğerinin üstüne yazacak haliyle aynı isimde olduğundan. Daha sonra da expiration time'ı dolduğu için de silecek. :)
Aşağıda örnek bir kod yer almaktadır.
HttpCookie cerez;
string cookieName;
int limit = Request.Cookies.Count;
for (int i=0; i
{
cookieName = Request.Cookies[i].Name;
cerez = new HttpCookie(cookieName);
cerez.Expires = DateTime.Now.AddDays(-1);
Response.Cookies.Add(cerez);
}
Şimdi de değiştirme ve silme işlemlerini subkeyi olan cookieler için yapalım.
Herhalde genel mantığı anlamışsınızdır. Bu yüzden değiştirme işlemini direkt kod üzerinden gösereceğim.
Response.Cookies["userInfo"]["lastVisit"] = DateTime.Now.ToString();
Response.Cookies["userInfo"].Expires = DateTime.Now.AddDays(1);
Subkeyleri silmek içinse,subkeyleri tutan Values koleksiyonunu kontrol etmelisiniz. Önce Cookies nesnesi yardımıyla yeniden oluşturmalısınız. Daha sonra Values koleksiyonunun Remove metodunu çağırmalısınız (Parametresine de silinecek subkeyin adını geçmelisiniz.). Sonra da bunu tarayıcıya yollarsanız işlem tamamlanmış olur.
string subkeyName;
subkeyName = "userName";
HttpCookie aCookie = Request.Cookies["userInfo"];
aCookie.Values.Remove(subkeyName);
aCookie.Expires = DateTime.Now.AddDays(1);
Response.Cookies.Add(aCookie);
Kısaca güvenliğine değinelim. Gerçi yazı içinde fark ettiyseniz bir-iki yerde biraz girdik bu konuya. Örneğin, kullanıcı bilgisayarından cookie'yi değiştirip size geri gönderebilir. Cookie üzerinde oynamalar olmuş olabilir. Çok fazla güvenli olmadığı için önemli bilgileri de tutmamanız gerektiğini bir kez daha hatırlatalım. Bahsedilen HtmlEncoding metodu da güvenlik konusu kapsamında düşünülebilir. Cookieler plaintext olarak gidip geldiğinden yolda(server-tarayıcı arasında) da değiştirilmiş olabilir. Bunun için SSL(Secure Sockets Layer) kullanılabilir. Kullanıcının makinasındayken SSL herhangi bir koruma sağlamaz ancak tarayıcı ile server arasında cookieyi şifreler ve cookie bu arada artık plaintext olarak değil, ciphertext olarak gidip gelir.
Son bir hususa daha değinmek istiyorum. Tarayıcılar cookieleri kabul etmeyebilirler. Eğer kullanıcı böyle bir düzenleme yaptıysa. Bu işlem sonrası, tarayıcıdan server'a herhangi bir bilgi de gitmez. Cookie yazdırılamayınca hata falan da almazsınız zaten. Ancak bunu anlamak için tek yol bir cookie yazıp okumaya çalışmak olacaktır. Son bir not: Cookies property'si size tarayıcının cookie alımına açık ya da kapalı olduğunu bildirmez. Sadece tarayıcının yapısında cookie alım özelliğinin bulunup bulunmadığını söyler.
Cookie konusu da kısaca böyle arkadaşlar. Maalesef yine State Management konusunu bitiremedim. :) Böylelikle ViewState ve Cookie'yi görmüş olduk. Diğer nesnelere de en yakın zamanda gireceğiz.
Görüşmek üzere..
Gürkan Alkan
İstanbul Üniversitesi Bilgisayar Mühendisliği
İlk bölümde State Management'ın ne demek olduğunu, neden ihtiyaç duyulduğunu incelemiş, ViewState konusunu ele almıştık. Şimdi ise diğer nesnelerimize değineceğiz. Cookie ile başlayalım isterseniz.
Cookies: Cookie, kelime anlamı olarak çerez. :) Nedir bu cookieler? Cookieler, kullanıcılar hakkında bilgileri saklayan zararsız dosyalardır. Server tarafından kullanıcının bilgisayarına gönderilir. Aslında bu en basit haliyle böyle. Birazdan tüm detaylarına gireceğiz. Ancak bu kavramı anlamanız için somut bir kaç örnek vermek istiyorum.
Örneğin bir bir foruma üyesiniz. Foruma en son ne zaman geldiğiniz, siz yokken hangi mesajlar atılmış cookie ile görülebilir. Cookie'den geliş tarihiniz bulunur ve uygun işlem yapılır. Başka bir örnek verelim. E-Posta hesaplarında "Beni Hatırla" seçeneği var. Beni Hatırla seçeneğini aktifleştirirseniz, o da örneğin cookie yardımıyla sizi tanır. Arkadaşlar dikkatinizi çekerim, bu verdiğim örneklerde cookie kullanımı çok yaygın demiyorum. Sadece cookie ile de olur diyorum. Mesela online alışverişteki alışveriş sepeti uygulaması. Siz siteden çıksanız da sepetiniz bir sonraki açılışta hala orada durur. Cookie ile bunu yapmak pek akıllıca değil(sebebini makaleyi okudukça anlayacaksınız), genelde de yapılmaz ama mantığını anlamanız açısından size fikir verecektir.
Cookie hakkında kafanızda bir şeyler canlandıysa şayet şimdi bir adım öteye gidip, genel yapısını inceleyelim. Kullanıcı herhangi bir siteye girdi diyelim. Sizin sitenize girmiş olsun. Siz, sitenizden ona cookie'yi atarsınız(Response ile atabilirsiniz, çünkü hatırlarsanız ASP.Net'te server'dan dönen cevap response idi, bu yüzden cookie'yi yazarken response nesnesinden yardım alabiliriz.). Farzı misal kullanıcı sitenize tekrar girmeye karar verdi.URL'yi girdiği zaman, kullanıcının tarayıcısı(IE, Mozilla, Opera, Chrome vs.) da sitenize cookie'yi atar. Yani sizin kullanıcının bilgisayarına attığınız cookieyi, kullanıcının tarayıcısı yardımıyla geri alırsınız(Request ile alabilirsiniz, yine hatırlarsanız ASP.Net't client'tan giden istek Request idi, bu yüzden cookie'yi aldığımızda request nesnesinden yardım alabiliriz.). Yalnız tarayıcı URL ile ilgili cookie varsa, bulursa atar. Yoksa, atamaz. Böylelikle siz, sitenize gelen kullanıcı ile ilgili bazı bilgileri edinmiş olursunuz.
Kullanıcının siteden hangi sayfayı istediği normalde önemli değildir. Aslında önemli olduğu durumlar var ancak buna da makalemizin ilerleyen satırlarında değineceğiz. Standart olarak, cookie siteniz ile ilşkilidir, sitenizdeki bir sayfa ile değil(İsterseniz farklı ilişkiler de yaratabilirsiniz. Birazdan birlikte yaratacağız zaten.).
Çoğu tarayıcılar 4096 byte'a kadar cookie destekler. Bu küçük limit yüzünden, cookielerde küçük veriler saklamak uygundur. Tarayıcılar, bir siteden kullanıcının ne kadar cookie alacağını da belirlerler. Bir çok tarayıcı site başına 20 cookie'ye izin veriyor. Eğer siteniz daha fazlasını gönderirse eski cookieler sırasıyla silinmiş olur. Ancak bir kısım tarayıcılar da genel bir limit belirliyor, ki genelde 300 cookie oluyor bu limit, site bazında değil de tüm sitelerden gelen cookie sayısına göre saklıyorlar.
Cookie sınırlandırmalarında en büyük sorun ise kullanıcının tarayıcı ayarlarından cookie alımını engellemesidir. Gerçi bazı yazılımcılar, cookie'yi reddediyorsa siteme girmesin, de diyebilmekte. ? Dolayısıyla yararlı da olsa uygulamalarınız cookielere bağımlı olmamalıdır. Alternatif yollarınız mutlaka olmalıdır. Veyahut diğer yöntemlerle verilerini taşıyıp, saklarsınız. Kritik verilerde cookie kullanmamanız gerektiğini de herhalde fark etmişsinizdir. Bu konuya birazdan tekrar gireceğim. Tarayıcı ayarlarında yapılacak değişiklikler her zaman güçlük yaratır dedik. Bu sorunu aşabilmenin bir yolu da sitenizde P3P(Platform for Privacy Preferences Project) tanımlamaktır. Bu sayede, tarayıcılarında belli policy ayarları yapmış kullanıcılar, policy ihlallerinde derhal uyarılır ve siteye girmeyebilirler. Bu durumu sağladığınızda tarayıcılar sitenizden cookie alımı yapabilirler.
Cookie Yazma
İsterseniz şimdi cookie yazma olayına geçelim. Cookieler, kullanıcıların tarayıcılarına (yukarıda bahsettiğim sebeplerden dolayı) HttpResponse nesnesi ile yollanırlar, ki bu nesnenin de Cookies adında bir koleksiyonu vardır. HttpResponse nesnesine Page sınıfımızın(yani sayfamızın), Response property'si ile ulaşabiliriz. Sitenizden, kullanıcının harddiskinde depolanmak üzere, tarayıcıya gönderilen her cookie'yi Cookies koleksiyonuna eklemelisiniz.
Cookie yaratınca bir Name ve Value vermelisiniz. Mantıksal olarak anlamanız için ViewState'te bahsettiğim(State Management-1 Makalesi) HashTable yapısı gibi düşüneblirsiniz. Cookie'nin de "Name"i unique(eşsiz,tek) olmalı. Bu sayede direkt o isme tekabül eden değeri de bulabiliriz. Siz kazara aynı isimde 2 cookie yaratırsanız, birini diğerinin üstüne yazar. Bunlardan başka Cookie'nin yaşam süresini de belirleyebilirsiniz(expiration date and time). Mesela bir cookie'nin expiration date'ini 10 gün olarak ayarlarsanız, kullanıcı 10 gün boyunca o siteye girmezse cookie silinir. Kullanıcının siteye son girişinden itibaren 10 gün dikkate alınır çünkü. Şimdi diyebilirsiniz cookie'nin ömrünü uzun tutarım diye ama bunun da %100 garantisi yok çünkü kullanıcının canı sıkılır ve gider tüm cookieleri siler. :) Bu yüzden cookielerde öenmli şeyler taşınmamalı demiştik yukarıda.
Eğer cookie'nin expiration time'ını ayarlamazsanız, cookie yaratılır fakat kullanıcının bilgisayarında saklanmaz. Daha sonra göreceğimiz Session gibi varlığını sürdürür. Kullanıcı tarayıcısını kapatırsa cookie de gider. Bu yüzden expiration time'ını ayarlamayı unutmamalısınız. Ancak bu şekilde kullanılabilecek cookieler de işe yarayabilir; ya da kullanıcının bilgisyaraına cookie yazmayı güvenli bulmayabilirsiniz. Bu durumlarda Expiration Time değerine girmez ve kalıcı olmayan cookieler yaratırsınız. Örneğin ortak kullanılan bir bilgisayarınız vardır, girdiğiniz sitelerin cookiesini istemeyebilirsiniz.
Cookieleri eklemenin yollarından iki tanesine bakalım şimdi:
Response.Cookies["userName"].Value = "gurkan";
Response.Cookies["userName"].Expires = DateTime.Now.AddDays(1);
Yukarıdaki yol ile Cookilere direkt değer verebilirsiniz. Cookieler, NameObjectCollectionBase'den türedikleri için bu şekilde değer verilebilirler. UserName adında bir cookie yaratılıyor ve ona değer olarak gurkan veriliyor. Eğer o siteye 1 gün içinde tekrar girmezseniz cookie siliniyor.
HttpCookie cerez = new HttpCookie("lastVisit");
cerez.Value = DateTime.Now.ToString();
cerez.Expires = DateTime.Now.AddDays(1);
Response.Cookies.Add(cerez);
Yukarıdaki yol ile de cookie'yi yaratmak için HttpCookie sınıfını kullandık. Bu şekilde kullanmak için constructor içinde cookie adını belirtmek zorundayız. Dikkat edilmesi gereken nokta: tüm cookie değerleri string olmak zorundadır. Expiration ise DateTime türünde olmalıdır.
Birden Fazla Değeri Olan Cookie Olur mu?
Yukarıdaki örneklerde de gördüğünüz üzere her cookie'de bir değer sakladık. Ancak bir cookie'de birden fazla name-value çifti saklayabilirsiniz. Name-Value çiftleri subkeys olarak adlandırılırlar. Örneğin; "username" ve"lastvisit" adında 2 farklı cookie saklamak yerine, "userInfo" adında tek bir cookie yaratabiliriz. "username" ve"lastvisit" adında da subkey'leri olur.
Subkey kullanmanın birçok sebebi olabilir. Öncelikle birbiriyle ilişkili bilgileri tek bir cookie'ye koymak gayet güzel bir düşüncedir. Bunun dışında mesela hepsine birden expiration süresini atayabilirsiniz (Tersten düşünürsek, eğer hepsine farklı farklı süreler atayacaksak, ayrı ayrı cookieler kullanmak daha mantıklıdır). Ayrıca tarayıcıların limitlendirmelerini de bir nebze olsun aşabiliriz bu yolla.
Subkeys ile cookie yaratmak için yine 2 yolu da görelim:
Response.Cookies["userInfo"]["userName"] = "gurkan";
Response.Cookies["userInfo"]["lastVisit"] = DateTime.Now.ToString();
Response.Cookies["userInfo"].Expires = DateTime.Now.AddDays(1);
Yukarıdaki örnekte önceki örnektekilerin aynısı yapılıyor ama gördüğünüz gibi userinfo'nun alt anahtarları olarak kullandık username ve lastvisit'i.
HttpCookie cerez = new HttpCookie("userInfo");
cerez.Values["userName"] = "gurkan";
cerez.Values["lastVisit"] = DateTime.Now.ToString();
cerez.Expires = DateTime.Now.AddDays(1);
Response.Cookies.Add(cerez);
Yukarıdaki örnekte bir önceki örnekle aynı işi HttpCookie nesnesi yardımıyla yapmakta.
Cookie Faaliyet Alanları
Daha önce bahsettiğimiz bir konuya geri dönelim. Normalde tüm siteler kullanıcılarına cookie'yi atarlar. Kullanıcı da bu siteye request gönderirse, bu cookiler server'a gider. Siteye geri dönmüş olur. Yani başka bir deyişle: o sitedeki tüm sayfalar cookie'leri alır. Cookielerin faaliyet alanlarını 2 yolla ayarlayabilirsiniz.
1) Server'da bir klasöre erişim hakkı verirsiniz.
2) Domainlerin faaliyetlerini belirlersiniz.
Şimdi bu iki yaklaşımı da inceleyelim.
Server'da bir klasöre erişim hakkı vermek: Server'da bir klasör açarsınız ve cookie'leri alabilecek sayfaları o klasör altında tanımlarsınız. Bunu da Cookie'nin Path property'si ile ayarlarsınız.
HttpCookie cerez = new HttpCookie("AppCookie");
cerez.Value = "written " + DateTime.Now.ToString();
cerez.Expires = DateTime.Now.AddDays(1);
cerez.Path = "/Application1";
Response.Cookies.Add(cerez);
Buradaki Path, root'un altında fiziksel bir yol olabileceği gibi virtual path de olabilir. Yukarıdaki örnekte, Application1 klasörü içindeki tüm sayfalar cookielere erişebilmekte. Örneğin: www.gurkanalkan.com/Application1/... içindekiler cookileri alır. Ancak: www.gurkanalkan.com ya da www.gurkanalkan.com/Application2/... içindekiler cookilere erişemez.
(Yukarıdaki örneği diğer yol ile de yapabilirdik.)
Bazı tarayıcılarda path, büyük-küçük harfe karşı duyarlıdır. Buna dikkat edilmesi gerekir.
Domaine Scope Vermek: Bunda da domaininize göre erişim hakkı verirsiniz. Cookie'nin Domain property'si ile ayarlanır.
Response.Cookies["domain"].Value = DateTime.Now.ToString();
Response.Cookies["domain"].Expires = DateTime.Now.AddDays(1);
Response.Cookies["domain"].Domain = "support.gurkanalkan.com";
Yukarıdaki örnekte, cookielere sadece support.gurkanalkan.com subdomaini erişebilir. Diğer domainlerden erişilebilemez.
Son satırı:
Response.Cookies["domain"].Domain = "gurkanalkan.com";
şeklinde değiştirirseniz, tüm subdomainlerden erişilebilir bir hale gelmiş olur. Örneğin; "support.gurkanalkan.com", " forum.gurkanalkan.com", "thisishalloween.gurkanalkan.com" gibi tüm alt domainler erişir.
Cookie Okuma
Cookieleri HttpRequest nesnesi ile okuruz. Page sınıfımızın(sayfamız tabi ki) Request nesnesi ile de ulaşabiliriz o nesneye. Daha önce bu işlemin nasıl olduğuna değindiğim için direkt olarak kod üzerinde göstereceğim.
if(Request.Cookies["userName"] != null)
Label1.Text = Server.HtmlEncode(Request.Cookies["userName"].Value);
Yukarıdaki örnekte yine direkt işlem yapılmış. Eğer username isminde bir cookie varsa, bunun değerini label1'e yazdırıyor. HtmlEncode metodu da parametresindeki metni eğer html kodları varsa, değiştirerek komut olarak görünmemesini sağlar.
if(Request.Cookies["userName"] != null)
{
HttpCookie cerez= Request.Cookies["userName"];
Label1.Text = Server.HtmlEncode(cerez.Value);
}
Yukarıda da aynı işlemi diğer yolla yaptık.
Burada dikkat edilmesi gekeren, cookieyi okumadan önce, o cookienin var olduğundan emin olmaktır. Eğer bunu kontrol etmezsek ve okumaya çalıştığımız cookie yoksa(mesela anahtarını[ismini] yanlış yazmışızdır.) NullReferenceException alırız.
HtmlEncode ile de encode yaparak, kötü niyetli kullanıcıların cookie üzerinde oynama yapmamalarını sağlıyoruz.
Farklı tarayıcılar cookieleri farklı şekillerde saklarlar. Aynı makinadaki farklı tarayıcılar bile birbirlerinin cookielerini okuyamazlar. Örneğin IE'nin sakladığı cookielere Mozilla'dan erişemezsin.
Subkey'i olan bir cookiden okuma yapalım.
if(Request.Cookies["userInfo"] != null)
{
Label1.Text =
Server.HtmlEncode(Request.Cookies["userInfo"]["userName"]);
Label2.Text =
Server.HtmlEncode(Request.Cookies["userInfo"]["lastVisit"]);
}
Gördüğünüz gibi yine önce böyle bir cookienin var olup olmadığına bakıyoruz. Daha sonra da cookie yazma konusunda da gördüğümüz yöntemi kullanarak bu sefer okuma yapıyoruz.
"lastvisit"i daha önce DateTime türünde kullanmıştık. Ancak cookieler string değer tuttuklarından yukarıdaki gibi kullanılmış.
DateTime dt;
dt = DateTime.Parse(Request.Cookies["userInfo"]["lastVisit"]);
şeklinde de değiştirebiliriz.
Daha önce de bahsettiğim gibi subkey'ler NameValueCollection idi. Yani bir koleksiyon. Dolayısıyla bu koleksiyondan subkeyi farklı bir şekilde de alabiliriz. (Name'inden value'sini ayırırız)
if(Request.Cookies["userInfo"] != null)
{
System.Collections.Specialized.NameValueCollection
UserInfoCookieCollection;
UserInfoCookieCollection = Request.Cookies["userInfo"].Values;
Label1.Text =
Server.HtmlEncode(UserInfoCookieCollection["userName"]);
Label2.Text =
Server.HtmlEncode(UserInfoCookieCollection["lastVisit"]);
}
"Expiration Date"i Değiştirmek
Tarayıcıların cookieleri yönetmekten sorumlu olduğunu söylemiştik(Server ile cookile alışverişi, bilgisayara yerleştirmesine izin vermes, vermemesi, limitlendirmeleri). Cookienin expiration time ve date'i de tarayıcya bu konularda yardım eder(saklanmaları, silinmeleri vs.). Dolayısıyla siz cookienin Name ve Value'suna erişip okuyabilirken, expiration Time ve Date'ini okuyamazsınız.
Tarayıcı, server'a cookie'yi yollarken, expiration bilgisini göndermez(sıfır değeri döndürür). Eğer cookienin expiration date'i ile ilgili şüpheleriz varsa cookie'yi değiştirebilirsiniz. (Birazdan cookie değiştirme konusuna da değineceğiz.)
Cookie Koleksiyonunu Okumak
Bazen sayfanızda geçerli olan tüm cookieleri okumak durumunda kalabilirsiniz. Aşağıdaki kod örneği de bu durumlar içindir.
System.Text.StringBuilder output = new System.Text.StringBuilder();
HttpCookie cerez;
for(int i=0; i
{
cerez = Request.Cookies[i];
output.Append("Cookie name = " + Server.HtmlEncode(cerez.Name)
+ "
");
output.Append("Cookie value = " + Server.HtmlEncode(cerez.Value)
+ "
");
}
Label1.Text = output.ToString();
Yukarıdaki örneğin bir problemi var. Eğer cookielerin subkeyleri varsa, subkeyler tek bir name/value stringi şeklinde görünecektir.
Subkey'in olup olmadığını anlamak için HasKeys property'si kullanılır. Eğer varsa; subkey koleksiyonunu, ayrı ayrı subkey name ve value'ları şeklinde okuyabilirsiniz. Subkey value'larını Values koleksiyonundan indeks ile direkt okuyabilirsiniz.Value'ların isimlerine de Values koleksiyonunun AllKeys property'si ile okuyabilirsiniz. Bu size bir string dizisi dönecektir. Aynı şekilde Name'leri Keys property'si ile de okuyabilirsiniz. Bu da size bir string dizisi döner. Ancak aralarında bir fark var. AllKeys ile isimler siteye ilk erişimden sonra cachelenir(önbellekleme) . Keys ile isimler siteye her erişimde tekrar tekrar bulunur. Bu yüzden şartlara göre her ikisini de kullanmak avantajlı olabilir.
Şimdi bir önceki örneği subkey durumunu kontrol edecek şekilde değiştirelim.
System.Text.StringBuilder output = new System.Text.StringBuilder();
HttpCookie cerez;
string subkeyName,subkeyValue;
for(int i=0; i
{
cerez = Request.Cookies[i];
output.Append("Name = " + cerez.Name + "
");
if(cerez.HasKeys)
{
for(int j=0; j
{
subkeyName = Server.HtmlEncode(cerez.Values.AllKeys[j]);
subkeyValue = Server.HtmlEncode(cerez.Values[j]);
output.Append("Subkey name = " + subkeyName + "
");
output.Append("Subkey value = " + subkeyValue +
"
");
}
}
else
{
output.Append("Value = " + Server.HtmlEncode(cerez.Value) +
"
");
}
}
Label1.Text = output.ToString();
Yukarıdaki kodu NameValueCollection nesnesi yardımıyla da yapabilirdik.
System.Text.StringBuilder output = new System.Text.StringBuilder();
HttpCookie cerez;
string subkeyName,subkeyValue;
for(int i=0; i
{
cerez = Request.Cookies[i];
output.Append("Name = " + cerez.Name + "
");
if (cerez.HasKeys)
{
System.Collections.Specialized.NameValueCollection CookieValues =
cerez.Values;
string[] CookieValueNames = CookieValues.AllKeys;
for (int j = 0; j <>
{
subkeyName = Server.HtmlEncode(CookieValueNames[j]);
subkeyValue = Server.HtmlEncode(CookieValues[j]);
output.Append("Subkey name = " + subkeyName + "
");
output.Append("Subkey value = " + subkeyValue +
"
");
}
}
else
{
output.Append("Value = " + Server.HtmlEncode(cerez.Value) +
"
");
}
}
Label1.Text = output.ToString();
Cookieleri Değiştirme ve Silme
Bir cookieyi direkt değiştiremezsiniz. Bunun yerine, yeni bir değer verip tekrar cookieyi yaratırsınız ve onu tarayıcıya gönderirsiniz. Eskisinin üzerine yazdırmış olursunuz.
Aşağıda da örnek olarak ziyaretçi sayısını tutan bir kod mevcuttur.
int sayac;
if (Request.Cookies["counter"] == null)
sayac = 0;
else
{
sayac = int.Parse(Request.Cookies["counter"].Value);
}
sayac++;
Response.Cookies["counter"].Value = sayac.ToString();
Response.Cookies["counter"].Expires = DateTime.Now.AddDays(1);
Silme işlemine geçelim isterseniz. Silme de bir nevi değiştirme işlemidir. Cookieyi sizin direkt silmeniz mümkün değil çünkü cookie kullanıcının bilgisayarında saklı. Cookieyi siz değil, kullanıcının tarayıcısı silecek. Ama bunu siz sağlayacaksınız. Silmek istediğiniz cookie ile aynı isimde bir cookie oluşturun; ama expiration time'ını geçmiş bir tarih olarak ayarlayın. Bunu gönderin. Tarayıcı da bunu diğerinin üstüne yazacak haliyle aynı isimde olduğundan. Daha sonra da expiration time'ı dolduğu için de silecek. :)
Aşağıda örnek bir kod yer almaktadır.
HttpCookie cerez;
string cookieName;
int limit = Request.Cookies.Count;
for (int i=0; i
{
cookieName = Request.Cookies[i].Name;
cerez = new HttpCookie(cookieName);
cerez.Expires = DateTime.Now.AddDays(-1);
Response.Cookies.Add(cerez);
}
Şimdi de değiştirme ve silme işlemlerini subkeyi olan cookieler için yapalım.
Herhalde genel mantığı anlamışsınızdır. Bu yüzden değiştirme işlemini direkt kod üzerinden gösereceğim.
Response.Cookies["userInfo"]["lastVisit"] = DateTime.Now.ToString();
Response.Cookies["userInfo"].Expires = DateTime.Now.AddDays(1);
Subkeyleri silmek içinse,subkeyleri tutan Values koleksiyonunu kontrol etmelisiniz. Önce Cookies nesnesi yardımıyla yeniden oluşturmalısınız. Daha sonra Values koleksiyonunun Remove metodunu çağırmalısınız (Parametresine de silinecek subkeyin adını geçmelisiniz.). Sonra da bunu tarayıcıya yollarsanız işlem tamamlanmış olur.
string subkeyName;
subkeyName = "userName";
HttpCookie aCookie = Request.Cookies["userInfo"];
aCookie.Values.Remove(subkeyName);
aCookie.Expires = DateTime.Now.AddDays(1);
Response.Cookies.Add(aCookie);
Kısaca güvenliğine değinelim. Gerçi yazı içinde fark ettiyseniz bir-iki yerde biraz girdik bu konuya. Örneğin, kullanıcı bilgisayarından cookie'yi değiştirip size geri gönderebilir. Cookie üzerinde oynamalar olmuş olabilir. Çok fazla güvenli olmadığı için önemli bilgileri de tutmamanız gerektiğini bir kez daha hatırlatalım. Bahsedilen HtmlEncoding metodu da güvenlik konusu kapsamında düşünülebilir. Cookieler plaintext olarak gidip geldiğinden yolda(server-tarayıcı arasında) da değiştirilmiş olabilir. Bunun için SSL(Secure Sockets Layer) kullanılabilir. Kullanıcının makinasındayken SSL herhangi bir koruma sağlamaz ancak tarayıcı ile server arasında cookieyi şifreler ve cookie bu arada artık plaintext olarak değil, ciphertext olarak gidip gelir.
Son bir hususa daha değinmek istiyorum. Tarayıcılar cookieleri kabul etmeyebilirler. Eğer kullanıcı böyle bir düzenleme yaptıysa. Bu işlem sonrası, tarayıcıdan server'a herhangi bir bilgi de gitmez. Cookie yazdırılamayınca hata falan da almazsınız zaten. Ancak bunu anlamak için tek yol bir cookie yazıp okumaya çalışmak olacaktır. Son bir not: Cookies property'si size tarayıcının cookie alımına açık ya da kapalı olduğunu bildirmez. Sadece tarayıcının yapısında cookie alım özelliğinin bulunup bulunmadığını söyler.
Cookie konusu da kısaca böyle arkadaşlar. Maalesef yine State Management konusunu bitiremedim. :) Böylelikle ViewState ve Cookie'yi görmüş olduk. Diğer nesnelere de en yakın zamanda gireceğiz.
Görüşmek üzere..
Gürkan Alkan
İstanbul Üniversitesi Bilgisayar Mühendisliği
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
----
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
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
15 Şubat 2009 Pazar
1 - 1 :(
4 gündür bloga girmedim. Bu süre zarfında ne oldu diye yazmadan önce az önce biten maçımızı izlemeyenlere haber ereyim: Beşiktaşımız: 1 - 1 : Ts
Tek kale maç oynadık, adamlar 1 pozisyonla golü aldılar. Yattara'nın pozisyonu dışında başka atakları yok neredeyse. Kısmetsiziz resmen. Tuhaf tuhaf goller kaçırdık. 1 golümüz sayılmadı. 26. hafta da yaklaştı Denizli Efendi. Sanırım Demirören sana da yol verecek. :)
Neyse maç dışında 12 Şubat'ta sunumu yaptım ve yaklaşık 3.5 saat sürdü. Cuma günü de YolBil için bir güvenlik modülü hazırladım.
Cumartesi gününü bilgisayarımı temizleyerek geçirdim. Sevgililer Günü hediyesi verdim bir nevi kendisine. :D
Ha unutmadan, State Management makale dizimin 3. versiyonunu yazdım. Yazılım Günlüğü'nden okuyabilirsiniz. YazGeliştir'e koydum ama sanırım orada editörler pek ilgilenemiyor, yayınlanma süresi bazen uzuyor böyle. Bir hatırlatma: 1 ve 2 no'lu makaleleri okursanız 3. makaleyi okumak bir eğlence olur size. :) Gerçi birbirlerinden bağımsız ama okumanızda fayda var.
Görüşmek üzere..
Tek kale maç oynadık, adamlar 1 pozisyonla golü aldılar. Yattara'nın pozisyonu dışında başka atakları yok neredeyse. Kısmetsiziz resmen. Tuhaf tuhaf goller kaçırdık. 1 golümüz sayılmadı. 26. hafta da yaklaştı Denizli Efendi. Sanırım Demirören sana da yol verecek. :)
Neyse maç dışında 12 Şubat'ta sunumu yaptım ve yaklaşık 3.5 saat sürdü. Cuma günü de YolBil için bir güvenlik modülü hazırladım.
Cumartesi gününü bilgisayarımı temizleyerek geçirdim. Sevgililer Günü hediyesi verdim bir nevi kendisine. :D
Ha unutmadan, State Management makale dizimin 3. versiyonunu yazdım. Yazılım Günlüğü'nden okuyabilirsiniz. YazGeliştir'e koydum ama sanırım orada editörler pek ilgilenemiyor, yayınlanma süresi bazen uzuyor böyle. Bir hatırlatma: 1 ve 2 no'lu makaleleri okursanız 3. makaleyi okumak bir eğlence olur size. :) Gerçi birbirlerinden bağımsız ama okumanızda fayda var.
Görüşmek üzere..
11 Şubat 2009 Çarşamba
PES Zaferi :)
Makineyi kapatacaktım ama yorgun da olsam şu zaferimi yazayım dedim. :D
Malumunuz, Beşiktaşımız Liverpool ile yaptığı bir maçı kazandı, diğerini ise farklı kaybetti. İnsanlar sadece kaybedilene odaklandı. İlk maçtaki zaferimizi görmezlikten geldiler. Yazacakların ne alaka diyeceksiniz. :)
Geçenlerde 3 arkadaş PES oynamaya gittik. Sınav vesilesiyle okula uğradım ve çıkışında müthiş bir oyun oldu. Ben Beşiktaşlıyım, diğer ikisi(Ziya-İbrahim:deşifre ettim ikinizi de, insan içine çıkamazsınız artık (: ) Fenerli.
Bunlar Liverpool'u aldı, ben Beşiktaş'ı. :) 3 net pozisyona girdim ve onların tek pozisyonu vardı. 68. dakikada İbrahim Üzülmez kırmızı gördü. :) O çıkınca kazanma ümidim arttı doğal olarak. :D Neyse efendim, 90+3'te korner kazandım ve sert ortaya Liverpool'lu oyuncu kendi kalesine gönderdi topu, 0-1 ile maçı kazandım. O anki yüz ifadelerini ve maçtaki ezikliklerini o günün anısı olarak saklayacağım. :D
Yalnız şunu da fark ettim o gün. Beşiktaşı alınca daha bir duygusal oynuyorum. :D
Kazanma hırsım 2 katına çıkıyor. Beşiktaş ile yenilmez olacağız inşallah. :D
Bu yazıyı Zico&Abr. Lİncoln ikilisine armağan ediyorum. :D
Hoşça kalın..
Malumunuz, Beşiktaşımız Liverpool ile yaptığı bir maçı kazandı, diğerini ise farklı kaybetti. İnsanlar sadece kaybedilene odaklandı. İlk maçtaki zaferimizi görmezlikten geldiler. Yazacakların ne alaka diyeceksiniz. :)
Geçenlerde 3 arkadaş PES oynamaya gittik. Sınav vesilesiyle okula uğradım ve çıkışında müthiş bir oyun oldu. Ben Beşiktaşlıyım, diğer ikisi(Ziya-İbrahim:deşifre ettim ikinizi de, insan içine çıkamazsınız artık (: ) Fenerli.
Bunlar Liverpool'u aldı, ben Beşiktaş'ı. :) 3 net pozisyona girdim ve onların tek pozisyonu vardı. 68. dakikada İbrahim Üzülmez kırmızı gördü. :) O çıkınca kazanma ümidim arttı doğal olarak. :D Neyse efendim, 90+3'te korner kazandım ve sert ortaya Liverpool'lu oyuncu kendi kalesine gönderdi topu, 0-1 ile maçı kazandım. O anki yüz ifadelerini ve maçtaki ezikliklerini o günün anısı olarak saklayacağım. :D
Yalnız şunu da fark ettim o gün. Beşiktaşı alınca daha bir duygusal oynuyorum. :D
Kazanma hırsım 2 katına çıkıyor. Beşiktaş ile yenilmez olacağız inşallah. :D
Bu yazıyı Zico&Abr. Lİncoln ikilisine armağan ediyorum. :D
Hoşça kalın..
7 Şubat 2009 Cumartesi
Alakasız..
Yatmadan buraya yazı yazayım da iyice uykum gelsin dedim. :S
En nihayetinde Kerberos ile sistem güvenliğine kadar geldim çalışmamda. Herhalde 1-1.5 güne sunum hazır olacak gibi.
Az önce Kayserispor gs'ye çelmeyi taktı: 1-1 :)
Haberlerine kısaca göz atayım dedim, HaberTürk sitesi yine berbat Türkçesi ile yazılar yazmış. Doğrusunu atıyorum, ayıp değil ki, değiştirmiyorlar bile. Bazı yazarları sanki Beyoğlu'nda yürürken almışlar gibi. Tabirimi bağışlayın ama sizler okurlarınıza değer verip yazılarınızda özen göstermezseniz, bizler de sizi protesto ederiz. Şikayet mesajları bırakıyorum sitelerine sürekli. Bir de bunların yorum onaylamaları var. Hoşlarına gidenlerinigösteriyorlar sitede. Çok güzel bir siteydi ama artık bana itici gelmeye başladı. Zaten Erol Bey ayrıldıktan sonra kanallarını da izlemiyorum.
Unutmadan, statlarında ırkçılık yapan gs'li holiganlar, bir de çArşı'ya hakarette bulunmuşlar bugün pankartlarla. çArşı cevap bile vermemeli bence. Kimin ne olduğu ortada. Biz duyarlı bir topluluğuz, onlar ise.. Neyse yazmıyorum. Kahrolsun ırkçılık!!..
Herkese iyi geceler..
En nihayetinde Kerberos ile sistem güvenliğine kadar geldim çalışmamda. Herhalde 1-1.5 güne sunum hazır olacak gibi.
Az önce Kayserispor gs'ye çelmeyi taktı: 1-1 :)
Haberlerine kısaca göz atayım dedim, HaberTürk sitesi yine berbat Türkçesi ile yazılar yazmış. Doğrusunu atıyorum, ayıp değil ki, değiştirmiyorlar bile. Bazı yazarları sanki Beyoğlu'nda yürürken almışlar gibi. Tabirimi bağışlayın ama sizler okurlarınıza değer verip yazılarınızda özen göstermezseniz, bizler de sizi protesto ederiz. Şikayet mesajları bırakıyorum sitelerine sürekli. Bir de bunların yorum onaylamaları var. Hoşlarına gidenlerinigösteriyorlar sitede. Çok güzel bir siteydi ama artık bana itici gelmeye başladı. Zaten Erol Bey ayrıldıktan sonra kanallarını da izlemiyorum.
Unutmadan, statlarında ırkçılık yapan gs'li holiganlar, bir de çArşı'ya hakarette bulunmuşlar bugün pankartlarla. çArşı cevap bile vermemeli bence. Kimin ne olduğu ortada. Biz duyarlı bir topluluğuz, onlar ise.. Neyse yazmıyorum. Kahrolsun ırkçılık!!..
Herkese iyi geceler..
6 Şubat 2009 Cuma
Dikkat "Odun" Çıkabilir!
Tam çıkıyordum ki bu konu hakkında yazmaya karar verdim. Herhalde hepimiz bir çok insanla gün boyu etkileşim içindeyizdir. Açıkçası bu etkileşimden hiç hoşlanmamaya başladım. Özellikle yolda, otobüs gibi toplu taşıma araçlarında insanlarla ister istemez etkileşim içine giriyorsunuz. Böyle yerler erkeklerin, tabirim için affedin, öküzlüklerine alışkınım da, bayanlarınki de çok fazla olmaya başladı.
Her gün en az 1 tanesi de denk mi gelir yahu. :@ Ya ayağınıza basar hiç birşey yokmuş gibi devam eder; kocaman bavul gibi çantasını(içine kendisi bile sığar vallahi) size çarpar, bir de ters ters bakar, sanki orası çantasına tahsis edilmiştir de siz bir ihlalde bulunmuşsunuzdur; araçlara sığma problemimden ötürü çok az yer versem de, arada iyi tarafıma denk gelip yer verdiğimde hanım(!)efendiler bir dirsek atar, sanki yer vermekten vazgeçebilirmişsiniz gibi. Bu düşünceyi taşıma ihtimalinizi düşünüp size pis pis de bakarlar. :) Aslında gözle görülmese de ince ve herkesin fark edemeyeceği detay diyebileceğiniz nezaketleri ise sakın yapmayın derim. Zaten kimseden teşekkür beklemiyoruz ama karşıdan başka "odunluklar" gelebiliyor. :)
Rahatladım yaaa. :D İyi geceler herkese. :)
Her gün en az 1 tanesi de denk mi gelir yahu. :@ Ya ayağınıza basar hiç birşey yokmuş gibi devam eder; kocaman bavul gibi çantasını(içine kendisi bile sığar vallahi) size çarpar, bir de ters ters bakar, sanki orası çantasına tahsis edilmiştir de siz bir ihlalde bulunmuşsunuzdur; araçlara sığma problemimden ötürü çok az yer versem de, arada iyi tarafıma denk gelip yer verdiğimde hanım(!)efendiler bir dirsek atar, sanki yer vermekten vazgeçebilirmişsiniz gibi. Bu düşünceyi taşıma ihtimalinizi düşünüp size pis pis de bakarlar. :) Aslında gözle görülmese de ince ve herkesin fark edemeyeceği detay diyebileceğiniz nezaketleri ise sakın yapmayın derim. Zaten kimseden teşekkür beklemiyoruz ama karşıdan başka "odunluklar" gelebiliyor. :)
Rahatladım yaaa. :D İyi geceler herkese. :)
Gurkan.Sleep(5000);
Buraya yazmayalı çok uzun zaman olmuş. Hiç bir derse katılmadan tüm dersleri vermemim mutluluğunu hala yaşamaktayım. :) 2. dönem "Bilgisayar Mimarisi"ni verirsem sanırım sonunda mezun oluyorum. :)
Beklediğim boşluk oluşmadı maalesef. GSM tabanlı projemiz sessizce devam ederken, aldığım projelerle iyice sıkıştım diyebilirim. Bugün bir de ".Net Security" konusunda sunum yapmam istendi. Sanırım buraya düzenli yazma işi başka bahara kalacak. :)
En kısa sürede görüşmek üzere..
Beklediğim boşluk oluşmadı maalesef. GSM tabanlı projemiz sessizce devam ederken, aldığım projelerle iyice sıkıştım diyebilirim. Bugün bir de ".Net Security" konusunda sunum yapmam istendi. Sanırım buraya düzenli yazma işi başka bahara kalacak. :)
En kısa sürede görüşmek üzere..
11 Ocak 2009 Pazar
Yakında.. :)
Çoğu şey bitti nihayet. 2 final kaldı, bir de tabi bunların olası bütünlemeleri. Bu hafta yine çok yoğun geçecek. Cumartesiden itibaren gerek buraya, gerek düşündüğüm kendi siteme, gerekse de yazgeliştir ile yazılımgünlüğü'ne daha özen göstereceğim. Tabi çevreme de. :)
Şu anda da maalesef son projemi yapmaya çalışıyorum. Prim Algoritması ile minimum spanning tree, connectivity cost vs. hesaplamalrı yaptırmam lazım. Zamanlama açısından bunun verilişi de saçma ya neyse.
Kısa bir süre sonra görüşmek üzere..
Şu anda da maalesef son projemi yapmaya çalışıyorum. Prim Algoritması ile minimum spanning tree, connectivity cost vs. hesaplamalrı yaptırmam lazım. Zamanlama açısından bunun verilişi de saçma ya neyse.
Kısa bir süre sonra görüşmek üzere..
1 Ocak 2009 Perşembe
2009 - Kalan Gün Sayısı:364
Herkesin yeni yılını kutlarım. Bu tebriği Beşiktaşımızın başlattığı kampanyanın haberini de vererek yapmış olayım..
Kaydol:
Kayıtlar (Atom)