Video Çubuğu

Loading...

14 Mayıs 2008 Çarşamba

BLOGunuzla Dünya'ya Açılın

Bu sabah maillerime bakarken Verve Earth başlıklı bir mail gördüm. İçeriği okuduktan sonra sitenin linkine tıklayınca karşıma Google Earth benzeri bir harita çıktı ve benden kayıt olmamı istedi.Kısacık bir kayıt aşamasının ardından siteyi kurcalamaya başladım. Haritadaki rss leri görünce ilk başta pek birşey gelmedi aklıma sonradan anladımki bu BlogSpot' un kullanıcılarına sunduğu süper bir sistem. BlogSayfası olan kişiler buraya kayıt oluyorlar sonra ortak alanları olan dünyadaki herkese ulaşabiliyorlar.

Şu anda İstanbulda bu sisteme kayıtlı 3 kişi var :) Logoya dikkat ederseniz site şu anda Beta aşamasında zaten. İlerde çok daha güzel olacağını tahmin ettiğim bir platform.

Bence blog sayfanız varsa kesinlikle katılmanız gereken bir yapı. Benim çok hoşuma gitti...

09 Mayıs 2008 Cuma

C# ile Excel 2007 'ye Bağlantı...

Merhaba arkadaşlar;

Bugün bir excel 2007 dosyasından (.xlsx uzsantılı dosyadan) bazı kayıtları okumam gerekti. Bende internette ufak bir araştırma yaptım hemen. Sonucunda bunun nasıl yapılacağını öğrendim ve vakit kaybetmeden buraya yazıyorum.

Veritabanı programcılıgı üzerine çalışmaya başlayan veya bu işe ilgi duyup ögrenmek isteyen herkes ilk başlarda mutlaka bir kezde olsa tabanlı ufak veritbanı programları yazmıştır. Biz C# kullanıcıları genelde Access gibi VT ‘lere bağlanmak istediğimizde OLEDB provider’ ını kullanırız. Excel dosyalarına bağlanıp işlem yapmanın da connection string ve 1-2 detay dışında access ‘e bağlanmaktan hiçbir farkı yok. Yani yine OLEDB üzerinden bağlantımızı kuracagız ve yine OLEDB sınıflarını kullanarak sorgularımız gerçekleştirebileceğiz.

Bu bilgilerden sonra örneğimize geçebiliriz.

Öncelikle basit bir excel dosyası yaratalım. Ben örnek olarak dosya adına musteriler diyorum.Ayrıca bu dosya icindeki 1.satırdaki farklı farklı hücrelere sırayla sütün isimlerini yazıyorum. AD,SOYAD,TELEFON… gibi. Ardından bu sütün isimlerinin altına birkaç örnek veri giriyoruz.

Ardından bu verilerin ve sütünların oldugu hücrelerin hepsini seçiyoruz. Ve sağ tıklayıp, Aralığı Adlandır diyoruz.Sonra bu alanı bir tabloymuş gibi belirtmek için bir isim veriyoruz. Ben tbl_Musteriler adını verdim.Bu adı ilerde kodumuzda SQL Sorgularımızdaki tablo ismi olarak kullanacağız. Ardından işlemi onaylıyoruz, dosyamızı kaydedip çıkabiliriz. Excel dosyamız üzerinde yapmamız gereken işlemler sadece bu kadar.Anlattıklarım yazıyla karışık gelmiş olabilir, anlaşılabilir olması acısından aşagıdaki resimleri inceleyebilirsiniz.

Resim 1- Önce bir tablo hazırlar gibi hücrelerimizi şekillendiriyoruz.
Resim 2 – Ardından dolu olan hücreler seçilip, sağ tıkladıktan sonra Aralığı Adlandır diyoruz.
Resim 3 – Son olarak bu tabloya bir isim veriyoruz. tbl_Musteriler gibi.

Bu işlemlerin ardından excel dosyasını kapatıp artık kod yazma aşamasına geçebiliriz.

Örnek uygulamamız basit bir windows application olacak. Form tasarımı aşagıdaki resimdeki gibi olabilir.

Ardından kod satırına geçip ilk işlem olarak OLEDB referansını kodumuza eklemeliyiz.

using System.Data.OleDb;

Ardından butonun Click_Event’ ine aşağıdaki kodu yazmanız yeterlidir.

private void btnGetDatas_Click(object sender, EventArgs e)
{
string constr = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\\musteriler.xlsx; Extended Properties=Excel 12.0";

OleDbConnection conn = new OleDbConnection(constr);
OleDbCommand cmd = new OleDbCommand();
cmd.Connection = conn;
cmd.CommandText = "SELECT * FROM tbl_Musteriler";

OleDbDataAdapter dap = new OleDbDataAdapter(cmd);
DataTable dt = new DataTable();

dap.Fill(dt);
dataGridView1.DataSource = dt;

}

Burda dikkat etmeniz gereken notka connection stringi yazarken excel dosyasının adresini acık bir şekilde belirtmeniz gerekliliğidir. Ben örneğimde dosyamı C: sürücümde tutuyordum.

Excel’e bağlanmak işte bu kadar basit arkadaşlar. Geriye kalan INSERT, UPDATE, DELETE gibi diğer veritabanı işlemlerinin de hiçbir farkı olmadıgını belirtmekte fayda var.

Umarım sizler için faydalı bir yazı olmuştur. Yardımcı olabildiysem ne mutlu bana.

Hepinize iyi çalışmalar dilerim…

Mehmet Aydın Ünlü
aydinunlu85@gmail.com
http://aydinunlu.blogspot.com



06 Mayıs 2008 Salı

C# - ASP.net 2.0 ile Mail Göndermek

Merhaba arkadaşlar,

Bugünkü makalemizde .net 2.0 ile asp.net ‘te nasıl mail gönderebileceğimizi anlatmaya çalışacağım. Bu makalede yapacağımız örnek web sitelerinizin iletişim sayfalarında sıklıkla kullanabileceğiniz işe yarar bir örnek olacak. Ayrıca uygulamayı geliştirip outlook gibi kendi mail organizasyon programınızı bile yazabilirsiniz. Birde bu uygulamayı aynı zamanda windows application gibi diğer proje tiplerindede kullanabileceğimizi unutmayalım. Biz basit bir şekilde en kısa yoldan nasıl mail gönderebiliriz bunun üzerinde duracağız.

Uygulamaya geçmeden önce kullanacağımız bir tane temel namespace var.
System.Net isimli namespace. Bu namespace altında yer alan bir cok sınıf tek başına bir makale konusu olabilecek kadar geniştir. Eğer daha derinden incelemek isterseniz MSDN ‘den bakabilirsiniz. http://msdn.microsoft.com/en-us/library/system.net.aspx

Biz uygulamamıza başlayalım. Öncelikle bir asp.net uygulması acıyoruz.Ben isim olarak SendMail adını verdim. Çok basit bir form tasarlıyoruz. Aşagıdaki resimde görebilirsiniz. Kontrollerin isimleri ise txtKonu, txtMesaj ve btnGonder ‘dir.

Artık kod yazmaya başlayabiliriz. Kod sayfasına geçip öncelikle şu 2 namespace ‘i ekliyoruz.

using System.Net;

using System.Net.Mail;

Mesela benim gmail de aydin@gmail.com diye ve şifresi 123 olan bir mail hesabım olsun. Ve ben bu hesaptan ahmet@hotmail.com ‘a mail atacagım. Ozaman;

btnGonder isimli butonumuzun Click eventine aşağıdaki kodları yazıyoruz.

SmtpClient client = new SmtpClient();
MailMessage msg = new MailMessage();
msg.To.Add("
ahmet@hotmail.com ");
msg.From = new MailAddress("
aydin@gmail.com");
msg.Subject = txtKonu.Text;
msg.IsBodyHtml = true;
msg.Body = txtMesaj.Text;

NetworkCredential guvenlikKarti = new NetworkCredential("aydin@gmail.com ", "123");
client.Credentials = guvenlikKarti;
client.Port = 25;
client.Host = "smtp.gmail.com";
client.EnableSsl = true;
client.Send(msg);

Evet yazacağımız kodlar sadece bu kadar.

Öncelikle client adında bir istemci nesnesi oluştuyoruz. Ardından biz bir mail göndereceğimiz için msg adında bir MailMessage nesnesi oluşturuyoruz. Bu nesne bir maildeki tüm özelliklere sahiptir. Mailin Kimden kime gideceği, konusu, içeriği, içeriğinin formatı gibi.

To : mailin kime yada kimlere gideceğini tutan bir özellik.
From : mailin kim tarafından gönderildiğini tutar.Ki bu bir iletişim formuysa kullanıcının mail bilgisi ve şifresi üzerinden işlem yapmak yerine, kullandıgımız domain üzerindeki standart bir e-mail hesabından mail gönderimi yapmak daha mantıklı.
Subject : Mailin konusunu belirten bir özellik.
Body : Mailin içeriğini tutan özelliktir. Burda body nin formatı html oldugu için biz istersen daha onceden hazırladıgımız bir html sayfasındaki kodları alıp mailin icine gömerek mail olarak bir html sayfası göndermiş oluruz. Bu e-bülten gibi haftalık haberleri yayınlarken kullanılabilecek hoş ve işlevsel bir özelliktir. Yani body özelliğine html kodlarını string bir değişkene atıp , mail olarakta bunu gönderebiliyoruz.

Ardından bir güvenlik kartı oluşturuyoruz.Bunun amacı sahte mail gönderimlerini engellemek. Burdada domain üzerinde kullandıgımız standart mail adresini ve şifresini yazıyoruz.

Port numarasını belirtiyoruz.Ardından hangi hosting ‘i kullandıgımızı seçiyoruz ki bu eger kendi domaininiz üzerinde çalışacak bir uygulama olacaksa smpt host bilginizi, hosting sağlayıcınızdan daha net bir şekilde öğrenebilirsiniz.

Ardından bilgilerimizi SSL ile encrypte ediyoruz.

Ve son olarakta istemci nesnemiz üzerinden mailimizi send methoduna parametre olarak verip gönderiyoruz.

Geldik bir makalemizin daha sonuna. Aslında bir makaleden çok örnek programcık havasında bir yazı oldu ama bir çok yerde işinize yarayacağından eminim.

Şimdilik hoşçakalın bir sonraki makalede görüşmek üzere…

Mehmet Aydın Ünlü
aydinunlu85@gmail.com
http://aydinunlu.blogspot.com

05 Mayıs 2008 Pazartesi

RSS Reader Yazmak

Merhaba sevgili arkadaşlar,

Bugünkü makalemizin konusu ufak bir RSS Reader uygulaması nasıl yazılır bunu açıklamak. Uygulamaya geçmeden önce RSS nedir, ne işe yarar nerelerde kullanılır gibi bazı ön bilgileri vermekte yarar var bence.

Günümüzde haber sitelerinden tutunda, blog sitelerine kadar bir cok alanda artık RSS (Really Simple Syndication) servisleri kullanılmaktadır. Özünde RSS servisleri aslında xml formatında hazırlanmış bir dosyadan ibarettir. Kullanıcılar RSS Reader programları ile bu servislere erişip içeriğini görebilirler. RSS Servisleri genelde güncel haberleri site ziyaretcilerine en hızlı ve kolay bicimde sunmak icin geliştirilmiş bir teknolojidir diyebiliriz.

RSS servislerine bir kaç örnek vermek gerekirse örneğin;
www.hurriyetim.com 'da bulunan servisleri gösterebiliriz.

Bu linkten sitedeki RSS Servislerine erişebilirsiniz.
http://dosyalar.hurriyet.com.tr/rss/

Bu linten ise Spor haberlerini güncel bir şekilde sunan spor servisine erişebilirsiniz.
http://rss.hurriyet.com.tr/rss.aspx?sectionId=14
Kaynak koda bakarsanız eger bu dosyanın xml tabanlı bir dosya oldugunu acıkca görebilirsiniz.
Bizde bu xml dosyalarını okuyup anlamlı bir şekilde kullanıcıya sunarak güzel bir RSS Reader programı yazacağız.

Uygulamaya geçmeden önce RSS hakkında daha detaylı bilgiler edinmek isterseniz wiki'den daha detaylı bilgilere erişebilirsiniz.
http://tr.wikipedia.org/wiki/Rss

Artık uygulamaya gecebiliriz arkadaşlar. Öncelikle uygulamız bir Windows Application olacak. RSS dosyaları internet ortamında bulundugu için, programımızın çalışabilmesi için tabiki internet bağlantısınada ihtiyacımız olacaktır.

Programın çalışma mantıgı ise gayet basit;
öncelikle bir rss servisine baglanıyoruz ki bu işlemi dosyanın adresini bir textbox ya yazarak yapıyoruz, ardından servisin sundugu başlıklar bir datagridde listeleniyor. Daha sonra herhangi bir başlıga tıklanırsa eger, tıklanan başlıgın içeriği bir WebBrowser kontrolü içersinde gösteriliyor. Bu arada adresler de bir xml dosyasına kaydediliyorki programı bir sonraki acışımızda daha önce eklediğimiz başlıklara ulaşabilelim. Ben makale uzamasın diye iceriği database 'de tutmuyorum, ama eger kendiniz güzel bir uygulama yazmak isterseniz aynı zamanda iceriğide bir veritabanında ki bir tabloda tutarsanız kısmen offline da çalışabilen bir uygulama yazmış olursunuz.

İlk adım olarak bir windows app. açıyoruz. Ben isim olarak RSS adını verdim.
Ardından formumuzu aşagıdaki şekilde tasarlıyoruz.Kontroller hakkında bilgi resimde vardır.



Ardından projenin bulundugu dizin içersindeki bin/debug klasörü icersine feeds adında bir xml bir dosyası acıyoruz. Bu dosya bizim rss servislerimizin adreslerini tutacak olan dosyadır. Ve bu dosyaya bir root eleman ekliyoruz. Ben Feeds diye bir root eleman ekledim. Sonrada bu root eleman icine feed adında bir alt eleman ekliyorum.

Artık işin zevkli kısmı olan kod yazma aşamasına geçebiliriz. Şahsen ben oldum olası tasarımdan hiç hoşlanmam :)

RSS servisleri için ne demiştik xml formatında dosyaların sunuldugu bir servis, demekki biz xml dosyaları üzerinde işlem yapacagız, ozaman ilk olarak
adında bir using System.Xml; ile xml namespace'imizi ekliyoruz.

Sonra global seviyedeki değişkenlermizi ve nesnelerimizi tanımlıyoruz.

DataSet dsFeeds; // Servisten gelen verileri tutacak olan dataset nesnemiz
XmlTextReader xrFile; // xml dosyayı okumak icin gerekli olan nesnemiz
string file_path; // debug klasorü icindeki xml dosyamızın adresi

Ardından FillNodes() isimli, datasetteki verileri çekip bunları soldaki treeview 'e dolduran methodumuzu yazalım. Method 'un yaptıgı tek işlem zaten dataset icindeki kayıtları bir for döngüsü ile tek tek okuyup bunları treeview 'e doldurmaktır. Her seferinde aynı kayıtları eklemesin diyede en basta Clear() ile treeview 'in node' ları temizleniyor.

private void FillNodes()

{

try

{

treeFeeds.Nodes.Clear();

for (int i = 0; i <>

{

string baslik = dsFeeds.Tables[0].Rows[i][0].ToString();

treeFeeds.Nodes.Add(baslik);

}

}

catch (Exception)

{

}

}

Ardından program çalışırken txtAddress isimli textbox ‘a yazılacak olan rss servisinin adresine gidip, ordan verileri cekip DataGridView ‘de listeleyecek olan FindFeeds() isimli methodumuzu yazalım. Bu method string tipinde address adında birde parametre almaktadır. İşte bu parametre bizim textbox a yazacagımız adresin kendisidir.

private void FindFeeds(string adress)

{

XmlTextReader rssReader = new XmlTextReader(adress);

DataSet ds = new DataSet();

ds.ReadXml(rssReader);

int tableNo = ds.Tables.Count - 1;

dtgHeader.DataSource = ds.Tables[tableNo];

}

Peki biz bu methodu ne zaman çağıracağız, ilk başta btnSearch isimli butona tıklanıldıgı zaman tabiki. Ozaman btnSarch isimli button’ un Click eventine aşagıdaki kodu yazıyoruz.

private void btnSearch_Click(object sender, EventArgs e)

{

FindFeeds(txtAddress.Text);

}

Peki biz birden cok servise programda baktık ve sonra programı kapadık. Bir sonraki acılısta bunları tekrar görebilmek istiyorsak bunları bir yerde tutmamız gerekiyor değilmi. Örneğimizde biz bunları daha önceden debug klasor altında olusturdugumuz xml dosyasında tutuyoruz. Ozaman btnAdd isimli button ‘a tıklandıgı zaman aşagıdaki kodları yazalım. Bu kodlar sayesinde biz o anki adresi xml dosyasına kaydediyoruz. Ve Form_Load’da bu dosyayı okudugumuz icinde programı her actıgımızda daha onceden eklediğimiz servisleri treeView ‘de görebiliyoruz.

private void btnAdd_Click(object sender, EventArgs e)

{

DataRow dr = dsFeeds.Tables[0].NewRow();

dr["feed"] = txtAddress.Text;

dsFeeds.Tables[0].Rows.Add(dr);

dsFeeds.WriteXml(file_path);

xrFile.Close();

FillNodes();

}

Daha once servislerin iceriğini görmek icin ne yapıyorduk adresi textbox a yazdıktan sonra Search butonuna basıyorduk. Ama artık eklediğimiz servisler zaten bizim treeview kontrolümüzde var. Ozaman ben FindFeeds() methoduna bu sefer parametre olarak textbox ‘ın icindeki degeri değilde, o anda treeview’de tıklanan node’ un text özelliğindeki bilgiyi gönderirsem tıklanan servisin adresini parametre olarak vermiş olurum ve o adresteki icerikte DataGridViewde görünür. Peki treeview’de tıklanan elemanın text özelliğini nasıl alacagız? Bunun içinde treeView’ in NodeMouseClick olayını kullanıyoruz. Ve aşagıdaki kodları bu evente yazıyoruz.

private void treeFeeds_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)

{

FindFeeds(e.Node.Text);

}

Evet artık daha önceden eklediğimiz servislerinde iceriğini görebiliyoruz. Peki biz bu servislerin bize sundugu asıl içeriğe nasıl erişeceğiz. Yani internet explorerdaki gibi bir haberin tüm iceriğini görmek istiyorsak ozaman browser kontrolümüzün navigate methoduna iligli haberin URL bilgisini vermemiz gerekiyor. Bunu nasıl yapacagız peki. Dikkat ettiyseniz gridview da listelenen kayıtlarda link diye bir alan var. İşte bu alan bizim haberimizin linkini tutuyor. Peki bu alan kacıncı kolonda? 2. Ozaman ben DataGridView’ in o anda tıklanan satırındaki 2.kolonundaki degeri browser kontrolüme gönderirsem o linkin iceriği karşıma gelmiş olacaktır. Bunun için DataGridView ‘in Cell_Click Eventine aşagıdaki kodları yazıyoruz.

private void dtgHeader_CellClick(object sender, DataGridViewCellEventArgs e)

{

int current_row = dtgHeader.CurrentRow.Index;

string link = dtgHeader.Rows[current_row].Cells[2].Value.ToString();

browser.Navigate(link);

}

Evet geldik bir makalenin daha sonuna. Ama burda ufak bir eksiklik var. Mesela link bilgisini 2.kolonda değilde 3.kolonda olsaydı program ne yapacaktı. Tabiki çalışmayacaktı J Ama bununda bir şekilde önüne geçilebilir. Benim aklıma ilk gelen yöntem, ilk kayıttaki tüm alanların degerleri tek tek startsWith ile http ile başlıyormu diye kontrol edilebilir mesela. Eger geriye true dönüyorsa bu bir link bilgisidir ve ozaman o kolondan degeri cekeriz gibi.

Umarım sizler için yararlı bir yazı olmuştur. Basitte olsa artık kendi yazdığımız bir RSS Reader programımız var.

Programın kaynağına aşagıdaki linkten erişebilirsiniz.

http://rapidshare.de/files/39320244/rss.rar.html

Hepinize iyi çalışmalar dilerim arkadaşlar…
Yorum, öneri, soru veya istekleriniz için mail atabilirsiniz. Bende elimden geldiği kadar cevaplamaya çalışırım.


Mehmet Aydın Ünlü
aydinunlu85@gmail.com

23 Nisan 2008 Çarşamba

Data Access Layer Yazmak...

Merhaba Arkadaşlar;


Uzun zamandır bir şeyler yazamıyordum maalesef. Bu sebepten dolayı 23 Nisan tatilini fırsat bilip hemen bir şeyler karalamak istedim bende :) Bu arada yeri gelmişken tüm Dünya çocuklarının 23 Nisan’ı kutlu olsun. Atatürk’ün bu bayramı sadece Türk olan çokcuklara değil de tüm Dünya’daki çocuklara armağan ettiğini de unutmamak lazım bence. Konumuza dönersek eğer, genelde hepimiz mutlaka bir gramlama diline başladıktan bir süre sonra bir veritabanı programı yazarız yada yazmaya çalışırız J veya veriler üzerinde işlemler yapan benzer nitelikte küçük programlar geliştiririz. Kimimiz basit bir telefon defteri, kimimiz bir stok takip programı yazar. Arada kendi muhasebe programını yazıp çok para kazanmayı düşünenler bile vardır mutlaka J ki kullandıgınız programlama dili C# ise bu gibi şeylere çok daha yakınsınızdır. Çünkü .net 3.0 ile gelen LINQ yapısının tek hedefi veri sorgulama olduğu için Microsoft’un bu alanı ne kadar önemsediğini çok daha net görebiliriz.

Peki bu veritabanı üzerinde işlem yapan programlar C# ile nasıl geliştiriliyor? Bildiğiniz gibi C# ta veriye erişim ADO.NET dediğimiz teknoloji ile sağlanıyor. Peki nedir bu ADO.NET? Burada konumuz ADO.NET mimarisi olmadığı için derin bir analiz yerine ADO.NET ‘in sadece belli başlı sınıflarına değineceğim ki konunun ilerleyen kısımlarında bunlar bize gerekli olacak. Ayrıca yeri gelmişken hemen söyliyeyim, ADO.NET için Aykut Taşdelen ‘in C# ile Veritabanı Programlama ve ADO.NET kitabını aynı zamanda www.csharpnedir.com ‘da ADO.NET başlığı altında Burak Selim Şenyurt ‘un yazdığı makaleleri kesinlikle okunmanızı tavsiye ederim. Eğer bu konularda bir sıkıntınız yoksa yazıyı okumaya devam edebilirsiniz ama C# ‘a yeni başlayan biri iseniz öncelikle veri tabanı programcılığı hakkında biraz bilgi edinmelisiniz.

Bildiğiniz gibi ADO.NET mimarisi ile bizler veritabanına bağlanıp, SQL sorgusu ile bir tablodan istediğmiz kayıtları seçip, bunları bir DataGrid kontrolünde listeleyebiliyor, yeni bir kayıt ekleyeceğimiz zaman bilgileri TextBox’lara girip kaydet dediğimizde de eklediklerimiz veritabanına kayıt ediliyordu. Peki bu işlemleri ADO.NET’ te hangi sınıflar yapıyordu ? (Örnek SQL Server üzerinde yapılacagı için kullanacagımız provider SqlClient olacaktır)

Öncelikle hangi server daki, hangi veritabanına hangi şekillerde bağlanacagımızı belirten bir connectionString yani bağlantı cümlesi yazmamız gerekiyor.
Ardından bir connection nesnesi yaratlıyordu ve buna yazdıgımız baglantı cümlesini parametre olarak veriyorduk.

Connection nesnesinin open methodu ile baglantı cümlesindeki veritabanına bağlanılıyordu.

Tüm kayıtları sececeğimiz zaman ise bir Sql SELECT sorgusu yazıyorduk ve bunuda bir DataAdapter nesnesi’nin Fill methodu ile bir DataTable nesnesine dolduruyorduk.

Sonra bu DataTable nesnesini bir GridView ‘e Data Source olarak gösteriyorduk ve sorgumuzun geriye döndürdüğü kayıtları artık uygulamız içindeki bir DataGridde görebiliyorduk.

Bu adımlar da bir tablo içeriği gösterilmiş oluyordu.

Peki yeni bir kayıt ekleyeceğimiz zaman ne yapıyorduk.

Bir Command nesnesi tanımlıyorduk, bu nesne bizim en başta tanımladıgımız Connection nesnesi ile ilişkili çalışıyordu.Bunu command nesnesinin connection özelliği sayesinde belirtiyorduk.

Eğer sorgumuz parametre alıyorsa bunuda Command nesnemizin parameters koleksiyonuna ekliyorduk.

Sonra CommandText özelliğine verdiğimiz Sql komutunu, bağlantıyı açtıktan sonra ExecuteNonQuery() methodu ile çalıştırabiliyorduk.

Ayrıca bu Command nesnesi aynı zamanda bir veritabanı nesnesi olan ve veritabanı üzerinde saklanan Stored Procedure’ leride çalıştırabiliyordu. Ve Command nesnesi aynı zamanda ExecuteScalar() methodu ile geriye tekil sonuclar döndüren Sql sorgularıda çalıştırabiliyordu. Mesela bir tablodaki kayıt sayısı gibi.

Buraya kadar maddeler halinde yazdıgım satırları okurken belki sıkılmışsınızdır ama sıkıcı bile olsa bunlar C# dilinde, ADO.NET mimaris ile en basit haliyle bir veritabanı üzerinde işlem yapmanın başlıca adımlarıdır. İşte bugünkü makalemin konusu sizi bu sıkıcı adımları sürekli gerçekleştirmekten kurtarmak :)

Bunuda Data Access Layer dediğimiz bir veri erişim katmanı sayesinde yapıyoruz. Adı sizi çok korkutmasın sakın J Aslında arka planda çalışan mantık yukarda yazdığım adımlardan pekte farklı değil. Peki nedir bu Data Access Layer (DAL) ? DAL, kısaca veritabanı üzerinde işlem yapan bir veya birkaç class’ın yazılıp, paketlenip bir .dll dosyası haline getirilmiş halidir diyebiliriz. Bu işlem bir nevi bizi veritabanından soyutlamış olur. Biz veri üzerinde bir işlem yaparken ADO.NET sınıflarına direk erişmek yerine bunlara DAL içindeki methodlar ile erişip işlemlerimizi yaptırıyoruz. Bildiğiniz gibi .dll dosyalarını projelerimize add referance ile ekleyip içindeki sınıfları kullanabiliyoruz. Bu sayede o sınıftaki kodları sürekli projemiz içinde yazmaktansa bir kez bir .dll dosyasına yazıp bunu her projede kullanabiliyoruz. İşte bu mantıktan yola çıkarak bizde ufak bir Data Access Layer geliştireceğiz. Amacım sadece size işin mantığını sunabilmek oldugu için cok karmaşık yapılara girmeyeceğim. Bu mantıgı kavradıkta sonra eminim çok zorlanmadan kendi DAL’ınız yazabileceksiniz. Ayrıca daha detaylı bir DAL yazımı için sevgili Levent Yıldız ‘ın linkteki makelesini inceleyebilirsiniz.

Bu ön bilgilerden sonra projemize başlama zamanı geldi sanırım. Şimdi kendimize bir şablon çıkarmamız gerekiyor. Aslında şablonu az önce yukardaki adımlar ile çıkarmıştık. Şimdi ondan yararlaranarak bu şablonun detaylarıda kapsayan bir yapı geliştirmek.

Bu yapıyı aşağıdaki grafikte özetlemeye çalıştım.

Data Access Layer adında bir ClassLibrary’miz var. Yani bu bizim NameSpace’imiz oluyor. Bunun içinde DataBase adında bir Class var. Ve onun içindede veritabanı nesnelerimiz, property’ lerimiz, SQL ve Stored Procedure sorgularını çalıştıracak methodlarımız ve son olarakta bu sorgulara gidecek olan parametreleri belirleyen yada temizleyen Parametre methodları var. Yapıyı anlaşılır olması amacıyla oldukça basit tutmaya çalıştım. Daha profosyonel bir şey yapmak isterseniz mesela Parameters bölümünü ayrı bir class olarak yazabilirsiniz.

DataBase bölümünde bağlantı cümlesine göre bir Connection nesnesi oluşturan 3 farklı method var. Bunlardan iki tanesi CreateDataBase adından parametre alan ve almayan methodlar. Diğeri ise Default Constructor’ ın overload edilmiş hali olan connection stringi direk parametre alarak bir Connection nesnesi oluşturan Constructor’ dır. Bunun bize kolaylıgı ilerde bu DataBase sınıfından bir nesne yaratırken aynı anda Connection nesnemizi oluşturabilmemizdir.
Objects bölümü bizim veritabanı işlemleri yapmamızı sağlayacak ADO.NET sınıflarını içeriyor.

Properties bölümü ise connection stringimizi dinamik bir yapı halinde sunabilmek için alacagı parametrelere değer atamayı sağlayacak özellikleri içeriyor.

Static SQL bölümünde ise Command nesnesi yardımı ile C# kodu içine gömülü SQL kodu çalıştırabilmek için geçerli olan methodları içeriyor. Bunlardan RunSqlTable bir select sorgusunu geriye bir DataTable şeklinde döndürüyor. RunSqlQuery ise Insert, Update, Delete gibi geriye değer döndürmesi şart olmayan SqlKodlarını çalıştırıyor(ExecuteNonQuery). Gerekirse sorgunun başarılı olup olmadıgının kontrolü için tabiki bool döndüren bir yapıyada sahip olabilir. RunSqlScalar ise geriye tekil sonuç döndüren Sql sorgularının çalıştırılması için çağrılır ve geriye sorgunun döndürdüğü degeri object olarak döndürür. Bizde bunu cast ederek istediğimiz tipe cevirebiliriz. Bu methodların hepsi SQL sorgusunu bir string parametre olarak alıyor.

Stored Procedure altında ise Static Sql ‘deki methodların Stored Procedure şeklinde çalışan versiyonları vardır. RunSPTable, RunSPQuery, RunSPScalar bu 3 method parametre olarak ise Stored Procedure’ ün ismini alır.

Son olarak ise Parameters bölümü vardır. Burada ise sorgularımıza parametre göndermek istersek AddParameter ile parametre ekliyoruz. Yada yeni bir sorguda, farklı isimde parametreler kullanacaksan önceden eklenen parametreleri ClearParameters methodu ile siliyoruz.

Dediğim gibi mantığın anlaşılması için çok basit bir yapı kurmaya çalıştım. Umarım karışık gelmez. Şimdi isterseniz uygulamamızı geliştirmeye başlayalım.

İlk olarak Visual Studio 2005 ‘i açıyoruz ve projemiz bir .dll dosyası olacagından vede diğer projelerde kullanacağımızdan dolayı projemizi bir ClassLibrary olarak açıyoruz. Adınada kısaca DAL diyoruz.

Sınıfımızın adınıda DataBase olarak belirleyelim. Ardından using deyimi ile System.Data ve System.Data.SqlClient namespace’ lerini ekleyelim.

Şimdi yukarda verdiğim tabloya göre projemizi geliştirmeye başlayalım. Sırayla gittiğimize göre ilk olarak nesnelerimizi ve property’lerimiz bir bir tanımlayalım bakalım.

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
namespace DAL
{
public class DataBase
{


#region Default Constructor
public DataBase()
{

}
#endregion

#region Properties

private string host;
public string Host
{
get { return host; }
set { host = value; }
}

private string dbName;
public string DbName
{
get { return dbName; }
set { dbName = value; }
}

private bool integratedSecurity;
public bool IntegratedSecurity
{
get { return integratedSecurity; }
set { integratedSecurity = value; }
}

private string userName;
public string UserName
{
get { return userName; }
set { userName = value; }
}

private string password;
public string Password
{
get { return password; }
set { password = value; }
}

private string others;
public string Others
{
get { return others; }
set { others = value; }
}

#endregion

#region Objects
private SqlConnection conn;
private SqlCommand cmd;
private SqlDataAdapter dap;
private DataTable dt;
#endregion
}
}

Bu property’lerden Others adında olan connection stringinize ek özellikler eklemek isterseniz bunu yapabilmeniz için eklenmiştir. Yani bağlantı cümlenizde yukarda tanımlı belli başlı özellikler dısında yeni bir şey eklemek isterseniz bunu others özelliğine string bir bilgi olarak ekleyebiliyorsunuz.

Property’lerimiz ve SqlConnection nesnemiz tanımlandıgına göre artık bunları kullanarak bir SqlConnection nesnesi yaratabiliriz. Bu amaçla aşagıdaki 3 methodu yazıyoruz. Bu methodlardan ilki overload edilmiş Default Constructor’ dır. String bir baglantı cümlesi alıyor ve buna göre hemen bir SqlConnection nesnesi oluşturuyor. Tabi biz sınıfımız oluştururken , SqlConnection nesnesi oluşsun istemiyorsak, nesneyi default constructor ile oluşturduktan sonra , gerekli olan server, database gibi bilgileri propertyler yardımı ile ekledikten sonra CreateDataBase methodu ile de aynı işlemi yapabiliyoruz. Bu methodu 2.overload versiyonu ise aynı constructordaki gibi tüm baglantı cümlesini string bir bilgi olarak alıyor ve buna göre bir SqlConnection oluşturuyor. Bu methodların 3 tane olması tamamen esneklik sağlamak amacıyla yapılmıştır. Yoksa mantıken yaptıkları işlem hepsinin aynı.

public DataBase(string con_str)
{
conn = new SqlConnection(con_str);
}

public bool CreateDatabase()
{
try
{
string conStr = "Server = " + host + "; DataBase = " + dbName + "; UID = + " + userName + "; Password = " + password + "; Integrated Security = " + integratedSecurity + "; " + others;
conn = new SqlConnection(conStr);

return true;
}
catch
{
return false;
}
}

public bool CreateDatabase(string con_str)
{
try
{
conn = new SqlConnection(con_str);

return true;
}
catch
{
return false;
}
}

Şimdi C# kodu içine gömülü SQL sorgularını çalıştıracak olan methodlarımızı yazabiliriz. Bu methodların 3 tane ve her birinin farklı şekilde çalışıtıgını yukarda söylemiştik.

public DataTable RunSqlTable(string sql)
{
if (cmd == null)
{
cmd = new SqlCommand();
}

cmd.Connection = conn;
cmd.CommandType = CommandType.Text;
cmd.CommandText = sql;

dap = new SqlDataAdapter(cmd);
dt = new DataTable();

dap.Fill(dt);

cmd.Dispose();
dap.Dispose();

return dt;
}

İlk olarak geriye sorgu sonucunu bir DataTable şeklinde döndüren methodumuza bir bakalım. Bu method bir string parametre alıyor. Aldıgı bu parametre sql kodunun ta kendisinidir. Methodumuz içerde eğer Command Nesnesi yaratılmadıysa yeni bir tane yaratıyor, ardından bağlantımıza bağlanıyor, ardından sql kodunu DataAdapter’ ın Fill Methodu ile bir DataTable’ a dolduruyor. Ve geriye bu DataTable’ ı döndürüyor. Bu işlemlerin yapılacagını ve temelde hep aynı olduklarını yukarda söylemiştim zaten. Gördüğünüz gibi ekstra olan veya farklı olan bir şey yok.

public void RunSqlQuery(string sql)
{
if (cmd == null)
{
cmd = new SqlCommand();
}

cmd.Connection = conn;
cmd.CommandType = CommandType.Text;
cmd.CommandText = sql;


conn.Open();
cmd.ExecuteNonQuery();
conn.Close();

cmd.Dispose();
}

RunSqlQuery ise yukardada dediğim gibi parametre olarak gelen sql sorgusunu çalıştırmakla yükümlüdür. Örnek vermek gerekirse bir DELETE veya UPDATE sorgusu. Bu sorgular gider veritabanı üzerinde işlem yapar ama geriye bir sonuc döndürmesi şart değildir.
public object RunSqlScalar(string sql)
{
if (cmd == null)
{
cmd = new SqlCommand();
}

cmd.Connection = conn;
cmd.CommandType = CommandType.Text;
cmd.CommandText = sql;

conn.Open();
object result = cmd.ExecuteScalar();
conn.Close();

cmd.Dispose();
return result;

}

RunSqlScalar methodu ise geriye tekil sonuç döndüren Sql sorgularının çalıştırılmasıyla yükümlüdür. Dikkat ederseniz command nesnemiz olan cmd ExecuteScalar() methodu ile sorguyu çalıştırmaktadır. ExecuteScalar() methodu geriye bir object döndürdüğü için bizim methodumuzun da return type’ ı object ‘tir. Bu degeri kullanacagımız zaman ilgili türe cast ederek kullancağız.

Bu 3 methodda kod içine gömülü sql kodlarını çalıştırıyordu. Yani bizim command nesemizin CommandType özelliği Text ‘ti dikkat ettiyseniz. Şimdi Stored Procedure’ler üzerinde işlem yapan 3 methodumuzu yazalım. Bu methodlar hakkında açıklama yazma gereği duymuyorum çünkü yukarda anlattıgım 3 method ile aynı işlevselliğe sahiptir, tek farklı bu sefer command nesnemizin CommandType özelliği Text değil, StoredProcedure ‘dür.

public DataTable RunSPTable(string sp_name)
{
if (cmd == null)
{
cmd = new SqlCommand();
}

cmd.Connection = conn;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = sp_name;

dap = new SqlDataAdapter(cmd);
dt = new DataTable();

dap.Fill(dt);

cmd.Dispose();
dap.Dispose();

return dt;
}

public void RunSPQuery(string sp_name)
{
if (cmd == null)
{
cmd = new SqlCommand();
}

cmd.Connection = conn;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = sp_name;

conn.Open();
cmd.ExecuteNonQuery();
conn.Close();

cmd.Dispose();
}

public object RunSPScalar(string sp_name)
{
if (cmd == null)
{
cmd = new SqlCommand();
}

cmd.Connection = conn;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = sp_name;

conn.Open();
object result = cmd.ExecuteScalar();
conn.Close();

cmd.Dispose();

return result;


}

İşte Stored Procedure’ler üzerinde işlem yapan methodlarımızda bunlar.Artık parametreler üzerinde işlem yapan methodlarımıza geçebiliriz. Bu arada belki dikkatinizi çekmiştir, neden her seferinde if(cmd == null) kontrolü yapıyoruz, bunun nedeni bu sınıfı kullanırken ilerde, parametre atama methodlarının, sql kodu calistirma methodlarından önce yazılıyor olmasıdır. Bu şu anlama gelir ben ozaman parametre atayacagım yerde bir command nesnesi yaratmalıyım. Ama ben sql kodu calistiran methodları çagırdıgım zaman null kontrolü yapmadan yeni bir command nesnesi oluşturursam önceden atadıgım parametreler yeni command nesnesinde olmayacaktır ve kodumuz calismayacaktır. Bu sebepten dolayı böyle bir önlem alarak bu sorunun önüne geciyoruz.

Şimdi parametre methodlarına bakabiliriz;

public void AddParameter(string name, object value)
{
if (cmd == null)
{
cmd = new SqlCommand();
}

cmd.Parameters.AddWithValue(name, value);
}

public void ClearParameters()
{
cmd.Parameters.Clear();

}

Aslında AddParameter yapı olarak command sınıfının AddWithValue methodundan pek farklı değildir. Zaten icerdede sizin methoda parametre olrak verdiğiniz parametre adını ve değerini AddWithValue methodu ile command nesnesinin parameters koleksiyonuna ekliyor.

ClearParameters methodu ise farklı bir sql sorgusunda kullanılmak üzere farklı parametreler tanımlanmadan önce var olan parametrelerin temizlenmesi amacıyla kullanılır.

Evet arkadaşlar bu işlemleri sırayla gerçekleştirdikten sonra artık projemizi derleyebiliriz. Yalnız projeyi derlerken Release modda derlemenizi tavsiye ederim. Bir proje sorunsuz bir şekilde tamanlandıktan sonra artık paketlenecek hale geldiyse bu modda derlenir.


Artık DAL.dll isimli dosyamız diğer projelerde kullanılmak üzere hazırdır J Test etmek amacıyla örnek bir windows application acıyoruz. Formumuzun üzerine;
1 tane DataGrid
4 tane TextBox
1 tane Button koyuyoruz.

Programımızın ilişkili çalışacagı veritabanının adı ise dbTest. İçinde tbl_Personel diye bir tablo ve, id, ad, soyad, maas adında 3 alan mevcuttur.

Şimdi DAL’ ımızı kullanarak bu veritabanına bağlanalım, tüm kayıtları cekelim, personel sayısını gösterelim ve yeni bir kayıt ekleyebilelim.

Öncelikle ilk yapmamız gereken DataAccessLayer projemizinin bulundugu dizine gidip, release klasorü icinden DAL.dll dosyamızı bulunması kolay bir yere kopyalayalım mesela masaüstü. Ardından window uygulamamıza geri dönüp, solution explorerda sağ tıklayıp add referance diyerek masaüstüne attıgımız dll dosyasını referanslarımıza ekleyelim.

Artık referansımız eklendiğine göre bu dll icindeki sınıfları yeni projemde rahatlıkla kullanabilirim. İlk olarak using deyimi ile referansım içindeki sınıflara direk erişebilmek için onu tanımlıyorum. Yoksa her sınıfa namespace adı ile erişmek zorunda kalacaktım.

Şimdi tüm kayıtları listelemek amacıyla form load ‘a şunları yazıyoruz.

private void Form1_Load(object sender, EventArgs e)
{
//DataBase db = new DataBase("Server=Localhost; DataBase = dbTest; Integrated Security = SSPI");

DataBase db = new DataBase();
db.Host = "Localhost";
db.DbName = "dbTest";
db.IntegratedSecurity = true;
db.CreateDatabase();

//db.CreateDatabase("Server=Localhost; DataBase = dbTest; Integrated Security = SSPI");

DataTable dt = db.RunSqlTable("SELECT * FROM tbl_Personel");
dataGridView1.DataSource = dt;

textBox4.Text = db.RunSqlScalar("SELECT COUNT(*) FROM tbl_Personel").ToString();
}

Gördüğünüz gibi veritabanına bağlanmanın 3 farklı yolu var. Öncelikle veritabanına bağlanıyoruz ve tüm kayıtları DataGridView ‘de gösteriyoruz. Bu işlem geriye bir DataTable döndürdüğü için ve C# kodu içine gömülü bir sql sorgusu oldugu için RunSqlTable methodunu kullandım.
Ardından tablodaki personel sayısını elde etmek için COUNT(*) ile geriye tekil bir sonuc döndüren RunSqlScalar() methodunu cagırdım ve geriye döndürdüğü personel sayısını TextBox4 e yazdırdım.
Son olarak button’ abasınca textboxlara girilen degerleri parametre olarak alıp bunları INSERT ile tabloya ekleyen bir Stored Procedure ‘ü kullanarak DAL’ ımızı test edelim. Bunun için Veritabanıma spPersonelEkle adından bir Stored Procedure yazıyorum.

CREATE PROCEDURE spPersonelEkle
@par_ad nvarchar(50), @par_soyad nvarchar(50), @par_maas int
AS
BEGIN
INSERT INTO tbl_Personel (ad, soyad, maas) VALUES (@par_ad, @par_soyad, @par_maas)
END
GO

Ardından buton ‘un click olayına aşagıdaki kodları yazıyorum.

private void button1_Click(object sender, EventArgs e)
{
DataBase db = new DataBase("Server=Localhost; DataBase = dbTest; Integrated Security = SSPI");

db.AddParameter("@par_ad", textBox1.Text);
db.AddParameter("@par_soyad", textBox2.Text);
db.AddParameter("@par_maas", Convert.ToInt32(textBox3.Text));

db.RunSPQuery("spPersonelEkle");

DataTable dt = db.RunSqlTable("SELECT * FROM tbl_Personel");
dataGridView1.DataSource = dt;

db.ClearParameters();
}

Gördüğünüz gibi normalde her seferinde SqlCommand veya DataAdapter’ lar la program yazmak yerine bunları 1 kereliğine bir DAL olarak yazıyoruz ve ardından her projede kullanabiliyoruz. Bu işte bize büyük bir esneklik ve kolaylık sağlamaktadır gerçekten.
Bir makalemizin daha sonuna geldik arkadaşlar. Bu yapıyı geliştirmek kendinize göre uyarlamak tamamen size bağlı. Amacım bu işin mantıgını anlatabilmekti. Umarım sizler için faydalı bir yazı olmuştur.

Projenin kaynak dökümanlarını buradan download edebilirsiniz.

http://rapidshare.de/files/39251710/dal.rar.html

İyi günler dilerim.

Mehmet Aydın Ünlü

03 Şubat 2008 Pazar

CETURK 5 Yaşında...


Türk bilişim sektörüne katkısı tartışılmayacak bir platform varsa oda tartışmasız CETURK' tür. 1 sene önce tanıştıgım bu site kurulalı tam 5 sene olmuş. Nice yıllara CETURK...

02 Ocak 2008 Çarşamba

Asp.net ile Dinamik Web Sayfaları

Merhaba Sevgili Arkadaşlar,

Bugün 2008 'in ikinci günü, yeni bir yıla güzel bir konuyla girmek istedim. Ayrıca 31 Aralık benim doğum günümdü, bu makalemin sizlere faydalı olması benim için güzel bir doğum günü hediyesi olacaktır :)

Bugünkü makalemizin konusunu kısaca açıklamak gerekirse, "asp.net ile dinamik web sayfaları nasıl yapılır" şeklinde özetleyebiliriz. Ayrıca bu konu içersinde fckeditor kullanımından tutunda, admin paneli tasarımı, master page kavramı ve hatta asp.net ile form tabanlı güvenlik gibi bir çok alt konuya değineceğim.

Bir çoğumuz bir web sitesi yaparken en başta şunu düşünür herhalde. Sitede kaç tane menü olacak ve bu menüler neler olacak. Doğal olarak her menü elemanının içeriğini gösteren birde sayfa olacaktır.
Örnek vermek gerekirse 4 menülü bir web sitesinde menülerimizin şunlar oldugunu düşünelim;


Ana Sayfa | Hakkımızda | Menüler | İletişim.

Şimdi burada 4 farklı sayfa olacagı kesindir. Birde işi daha kompleks düşünürsek eğer, Menüler için birde alt menüler olacaktır. Mesela bir restaurant' ın web sitesi ise, bu sefer sıcak icecekler, soguk icecekler, kahvaltı, ögle yemegi, aksam yemegi gibi bir çok alt menü olacaktır. Gördüğünüz gibi sadece bir menüye alt menü elamanları eklemek ile bi anda onlarca menümüz ve sayfamız oldu. İşte tüm bu menülerin, sayfaların ve sayfa içeriklerinin tek tek eklenmesi ve kontrolü gerçekten cok zordur. Bu sıkıntıdan kurtulmak için bir admin paneli tasarlayıp, tamamen dinamik bir mimari ile sitemizi geliştirirsek eğer, ilerde asla bu tarz şeyler ile başımız ağrımayacaktır. Bende bu makalemde sizleri bu dertlerden kurtarmaya çalışacağım elimden geldiği kadar :) Ufak bir örnek daha vermek gerekirse mesela hepsiburada.com 'u verebiliriz. Binlerce ürün için binlerce sayfa yok. Bir ürün secildiği zaman ona ulaşmak icin querystringler ile erişilebiliyor. Bizim makalemizinde özü aslında tam olarak budur.


Bu önbilgilerden sonra dilerseniz projemizde kullanacagımız veritabanını tasarlamak ile işe başlayabiliriz.

Öncelikle 2 tane tablomuz olacak, birincisi admin bilgilerini tutacak, ikinicisi ise sayfaları ve iceriklerini tutacak. Veritabanımızın adi "dinamik" olsun, tablolarda bulunması gereken alanları ise aşagıdaki resimlerde görebilirsiniz.



Tabloları oluşturduktan hemen sonra admin tablosunu acıp, username ve pwd bilgisine "0cc175b9c0f1b6a831c399e269772661" bu bilgiyi girin. Bu a harfinin md5 karşılıgıdır.Yani ilk basta kullanıcı adımız ve şifremiz "a" olacaktır. Bunu ilerde admin panelinden şifre değiştirme modülünden değiştirebilirsiniz. Gördüğünüz gibi güvenlik önlemi icin bilgiler md5 ile şifrelenip öyle yazılyor veritabanına.

Ardından tbl_Sayfalar tablosuna, menülerde görünen sayfaların başlıklarını ekliyoruz.Aşagıda göründüğü gibi.

Bu işlemlerden sonra veritabanı ile işlerimiz şimdilik bitti. Sitemizi oluşturmaya başlayabiliriz artık.


Visual Studio 'da bir asp.net web site projesi acıyoruz. Ben adını "dinamiksite" olarak verdim. Solution explorerdan default.aspx 'i siliyoruz. Ardından sitemize "pMaster.master" adında bir master page ekliyoruz. Sonra "index.aspx" adında, bu master page 'e baglı bir web form ekliyoruz. index.aspx içine bir datalist ve datalistin içinede bir label ekliyoruz. Datalistin adını "dtIcerik" ve label 'in adını da "lblIcerik" olarak değiştiriyoruz. İlerde bizim veritabanında cekip göstereceğimiz tüm icerik bu label icinde görünecektir. Tasarım konusunu tamamen sizin hayal gücünüze bırakıyorum, ama ne yaptıgımı kısaca görmeniz acısından bu aşagıdaki ekran görüntüsüne bakabilirsiniz. Master Page kavramı hakkında detaylı bilgi için BURADAKİ makaleyi okuyabilirsiniz.

Projemizde web sitesinin ziyaretçiler kısmını oluşturan sadece masterpage ve index sayfamız var. İsterseniz 100 lerce sayfamız olsun, index 'ten başka bir sayfaya ihtiyacımız yok.


Artık Admin panelini tasarlayabiliriz. Bunun için solution explorer 'da "admin" adında bir klasor acıyoruz ve icine 1 tane master olmak üzere toplam 4 sayfa koyuyoruz.
a- pMasterAdmin.master
b- giris.aspx ( şifreli giriş sayfası )
c- ayarlar.aspx ( admin ayarlarını değiştirmek için )
d- sayfalar.aspx ( sayfa içeriklerini düzenlemek için )

Bu sayfaların tasarımına ve kodlarına gecmeden önce güvenlik acısından yapmamız gerekenleri acıklamak gerekiyor. Öncelikle kullnacagımız güvenlik yöntemi form tabanlı güvenliktir. Form tabanlı güvenlik, belirtiğimiz dizin altına erişebilecek veya erişemeyecek kişileri config dosyamızdan gerekli ayarları yaparak belirttiğimiz bir güvenlik türüdür. Bu konuda ayrıntılı bilgi almak icin BURADAKİ makaleyi okuyabilirsiniz.

Öncelikle projemize bir web config eliyoruz ve iceriğini aşagıdaki gibi değiştiriyoruz.

web.config
--------------



Buradaki location path bilgisi ve
authentication bilgisinde verdiğimiz değerler, belirttiğimiz dizin altında herhangi bir sayfaya izinsiz giriş yapıldıgı taktirde, ekrana gelmesini istediğimiz giris sayfasını göstermekten ibarettir kısaca. Yani önce giris yapılır , eğer dogruysa diger admin sayfalarına girilebilir.
Güvenlik ayarlarımız sadece bukadar.

Şimdi sırasıyla admin panelindeki bu sayfaların iceriklerini tasarlayalım. İlk olarak giris.aspx'ten başlıyoruz. Bu sayfa yönetim panelindeki herhangi bir sayfaya erişebilmek icin gerekli olan kullanıcı adı ve şifrenin kontrolünü yapıyor ve admin paneline girilmek istendiği zaman ilk olarak bu sayfa açılıyor.


Bu sayfada yazılan kodları kısaca anlatmak gerekirse, önce kullanıcıdan username ve password bilgisi alınıyor, sonra veritabanındaki admin isimli tabloya bakılıyor. Ardından geri dönen kayıt sayısına bakılıyor eger 1 ise dogru bilgi girilmiştir ve sayfalar.aspx isimli sayfaya yönlendirme yapılıyor. Eğer geri dönen kayıt sayısı 1 değilse ozaman yanlış bilgi girilmiş demektir.

giris.aspx.cs ( Kodlar )
-------------------------------
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

using System.Data.OleDb;

public partial class admin_giris : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
txtUserName.Focus();
}
protected void btnGiris_Click(object sender, EventArgs e)
{
Login();
}

#region Login

private void Login()
{
string constr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + Server.MapPath("../App_Data/dinamik.mdb");

OleDbConnection conn;
OleDbCommand cmd;

conn = new OleDbConnection(constr);
cmd = new OleDbCommand();
cmd.Connection = conn;

string _username = Hash(txtUserName.Text);
string _pwd = Hash(txtPwd.Text);

cmd.Parameters.AddWithValue("@par_username", _username);
cmd.Parameters.AddWithValue("@par_pwd", _pwd);

cmd.CommandText = "SELECT COUNT(*) FROM tbl_Admin WHERE username = @par_username AND pwd = @par_pwd";

int kayit_sayisi = 0;

conn.Open();
kayit_sayisi = (int)cmd.ExecuteScalar();
conn.Close();

if (kayit_sayisi == 1)
{
FormsAuthentication.RedirectFromLoginPage(txtUserName.Text, true);
Response.Redirect("sayfalar.aspx");
}
else
{
txtUserName.Text = "";
txtPwd.Text = "";
txtPwd.Focus();
}
}

#endregion

#region Hash

private string Hash(string MD5)
{
System.Text.UTF8Encoding ue = new System.Text.UTF8Encoding();
byte[] bytes = ue.GetBytes(MD5);

// encrypt bytes
System.Security.Cryptography.MD5CryptoServiceProvider md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
byte[] hashBytes = md5.ComputeHash(bytes);

string hashString = "";

for (int i = 0; i <>


ayarlar.aspx' sayfası da admin bilgilerini değiştirmek icin kullanılacak sayfadır. Admin şifresini ve kullanıcı adını değiştirmek icin bu sayfa kullanılacaktır. Burda yazılan kodlar ise en basit tanımıyla klasik bir update sorgusudur. Tasarımı yine gördüğünüz gibi cok basittir.


ayarlar.aspx.cs ( Kodlar )
-----------------------------------
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

using System.Data.OleDb;

public partial class admin_ayarlar : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{

}
protected void btnOK_Click(object sender, EventArgs e)
{
Login();
}


#region Login

private void Login()
{
string constr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + Server.MapPath("../App_Data/dinamik.mdb");

OleDbConnection conn = new OleDbConnection(constr);
OleDbCommand cmd = new OleDbCommand();
cmd.Connection = conn;

if (txtYeniSifre1.Text != txtYeniSifre2.Text)
{
lblState.Visible = false;
lblState.Text = "Şifreler Uyuşmuyor!";
}
else
{
cmd.CommandText = "SELECT COUNT(*) FROM tbl_Admin";

conn.Open();
int data_count = (int)cmd.ExecuteScalar();
conn.Close();

if (data_count == 1)
{
string _username = Hash(txtUserName.Text.ToLower());
string _pwdnew = Hash(txtYeniSifre1.Text.ToLower());

cmd.Parameters.AddWithValue("@par_username", _username);
cmd.Parameters.AddWithValue("@par_pwdyeni", _pwdnew);

cmd.CommandText = "UPDATE tbl_Admin SET username = @par_username, pwd = @par__pwdnew;";

conn.Open();
cmd.ExecuteNonQuery();
conn.Close();

lblState.Visible = true;
lblState.Text = "Bilgiler Güncellendi.";
}
else
{
lblState.Visible = true;
lblState.Text = "Bilgiler Uyuşmuyor.";
}
}
}

#endregion

#region Hash

private string Hash(string MD5)
{
System.Text.UTF8Encoding ue = new System.Text.UTF8Encoding();
byte[] bytes = ue.GetBytes(MD5);

// encrypt bytes
System.Security.Cryptography.MD5CryptoServiceProvider md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
byte[] hashBytes = md5.ComputeHash(bytes);

string hashString = "";

for (int i = 0; i <>


Şimdi işte işin can alıcı noktasına geldik. sayfalar.aspx 'i tasarlayarak dinamik çalışan web sitemizin icerik yönetim modülünü oluşturma bölümü. Konuya girmeden önce aklınızda bir kac soru oluşmasını istiyorum. Tamam içeriği burda ekleyebiliriz, iyi güzelde peki ben iceriği eklerken sadece text tabanlı veri girmiyorsam ne olacak. Yani bir web sitesi sadece düz yazılardan ibaret değildir. Flash objelerinden tutunda, resimlere kadar, hatta html input kontrollerinden, tablolara kadar bir cok obje barındırıyor. Biz bunları nerden ve nasıl ekleyebiliriz? İşte tam bu noktada imdadımıza fckEditor yetişiyor. FCKEditor 'ü anlatmak gerekirse ufak bir frontpage olarak düşünebilirsiniz. Online olarak çalışan ufak bir front-page yani.

Bu acıklama bilgilerinden sonra fckeditor 'ü nerden nasıl buluruz ve nasıl kullanabiliriz sorunlarının cevaplarına gecebiliriz.

Öncelikle şunu söylemekte fayda var, fckeditor ile calisabilmek icin 2 farklı dosya download etmemiz gerekiyor. Bunlardan birincisi fckeditor 'ün kendi dosyaları. İkincisi ise .net platformunda kullanabilmemiz icin asp.net connectorüdür. Bu connector dediğimiz şey aslında bir .dll dosyasıdır.

http://www.fckeditor.net/download
Bu sayfadan editor 'ü ve connector 'ü download edebilirsiniz.
Bu iki dosyayı indirdikten sonra yapmamız gereken işlemler cok basit. Birincisi connector 'ün bulundugu zip dosyasını acıyoruz. Ayrıca bu dosya icinde fckeditor ile ilgili örnekleri inceleyebilirsiniz. Dosyaları actıktan sonra "bin\Release\2.0" dizini altında bulunan "FredCK.FCKeditorV2.dll" isimli dll dosyasını, "C:\WINDOWS\system32" altına kopyalıyoruz. Ardından solution explorerda proje sag tıklayıp add referance ile bu dll, dosyasının adresini gösterip referance ediyoruz.

Bu işlemden sonra solution explorer 'a dikkat ederseniz Bin adında bir klasor olusup icinede bu dll 'in eklendiğini görebilirsiniz. Referance eklendikten sonra bu dll i toolbox 'a da ekliyoruz ki fckeditor kontrolünü kullanabilelim. Toolbox ' a sag tıklayıp, "Choose Items..." ı seçiyoruz ve acılan pencereden browse 'a tıklayıp .dll 'in yerini tekrar gösteriyoruz. Artık editörümüz toolbox 'ta var ve formumuzda kullanmak istersek sürükleyip bırakmamız yeterli.

Ardından download ettiğmiz fckeditor dosyalarının bulundugu dosyayı projemizin bulundugu dizin altına kopyalıyoruz.


Bu işlemlerden sonra bir iki ufak ayar daha yapmamız gerekiyor.Bu ayarlardan en önemlisi webconfig dosyasında AppSettings altına şu satırları yazmaktır

Bu anahtarlardan birincisi fckeditor dosyalarının bulundugu dizini gösteriyor, ikincisi ise upload işlemleri sırasında dosyaların upload edileceği adresi belirtiyor. Mesela sayfanıza bir resim eklemek istiyorsunuz bunu upload etmeniz gerekiyor. Ozaman bu resim burda belirttiğiniz adres altına kaydediliyor serverda.

Ardından "fckeditor\editor" altındaki "fckconfig.js" isimli dosyadaki bu 2 satırdaki tırnak icindeki bilgiyi aspx yapıyoruz.

var _FileBrowserLanguage = 'aspx' ; // asp | aspx | cfm | lasso | perl | php | py
var _QuickUploadLanguage = 'aspx' ; // asp | aspx | cfm | lasso | perl | php | py

Sonra "fckeditor\editor\filemanager\connectors\aspx" dizini icine "userfiles" isminde bir klasor olusturuyoruz.

Sonra aynı dizinde bulunan "config.asx" isimli controlün code-behind' daki kodlarında bulunan
CheckAuthentication() metodundaki return değerini true olarak değiştiriyoruz.

private bool CheckAuthentication()
{
// WARNING : DO NOT simply return "true". By doing so, you are allowing
// "anyone" to upload and list the files in your server. You must implement
// some kind of session validation here. Even something very simple as...
//
// return ( Session[ "IsAuthorized" ] != null && (bool)Session[ "IsAuthorized" ] == true );
//
// ... where Session[ "IsAuthorized" ] is set to "true" as soon as the
// user logs in your system.

return true; // Bu false 'ı true yapıyoruz.
}

Burda ufak bir parantez acayım sanırım bu yaptıgımız dogru değil, ama ben daha fckeditor' ü tam anlamıyla çözemediğim icin böyle yapıyorum. Buradaki amac upload sırasında serverdaki klasor üzerinde işlem yapabilmemizi sağlamak. Yani upload 'u gerçekleştirebilmek. Ama bu bir güvenlik acıgı olarak görülebilir. O yüzden temkinli davranmak gerekiyor. Nitekim fckeditor ile internette hacklenen siteleri inceleyebilirsiniz. Bu editor icinize sinmezse baska editorler de kullanabilirsiniz. Ozaman neden fckeditor'ü anlatıyorum burda derseniz, cok esnek olması diyebilirim. Gördüğünüz gibi sayfaları tamamen düzenleyebiliyoruz. Bu tarz sorunlar bir sekilde aşılır zaten, içiniz rahat olsun.

Bu işlemlerden sonra projenizi çalıştırırsanız internet explorerda editorunuz görünecektir. Gördüğünüz gibi bir çok özelliği var bu editorun. Sayfanızın görsel tasarımını istediğiniz gibi değiştirebilirsiniz.


Editorü kullanabilmek için gerekli ayarlamalar ve işlemler tam anlamıyla bukadar.

Şimdi bu editorde yapılan değişikliklerin, oluşturulan sayfaların iceriklerinin veritabanına editorden nasıl aktarılacagını anlatacagım. İlk olarak sayfalar.aspx 'e editor dısında birkac kontrol daha ekliyoruz. Bunlardan birincisi bir dropdownlist 'tir. Bu veritabanındaki safyaların başlıklarını gösterecek olan kontroldür. Burdan bir sayfa seçiyoruz, ardından düzenle diyoruz ve icerik oldugu gibi editorde görünüyor. Sonra istediğimiz değişiklikliği yapıyoruz ve kaydet diyoruz ve yapılan tüm değişiklikler veritabanına yazılıyor. İşte bu kadar basit...
Birde sayfanın adını ve id degerini tutan 2 farklı label koyuyoruz.

Sayfa tasarımını aşagıda görebilirsiniz;

sayfalar.aspx.cs ( Kodlar )
--------------------------------

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

using System.Data.OleDb;

public partial class admin_sayfalar : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
Baglan();
}
}

private void Baglan()
{
string constr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + Server.MapPath("../App_Data/dinamik.mdb");

OleDbConnection conn = new OleDbConnection(constr);
OleDbCommand cmd = new OleDbCommand();

cmd.Connection = conn;
cmd.CommandText = "SELECT * FROM tbl_Sayfalar";

OleDbDataAdapter dap = new OleDbDataAdapter();
dap.SelectCommand = cmd;

DataTable dt = new DataTable();

conn.Open();
dap.Fill(dt);
conn.Close();

comboSayfalar.DataTextField = "baslik";
comboSayfalar.DataValueField = "baslik";
comboSayfalar.DataSource = dt;
comboSayfalar.DataBind();
Session["baslik"] = dt.Rows[0]["baslik"].ToString();
Session["id"] = dt.Rows[0]["id"].ToString();
}

protected void btnDuzenle_Click(object sender, EventArgs e)
{
string constr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + Server.MapPath("../App_Data/dinamik.mdb");

OleDbConnection conn = new OleDbConnection(constr);
OleDbCommand cmd = new OleDbCommand();

cmd.Connection = conn;
cmd.CommandText = "SELECT * FROM tbl_Sayfalar WHERE baslik = '" + Session["baslik"].ToString() + "'";

OleDbDataAdapter dap = new OleDbDataAdapter();
dap.SelectCommand = cmd;

DataTable dt = new DataTable();

conn.Open();
dap.Fill(dt);
conn.Close();

fckeditor.Value = dt.Rows[0]["icerik"].ToString();
lblId.Text = dt.Rows[0]["id"].ToString();
lblSayfaAdi.Text = dt.Rows[0]["baslik"].ToString();

Baglan();
}

protected void btnKaydet_Click(object sender, EventArgs e)
{
if (lblId.Text == "")
return;

string constr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + Server.MapPath("../App_Data/dinamik.mdb");

OleDbConnection conn = new OleDbConnection(constr);
OleDbCommand cmd = new OleDbCommand();

cmd.Connection = conn;

cmd.Parameters.AddWithValue("@par_icerik", fckeditor.Value);

Session["mpid"] = comboSayfalar.SelectedIndex;

cmd.CommandText = "UPDATE tbl_Sayfalar SET icerik = @par_icerik WHERE id = " + lblId.Text + "";

conn.Open();
cmd.ExecuteNonQuery();
conn.Close();

Baglan();

comboSayfalar.SelectedIndex = Convert.ToInt32(Session["mpid"].ToString());
}

protected void comboSayfalar_SelectedIndexChanged(object sender, EventArgs e)
{
string baslik = comboSayfalar.SelectedItem.Value;
Session["baslik"] = baslik;

if (Session["baslik"] != null)
{
ListItem item = comboSayfalar.Items.FindByValue(baslik.ToString());
item.Selected = true;
}
}
}



Bu işlemlerden sonra artık tek yapmamız gereken index.aspx 'te secilen menü'ye göre iceriği göstermek. Burda işin püf noktası bir menüye tıklayınca onun bir querystring ile yine aynı sayfayı acması. Bu querystring ile taşınan deger, sql cümlesinde where niteliğine parametre olarak verilince geri dönen kayıt ilgili sayfanın iceriği olacaktır. Bunuda daha önceden koydugumuz label' e Eval ile atamaktır.

index.aspx 'in markup kodları



index.aspx.cs ( Kodlar )
---------------------------
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

using System.Data.OleDb;

public partial class index : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
try
{
Baglan(Convert.ToInt32(Request.QueryString["id"].ToString()));
}
catch (Exception)
{
Baglan(1);
}
}

public void Baglan(int id)
{
string constr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + Server.MapPath("App_Data/dinamik.mdb");

OleDbConnection conn = new OleDbConnection(constr);
OleD