05 Eylül 2008

CLR SQL ile Hazırlanan Nesneyi Visual Studio'da Debug Etmek

SQL Server 2005 ve ADO.NET 2.0 ile gelen yeniliklerden sonra çoğunuzunda bildiği gibi .NET ortamında hazırladığınız nesneleri SQL Server sunucusu üzerinde CLR (Common Language Runtime) desteğiyle çalışmasını sağlayabiliyoruz. Oluşturulan bu nesnelerin IL çıktıları .dll'dir, dolayısıyla ilk bakışta nesneleri kodlama aşamasında nasıl debug işlemine tabi tutacağımız bizler için soru işareti olabilir. Bu başlıkta .NET tabanlı bir dilde yazdığımız CLR SQL kodlarımızın çalışmasını debug etmek, kodların takibini ve analizini yapmak için oluşturulan projede nasıl bir yol izleyeceğimizi anlatmaya çalışacağım.

Test.sql dosyasına eklenen SQL cümlesi"SQL Server Projects" şablonunu oluşturduğunuzda proje içerisinde Test Script adında bir klasör ve içerisinde örnek kodları içeren Test.sql adında bir dosya bulunmaktadır. Debug işlemi için öncelikli olarak nesneyi çalıştıracak bir SQL ifadesine ihtiyacımız olacaktır. Bu dosya SQL ifadesinin veya ifadelerinin saklanacağı yerdir. Nesneyi oluşturduktan sonra öncelikli olarak bu dosyaya nesneyi test etmemizi sağlayan SQL cümlesini ekliyoruz.

clrsql_debug_image3 Bu işlemin ardından Test.sql dosyasını projemizin varsayılan script dosyası olarak seçmemiz gerekiyor. Solution Explorer'da dosyanın üzerine sağ tıkladığımızda karşımıza çıkan Set as Default Debug Script seçeneğinden dosyayı varsayılan debug dosyası olarak belirliyoruz. İlgili seçenek sağ kısımda yer alan resimde görülmektedir.

Nesneyi oluşturduktan sonra debug işlemini başlatacağımız satıra breakpoint ekliyoruz. Bu işlemin ardından projemizi yayınlayıp IL çıktısını üretmemiz ve çalıştırmamız gerekecektir. Bu işlem için Solution Explorer'da projemizin üzerine sağ tıklayıp Deploy seçeneğini seçiyoruz.

Artık projeyi debug modunda çalıştırıp kodların adım adım takibini yapabiliriz. Bu işlem için yine Solution Explorer'dan az önce debug dosyası olarak ayarladığımız Test.sql dosyasına sağ tıklayıp Debug Script seçeneğine tıklıyoruz. Dosya içerisindeki sorgu çalıştırılacak ve derleyici seçtiğimiz satıra geldiğinde Visual Studio debug moda geçecektir.

clrsql_debug_image4

Bu şekilde bir CLR SQL nesnesini oluşturan kodların debug edilmesi sağlanabilir. Özellikle karmaşık User Defined Function, Stored Procedure ve Trigger oluşturduğumuz durumlarda nesneyi sürekli SQL Server'a taşımak, burada çalışma sonucuna göre tekrar Visual Studio'ya dönüp değişiklikleri yapmak uzun ve çözümü zor bir yol olabilir. İşte bu tip durumlarda nesnenin SQL Server'a gitmeden doğrudan CLR üzerinde çalışmasını debug edebilmek biz programcıların işini oldukça kolaylaştıracaktır.

06 Ağustos 2008

LINQ Sunumu ve Örnek Kodlar

Geçtiğimiz pazar günü INETA Summer Hit'in son gününde C# 3.0 ve LINQ sunumunu gerçekleştirdim. Sürenin az olması nedeniyle LINQ to SQL ve LINQ to XML konularını derinlemesine anlatma şansım olmadı ama güzel ve iyi izlenimler bırakan bir sunum gerçekleştirmişimdir diye umuyorum. Seminerde öyle bir kod arşivi üzerinden demolar gerçekleştirmişim ki; sadece bugün 4-5 farklı kişiden bu kodlara ulaşmak için mailler aldım :) Aşağıdaki linklerden etkinlikte kullandığım sunumu ve örnek kodları içeren demo dosyasını indirebilirsiniz.

LINQ Sunumu
LINQ Demolar

Ve etkinlikten kalan iki hatıra fotoğrafı...

ineta_summer_hit_cikis
ineta_summer_hit_sunum

Bu güzel etkinliği düzenleyen başta Daron Yöndem ile Ali Rıza Babaoğlan'a ve emeği geçen tüm arkadaşlara teşekkürlerimi buradan da sunmak isterim.

Not: Askerlik nedeniyle biraz uzak kaldığım yeni teknolojilere yeni yeni ısınmaya başlıyorum. Bundan sonra blogumda C# 3.0, LINQ, MVC ve WPF gibi konularda daha sık yazılar yazmaya çalışacağım. Beni takip etmeye devam edin...

26 Temmuz 2008

ASP.NET'te Gelecek WebForm'larında mı, Yoksa MVC'de mi?

WebForms vs. ASP.NET MVCSon yıllarda web programlama dünyasında yaygınlaşan MVC uygulama modeli yavaş yavaş ASP.NET uygulamalarında da yerini almaya başladı. .NET Framework ile birlikte web sitelerine getirilen Windows formlarının çalışma modeli giderek benimsenmiş ve web literatürüne oturmuşken birden çıkıveren MVC Framework kafalarımızda şu soruları da oluşturdu: Hangi modeli kullanmak daha avantajlı, hangisi daha verimli çalışır? Belki de en önemli soru "Gelecek hangisinde? WebForm'larında mı, yoksa MVC Framework'te mi?" Hatta benim kafamda oluşan önemli sorulardan birisi de "Acaba Microsoft gelecekte WebForm'larını bırakıp ASP.NET'te MVC modelini mi kullanabilir mi?" idi birkaç gün öncesine kadar...

Geçtiğimiz günlerde Joe Stagner'ın blogunda okuduğum bir haber aklımdaki bu soru işaretini biraz da olsun kaldırdı. Zira Joe Stagner yazısında WebForm'larının gelecekte de ASP.NET uygulamalarındaki ana platform olacağını, Microsoft'un bu strateji üzerinden ilerleyeceğini, fakat MVC Framework'ün de geliştiremeye devam edeceğinden bahsediyordu. Yani; gönül rahatlığıyla WebForm'ları üzerinde kontrolleri sürükleyip bırakıp, üzerine çift tıklayıp, olay tabanlı programlama yapmaya devam edebiliriz. Peki MVC bu noktada programlama anlayışımızın neresinde yer almalı?

Bu sorunun cevabını bulabilmek için öncelikle ASP.NET WebForm'larının ve ASP.NET MVC Framework'ün ne gibi özelliklere sahip olduğunu, avantaj ve dezavantajlarının neler olduğunu iyi çözümlemek gerekir. MVC Framework ASP.NET uygulamalarına şu anki anlayışa biraz aykırı gelebilecek, ASP'de olduğu gibi HTML ile içiçe ve daha fazla kod yazılmasını gerektiren, durum verisinin saklanmasını zorlaştıran, diğer yandan da programcının web sayfasına daha fazla hakim olmasını sağlayan, control-view mekanizmasını kendi istediği gibi geliştirebileceği ve arama motorlarının çok sevdiği az karmaşık URL'ler oluşturulmasını sağlayan bir uygulama modelidir. MVC Framework web programlama hayatımıza iyiden iyiye oturan olay tabanlı(event-driven) programlamadan, ViewState ve PostBack'ten uzak bir ortam sunuyor. Bu gelişme kimilerine göre çok olumlu iken, kimilerine ise "Aman benden uzak dursun" dedirtiyor. WebForm'ları bize o kadar rahat bir programlama ortamı sunuyor ki, MVC'ye geçiş biraz zor geliyor sanırım. Fakat MVC Framework'ün özellikle hız, performans, arama motorlarına tam uyumluluğun önemli olduğu, uzun soluklu kurumsal projelerde çok sık ihtiyaç olacağı da bir gerçek.

Konumuzun başlığına dönecek olursak; Gelecek WebForms da mı, yoksa MVC Framework'te mi, benim şahsi düşüncem gelecek dün olduğu gibi yine WebForm'larında(ki Microsoft'un dediklerini tercüme etmiş oluyorum), fakat MVC Framework önümüzdeki yıllarda iyi bir web programcısının mutlaka bilmesi gereken bir uygulama deseni olacaktır. Microsoft'un şu anki stratejisi ASP.NET WebForm'ların üzerinde gelişmeye ve zenginleşmeye devam edecektir, fakat MVC Framework'te programcılara ikinci bir seçenek olarak sunulacaktır.

22 Temmuz 2008

ASP.NET AJAX Roadmap ve ASP.NET AJAX 4.0 Preview 1

Geçtiğimiz günlerde CodePlex'te yayınlanan ASP.NET AJAX'ın yol haritasının ardından dün de ASP.NET AJAX 4.0'ın ilk önizleme sürümü duyuruldu. ASP.NET AJAX ekibinin önümüzdeki aylarda web uygulamalarında biraz daha istemci tabanlı çalışacak bileşenler geliştirme yolunda ilerlediğini söyleyebiliriz. İstemci tarafında çalışacak veri-veri kaynağı (data-data source) kontrolleri ile istemci tarafında içeriğin render edilmesi fikirleri Preview 1 sürümünde zaten gerçekleşen birkaç adım. Animasyon ve sürükle-bırak (drag-drop) özellikleri, yine ASP.NET MVC Framework için şu anda olmayan ASP.NET AJAX MVC desteği ilerleyen günlerde bizi bekleyen yeniliklerden sadece birkaç tanesi. Sanırım sonraki sürümlerde ASP.NET AJAX'ın biraz da JQuery'den etkilenerek bizleri daha da heyecanlandıracak yeniliklerle karşımıza gelmesi hiç birimizi şaşırtmayacaktır(En azından beni). Artık HTML kodları içerisine bol bol inline kod yazılacak AJAX uygulamaları bizi bekliyor diyebilirim.

ASP.NET AJAX yol haritası ve ASP.NET AJAX 4.0 Preview 1 ile ilgili dosya ve dökümanları aşağıdan, CodePlex sitesindeki linklerinden indirebilirsiniz. Yine aynı sayfa üzerinden proje ile yapılan yenilikleri takip edebilirsiniz.

ASP.NET AJAX Roadmap
ASP.NET AJAX 4.0 CodePlex Preview 1

17 Temmuz 2008

Yazılımcılar için Yaz Etklinliği: INETA Summet Hit

inetasummerhit

INETA Türkiye olarak güzel bir yaz etkinliği ile karşınızdayız. 2-3 Ağustos 2008 tarihlerinde Yıldız Teknik Üniversitesi Auditorium'da gerçekleşecek olan iki günlük etkinlikte birçok önemli konu ile ilgili seminerleri ve konuşmaları bulabileceksiniz. 3 Ağustos'ta 15:00-17:30 saatleri arasında benim de LINQ (Language Integrated Query) sunumumun olacağı bu etkinliğe ilgilenen herkesi bekliyoruz.

Etkinlikle ilgili bilgiler ve kayıt işlemi için bu linkten faydalanabilirsiniz.

10 Temmuz 2008

GridView'da Silme ve Güncelleme İşlemi Onayı

GridView kontrolünde silme ve güncelleme işlemleri yapılırken işlem tamamlanmadan önce kullanıcıdan onay alınmak istenilebilir. Özellikle silme işlemleri geri dönüşü olmayan sorunlara yol açabileceği için bu tip bir işlemi kazara bir butona basılarak yapılmasına izin vermemek son derece doğru olacaktır. GridView kontrolünde yapacağımız çok basit 2 değişiklik ile Update ve Delete işlemlerinin kullanıcıdan onay alarak gerçekleştirilmesini sağlayabiliriz.

İlk adımda Update ve Delete butonlarımızın bulunduğu CommandFieldTemplateField'a dönüştürmek gerekecektir. Böylece artık Update ile Delete butonlarına erişebilir, gerekli istemci olayına istediğimiz JavaScript kodunu ekleyebiliriz. GridView'in smart tag ikonundan Edit Columns linkine tıklayıp açılan pencereden CommanField kolonunu seçmeli ve sağ kısımda yer alan Properties penceresinin altındaki Convert this field into a TemplateField linkine tıklamalıyız. Böylece artık Update, Delete, Cancel gibi butonların kontrol tanımlamalarına sayfanın HTML kodlarından erişebileceğiz.

Gridview - Kolonu templatefielda çevirme

İkinci adımda ise gerekli butonun OnClientClick olayına ufak bir JavaScript kodu eklememiz gerekecektir. Böylece onay işleminde sunucuya gidilmeden, istemci tarafında yapılacak ve gereksiz bir postback işlemi de engellenmiş olacaktır. Aşağıda Delete butonuna tıklandığında kullanıcıdan onay alma işlemini gerçekleştirecek kod parçası yer almaktadır.

<ItemTemplate>
<asp:LinkButton ID="LinkButton1" runat="server" CausesValidation="False"
CommandName="Edit" Text="Değiştir"></asp:LinkButton>&nbsp;
<asp:LinkButton ID="LinkButton2" runat="server" CausesValidation="False"
CommandName="Delete" Text="Sil"
OnClientClick="return confirm('Silmek istediğinizden emin misiniz?');">
</asp:LinkButton>
</ItemTemplate>
Basit iki işlemin ardında gridview oldukça kullanışlı bir hale gelebiliyor. Sonuç aşağıdaki gibi...

Gridview - Silme işlemi için onay

20 Mayıs 2008

VS 2008 ile SQL Server 2005 Kurulumunda Problem ve Çözümü

Bugün bilgisayarıma Windows XP'yi yeniden kurdum. Visual Studio 2008 ve SQL Server 2005'in kurulumları sorunsuz bitti, fakat Management Studio ve SQL Profiler gibi araçların kurulmadığını görünce bu sorunun neden kaynaklandığını ve nasıl çözebileceğimi internetten biraz araştırdım. Sorun ve çözümü şöyle:

Sorun: Visual Studio 2008'i SQL Server 2005'ten önce kurduğunuzda SQL Server sunucu olarak bilgisayarınıza kurulmuş olsa da, beraberinde gelen bileşenlerin kurulumu gerçekleşmiyor.

Çözüm-1: Önce SQL Server 2005'i, ardından Visual Studio 2008'i kurun.

Çözüm-2: Çözüm-1'deki sıranın tersinde kurulum yaptıysanız; SQL Server kurulum CD'sinden Tools klasörünün altındaki setup.exe'yi Command Prompt'tan aşağıdaki parametreleri kullanarak çalıştırın. Açılan kurulum penceresinden de Client Components ve Documentation, Samples and... seçeneğinden gerekli bileşenleri seçerek güncelleme kurulumunu tamamlayın.
Command Prompt'ta yazılacak komut: start /wait setup.exe SKUUPGRADE=1

Gerekli bileşenler artık bilgisayarınıza kurulacaktır.

Not: Gerçekleştirdiğim kurulum Windows XP Professional işletim sistemi üzerinde Visual Studio 2008 Team System Edition ve SQL Server 20005 Developer Edition sürümleri ile yapıldı.

18 Mayıs 2008

Makaleler E-Kitabım

Yapımına askerde başladığım ve ancak bitirebildiğim, içerisinde bugüne kadar çeşitli sitelerde yayınlanan makalelerimin bulunduğu e-kitabı bu linkten bilgisayarınıza yükleyebilirsiniz. Başta ASP.NET ve ASP.NET AJAX konularında yazdığım makalelerden ve yaklaşık 160 sayfadan oluşan bu doküman umarım sizler için faydalı olur.

E-kitabımı zaman içerisinde yeni makalelerimle güncellemeye çalışacağım. Bu başlıktaki linkten veya www.umutluoglu.com adresinden güncel versiyonunu takip edebilirsiniz.

16 Mayıs 2008

Askerlik Görevim Sona Erdi

Askerlik maceram bugün sona erdi. Bu sabah 1.5 saatlik uçak yolculuğunun ardından Elazığ'a hoşçakal dedim ve İstanbul'a 5 ay 5 gün sonra ayak bastım. İnsanın tekrar sivil hayata dönmesi, ailesine, sevdiklerine (ve dizüstü bilgisayarına) kavuşması kelimelerle anlatalımayacak kadar güzel bir duygu!

Elazığ'da Jandarma Komando Taburu'nda başlayan askerliğimin usta birliğini 8.Kolordu Komutanlığı Askeri Mahkemesi'nde tamamladım. Oldukça güzel dostluklar edindiğim bu beş aylık maceramda sivil hayatta belki de 1-2 yılda göremeyeceğim tecrübeler edindim. 26 yaşında asker olsam da, askerliğin insanın olgunlaşma sürecinde oldukça önemli bir yeri olduğunu görmüş oldum.

Blogumdan da takip ettiğiniz üzere aslında bilgisayardan ve .NET dünyasından askerlikte de pek kopmadım. Görev yaptığım Askeri Mahkeme'ye boş zamanlarımda oldukça önemli bir uygulama geliştirme şansını buldum. .NET Framework 2.0 üzerinde çalışan Esas Defteri adındaki masaüstü bir uygulama ile artık Kolordu'daki tüm dava dosyaları bilgisayar ortamında saklanabiliyor. Gelişmiş arama, raporlama arayüzleri ve devir işlemleri arayüzleri ile hazırladığım bu uygulama uzun yıllar mahkememize hizmet edecektir diye düşünüyorum. Kullandığım Pentium-2 işlemcili makina beni biraz kısıtlasa da, birkaç makale ve birkaç blog postu askerlik günlerimde bilgi paylaşımı adına klavyemden çıkarabildiklerim oldu.

İyisi ile kötüsü ile bitti gitti askerliğim. Beş ay kadar önce yazdığım veda yazısında da dediğim gibi "kaldığımız yerden devam ediyoruz..."

11 Mayıs 2008

RenderControl Metodu ile Kontrolün HTML Çıktısını Üretmek

ASP.NET uygulamalarında kullandığımız tüm kontroller HTML çıktılara dönüştürülmekte ve sayfanın HTML kodları içerisine yerleştirilmektedir. Basit olarak bir Label kontrolü sunucuda çalıştırıldığında <span> elementine dönüştürülürken, GridView gibi karmaşık bir kontrol ise tablo (<table> elementi) ve tablo içerisindeki elementlere dönüştürülür. Web uygulamalarında kullandığımız tüm sunucu kontrolleri WebControl sınıfından, WebControl ise Control sınıftan türetilmektedir. Control sınıfında yer alan RenderControl metodu (virtual metot olduğu için türetilen sınıflarda override edilir) sunucuda oluşturulan kontrolün HTML çıktısını string olarak elde edebilmemizi sağlar. Control sınıfında yer alan bu metot dolayısıyla tüm sunucu kontrollerinin de sahip olduğu bir üyedir ve programatik olarak oluşturulacak bir sunucu kontrolünün RenderControl metodu ile HTML çıktısına ulaşılabilir.

"Neden bir kontrolün HTML çıktısını alayım ki?" gibi bir soru akla gelebilir. Nerelerde karşımıza çıkabilir bir kontrolün HTML çıktısını programatik olarak elde etmek? Aklıma gelen bir kaç noktayı hemen şöyle listeleyim:

- Substution Caching (sayfanın tümünü önbellekten okuyup sadece belirli bir alanı dinamik oluşturmak) işlemlerinde sunucuda çalışacak metodun içerisinde bir kontrolü oluşturmak ve metodun geri dönüş değeri olarak kontrolü döndürmek,
- AJAX uygulamalarında WebMethod'lar ile asenkron güncellemeler yapılacağı zaman yine sunucudaki metodun içerisinde bir kontrol oluşturmak ve metottan kontrolün HTML çıktısını geri göndermek,
- Kullanıcılara toplu mail gönderimi yapılacağı zaman veritabanından çekilen kayıtların oluşturacağı grid türevi kontrolün kodlarını mailin HTML içeriğine eklemek,
- Raporlama sistemlerinde farklı kriterlere göre oluşturulan sonuçların HTML çıktısının veritabanına kaydedilmesi ve daha sonradan tekrar takip edilebilmesi...

Biraz daha düşünüldüğünde farklı senaryolar da akla gelebilir. Zaten bu tip varsayımlar ilk başta akla gelmeyen, fakat uygulamanın geliştirme safhalarında karşımıza çıkabilen durumlardır. Bu yazım belki karşınıza çıkan bu tip bir duruma ilaç olabilir:) Gelelim RenderControl metodunun nasıl kullanılacağına. Senaryoyu karmaşık hale getirmeden basit şekilde inceleyelim. Sayfamızda bir Label kontrolü olsun ve sunucuda oluşturacağımız GridView kontrolünün HTML çıktısını alıp Label'a yazdıralım. Aşağıda sayfamızın kodları yer almaktadır.


...
using System.Collections.Generic;
using System.IO;

public partial class RenderControlKullan : System.Web.UI.Page
{
   protected void Page_Load(object sender, EventArgs e)
   {
      Dictionary<string, string> liste = new Dictionary<string, string>();
      liste.Add("Uğur Umutluoğlu", "http://umutluoglu.blogspot.com");
      liste.Add("Burak Batur", "www.burakbatur.com");
      liste.Add("Burak Selim Şenyurt", "www.bsenyurt.com");
      liste.Add("nedirTV?com", "www.nedirtv.com");
      liste.Add("Türk Aspx", "www.turkaspx.net");

      GridView gvSiteler = new GridView();
      gvSiteler.DataSource = liste;
      gvSiteler.DataBind();

      StringWriter sw = new StringWriter();
      HtmlTextWriter htw = new HtmlTextWriter(sw);
      gvSiteler.RenderControl(htw);
      lblGrid.Text = sw.ToString();
   }
}

Sayfa çalıştırıldığında lblGrid.Text = sw.ToString(); satırına bir break-point atalım ve sw'nin içerisinde neler varmış bir bakalım.

GridView nesnesi üretildikten sonra RenderControl metodu ile işlem gerçekleşiyor. RenderControl geriye herhangi bir değer dönen bir metot değildir (void); parametre olarak aldığı HtmlTextWriter tipinden nesneye kontrolün çıktısını aktarır. HtmlTextWriter'da InnerWriter özelliğindeki HTML elementlerini TextWriter ve türevi nesnelerden birine aktarır. Burada StringWriter en uygun tip. Performans açısından StringWriter'ı da bir StringBuilder'a aktarmak iyi bir yol olabilir ama işi uzatmadan kısaca sonuca gidelim. sw adındaki StringWriter nesnesinin çıktısını stringe dönüştürerek lblGrid adındaki kontrole değeri yazdırıyoruz. Aşağıdaki sayfamızın çıktısı görülmektedir.

13 Nisan 2008

SQL Sorgusuna Tablo Adını Parametre Olarak Aktarmak

Web uygulamalarında en çok saldırı alabileceğimiz yerler veritabanı üzerinde çalıştırdığımız SQL sorgularımızdır. SQL Injection adı verilen teknik ile kötü niyetli kullanıcılar arka planda çalıştırdığımız SQL sorgularına ek SQL cümleleri ekleyebilmekte ve yeri geldiğinde "DROP DATABASE ..." gibi bir sorgu ile tüm veritabanını bile silebilmektedir! Gerek SQL Server ortamında hazırladığımız stored procedure'larda, gerekse uygulama tarafında kullandığımız ADO.NET nesnelerinde parametre (parameter) kullanarak bu tip tehditlerden veritabanımızı koruyabilmekteyiz. Parametreler SQL cümlelerinde sadece sütunlarda aranacak değerleri taşıyabilmekte, tablo veya sütun isimlerini ise taşıyamamaktadır. "Select * From Haberler Where HaberID=@id" gibi bir SQL cümlesinde HaberID sütununda aranacak değer parametre olarak aktarılabilir. Peki SQL cümlesine tablo adını parametre olarak aktarmak gibi bir durumda nasıl bir yolu izleyebiliriz? Yani "Select * From @TabloIsim" gibi bir SQL cümlesi yazabilsek ve parametre olarak Haberler bilgisini yolladığımızda sorgumuz Haberler tablosundaki, Duyurular bilgisini yolladığımızda da Duyurular tablosundaki tüm verileri getirse...


Tablo adını parametre olarak aktarma şansımız sadece stored procedure kullanma durumunda bulunmaktadır. Tabi ki sp içerisinde standart bir cümle yazmak yerine ufak bir hile ile bu işlemi gerçekleştirebileceğiz. Eğer sp içinde SQL cümlemizi bir değişkende saklayıp, alınan parametre değerini cümlemize eklersek tablo adını cümlemiz içerisine aktarabiliriz. Tabi ki cümle bir değişkende saklandığı için sp içerisinde bu cümleyi çalıştırmak ta gerekecektir. Aşağıda tablo adını parametre olarak alan basit bir stored procedure görülmektedir.

CREATE PROC TabloKayitlar
@tablo_isim nvarchar(30)
AS
BEGIN
   DECLARE @sql_str nvarchar(50)
   SET @sql_str = 'Select * From ' + @tablo_isim
   EXEC(@sql_str)
END

08 Nisan 2008

Accordion Kontrolünde Veritabanı ile Çalışmak

Bir önceki yazımda Accordion kontrolünün CSS ile kullanımından bahsetmiştim. Accordion kontrolünün içeriğini statik içerikle HTML kodları ile oluşturabileceğimiz gibi dinamik verilerle de oluşturabiliriz. Bir XML dosyasından, veritabanından veya koleksiyon gibi nesnelerden alınan veriler bu kontrole kolaylıkla yüklenebilir. Bu yazımda Accordion kontrolünü veritabanından alınan verilerle nasıl besleyebileceğimize bakıyoruz.

Accordion kontrolünde dinamik veri ile çalışmak Repeater ve DataList gibi kontrolleriyle benzerlik göstermektedir. Eğer SqlDataSource, XmlDataSource gibi veri kaynakları ile çalışırsak sayfada bağlanacak veri kaynağını belirtmek yeterli olmayacak, HTML kısmından Eval veya Bind metotlarıyla veri yükleme işlemini de gerçekleştirmemiz gerekecektir. HTML koduna istediğimiz gibi müdahale edebildiğimiz için aslında olumlu bir durum olduğunu belirtmekte fayda var. Yine programatik yollarla DataTable, DataSet veya koleksiyon nesneleri ile Accordion kontrolünün çalışmasını sağlayabiliriz. Dilerseniz iki ayrı örnekte bu iki farklı yolu nasıl uygulayabileceğimizi görelim.

DataSource Kontrolleri ile Çalışmak
Veriyi en kolay şekilde bağlayacağımız bu yolda sayfamızdaki DataSource nesnesini Accordion kontrolünün DataSourceID özelliğinde belirlememiz gerekecektir. Accordion kontrolünün ise HeaderTemplate ve ContentTemplate kısımlarında yüklenecek verilerin başlık ve içerik bilgilerini Eval metodu ile bağlıyor olacağız. Access'te oluşturulmuş bir veritabanında saklanan haberlerin listeleneceği sayfada Accordion kontrolü ile çalışmak aşağıdaki kodlardan da görüleceği gibi oldukça kolay!

<ajaxToolkit:Accordion ID="accHaberler" runat="server" HeaderCssClass="baslik" HeaderSelectedCssClass="secilenBaslik" ContentCssClass="icerik" DataSourceID="dsHaberler" Width="460">
<HeaderTemplate>
<%#Eval("Baslik") %>
</HeaderTemplate>
<ContentTemplate>
<%#Eval("Icerik") %><br />
Eklendiği tarih: <%#Eval("Tarih") %>
</ContentTemplate>
</ajaxToolkit:Accordion>
<asp:AccessDataSource ID="dsHaberler" runat="server" DataFile="~/App_Data/Site.mdb" SelectCommand="SELECT [Baslik], [Icerik], [Tarih] FROM [Haberler] ORDER BY [Tarih] DESC"> </asp:AccessDataSource>

Template alanları içerisine açılmış ASP etiketleri ile veri yükleme işlemini gerçekleştiriyoruz. HTML kodlarını istediğimiz şekilde değiştirebilme kolaylığı belki de bu yolun en önemli avantajı.

DataTable vb. Nesneler ile Çalışmak
Bazı durumlarda ise Accordion kontrolüne DataTable gibi veri nesneleri ile veri yüklemek isteyebiliriz. Programatik yollarla yapacağımız bu işlemlerde HTML tarafında müdahale şansımız daha zor olsa da programın ve verilerin akışını istediğimiz gibi değiştirebilme şansına sahip olabiliyoruz. Bu yöntemde bir döngü içerisinde AccordionPane nesneleri oluşturarak AccordionPane'in HeaderContainer ve ContentContainer'larındaki Controls koleksiyonuna kontroller ekleyebiliriz. Sunucu tarafında performans açısından Label gibi bir kontrol yerine LiteralControl kullanmak iyi bir pratik olacaktır. Aşağıda böyle bir işlemi nasıl yapabileceğimiz görülmektedir. Sayfamızın HTML kısmına eklenmiş accHaberler adında bir Accordion kontrolünü daha önceden eklediğimizi hatırlatayım.

...
using System.Data.OleDb; // Access veritabanına bağlanmak için
using AjaxControlToolkit; // AccordionPane kontrolüne erişmek için

public partial class Haberler : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string yol = Server.MapPath("App_Data/Site.mdb");

OleDbConnection con = new OleDbConnection("Provider=Microsoft.Jet.OleDB.4.0; Data Source=" + yol);
OleDbDataAdapter daHaberler = new OleDbDataAdapter("Select Baslik, Icerik, Tarih From Haberler Order By Tarih Desc", con);
DataTable dtHaberler = new DataTable();
daHaberler.Fill(dtHaberler);
foreach (DataRow dr in dtHaberler.Rows)
{
AccordionPane paneHaber = new AccordionPane();
paneHaber.HeaderContainer.Controls.Add(
new LiteralControl(dr["Baslik"].ToString()));
paneHaber.ContentContainer.Controls.Add(
new LiteralControl(dr["Icerik"].ToString()));
paneHaber.ContentContainer.Controls.Add(
new LiteralControl("<br>"));
paneHaber.ContentContainer.Controls.Add(
new LiteralControl("Ekleme tarihi: " + dr["Tarih"].ToString()));
accHaberler.Panes.Add(paneHaber);
// Oluşan AccordionPane'i Accordion kontrolüne ekliyoruz.
}
}
}

Görüldüğü gibi bir foreach döngüsü içinde DataTable'ın her satırı bir AccordionPane kontrolünün içeriğini oluşturmakta ve AccordionPane kontrolü de Accordion'un Panes koleksiyonuna eklenmektedir. Sayfayı çalıştırdığımızda her iki örnektede veritabanından getirilen verilerin Accordion kontrolüne yüklendiğini görebiliriz. Kontrolümüzü hazırladığımız imajlar ve CSS ile kullandığımızda göze hoş gelen bir tasarım elde edebiliriz. Aşağıda Accordion kontrolünün son hali görülmektedir.

AJAX Control Toolkit - Accordion Kontrolünde Veritabanı ile Çalışmak

05 Nisan 2008

Accordion'un CSS ile Etkin Kullanımı

AJAX Control Toolkit ile gelen en kullanışlı kontrollerden birisi Accordion kontrolüdür. Web sayfalarının genellikle Sık Sorulan Sorular veya Yardım gibi bölümlerinde sıra sıra dizilmiş başlıklar bulunur ve kullanıcı hangi başlığa tıklarsa dinamik olarak o maddenin altındaki içerik görünür hale gelir. Diğer başlıkların içerikleri ise saklı durumda bulunur. Aslında uzun içeriklerin listeleneceği web sayfalarında hem kaplayacağı az alan açısından hem de görsel olarak sayfamızı daha kullanışlı hale getirecek bir kontrol Accordion. Başlık ve içerik olarak iki ana kısımdan oluşan AccordionPane'leri taşıyan Accordion kontrolünü CSS kullanarak zengin ve göze hoş gelen tasarımlar ortaya çıkarabiliriz. Accordion'un HeaderCssClass, HeaderSelectedCssClass ve ContentCssClass özelliklerinde önceden hazırladığımız CSS sınıfları (class) tanımlayarak bu işlemleri basit halde gerçekleştirebiliriz. Hazırladığım basit bir örnekle önce CSS tanımlamalarını, ardından da sayfamızdaki Accordion kontrolünü nasıl tanımlayacağımıza bakalım.

Projemize ekleyeceğimiz style.css dosyasında başlık, seçilen maddenin başlığı ve içerik kısımlarının nasıl görüntüleneceğini belirliyorum. Göze hoş gelmesi için bir grafik programında hazırladığım gradient geçişleri olan 3 tane gif dosyasını bu alanların zeminlerinde kullanıyorum.

style.css
.baslik {
   font-size: 13px; font-family: Verdana; font-weight: bold; height:18px;
   text-indent: 5px; padding: 1px; margin-top: 1px; cursor: pointer;
   border-right: #ffcd70 1px solid; border-top: #ffcd70 1px solid;
   border-left: #ffcd70 1px solid; border-bottom: #ffcd70 1px solid;
   background-image: url(images/baslik_zemin.gif);
   background-position: top; background-repeat: repeat-x;
}

.secilenBaslik
{
   font-size: 13px; font-family: Verdana; font-weight: bold; height:18px;
   text-indent: 5px; padding: 1px; margin-top: 1px;
   border-right: #ffcd70 1px solid; border-top: #ffcd70 1px solid;
   border-left: #ffcd70 1px solid; border-bottom: #ffcd70 1px solid;
   background-image: url(images/secilen_baslik_zemin.gif);
   background-position: top; background-repeat: repeat-x;
}

.icerik {
   font-size: 11px; font-family: Verdana; padding: 5px;
   border-right: #ffcd70 1px solid; border-top: none;
   border-left: #ffcd70 1px solid; border-bottom: #ffcd70 1px solid;
   background-image: url(images/icerik_zemin.gif);
   background-position: left; background-repeat: repeat-y;
}

Açık olmayan başlıkların üzerine gelindiğinde farenin simgesini değiştirmek için başlık sınıfında cursor: pointer tanımlamasını yapmak daha güzel olacaktır. Gelelim sayfamızın tasarımına. CSS dosyamıza link vereceğimiz bir aspx dosyasında Accordion'un yukarıda belirttiğimiz özelliklerini CSS dosyasında tanımladığımız sınıflarla dolduruyoruz. Geriye kalan tek şey ise AccordionPane'lerin başlık ve içeriklerin doldurmak olacaktır.

Default.aspx
<head runat="server">
<title>Accordion'un CSS ile Etkin Kullanımı</title>
<link href="style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<form id="form1" runat="server">
<ajaxToolkit:ToolkitScriptManager ID="ScriptManager1" runat="server" />
<ajaxToolkit:Accordion ID="Accordion1" runat="server" HeaderCssClass="baslik"
HeaderSelectedCssClass="secilenBaslik" ContentCssClass="icerik"
Width="185">
   <Panes>
      <ajaxToolkit:AccordionPane ID="pane1" runat="server">
         <Header>Başlık-1</Header>
         <Content>İçerik-1</Content>
      </ajaxToolkit:AccordionPane>
      <ajaxToolkit:AccordionPane ID="pane2" runat="server">
         <Header>Başlık-2</Header>
         <Content>İçerik-2</Content>
      </ajaxToolkit:AccordionPane>
      <ajaxToolkit:AccordionPane ID="pane3" runat="server">
         <Header>Başlık-3</Header>
         <Content>İçerik-3</Content>
      </ajaxToolkit:AccordionPane>
   </Panes>
</ajaxToolkit:Accordion>
</form>
</body>


Sayfayı çalıştırdığımızda Accordion kontrolünün görünümü yandaki gibi olacaktır. Burada Accordion panelerinin genişlik ve yüksekliklerine göre zemin resimlerini hazırlamamız görünümün düzgün olmasındaki en önemli etkenlerden biri olacaktır.

23 Mart 2008

Session ve Cache Nesneleri Üzerine

Bir web uygulamasında Session ve Cache nesnesi arasında tercih yapacağını ve bu tercihini neye göre belirleyeceğini merak eden bir okuruma yazdığım cevap üzerine blogumda da bu iki nesne üzerine birşeyler yazmaya karar verdim. Zira geçtiğimiz günlerde yazgelistir.com'un forumunda da buna benzer bir başlık görmüştüm. Aslında karşılaştırma yapmaktan ziyade bazı programcı arkadaşların bu iki nesneyi yanlış tanıdıkları için bu yanlış anlaşılmayı biraz olsun düzeltmek niyetindeyim.

Session ve Cache kullanım amaçları bakımından birbirinden tamamen farklı nesnelerdir dersem yanlış olmaz. Zira Session tarayıcıya bağımlı olarak bir kullanıcı ile ilgili bilgiler saklayabileceğimiz bir nesne iken, Cache tüm kullanıcıların erişebileceği ve uygulamada performans kazancı sağlamak için kullanabileceğimiz bir nesnedir. Session nesnesindeki tek amaç belirli bir süreliğine bir değeri veya nesneyi saklamaktır ve performans adına herhangi bir getirisi olmayacaktır. Cache'deki en temel amaç ise performanstır. Dilerseniz şöyle madde madde bir bakalım Session ve Cache arasındaki farklılıklara:

Session
- Kullanıcı ile ilişkili verileri saklar. Her kullanıcının bilgisi bellekte farklı bir alanda saklanır. O an sitede 20 kullanıcı var ise 20 tane farklı Session nesnesi bellekte saklanır. Bir kullanıcı sitedeki diğer kullanıcının Session bilgisine ulaşamaz.
- Genellikle kullanıcı adı veya açılan oturum ile ilgili bilgiler saklanır. Bu bilgiler her kullanıcı için saklanacağı için büyük boyutta olmaması gerekir.
- Bilgiler varsayılan olarak sunucunun belleğinde (InProc modu) saklanır. Eğer istenilirse SQL Server veritabanında (SQLServer modu) veya başka bir sunucunun belleğinde (StateServer modu) saklanabilir.
- Varsayılan olarak Session nesnelerinin yaşam süreleri 20 dakikadır. Kullanıcı sistemden çıkış yapar ise veya 20 dakika boyunca aktif olmazsa Session nesneleri bellekten kaldırılır. Eğer istenilirse bu süre değiştirilebilir. (web.config dosyasında sessionState düğümünden)
- Performans açısından herhangi bir kazanç sağlamaz. Fakat durum yönetimi adına kullanıcıyı tanımamız ve buna göre işlemler yapmamız adına kolaylıklar sağlar.

Cache
- Kullanıcıya özel bilgi saklamaz. Saklanan veriye aynı anda tüm kullanıcılar erişebilir. Sitede 20 kullanıcı var ise 20 tane Cache nesnesi değil 1 tane Cache nesnesi saklanır. (En sık karıştırılan noktalardan biri burası)
- Genellikle bir sayfanın tamamının HTML kodları (output caching), bir sayfanın belirli bir kısmının HTML kodları (fragment caching) veya DataTable gibi bir nesne (data caching) Cache nesnesinde saklanır.
- Bilgiler sunucunun belleğinde saklanır. Bu veriler ASP.NET tarafından yönetilir. Hatta Cache'e eklenecek nesnelere öncelik ataması yapılarak gerektiğinde ASP.NET'in hangi Cache nesnelerini öncelikli olarak bellekten kaldıracağı belirlenebilir.
- Zamana bağımlı olarak veriler Cache'de saklanabileceği gibi nesnenin değişim durumunda göre veya dosya-klasör içeriğinin değişimine bağımlı olarakta değerler saklanabilir.
- Performans kazancı sağlamak amacıyla kullanılır. Bir nesneyi veya bir sayfayı tekrar tekrar üretmek sunucuya belirli bir yük getiriyorsa nesne veya sayfa bellekte saklanarak sayfaların daha hızlı çalıştırılması sağlanır.

Görüldüğü gibi Session ve Cache farklı amaçlar için kullanabileceğimiz nesnelerdir. Session yerine Cache, Cache yerine Session kullanmak teoride olabilse de pratikte kullanılmaz, en azından benim aklıma kullanılabileceği bir yer gelmiyor.

07 Mart 2008

Visual Studio 2008 - Ürün Karşılaştırması

Visual Studio 2008'in piyasaya sürülen bütün ücretli ve ücretsiz sürümlerinin karşılaştırmasını bulabileceğiniz faydalı bir link. Öğrencilerim genelde "Hocam Express Edition'lar ile tam sürümler arasında ne gibi farklılıklar var" diye sorardı. Artık cevabı için bu linki kullanabilirim!

"Visual Studio 2008 Product Comparison" başlıklı incelemeye bu linkten ulaşabilirsiniz.

25 Şubat 2008

ASP.NET Uygulamalarında Birden Fazla Sitemap Dosyası Kullanma

ASP.NET Uygulamalarında Birden Fazla Sitemap Dosyası KullanmaASP.NET uygulamalarında navigasyon kontrollerini SiteMapDataSource ile birlikte kullandığımızda sadece bir tane sitemap dosyası kullanılabilmekteyiz. Bu durumun sebebi uygulamalarındaki web.config dosyasının miras alarak kullandığı .NET Framework'ün kurulu olduğu dizindeki web.config dosyasında sadece bir tane SiteMap sağlayıcısı (provider) tanımlamasının yapılmasıdır. .NET Framework 2.0 kurulu bir makinada C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG dizininde bulunan web.config dosyasındaki <siteMap> düğümüne bakacak olursanız tanımlanan tek bir provider'ın olduğunu ve bununda siteMapFile niteliğinde web.sitemap dosya isminin olduğunu görebilirsiniz. Aslında buradan yola çıkarak birden fazla sitemap dosyasını nasıl kullanabileceğimizi çözümleyebiliriz. Uygulamamıza ikinci bir sitemap dosyası eklemek ve navigasyon kontrolleri ile birlikte kullanmak istersek öncelikli olarak uygulamadaki web.config dosyasına yeni bir siteMap provider tanımlaması yapmamız gerekecektir. Aşağıda web.config dosyamızın <system.web> kısmına ekleyeceğimiz kodlar bulunmaktadır.


web.config
<system.web>
...
<siteMap>
<providers>
<add name="SiteMapProvider2" siteMapFile="web2.sitemap" type="System.Web.XmlSiteMapProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
</providers>
</siteMap>
</system.web>

SiteMapProvider2 adında web2.sitemap isimli dosya ile çalışacak yeni bir siteMap sağlayıcısı tanımladık. Bu uygulama içerisinde artık web.sitemap dışında web2.sitemap isimli bir site haritası dosyası da kullanabiliriz. Bir ASP.NET sayfasına iki tane Menu kontrolü ve iki tane SiteMapDataSource kontrolü ekleyerek birden fazla sitemap dosyası kullanımını test ediyoruz. Burada dikkat edeceğimiz nokta web2.sitemap isimli dosyamıza bağlanacak olan SiteMapDataSource kontrolünde SiteMapProvider özelliğini web.config'de tanımladığımız SiteMapProvider2 isimli sağlayıcıya eşitlemek olacaktır.


Default.aspx
<asp:Menu ID="Menu1" runat="server" BackColor="#B5C7DE" DataSourceID="SiteMapDataSource1" Font-Names="Verdana" Font-Size="12px">
</asp:Menu>
<br />
<asp:Menu ID="Menu2" runat="server" BackColor="#E3EAEB" DataSourceID="SiteMapDataSource2" Font-Names="Verdana" Font-Size="12px">
</asp:Menu>
<asp:SiteMapDataSource ID="SiteMapDataSource1" runat="server" ShowStartingNode="False" />
<asp:SiteMapDataSource ID="SiteMapDataSource2" runat="server" ShowStartingNode="False" SiteMapProvider="SiteMapProvider2" />

17 Şubat 2008

SiteMap Dosyasında Kendi Bilgilerimizi Saklamak

Site navigasyon işlemlerinde kullanmak için oluşturduğumuz sitemap dosyaları bildiğiniz gibi site içindeki sayfaların hiyerarşik yapılarını saklamaktadır. url, title ve description gibi sayfa hakkında detaylı bilgileri içerisinde saklayan siteMapNode düğümlerinde istersek kendimize ait nitelikler tanımlayarak özel bilgileri de saklayabiliriz. Nasıl mı?

Olayı basite indirgemek için site haritamızda sadece 4 kategori bulunsun: ASP.NET, ADO.NET, C# ve SQL Server. Normal durumlarda bu sayfalar hakkında url ve title, bazen de description bilgilerini saklarız. İstiyoruz ki bu 4 bölümün editörlerini de site haritası dosyasında saklayalım. Yapılacak tek işlem ilgili düğümler içerisine Editor="Veli" gibi tanımlamalar yapmak olacaktır. Bir sonraki adımda sayfa içerisinden bu bilgileri okumakta yine bu kadar kolay olacak! Aşağıdaki örnekte web.sitemap dosyası ve bir sayfadan bu bilgiyi nasıl elde edeceğimiz görülmektedir.

Web.sitemap
<?xml version="1.0" encoding="windows-1254" ?>
<siteMap>
   <siteMapNode url="Default.aspx" title="Anasayfa">
     <siteMapNode url="Aspnet.aspx" title="ASP.NET" description="" Editor="Uğur UMUTLUOĞLU" />
     <siteMapNode url="Adonet.aspx" title="ADO.NET" description="" Editor="Burak BATUR" />
     <siteMapNode url="Cs.aspx" title="C#" description="" Editor="Emrah USLU" />
     <siteMapNode url="SqlServer.aspx" title="SQL Server" description="" Editor="Bülent SÖZGE" />
   </siteMapNode>
</siteMap>


Sablon.master.cs
Response.Write(SiteMap.CurrentNode["Editor"]);

12 Şubat 2008

web.config Dosyasından URL ReWriting

URL ReWriting (sayfa adresini yeniden oluşturma) işlemi özellikle sayfalarımızda QueryString'leri kullanırken sıklıkla başvurmak istediğimiz bir işlemdir. Bu işlem karmaşık olan sayfa adresleri daha okunur ve sade hale getireceği gibi arama motorlarının sitemizdeki sayfaları daha verimli şekilde yakalamasını da sağlar. URL ReWriting'i uygulamanın birçok yolu bulunmaktadır. Kullanım bakımından en kolay yollardan biri de web.config dosyası ile bu işlemi gerçekleştirmektir. web.config dosyasında <system.web> düğümü içerisinde açacağımız <urlMappings> düğümü ile bu işlemin kolay şekilde yapılmasını sağlayabiliriz. Örneğin yazarların bilgilerini görüntüleyen bir sayfada içerik QueryString'den alınan bir veriye göre oluşsun. Sayfa arka planda aslında Yazar.aspx?isim=ugur şeklinde çalışıyor fakat biz adresin Ugur.aspx şeklinde görüntülenmesini istiyoruz. web.config dosyası içerisine ekleyeceğimiz aşağıdaki kod parçaları işimizi görecektir. mappedUrl niteliği sayfanın gerçek URL'ini, url niteliği ise görüntülenmesi istenilen URL'ini belirler. Yani Ugur.aspx gibi bir sayfaya istek geldiğinde aslında böyle bir sayfa olmayacaktır fakat adres kısmında bu URL görünecek ve arka planda Default.aspx?isim=ugur URL'i çalıştırılacaktır.


<configuration>
   <system.web>
      <urlMappings enabled="true">
         <add url="~/Ugur.aspx" mappedUrl="Default.aspx?isim=ugur" />
         <add url="~/Emrah.aspx" mappedUrl="Default.aspx?isim=emrah" />
         <add url="~/Burak.aspx" mappedUrl="Default.aspx?isim=burak" />
      </urlMappings>

      ...
      ...
   </system.web>
</configuration>


url niteliğinde relative adres belirlemek zorunludur. Yani çağrılacak URL'in tam yolunu ~/ şeklinde belirlemek gerekecektir. Bu işlemin çok az da olsa performans kaybına sebep olacağını da unutmamak lazım!

31 Ocak 2008

Katılamadığım Yazgelistir.com Toplantısı ve Ödülüm

Geçtiğimiz günlerde İstanbul'da yazgelistir.com editörleri ve yazarlarının katıldığı bir toplantı gerçekleştirildi. Malumunuz askerde olduğum için toplantıya katılamadım ama aldığım güzel bir haber ile de üzüntüm biraz olsun azaldı. Yazgelistir.com tarafından yazdığım makaleler ile site içeriğine 2007 yılında yaptığım katkılarda dolayı yanda gördüğünüz ödülü almışım. Amacımız sahip olduğumuz bilgileri insanlarla paylaşabilmek. Bunun sonucunda insanlardan aldığımız teşekkür mailleri ve bu tip ödüllerde bizleri gerçekten sevindiriyor ve motivasyonumuzu arttırıyor. Ödülüm şu anda değerli dostum Burak Batur'un evinde, yani emin ellerde!

Askerde iken ödül almakta başka bir duyguymuş onu da yaşamış olduk.

25 Ocak 2008

Elazığ'dan Sevgilerle

Farklı bir şehire gidiş sebebim genelde seminerler olurdu ve seminerlerin nasıl geçtiği ile ilgili haberlerimi blogumu takip edenlerle paylaşırdım. Ama şimdi askerdeyiz. Eee asker ocağında da .NET semineri verecek halimiz yok değil mi?

Bugün 25 Ocak 2008 ve Şafak 114. Usta birliğinde Elazığ 8. Kolordu Komutanlığı Askeri Mahkemesi'nde vatani görevime devam ediyorum. Soranlar olursa halim, vaktim, keyfim... yerinde. Burada ara sıra da olsa interneti kullanabilme şansım belki de askerliğimin en keyifli yanı. En azından yazılan bazı makaleleri ve yazılım dünyasındaki yenilikleri takip edebilme, eş-dost ile mesajlaşabilme şansı bulabiliyorum. Benden haberler şimdilik bu kadar. En yakın zamanda teknik içerikli yazılarla, makalelerle ve seminerlerle tekrar görüşmek dileğiyle..