AJAX'tan ilk bahsetmeye başladığımız yıllarda en çok aldığım sorulardan biri
asenkron File Upload işlemi ile ilgiliydi. Asenkron işlem yapabilmek ve sayfanın
Refresh atmaması çok hoş bir durumdu ve bu durumu istemciden sunucuya dosya
yüklerken de yaşayabilmek istiyorduk. Bugünler bu gibi bir sorunu çözmek için
Silverlight kullanmayı tercih etsem de özellikle 2GB'dan ufak dosyaların
yüklenmesi noktasında aslında hala eski taktikler kullanılabilir.
Eminim bazılarınız "Yapılıyor zaten AJAX ile" şeklinde içinden cevap
verecektir. Tabi ki yapılır fakat pek de kolay değil. İnternette bulunan çoğu
çözüm seksen tane ekstra ayar gerektirirken hiçbir ayar gerektirmeden çalışan
ASP.NET FileUpload kontrollerinin çoğu ise ücretli olarak karşımıza çıkıyor.
Kişisel yorumumla geç kalınmış olsa da artık sonunda
AJAX Control Toolkit içerisinde bir FileUpload kontrolü
var!
ASP.NET için asenkron çalışan FileUpload kontrolü!
Her zamanki gibi tüm AJAX Control Toolkit kontrollerinde yaptığımız üzere ilk
olarak Toolkit'in en güncel DLL'ini
sitesinden bilgisayarımıza indiriyor sonra da Visual Studio içerisinde
yarattığımız ASP.NET projesine Reference olarak Toolkit
içerisinde DLL'i ekliyoruz. Eğer sürekli olarak AJAX Control Toolkit
kontrollerini kullanacaksanız Toolbox'a da bu kontrolleri ekleyebilirsiniz.
[ASP.NET]
<%@ Register assembly="AjaxControlToolkit" namespace="AjaxControlToolkit" tagprefix="cc1" %>
Eğer Toolbox'a eklemediyseniz yukarıdaki şekilde Control Toolkit'i
kullanacağınız her sayfada elle gerekli tanımlamaları yapmanız gerekiyor ki
mark-up tarafında bu assembly içerisinde kontrolleri kullanabilelim. Eğer
Toolbox'a kontrolleri eklerseniz zaten sürükle-bırak işlemi ile kontrolü sayfaya
yerleştirebilir hale gelirsiniz. Böylece yukarıdaki kod da otomatik olarak
yaratılır. İtiraf etmek gerekirse ben de otomatik yaratılanı yukarıya
yapıştırdım :)
[Default.aspx]
<%@
Page Language="VB"
AutoEventWireup="false"
CodeFile="Default.aspx.vb"
Inherits="_Default"
%>
<%@
Register assembly="AjaxControlToolkit"
namespace="AjaxControlToolkit"
tagprefix="cc1"
%>
<!DOCTYPE
html PUBLIC
"-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html
xmlns="http://www.w3.org/1999/xhtml">
<head
runat="server">
<title></title>
</head>
<body>
<form id="form1"
runat="server">
<cc1:ToolkitScriptManager ID="ToolkitScriptManager1" runat="server">
</cc1:ToolkitScriptManager>
<div>
<cc1:AsyncFileUpload ID="AsyncFileUpload1" runat="server" />
</div>
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
</form>
</body>
</html>
Yukarıda basit bir ASP.NET sayfasında AsyncFileUpload
kontrolünü bulabilirsiniz. Tabi sayfada ayrıca bir de
ToolkitScriptManager bulunuyor ki Toolkit kontrollerini kullanabilelim.
Son olarak alt tarafta göreceğiniz Label kontrolünü ise sadece
sayfanın Refresh atıp atmadığını kontrol etmek için kullanacağız. Dikkatinizi
çektiyse AsyncFileUpload kontrolü herhangi bir UpdatePanel
içerisinde değil. Zaten normal olanda budur. Fakat eğer isterseniz
AsyncFileUpload kontrolünü bir UpdatePanel içerisinde de rahatlıkla
kullanabilirsiniz. İşlevsellikte herhangi bir değişiklik olmuyor.
[VB]
Partial Class _Default
Inherits System.Web.UI.Page
Protected Sub AsyncFileUpload1_UploadedComplete(ByVal sender As Object, ByVal e As AjaxControlToolkit.AsyncFileUploadEventArgs) Handles AsyncFileUpload1.UploadedComplete
AsyncFileUpload1.SaveAs(MapPath("~/Konum/") & IO.Path.GetFileName(e.filename))
End Sub
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Label1.Text = Date.Now.ToLongTimeString
End Sub
End Class
Yukarıdaki kodun ilk kısmında önemli olan şey AsyncFileUpload
kontrolünün UploadedComplete eventını yakalamak. Adından da
anlaşılacağı üzere Upload işlemi bittiğinde bu event çalışıyor ve biz de
rahatlıkla AsyncFileUpload kontrolünün SaveAs
metodu ile dosyamızı sunucuya kaydedebiliyoruz. Kaydederken de diskteki uygun
bir yolu vermekte fayda var.
Alt kısımda göreceğiniz kod ise sayfa her refresh attığında sayfaya o anki
saat bilgisini saniyesi ile yazdırıyor. Yaptığınız denemede göreceksiniz ki
dosya yüklenmesine rağmen saat bilgisi hiç değişmeyecek. Bu da sayfanın tamamen
refresh atmadığının bir kanıtı.
Animasyon göstermek istersek?
Yükleme işlemi asenkron olsa da kullanıcıya her zamanki AJAX
animasyonlarından birini göstermek çok önemli. Malum zaten AJAX animasyonu
olarak bahsettiğim şey aslında basit ve sürekli aynı animasyonu gösteren bir GIF
dosyasından farklı değil.
 Örnek AJAX Loading animasyonu.
Bu GIF dosyasını bildiğimiz şekilde ASP.NET sayfasına ekledikten sonra
AsyncFileUpload kontrolünün ThrobberID özelliğine Image kontrolümüzün ID'sini
vermemiz yeterli olacaktır.
[Default.aspx]
<%@
Page Language="VB"
AutoEventWireup="false"
CodeFile="Default.aspx.vb"
Inherits="_Default"
%>
<%@
Register assembly="AjaxControlToolkit"
namespace="AjaxControlToolkit"
tagprefix="cc1"
%>
<!DOCTYPE
html PUBLIC
"-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html
xmlns="http://www.w3.org/1999/xhtml">
<head
runat="server">
<title></title>
</head>
<body>
<form id="form1"
runat="server">
<cc1:ToolkitScriptManager
ID="ToolkitScriptManager1"
runat="server">
</cc1:ToolkitScriptManager>
<div>
<asp:Image ImageUrl="~/ajax-loader.gif" ID="Image1" runat="server" />
<cc1:AsyncFileUpload ThrobberID="Image1" ID="AsyncFileUpload1" runat="server" />
</div>
<asp:Label
ID="Label1"
runat="server"
Text="Label"></asp:Label>
</form>
</body>
</html>
Eğer kontrolün tasarımında da hızlı bir değişiklik yapmak isterseniz şimdilik
iki farklı tasarım hazır olarak sizi bekliyor.
 Kontrolde kullanılabilecek hazır iki farklı tasarım var.
Hepinize kolay gelsin.
Bu hafta sonu için sizlere iki ayrı etkinlik duyurum var. Her ikisi de
Ankara'da! Cumartesi günü SQL Kampı
etkinliğimizin Ankara ayağını yapıyoruz, Pazar günü ise benim de konuşmacı
olacağım NedirTV'nin 3. yıldönümü kutlama etkinliği olacak. Her ikisinin de
planını aşağıda bulabilirsiniz.
02.05.2009 / SQL Kampı
09.30-10.30 Silverlight 3.0 ve İş Uygulamaları - Daron Yöndem
10.30-12.00 SQL 2008 Platform ve Development Yenilikleri - Tarık Kranda
13.00-15.00 Index Strategies and Performance Tunning - Pamir Erdem
15.30-17.00 IIS 7 üzerinde PHP ve MSSQL - Muammer Benzeş
03.05.2009 / NedirTV Günü
09:45-11.15 ASP.NET MVC - Uğur Umutluoğlu
11:30-13.00 What is SharePoint? - Burak Batur 14:00-15.30 WCF 4.0 & WF 4.0 - Burak Selim Şenyurt
15:30-16.30 WPF ve MultiTouch Programlama – Daron Yöndem
Her iki etkinlik de Bilkent Üniversitesi'nde gerçekleştirilecek. Merkez Kampüs
Rektörlük Binası Mithat Çoruh Amfi Salonu'nda olacağız. Hepinizi bekliyoruz!
Not: Etkinlik sonrası "Haberimiz olsa gelirdik" diyen her birey saçımdan
bir tel daha kopartıp üzerinde tepinmeme neden oluyor :) O nedenle sizden ricam
etrafınızda bu etkinlik ile ilgilenebilecek herkesi haberdar etmeniz. Görüşmek
üzere...
Bugün tam günlük
NedirTv.com etkinliğindeydik. NedirTv'nin üçüncü yılını kutladığımız bu
etkinlikte ilk olarak Windows 7 oturumumuz oldu. Ayrıca ben de İstanbul'da ilk
olarak MultiPoint programlama anlattım. Sonrasında sevgili Uğur
ASP.NET 3.5,
Burak Selim C# ve Pamir Erdem ise SQL 2008 yenilikleri ile hızlı bir marator
gerçekleştirdik.
 MultiPoint Semineri, İstanbul
Etkinlik epey heyecanlı geçti, özellikle hediyelerimiz ve Windows 7 Beta'lar
ve "Random gerçekten Random mıdır?" tartışması unutulmazlar arasında :)
olsa gerek. Buradan sevgili Uğur'a NedirTV'deki emeği ve sosyal
topluluk olarak INETA tarafına katkısı için çok teşekkür ediyorum. Diğer yandan
tüm diğer NedirTV editörleri ve konuşmacılarımıza da çok teşekkürler ve tabi ki
katılımcılarımız :) sizleri de unutamam. Hepinize sonsuz teşekkürler, umarım
faydalı olmuştur.
 NedirTV 3. Yıl Dönümü, İstanbul
Etkinlikte çekilen tüm fotoğrafları tam çözünürlüklü halleri ile aşağıdaki
adresten bilgisayarınıza indirebilirsiniz ;)
http://cid-8eca4439fd9a640f.skydrive.live.com/browse.aspx/NedirTV%203.%20Yıl%20Dönümü%20İstanbul%20Etkinliği
Blogdan da duyurduğum üzere geçen hafta sonunu Eskişehir'de geçirdik. Yine
çok zevkli bir etkinlikte iki gün boyunca yoğun bir tempo ile birçok konuya
değindik. Silverlight, Oyun Programlama, WPF, LINQ, ASP.NET 3.5
vs derken yoğun bir bombardımanın altında tüm katılımcıların da yüzlerinde
memnuniyetin izlerini görüyor olmak gerçekten çok sevindirici oldu. Umarım
katılan herkes için olabildiğince faydalı ve efektif geçmiştir hafta sonu.
 Osmangazi Üniversitesi, INETA Eskişehir Seminerleri
Aktivitenin organizasyonundaki katkısından dolayı sevgili MSP,
Selim Özenç'e buradan
çok teşekkür ediyorum. Ayrıca beni yalnız bırakmama konusundaki ısrarlı duruşu
ile :) sevgili MSP, Ali
Uğur Çakmak'a da çok teşekkürler. Tabi organizasyonda emeği geçen tüm diğer
arkadaşları da kesinlikle unutmadım, özellikle, büyük ihtimal yakında blogdan da
sizlerle paylaşacağım bir röportaj maceramız oldu ki :) dillere destan.
Eskişehir'e buradan en kısa zamanda tekrar görüşmek üzere diyerek seminerlere
katılan tüm arkadaşlara çok teşekkür ediyorum.
Hafta sonu Eskişehir'deyiz! Osmangazi Üniversitesi Fen Edebiyat Fakültesi (F5 Blok) Konferans Salonu'nda
iki günlük bir program ile zevkli bir hafta sonu geçirmek isteyen herkesi
bekliyoruz. Etkinlik planını aşağıdaki görselde bulabilirsiniz.
 INETA Eskişehir Hit Afişi
Etkinlik serisi tamamen halka açık ve herhangi bir şekilde kayıt olmanız
gerekmiyor. Görüşmek üzere...
Son iki gündür Erzurum, Atatürk Üniversitesi'ndeydim.
Silverlight, WPF, AJAX, LINQ konularına değindiğimiz ikin
günlük bir serinin sonunda minik bir de DreamSpark dağıtımı yaptıktan sonra iki
saatlik gecikme ile uçağıma binip dönüp dolaşım yine :) İstanbul'a döndüm. Oturumlarda şaşkınlık ile
karışık bir tepkisizliğin hakimiyetine karşın aralarda aldığım tepkiler çok
sıcaktı. Anadolu'daki üniversitelerin havası gerçekten çok farklı, Erzurum'da da
bunu yaşadım. Gençlerin gözlerindeki ışıltı ve kaba tabiri ile doğu
bölgelerindeki bu gibi etkinliklere yönelik ihtiyacın tam olarak giderilememesi tezatı beni gerçekten üzüyor. Olanaklar el verdikçe Anadolu üniversitelerine
gidiş sevdamı ben de bu şekilde tatmin etmeye çalışıyorum :)
 Erzurum, Atatürk Üniversitesi Seminerlerim
Tabi ki yine teşekkür etmem gereken onlarca dost var Erzurum'dan.
Yüksel hocama ve afacana buradan selamlarımı gönderdikten sonra :)
öğrenci kardeşlerimden de Mehmet Keklik'e etkinliğe vesile
olması ve organizasyondaki katkısı için çok teşekkür ediyorum. Umarım seneye
taptaze ve daha dolu bir etkinlik ile tekrar buluşuruz ;)
Son iki gündür sevgili
Uğur Umutluoğlu ile Ankara, Bilkent Üniversitesi'ndeyiz. Toplam iki gün
süren ve 6 oturumdan oluşan bir seri ile birçok konuya değindik. WPF,
WCF, LINQ, C# 3.0, Silverlight, ASP.NET 3.5 SP1 başlıklarına sahip
oturumların hepsinde de muhteşem ilgili bir kitle bulunduğunu itiraf etmeliyiz.
 Bilkent Üniversitesi, Ankara, Silverlight Oturumum
Oturumlarımızdan birini de LAB çalışması olarak gerçekleştirdik ve
Silverlight seminerinde öğrendiklerimizi Silverlight ile bir oyun geliştirerek
pekiştirdik. LAB çalışması benim neredeyse etkinlik içerisinde en sevdiğim bölüm
oldu. "Üretmenin" zevkini herkesin gözlerinde gördüm.
 Silverlight Lab Çalışması
Buradan teşekkür etmem gereken o kadar çok kişi var ki :) Sevgili MSP'lerimiz
Ali Uğur Çakmak,
Alper Özçetin'a çok
teşekkürler. Ayrıca BTS ve ACM'deki herkese teşekkürler. Süper bir hafta sonu
geçirdim, "dayının yeri"ni hala unutamıyorum :)
Bu hafta sonu INETA Professional Hit etkinliğimizi
gerçekleştirdik. Kayıt alımındaki sorunlara karşın etkinlik boyunca gelen olumlu
tepkiler epeyce moralimi düzeltti. Level 300 hedefi ile yola çıksak da maalesef
beni dinlemeyip :) oturumlardaki konularla ilgili hiç çalışmamış arkadaşlar da
geldi! Umarım bir sonraki Level 300 etkinliğimizin seviyesi ile ilgili biraz da
olsa fikir oluşmuştur kafalarda. Özellikle benim Silverlight oturumunda salonun
yarısının hiç Silverlight ile ilgilenmemiş olması Level 300 seviyelerine
çıkmamızı engelledi diyebilirim.
 INETA Professional Hit İlk Gün
Neyse :) Bu her açıdan bir "ilk"ti ve hepimiz Level 300 seminerlerle ilgili
bir şeyler öğrendik. Bir dahakinin daha verimli olması için bazı notlar da aldık
kenara. Şimdi sıra geldi artık fotoğrafları :) ve örnek kodlar ile sunumları
sizlerle paylaşmaya.
http://cid-8eca4439fd9a640f.skydrive.live.com/browse.aspx/INETA%20Professional%20Hit%20012009
Yukarıdaki adresten tüm fotoğrafları orijinal çözünürlükleri ile
indirebilirsiniz. Ayrıca yukarıdaki adreste bir de Ozel.rar dosyası göreceksiniz
:) O dosya içerisinden de kişisel çekilmiş fotoğraflar var.
 INETA Professional Hit 2. Gün
Son olarak aşağıdaki download linklerinden de her oturumla ilgili örnekleri
ve sunumları indirebilirsiniz.
28012009_ADONET.rar (1,13 MB)
28012009_AJAX.rar (75 KB)
28012009_CSHARP.rar (551,66 KB)
28012009_LifeCycle.rar (126,8 KB)
28012009_Silverlight.rar (672,98 KB)
Katılan herkese çok teşekkürler. Bir başka aktivitede görüşmek üzere ;)
Uzun bir aradan sonra tekrar İstanbul'da güzel bir etkinlik ile
karşınızdayız. Ankara ve İzmir derken biraz İstanbul'u boşladığımızı kabul
ediyorum. Ama önümüzdeki dönemde bolca telafilerimiz olacak. Gelelim konumuza;
INETA Professional Hit!
İki günlük bir etkinlik dizisi ile bu sefer Microsoft binasında buluşuyoruz.
Fakat farklı bir şeyler var! Türkiye'de ilk defa tamamen Level 300 ve üstü
oturumlardan oluşan halka açık bir aktivite yapıyoruz. Gelin bu konuyu biraz
açıklığa kavuşturalım ve şu Level konusuna göz atalım.
- Level 100: Bahsi geçen konuya giriş ve genel anlatım
içerir. Katılımcıların oturumun konusu ile ilgili herhangi bir bilgi
birikimine sahip olmadıkları ön görülür.
- Level 200: Level 100 bilgisine sahip olunduğunu ve buna
ek olarak anlatılacak konu ile ilgili genel bir bilgi birikiminin
katılımcılarda olduğu var sayılır. Genelde bu oturumlarda anlatılan
teknolojilerin detayları ve kullanım alanları ile ilgili gerçek hayat
senaryoları işlenir.
- Level 300: Anlatılacak konu ile ilgili Level 200
bilgisine sahip olunduğu düşünülür. Bu oturumlarda bahsi geçen
teknolojilerin uç noktada kullanımına dair örnekler derinlemesine işlenir.
- Level 400: Bu oturumlar uzmanından uzmanına
oturumlardır. Anlatılan teknoloji ile ilgili en gelişmiş ve üst seviyeli
bilginin aktarıldığı bu oturumlar ürünlerin üst sınırlarını zorlayan
oturumlardır.
Gördüğünüz gibi normal şartlarda bizim INETA tarafındaki etkinliklerimiz
ağırlıklı olarak Level 100 ile Level 200 arasında dolaşıyor. Genel olarak
baktığımızda bu seviyenin üzerinde etkinliklerin eksikliğini sizler de
değerlendirme formlarında defalarca dile getirdiniz. INETA Professional Hit
tamamen uzmanlara hitap eden Level 300 ve Level 400 oturumlar içeriyor. Bu
kapsamda giriş seviyesi bir beklenti ile etkinliğe gelmemekte fayda var. Giriş
seviyesi için yakın zamanda bir etkinliğimiz daha olacak.
Program içeriğimiz ve oturumların seviyeleri şu şekilde;
24 Ocak
10.00-12.30 Silverlight ile Veri Uygulamaları -
Daron Yöndem - Level 300
13.00-16.00 ADO.NET Data Services -
Burak Selim Şenyurt - Level 300
16.30-18.00 SharePoint üzerinde özel kolon geliştirmek -
Nezih Tınas - Level 400
25 Ocak
10.00-12.30 Derinlerde C# 3.0 -
Burak Selim Şenyurt - Level 300
13.00-15.00 ASP.NET AJAX 4.0 -
Daron Yöndem - Level 300 15.30-18.00 Asp.Net Application ve Page LifeCycle
- Oğuz Yağmur - Level 300
Etkinlik Microsoft İstanbul ofisinde olacak. Adres şu şekilde; Bellevue Residence, Levent Mahallesi
Aydin Sokak, No: 7
Levent
Etkinliğe katılabilmeniz için aşağıdaki adresten kayıt olmanız gerekiyor.
http://daron.yondem.com/kayit/
Çok yakında giriş seviyesi etkinliklerde de görüşmek üzere.
Bu hafta sonu İzmir'deydik. Daha önce sizlere duyurmuş olduğum
INETA EGE HIT etkinliğini Dokuz Eylül Üniversitesi'nde gerçekleştirdik.
Katılımcı profili gerçekten muhteşemdi, hem Cumartesi hem de Pazar günü en ufak
bir oturumu bile kaçırmayın daimi bir kitlemiz vardı :) Benim için çok eğlenceli
ve sevindirici oldu diyebilirim. Her oturumda aldığım tepkiler çok güzeldi.
 INETA
Ege Hit başlangıcı.
Her zamanki gibi iki de anekdot yarattık; birincisi benim gülen surat
çizimimi görüp animasyon olarak "yağmur yağsın ve şemsiye açılsın" diyen
arkadaşımızdı :) Dikkatinizi çekerim gülen suratın ne yağmur ne de şemsiye ile
alakası yok ayrıca İzmir'de yağmur falan da yapmıyordu :) Her neyse... İkinci
anekdot ise buradan paylaşamayacağım hatta sanırım ömür boyu hiç
paylaşamayacağım bir şey :) Üzgünüm...
 INETA
Ege Hit sonu...
Organizasyondaki katkılarından dolayı sevgili İzmir MSP'lerimize buradan ÇOK
teşekkür ediyorum. Sevgili
Buğra, Murat,
Gülşah ve
Okan'a çok
teşekkürler. Etkinlik boyunca çekilen resimlerin orijinal boyutlu hallerine
buradan ulaşabilirsiniz. Ayrıca tüm oturumlardaki örneklere ait kodları da
aşağıdaki linkten bilgisayarınıza indirebilirsiniz.
Oturumlardaki örnek projeler - 11012009.rar (5,11 MB)
Yeni yılda hayatınızı kolaylaştırma yolunda iddialıyım :) Bu sefer de benim
işimi çok kolaylaştıran bir aracı sizlerle paylaşacağım.
Visual Studio içerisinde F5'e bastığımızda System Tray'de beliren "ASP.NET Development Server"'ı hatırlarsınız. Aslında adı "Cassini" olan bu server
işimizi epeyce kolaylaştırır ve bizim her sererinde IIS'te sitemizi veya
uygulamamızı ayarlamamızı gerektirmeden uygulamanın sanal bir sunucu ortamında
test edilmesini sağlar.
Peki hiç herhangi bir projenizi doğrudan çalıştırıp görmek istediğinizde
mecburen Visual Studio ile açıp F5'e bastığınız oldu mu? :) Veya mecburen IIS'te
web site ayarlamak zorunda kaldınız mı? sadece sitenizi çalıştırabilmek için?
İşte bu işkence aslında sürekli yaşadığımız bir süreç ve çok kolay bir çözümü
var. Biz de Visual Studio gibi gidip Cassini'yi kullanabiliriz.
Aslında Cassini bizim bilgisayarlarımızda WebDev.WebServer.exe
olarak yüklü bulunuyor. Tabi ki EXE'yi doğrudan alıp taşıyamazsınız, çok sayıda
bağlantılı DLL vs de söz konusu. Ama biz bu EXE'ye doğru parametreleri
gönderirsek aynı Visual Studio'nun kullandığı gibi herhangi bir klasördeki
dosyaları web sunucudaymış gibi çalıştırabiliyor. Bu EXE'nin nasıl
kullanıldığını merak edenleri veya birazdan sizlerle tanıştıracağım uygulamanın
nasıl yazıldığını merak edenleri İngilizce blogumdaki
bir yazıya davet edebilirim :)
 Sağ tıkla sunucudaaymış gibi çalıştır!
Gelelim sadede... Infragistics'te çalışan J. Ambrose Little tüm bunları yaparak uygulamayı da bir SETUP paketi şeklinde hazırlamış ve bununla da kalmamış ve bu sistemi işletim sisteminin context menü'süne bağlamış. Yani özetle; herhangi bir klasöre sağ tıklayıp "ASP.NET 2.0 Web Server Here" dediğizde Cassini açılıyor ve söz konusu klasör içerisindeki uygulama server üzerinden çalıştırılıyormuş gibi karşınıza çıkıyor. Aynı Visual Studio'da F5'e basmış gibi :)
Uygulamayı aşağıdaki linkten bilgisayarınıza indirip yükleyebilirsiniz.
Cassini Web Server Launcher - 02012009_1.msi (355 KB)
ASP.NET 2.0 dediğine bakmayın 3.5 SP1 ile herhangi bir sorunu yok.
Hepinize kolay gelsin...
Bu aralar birçok yazıma "gelen maillerde de sürekli istediğiniz gibi" şeklinde cümlelerle başladığımı görünce aslında bir süredir sizden gelen istekleri yerine getirmekle uğraştığımın farkına vardım :) İşte bu yazımda da böyle bir konu söz konusu. Bana gelen maillerde benden AJAX anlatmamı isteyenler oluyor ve neden ajax semineri vermediğimi soranların sayısı epey fazla. Aslında tam olarak kesin bir cevabı yok bu sorunun. Sanırım AJAX kelimesinin pazarlama anlamında tükettiğimiz içindir! Bu tüketimin sonucunda o kadar çok "AJAX AJAX" denilen dönemler yaşadık ki sanki herkes AJAX'ı yuttu ve biliyor gibi bir izlenim oluştu ki bu tamamen YANLIŞ!
Maalesef kimse AJAX falan bilmiyor! UpdatePanel kullanmanın bile herşeyiyle bilinmediğini iddia edebilirim ki UpdatePanel'in AJAX dünyasında yeri cidden komiktir. O nedenle ben de bir süre önce bir
AJAX seminer ayarladım ve semineri videoya kaydettim. Şimdi sizinle bu video yu paylaşıyorum.
Video tabi ki giriş seviyesi, daha anlatmak istediğim çok şey var. Umarım bir gün
İleri AJAX semineri verme şansım da olur, böylece onun da videosunu buradan sizinle paylaşırım.
Yukarıdaki videoyu bilgisayarına indirmek isteyenler
blogumun
SeminerTV bölümünden bunu yapabilirler ;)
İyi seyirler...
Bugün sabahtan Bursa Uludağ Üniversitesi'ndeydim. Hazır Microsoft'un Gençsen
Geleceksin etkinliği için gitmişken üniversiteye biraz daha erken gidiyim ve
arada bir de ASP.NET 3.5 AJAX semineri yapalım dedim. Yaklaşık sanırım 2.5 saat
süren bir AJAX semineri sonrasında Gençsen Geleceksin kısmını da tamamlayarak
Uludağ Üniversitesi'nden ayrıldım.
 Uludağ Üniversitesi, Bursa
Aslında bu AJAX seminerini yapmamın özel bir nedeni var. AJAX biraz eskimiş
bir terim olarak gözükse de işin gerçeği Türkiye'de AJAX'ı ve özellikle
Microsoft'un AJAX Framework'ünün detaylarını bilen kişi sayısı hala ciddi
şekilde kısıtlı. Herkes UpdatePanel'den ötesini bilmiyor. Bu derdime ek olarak
bir de arada sırada aldığım "Hocam niye AJAX anlatmıyorsunuz?" maillerini de
katarsak ortaya Uludağ Üniversitesi'ndeki AJAX seminerim çıktı. 2.5 saatte
herşeyi anlatabildim diyemem, seminerin sonuna doğru bazı şeyleri hızlı geçmem
gerekti ama en azından güzel bir giriş oldu. Tabi ki seminerin tamamını videoya
da kaydettik ve yakında sizlerle blogumun SeminerTV bölümünden paylaşacağım.
Böylece artık mail atmadan AJAX seminerimi webden izleyebileceksiniz.
Uludağ Üniversitesi'ndeki organizasyonlardaki katkısından dolayı özellikle
sevgili Muhammed Medeni Baykal kardeşime buradan çok teşekkür ediyorum.
Evet biliyorum daha organizasyona katkısı olan bir çok kardeşim var :) onları da
buradan kucaklıyor ve çıkışta İskender yemeye gelmedikleri için kınıyorum :)
Son üç gündür Isparta, Süleyman Demirel Üniversitesi'ndeydim. Cumartesi günü
başladığımız INETA Boot Camp Isparta etkinliğimizde
LINQ ve WCF konularını işledik. Pazar günü
Microsoft'un Oyun Turu'nun da Isparta ayağını kampımıza ekleyerek dün de
bahsettiğim gibi SL 2.0 ile ve XNA ile Oyun Programlama konularını inceledik.
Son günümüz olan Pazartesi günü de ASP.NET Dynamic Data Web Site
yapılarını göz attık sonra "Silverlight 2.0 ile Data Uygulamaları"
ve "WPF" oturumlarımızı tamamladık. Böylece dolu dolu bir üç
gün geçirdik.
 Isparta, Süleyman Demirel Üniversitesi, INETA Boot Camp
Etkinliklere katılan hem konuşmacı arkadaşlarıma hem de sevgili öğrenci
kardeşlerime çok teşekkür ediyorum. Geçen öğretim yılında da Süleyman Demirel
Üniversitesi'nde gittiğimde blogumda yazmıştım hatta dün de yazmışım :) SDÜ'nün
yeri benim için çok ayrı. Yukarıda resimde gördüğünüz tüm öğrencilerin
Silverlight ve WPF konulu ödevleri var. Hepsi giriş seviyesini çoktan geçmiş
durumda. Bu duruma tabi ki öğretim görevlilerinin katkısı çok büyük.
Özellikle organizasyonun gerçekleşmesindeki katkılarından dolayı sevgili Eğitim Görevlisi dostum
Mehmet Albayrak'a çok teşekkür ediyorum.
Son gün yaptığımız bazı örnekleri toparlayıp bir poşete koydum :) aşağıdaki
linkten indirebilirsiniz.
Örneklere ait kaynak dosyalar - 01122008_2.rar (2,81 MB)
Bugün Afyon Kocatepe Üniversitesi'ndeydim. Sabahtan
başlayarak Silverlight 2.0, WPF, LINQ ve ASP.NET
Dynamic Data konularına değinerek zevkli bir gün geçirdik. Günün
sonunda tadına vardığım Afyon kaymağı ve ekmek kadayıfı süper ikilisi aslında
neredeyse oturumları uzatarak Afyon'a yerleşmeme bile sebep olacaktı :)
 Kocatepe Üniversitesi 2. Bilişim Günleri oturumlarımın sonundan bir kare.
Aktivite boyunca yardımlarından dolayı teşekkür etmem gereken o kadar çok
kişi var ki kesinlikle atladığım kardeşlerim olacaktır. İster üniversite
dahilinde öğretim görevlisi olsun ister öğrenci olsun aktivitede emeği geçen
herkese ve tabi ki tüm katılımcılara çok teşekkürler. Muhteşem bir aktiviteydi.
Organizasyondaki katkılarından dolayı sevgili Sadık Oral'a
özellikle teşekkür ediyorum.

Rektör Yardımcısı Prof. Dr. Belkıs Özkara - Daron Yöndem
Bugün Microsoft Ankara ofisinde hosting sağlayıcılara
yönelik bir eğitimimiz var. IIS 7 ile beraber gelen yeni özelliklerin yanı sıra
ASP.NET 3.5 ve programcıların dertlerinden bahsettik. Tabi hosting
sağlayıcılarımız da dertleri vardı. Programcıların hatalarından kaynaklanan bazı
sorunlar yüzünden hosting sağlayıcıların müşteri ile uğraşmak zorunda kaldığı
derdi de aslında bir gerçek :)
 Microsoft Ankara hosting sağlayıcılar eğitimi.
Eğitimde kullandığım sunumu aşağıdan indirebilirsiniz.
IIS 7 ve ASP.NET 3.5 sunumu - 09112008_1.pptx (206,66 KB)
Hepinize kolay gelsin.
.NET 3.5 SP1 ile beraber gelen Dynamic Data Web Site yapısı
ile beraber doğrudan sadece veri üzerinde çalışan web uygulamaları yazmanın
gerçekten kolaylaştığını itiraf edebiliriz. Fakat her yeni araç gibi Dynamic
Data ile beraber de istediklerimizi yapabilmek için kendine özgü özelleştirme
kurallarını bilmemiz gerek. Bu yazıda elimizde hazır bir Dynamic Data
Web Site olacak ve bu web sitesinde gösterilen veritabanındaki bazı
tablolardaki bazı sütunların gösterim esnasındaki özelleştirmelerine
değineceğiz. Cevaplayacağımız sorulardan bazıları şunlar olacak;
- Belirli bir tablonun sadece bir sütununun görünmemesini nasıl sağlarım?
- İstediğim bir sütunun istediğim değerleri almasını nasıl sağlarım?
Yazımızda kullanacağımız örnek siteyi yaratmak için
buradaki yazıyı inceleyebilirsiniz.
MetaData üzerinden ayarlamalar...
Dynamic Data yapısına baktığımızda olabildiğince her şeyin otomatik
ilerlediğini görüyoruz. Örneğin bir tablonun içerisindeki tüm sütunlar otomatik
olarak söz konusu tablo ile beraber tüm sayfalarda düzenlenebilir şekilde
gözükmeye başlıyor. Sütunlarla ilgili tek tek ayar yapmanın tek yolu söz konusu
sütunlara ek MetaData bilgileri vermek. Peki bizim sütunlarımızı kodumuzla kim
tanımlıyor?
Biz projemizde LINQ2SQL kullanarak ilerlediğimiz için veritabanındaki her bir
nesneyi tanımlayan objeler LINQ'e ait DBML'in arkasında tanımlanmış durumda. Bir
DBML dosyasının arkasına baktığınızda designer.vb veya
designer.cs uzantılı dosyalar görebilirsiniz. Bu dosyalar içerisinde
veritabanındaki tüm nesnelerin birer kopyası .NET nesneleri olarak
yaratılmıştır.
[VB]
<Table(Name:="dbo.Urunler")> _
Partial Public Class Urunler
Implements System.ComponentModel.INotifyPropertyChanging, System.ComponentModel.INotifyPropertyChanged
[C#]
[Table(Name="dbo.Urunler")]
public partial class Urunler : INotifyPropertyChanging, INotifyPropertyChanged
{
Yukarıda gördüğünüz şekilde başlayan Urunler adındaki Class
DBML dosyasının arkasında duruyor ve bizim her bir ürünümüzü tanımlıyor.
Maalesef bu designer dosyalarında değişiklik yapamıyoruz. Aslında değişiklik
yapabilirsiniz fakat DBML dosyasında Visual Studio arayüzündeki tasarım araçları
ile yaptığınız her işlem bu dosyaların sistem tarafından tekrar yaratılmasına
neden olacağı için kullanıcı tarafından yapılan tüm kod değişiklikleri
kaybolacaktır. Peki bu durumu nasıl çözeceğiz? Dikkat ettiyseniz tüm bu sınıflar
Partial olarak tanımlanmıştır yani bir başka bir dosyada tekrar
Partial birer sınıf yaratarak işlemlerimize devam edebiliriz.
Bu durumda buyurun yeni bir VB/CS dosyası oluşturalım ve Partial
olarak aynı sınıftan bir adet daha yaratalım.
[VB]
<ComponentModel.DataAnnotations.MetadataType(GetType(UrunlerMeta))> _
Partial Public Class Urunler
End Class
[C#]
[System.ComponentModel.DataAnnotations.MetadataType(typeof(UrunlerMeta))]
public partial class Urunler
{
}
Yukarıdaki koda baktığınızda özellikle en üstteki MedadataType
işaretleri dikkatinizi çekecektir. Aslında bu da bir MetaData fakat maalesef bu
şekilde Partial sınıflara doğrudan MetaData
veremiyoruz. O nedenle başka bir sınıf yaratarak MetaData'ları orada tutacağız
ve o sınıftan MedaData'ları bu tarafa aktaracağız. Kodumuz içerisinde
UrunlerMeta olarak geçen obje aslında başka bir sınıfın adı.
[VB]
Public Class UrunlerMeta
Private _Fiyati As Object
<ComponentModel.DataAnnotations.Range(10, 20, errormessage:="Hata!")> _
Public Property
Fiyati() As Object
Get
Return _Fiyati
End Get
Set(ByVal value As Object)
_Fiyati = value
End Set
End Property
End Class
[C#]
public class UrunlerMeta
{
[System.ComponentModel.DataAnnotations.Range(10, 20, ErrorMessage = "Hata!")]
public object Fiyati { get; set; }
}
UrunlerMeta sınıfı içerisinde sadece Fiyati
adında bir Property var. Aslında ana Urunler
sınıfındaki tüm Property'leri burada da tanımlayarak kullanabilirdik fakat
şimdilik bize Fiyati Property'si yeterli.
ComponentModel.DataAnnotations altından Range sınıfını
kullanarak Fiyati değerinin 10 ile 20 arasında olmak zorunda
olduğunu ve bu durumun sağlanmaması halinde de hata olarak "Hata!"
yazısının gösterilmesi gerektiğini belirtiyoruz. Gelin bu kodun bir de web
sitesindeki yansımasına göz atalım.
 Range sınıfı ile yaptığımız ayarlamalar arayüzde kendini gösteriyor.
Başka neler yapabiliriz?
MetaData'lar üzerinden başka neler yapılabileceği ile ilgili çok sayıda
farklı senaryo mevcut fakat en basit örnekleri inceleyebilmek için kabaca
ComponentModel.DataAnnotations sınıfına göz atmak yeterli olacaktır.
Örneğin aşağıdaki gibi bir kod istediğiniz bir kolonun web sitesinde
gösterilmemesini sağlayabilir.
[VB]
<ComponentModel.DataAnnotations.ScaffoldColumn(False)> _
[C#]
[System.ComponentModel.DataAnnotations.ScaffoldColumn(false)]
Peki ya diğer seçenekler? Gelin hızlı bir tur atalım.
DisplayColumn
Bu özellik toplam en fazla üç parametre alabilir. Amacı tablolar arası
ilişkilendirmelerde kullanıcının gördüğü metinleri değiştirmektir. Örneğin bizim
projemizde ürünlere bağlı olan kategorilerin adları otomatik olarak her üründe
gösteriliyor. Sistem aslında arka planda Kategoriler tablosunda
ID(PK) kolonundan sonra karşılaştığı ilk String kolonu alarak göstermeye göre
ayarlı. Oysa bazı durumlar FK'in bağlı olduğu tablodan alınması gereken ve
gösterilecek olan metin çok daha ileride farklı bir sütunda olabilir. İşte
DisplayColumn bunu ayarlıyor ve bir FK durumunda ana tablodan
hangi sütunun bu üründe gösterilmesi gerektiğine karar veriyor. Bunun haricinde
aldığı iki diğer parametrenin ilki hangi kolon üzerinden Sorting
yapılabileceği ve üçüncü parametre ise Sorting işleminin ilk açılışında hangi
yönde yapılacağı verisini taşıyor.
RegularExpression
Kendisine ilk parametre olarak verilen RegEx desenini hedef kolona test eden
ve uyuşmaması durumunda da ikinci parametre olarak verilen hata mesajının
gösterilmesini sağlayan bir Validation sisteminin entegrasyonuna yönelik olarak
kullanılabilir.
Required
Sadece tek bir parametresi vardır; eşleştirildiği sütun için veri girilmez
ise gösterilmesi gereken hata mesajını String olarak alır.
ScaffoldTable
Tablo sınıflarına doğrudan verilebilen bu MetaData ile bir tablonun web
sitesi görselliğinde gösterilip gösterilmeyeceğini belirler.
StringLength
Bir sütuna girilebilecek maksimum metin uzunluğu ilk parametresi olarak alır.
İkinci parametresinde ise söz konusu uzunluk aşıldığında gösterilecek olan hata
mesajını saklar.
Sonuç
Yazı boyunda Annotation'lar içerisinde atladığım bazı seçenekler oldu. Bu
seçenekleri ileriki yazılarda daha detaylı olarak incelememiz gerektiği için
şimdilik yüzeysel olarak geçmek istemedim.
Hepinize kolay gelsin.
Hafta sonunu Ankara'da geçirdik. Neden mi?
INETA Capital Hit zamanıydı! Atladık INETA minibüsümüze :) yollara düştük.
Maceralarımızla ilgili videolar ve fotoğraflar çok yakında bu blogda :)
İki kocaman gün boyunca dopdolu bir programla Çankaya Üniversitesi'nde
iki yüz elli kişilik bir ekip olarak yattık kalktık diyebilirim. Yine her zamanki gibi benim için muhteşem zevkliydi.
 Pazar akşamı saat yedide Capital Hit'i sonlandırdık.
Aktiviteye katılan tüm konuşmacı dostlarıma binlerce teşekkür. Ayrıca Çankaya
Üniversitesi Bilişim Kulübü ve sevgili MSP, Çağrı Erdoğan'a da çok teşekkürler.
Bir organizasyonda ancak bu kadar başarılı bir misafirperverlik
sergilenebilirdi.
Tabi ki her şey bu kadarla bitmiyor! Elimde birçok fotoğraf, minibüs
yolculuğumuzdan videolar ve panel kaydımız var. Hepsini büyük bir hızla
hazırlamaya çalışıyorum. En kısa zamanda sizlerle buradan paylaşacağım.
Şimdilik aşağıdaki sunumlarla idare edelim :)
AdoNet Data Services / Burak Selim Şenyurt - 20102008_1.pptx (1,01 MB) LINQ / Uğur Umutluoğlu - 20102008_2.pptx (750,29 KB) WCF / Burak Selim Şenyurt - 20102008_3.pptx (460,14 KB)
Not: Bu sefer ben hiç sunum kullanmadım, doğrudan demolarla ilerledim. O
nedenle sunum paylaşamıyorum.
Bir
önceki yazımda yeni bir Dynamic Data Web Site'ın nasıl oluşturulabileceğine
göz atmıştık. Aynı proje üzerinden devam ederek Dynamic Data Web Site'larda
otomatik olarak karşımıza çıkan sayfaların yapılarını, nerelerden geldiklerini
ve yönlendirme sistemlerini inceleyeceğiz.
Tamamen boş, yeni bir Dynamic Data Web Site yarattığınızda aslında Visual
Studio sizin için birçok gerekli dosyayı projenize otomatik olarak ekliyor. Tüm
bu otomatik eklenen dosyalar proje içerisinde DynamicData adında bir klasörün
altında saklı.
 DynamicData klasöründeki SAKLI GÜÇ
Dynamic Data klasöründeki farklı yapıların amaçlarını hızlıca açıklayalım.
Content klasörü altındaki içerik genelde diğer UserControl ve
sayfalarda kullanılan içeriği taşır. Bu klasörde resimler veya harici
UserControll'ler bulunabilir. Varsayılan ayarlarla gelen iki UserControl'den
biri olan FilterUserControl bizim örneğimizde Kategorilerin
filtreleme amaçlı olarak kullanıldığı yerlerde nasıl gözükeceğini ve
çalışacağını belirler. FilterUserControl.ascx'in içindeki kod
baktığımızda aşağıdaki manzara ile karşılaşıyoruz.
<%@ Control Language="VB" CodeFile="FilterUserControl.ascx.vb" Inherits="FilterUserControl" %>
<asp:DropDownList ID="DropDownList1" runat="server" AutoPostBack="true" EnableViewState="true" CssClass="droplist">
<asp:ListItem Text="All" Value="" />
</asp:DropDownList>
Bu kodda gördüğünüz DropDownList'i farklı bir kontrol ile değiştirirseniz
doğrudan tüm proje içerisinde Filtreleme işlemlerinde bu kontrol
kullanılacaktır. Sanırım yavaş yavaş Dynamic Data Web Site yapısının
avantajlarını da hissetmeye başladık. Tabi bu gibi özelleştirme konularının
detaylarına ileride daha derinlemesine gireceğiz.
DynamicData klasörümüzün içeriğine geri dönmek gerekirse sırada
FieldTemplates klasörü vardı. Hatırlarsanız bir önceki makalemizde
veritabanındaki tabloların Field'lerinin veri tipine göre farklı kontrollerin
sahneye geldiğini görmüştük. Yerine göre MultiLine bir Textbox veya
Chechbox gelebiliyordu. İşte FieldTemplates klasörü altında farklı veri
tiplerine için sahneye gelecek olan UserControl'ler bulunuyor. Örneğin
Boolean.ascx'i açarak karşımıza bir Checkbox gelecektir.
<%@ Control Language="VB" CodeFile="Boolean.ascx.vb" Inherits="BooleanField" %>
<asp:CheckBox runat="server" ID="CheckBox1" Enabled="false" />
Yine bu dosya içerisinde yapılan herhangi bir değişiklik tüm projede Boolean
Field'lerin gösteriminde etkili olacaktır.
Son olarak bizi yakından ilgilendiren klasörlerden biri de
PageTemplates klasörü. Bu klasör içerisinde veri kaynağımızdaki tüm
tablolarla dinamik olarak çalışabilecek şekilde hazırlanmış ve CRUD işlemlerini
yapmayı hedefleyen farklı ASPX sayfaları bulunuyor. Bu sayfalar bizim
örneğimizde de hem Kategoriler hem de Ürünler tablosunu düzenlerken
kullanılıyordu.
 Dynamic Data Web Site'ın URL yapısı.
Yukarıdaki ekran görüntüsünde de görebileceğiniz gibi Kategorilers adındaki
LINQ serisini düzenlerken düzenlediğimiz tablonun / nesnelerin adı URL
içerisinde belirdikten sonra doğrudan List.aspx adında bir
dosya çağrılıyor. Bu dosya hali hazırda PageTemplates
içerisinde bulunan dosyanın ta kendisi. Bunun gibi Edit
düğmesine tıkladığımızda da Edit.aspx ve tüm diğerleri de uygun
işlemlerde tablo isminin ardından geliyorlar. Tabi ki
URLRewriting'den bahsediyoruz ama konumuz o olmadığı için detaylara
girmeyeceğim.
PageTemplates içerisinde herhangi bir dosyanın görselliğini veya yapısını
değiştirdiğiniz anda projenizdeki tüm tablolarla ilgili işlemlerde gözükür hale
gelecektir. Unutmayın tüm tablolar için bu dosyalar kullanılıyor. Peki bu durumu
nasıl değiştirebiliriz?
Farklı tablolara farklı sayfalar?
Aslında tüm bu yönlendirme işlemlerinin yapıldığı yer projenin Global.asax
dosyası. Global.asax içerisinde kodlar tabloların ne şekilde hangi dosyalarla
işlem yapacağına karar veriyor.
[VB]
routes.Add(New DynamicDataRoute("{table}/{action}.aspx") With { _
.Constraints = New RouteValueDictionary(New With {.Action = "List|Details|Edit|Insert"}), _
.Model = model})
[C#]
routes.Add(new DynamicDataRoute("{table}/{action}.aspx") {
Constraints = new RouteValueDictionary(new { action = "List|Details|Edit|Insert" }),
Model = model
});
Yukarıdaki gördüğünüz kod Global.asax içerisinde hazır olarak bulunuyor ve
List, Details, Edit, Insert işlemlerinin hepsini tablo adı / aksiyon adı
.aspx şeklinde yönlendiriyor. Aslında Dynamic Web Site yapısına gelen
bir diğer özellik de tüm bu CRUD işlemlerinin tek bir sayfada yapılacak şekilde
düzenlenmesi. Yani verileri ekleme, çıkarma ve düzenleme işlemlerinin hepsini
tek bir sayfada halledebilecek şekilde hazırlanmış bir şablon da DynamicData
klasöründeki PageTemplates içerisinde duruyor : ListDetails.aspx.
Bu dosya içerisindeki bir GridView Inline Editin sağlarken DetailsView'de
detayların gösterilmesi ve yeni kayıt eklenmesini sağlıyor. Peki yönlendirmeyi
nasıl değiştirebiliriz? Bu işlemin kodu de Global.asax içerisinde pasif bir
şekilde duruyor. Tek yapmanız gereken yukarıdaki kodu pasif hale alıp aşağıdaki
aktif hale getirmek.
[VB]
routes.Add(New DynamicDataRoute("{table}/ListDetails.aspx") With { _
.Action = PageAction.List, _
.ViewName = "ListDetails", _
.Model = model})
routes.Add(New DynamicDataRoute("{table}/ListDetails.aspx") With { _
.Action = PageAction.Details, _
.ViewName = "ListDetails", _
.Model = mod
[C#]
routes.Add(new DynamicDataRoute("{table}/ListDetails.aspx")
{
Action = PageAction.List,
ViewName = "ListDetails",
Model = model
});
routes.Add(new DynamicDataRoute("{table}/ListDetails.aspx")
{
Action = PageAction.Details,
ViewName = "ListDetails",
Model = model
});
Kodlarda da yer aldığı üzere toplam iki yönlendirme yapıyoruz. Birincisi "List"
işleminin tablo adı / ListDetails.aspx sayfasında yapılacağı
ile ilgili diğer ise Details görünümünün de aynı şekilde
yapılacağı ile ilgili. Edit ve Insert işlemlerini yönlendirmemize gerek yok
çünkü zaten onlar artık ListDetails içerisinde hallediliyor olacak.
 ListDetails ile herşey aynı sayfada halloluyor.
Yukarıdaki ekran görüntüsünde ListDetails.aspx'i görüyorsunuz. GridView artık
kendi içerisinde InlineEdit destekliyor ve bizim kategori kolonu da gördüğünüz
gibi Edit modunda bir DropDownList olarak
beliriyor.
Peki bizim esas konumuz neydi? Biz farklı bir tabloyu farklı bir dosya ile
göstermek istiyorduk. Gelin örneğimizdeki Urunler tablosunun
ListDetails ile gösterilmesini ayarlarken geri kalanların
normal bir şekilde ayrı ayrı dosyalarla düzenlenmesini sağlayalım.
[VB]
routes.Add(New DynamicDataRoute("Urunlers/ListDetails.aspx") With { _
.Action = PageAction.List, _
.ViewName = "ListDetails", _
.Table =
"Urunlers", _
.Model = model})
routes.Add(New DynamicDataRoute("Urunlers/ListDetails.aspx") With { _
.Action = PageAction.Details, _
.ViewName = "ListDetails", _
.Table =
"Urunlers", _
.Model = model})
routes.Add(New DynamicDataRoute("{table}/{action}.aspx") With { _
.Constraints = New RouteValueDictionary(New With {.Action = "List|Details|Edit|Insert"}), _
.Model = model})
[C#]
routes.Add(new DynamicDataRoute("Urunlers/ListDetails.aspx")
{
Action = PageAction.List,
ViewName = "ListDetails",
Table =
"Urunlers",
Model = model
});
routes.Add(new DynamicDataRoute("Urunlers/ListDetails.aspx")
{
Action = PageAction.Details,
ViewName = "ListDetails",
Table =
"Urunlers",
Model = model
});
routes.Add(new DynamicDataRoute("{table}/{action}.aspx")
{
Constraints = new RouteValueDictionary(new { action = "List|Details|Edit|Insert" }),
Model = model
});
Yukarıdaki kodlar Urunlers tablosunun ListDetails.aspx
ile gösterilmesini ve geri kalan tüm tabloların standart bir şekilde
tablo adı / aksiyon adı.aspx ile düzenlenmesini sağlayacaktır. Burada
önemli olan noktalardan biri kodumuzun içerisindeki istisnai durumların yani
bizim örneğimizde Urunlers tablosunun durumunun kod sırasında
daha önde tanımlanmış olmasının şart olması. Aksi halde sistem istediğimiz gibi
çalışmayacaktır.
Bu yazıda Dynamic Web Site yapısının nasıl çalıştığını ve proje yapısını
incelemekle beraber web sitelerini özelleştirme dünyasına da ufak bir giriş
yaptık. Sonraki yazılarımda derin detaylara yolculuğumuz devam edecek.
Hepinize kolay gelsin.
ASP.NET tarafında programlama yaparken çoğu zaman yaptığımız işlemlerin veya
kullanıcılara sağlamaya çalıştığımız ortamında sadece CRUD (Create, Read, Update,
Delete) operasyonlarını yapmakla yükümlü olduğunu farkına bile varmayız. Aslında
tüm yaptığımız sürekli farklı toplolar için INSERT, UPDATE, DELETE işlemlerini
yapan sayfalar, arayüzler ve kodlar yaratmaktır. Bazen bu kodların tabloların
niteliğine göre biraz değişir bazen de tablolar arası ilişkiler nedeniyle ek
filtrelemeler koymamız gerekir. Fakat özünde baktığımızda işin büyük kısmı ve
sürekli tekrar etmekten bir programcı olarak genelde sıkıldığımız kısmı klasik
CRUD işlemleridir.
İşte tam da bu noktada bizim sorunumuzu çözecek olarak yapı .NET Framework
3.5 SP1 ile beraber artık Visual Studio'nun içerisinde: ASP.NET Dynamic
Data Web Site!
Önce bir hazırlanalım!
Nesne Tabanlı Tasarım mimarisinin mantığına tamamen aykırı olsa da maalesef
çoğu projede hala öncelikle veritabanı tasarımını yaparak ilerliyoruz. Bu kötü
bir alışkanlık gibi gözükse de ufak projelerde çok sorun yaratmayacağını
öngörebiliriz. Dynamic Data Web Site mantığında da önce elinizde hazır bir
veritabanı olması şart. Bunun için hemen hızlı bir şekilde SQL 2008'de örnek bir
veri tabanı yaratacağız.
 Örneğimizdeki veritabanının tasarımı.
Veritabanımızı yukarıdaki şemaya göre yarattıktan sonra artık hemen bu
veritabanını kontrol edecek olan web sitesini yaratmak üzere Visual Studio
tarafına geçebiliriz.
Yeni bir Dynamic Web Site!
Visual Studio içerisinde "File / New Web Site" menüsüne ufak bir yolculuk
yaparsak karşımıza seçenekler arasında bir de "Dynamic Data Web Site"ın
geldiğini göreceğiz. Hemen bu seçeneği işaretleyerek yeni web sitemizi
yaratalım.
Projenizi yarattıktan sonra "Solution Explorer" içerisinde gördüğünüz farklı
klasör ve dosyalar aklınızı karıştırmasın. Bu konulara ileriki makalelerde
detaylı olarak değineceğiz. Şu an için önemli olan hemen web sitemizi veritabanı
ile ilişkilendirerek ayağa kaldırıp sonuca ulaşmak.
Dynamic Data Web Site'ın veritabanına ulaşması için Entity Framework
kullanabileceğiniz gibi rahatlıkla LINQ2SQL sınıflarından da
faydalanabilirsiniz. Biz örneğimizde LINQ2SQL kullanacağız. Bu nedenle hemen
yeni bir DBML dosyasını projemize ekliyoruz ve veritabanımızdan "Kategoriler" ve
"Ürünler" tablolarını DBML dosyasına taşıyoruz.
LINQ2SQL'in detayların bu yazıda girmeyeceğim, merak edenler bu konudaki
detayları "LINQ2SQL'e
Giriş" yazımdan edinebilirler.
Artık LINQ2SQL sınıflarımız da hazır olduğuna göre geriye sadece tek bir
nokta kalıyor; Dynamic Data Web Site'ı LINQ2SQL sınıflarımız ile haberleştirmek.
Bu işlemi yapabilmemiz için gerekli kod aslında hazır bir şekilde projenin
Global.asax dosyasında duruyor.
' IMPORTANT: DATA MODEL REGISTRATION
' Uncomment this line to register LINQ to SQL classes or an ADO.NET Entity Data
' model for ASP.NET Dynamic Data. Set ScaffoldAllTables = true only if you are sure
' that you want all tables in the data model to support a scaffold (i.e. templates)
' view. To control scaffolding for individual tables, create a partial class for
' the table and apply the [Scaffold(true)] attribute to the partial class.
' Note: Make sure that you change "YourDataContextType" to the name of the data context
' class in your application.
' model.RegisterContext(GetType(YourDataContextType), New ContextConfiguration() With {.ScaffoldAllTables = False})
Yukarıdaki gibi tamamen pasif hale getirilmiş bir paragraf yazı ve bir satır
kod Global.asax'ın en başında yer alıyor. Bizim için önemli olan en alttaki kod
satırı tabi ki. Bu satırı aktif hale getirerek YouDataContextType'ın
yerine kendi DBML dosyamızın DataContext'ini atamamız gerek. Sonrasında da
ScaffoldAllTables özelliğini False değerinden
True'ye çevirmeliyiz.
[VB]
model.RegisterContext(GetType(DataClassesDataContext), New ContextConfiguration() With {.ScaffoldAllTables = True})
[C#]
model.RegisterContext(typeof(DataClassesDataContext), new ContextConfiguration() { ScaffoldAllTables = true });
Son olarak yukarıdaki kod işimizi görecektir. Burada özellikle açıklanması
gereken nokta sanırım ScaffoldAllTables özelliği. Bu özellik sayesinde Dynamic
Data Web Site hedef veritabanındaki (Şu anda sadece LINQ2SQL'in sağladığı
tablolar) tüm tablolara ulaşarak gerekli CRUD işlemlerinin yapılabilmesini
sağlayacaktır. Bu işlemin yapılıp yapılmayacağına isterseniz tablo bazında da
karar verebilirsiniz, fakat bunun detaylarına daha ileride gireceğiz.
Şimdi son değişikliklerle beraber Global.asax dosyamızı da kaydedelim ve
projemizi çalıştıralım :)
 Dynamic Data Web Site'ın ilk görünümü.
Gördüğünüz gibi site çalıştığında anda kendisine bağlı tüm tabloları hemen
listeledi. Şimdi hızlıca bir Kategorilers sayfasına yönelelim. Unutmadan,
buradaki isimlerin LINQ2SQL'deki nesne isimleri olduklarını hatırlamakta fayda
var, isterseniz bu isimleri LINQ2SQL tarafından rahatlıkla değiştirebilirsiniz,
başka seçenekler de var ama onları da ileride inceleyeceğiz.
 Kategoriler tablosu listeleniyor.
Benim daha önce veritabanına girişini yaptığın birkaç veriyi yukarıdaki
ekranda görebilirsiniz. Gördüğünüz gibi otomatik olarak tüm bu kategoriler için
Edit / Delete ve Details bölümleri açılmış. Kategoriler'in Aciklama özellikleri
burada gösterilmemiş ve Details bölümü ile gidilen sayfaya saklanmış. Daha da
güzeli her kategorinin yanına bir "View Urunlers" linki konarak bu kategorideki
ürünlerin görülebileceği sayfaya birer de link konmuş. Eh gönül daha ne ister?
 Ürünler'in gösterildiği Dynamic Data Sayfası
Ürünlerin gösterildiği sayfaya gittiğimizde ise otomatik olarak
Kategoriler'in bir DropDownList'e dönüştüğünü ve filtreleme amaçlı olarak
kullanılabildiğini görüyoruz. Ayrıca burada da hem yeni ürün ekleme amaçlı hem
de düzenleme için gerekli tüm detaylar hazırlanmış.
 Ürünler'imizin detaylarını düzenleyebileceğimiz sayfalar da hazır.
Herhangi bir ürüne ait Edit linkine tıkladığımızda gittiğimiz sayfada Urunler
tablosundaki her bir Field'e uygun şekilde gerekli görsel öğelerin yaratıldığını
görebiliyoruz. Veritabanına NText olarak düzenlediğimiz yerler MultiLine
TextBox'lar haline gelirken kategorilerimiz de bir DropDownList haline gelmiş.
Tabi ki bu web sitesi bu şekilde kullanılabileceği gibi özelleştirmelerin
gerekeceği de kesin. Sonraki Dynamic Data ile ilgili yazılarımda
özelleştirmelerle ilgili detayların yanı sıra arka plandaki mekanizmaları da
inceleyeceğiz.
Hepinize kolay gelsin.
Bugün CEBIT fuarında TBDGenc
organizasyonundaki Geek Zone dahilinde "Facebook
Uygulama Geliştirme" oturumunu sundum. Geek Zone'un konsepti gereği
20 dakikalık oturumlar gerçekleşiyor. Benim oturumu çaktırmadan 30 dakikaya
kadar uzattım :)
 Geek Zone'daki "Facebook Uygulama Geliştirme" oturumum.
Gerçek anlamda "hap" niteliğinde bir oturum oldu, eğer anlattığım her
kelimeyi katılımcılara doğru şekilde aktarabildiysem ASP.NET ile FaceBook için
uygulama geliştirme yolunda neredeyse karşılaşabilecekleri tüm soruları çözdük
diyebilirim.
Aktivite de söz verdiğim üzere kullandığım sunumu aşağıdan indirebilirsiniz
;)
Facebook Uygulama Geliştirme Sunumu - 07102008_2.pptx (807 KB)
Cuma günü "WPF ile 3D animasyonları" anlatıyor olacağım.
Sonrasında da CEBIT fuarını gezeceğim :) Bugün gezemedim. Hepinizi beklerim.
Önümüzdeki hafta CEBIT fuarının haftası. CEBIT fuarı çerçevesinde TBDGENC'nin
düzenlediği GeekZone aktivitesinde ben de iki oturumda
konuşmacı olacağım. İşleyeceğimiz konulardan ilki "FaceBook'da Uygulama
Geliştirme" ikincisi ise "WPF ile 3D Animasyonlar".
GeekZone'da her bir oturum hap niteliğinde sadece 20 dakika sürüyor. Bana MCT
eğitimlerindeki 5 dakikalık sunumlarımızı hatırlattı :)
GeekZone programını aşağıda inceleyebilirsiniz.
 GeekZone Programı
INETA Summer Hit üzerinden uzun bir zaman geçti gibi hissettiğimiz bu
günlerde yeni bir aktivite serisi ile tekrar karşınızdayız. Bu sefer İstanbul
değil Anadolu'nun merkezi, Başkentimiz Ankara'da olacağız.

Dikkat ederseniz İstanbul'daki Summer Hit sonrası içeriğimizi de epeyce
değiştirdik. Tabi bunda sizlerin doldurmuş olduğu değerlendirme formlarının
etkisi çok büyük. Bu sefer çok daha sıkışık ve yoğun bir tempomuz olacak.
Hediyelerimiz daha fazla (hatta çok ilginç beklenmedik şeyler var :)) ve içecek sorununu da hallettik (:))
İlk gün sabah yine SL 2.0 ile başlayıp sonra benim çok önem
verdiğim IIS 7'ye geçeceğiz. IIS 7.0 üzerinde ASP.NET
ve PHP tarafında çok güzel yenilikler var. Sonrasında her
zamanki gibi bir sohbet panelimiz olacak. Son olarak LINQ ile
ilk günümüzü kapatacağız. İkinci gün WPF ile başlayarak
ADO.NET Data Services konusunu inceleyeceğiz. Heyecanlandığınızın
farkındayım :) Sonrasında IE 8.0 ile gelen yazılımcı ve
tasarımcıları ilgilendiren yenilikler ve yeni uygulama platformlarını
inceleyerek WCF dünyasına da atılarak iki günü sonlandıracağız.
Aktiviteye üniversite girişinde güvenlik sorunları yaşamamak adına kayıt
olmanız şart.
Kayıt adresi:
http://daron.yondem.com/kayit/
Emeklerinden dolayı buradan sevgili MSP, Çağrı Erdoğan'a
çok teşekkür ediyorum.
Aktiviteyi duyururken geçen sefer güzel bir başarı elde etmiştik. Bu sefer de
yine aşağıdaki bannerı kullanabilirsiniz. Banner'a tıklandığında link olarak da
kayıt adresini verebilirsiniz.

Hepinizi bekliyorum ;)
Başlık olarak “Reflection” yazdıktan sonra ardına sayfalarca açıklama ve örnek konulabilir. Hatta bu konuda ayrı bir kitap bile yazılabilir. Reflection’ın çok farklı kullanımlar var. Özetleyerek hızlı bir şekilde tanımlamak istersek aslında Reflection bize hakkında bilgi sahibi olmadığınız programatik nesnelerle ilgili çalışma zamanında (run-time) bilgi alabilmemize olanak tanıyan bir metottur. Peki böyle bir şeye neden ihtiyacımız olsun? En basit örnek gerçek zamanlı olarak uygulamalara farklı DLL dosyalarının bağlandığı durumları gösterebiliriz. Böyle bir durumda kaynak konumdaki sınıflar veya metotlar ile ilgili herhangi bir bilgi bulunmaz. Söz konusu bu bilgilerin program çalışırken elde edilerek kullanılması gerekir.
Gelin ilk olarak Reflection’ın yapısını ve sistemini tanımak adına tek bir uygulama içerisinde nasıl kullanılabileceğimize göz atalım. Örnek uygulamamızda aşağıdaki şekli ile tanımlanmış bir Urun sınıfı kullanacağız.
[VB]
Public Class Urun
Private PAdi As String
Public Property Adi() As String
Get
Return PAdi
End Get
Set(ByVal value As String)
PAdi = value
End Set
End Property
Sub New()
End Sub
Sub New(ByVal adi As String)
Me.Adi = adi
End Sub
Function Uyari() As String
Return "Ürünün adı: " & Me.Adi
End Function
End Class
[C#]
public class Urun
{
private string PAdi;
public string Adi
{
get { return PAdi; }
set { PAdi = value; }
}
public Urun()
{
}
public Urun(string adi)
{
this.Adi = adi;
}
public string Uyari()
{
return "Ürünün adı: " + this.Adi;
}
}
Uygulamamız içerisinde iki adet düğme yer alacak ve kullanacağımız Windows penceresinde global olarak tanımlanmış bir de
Object tipinde değişkenimiz bulunacak.
[VB]
Dim BirUrun As Object
[C#]
object BirUrun;
Uygulama içerisindeki düğmelerden birine basıldığında global BirUrun değişkenimiz yeni bir
Urun değişkenine dönüştürülecek.
[VB]
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
BirUrun = New Urun
End Sub
[C#]
private void button1_Click_1(object sender, EventArgs e)
{
BirUrun = new Urun();
}
Programımız içerisinde diğer düğmeye basıldığında BirUrun adındaki değişkenimizin
Adi özelliğini değiştirerek Uyari adındaki metodunu kullanmak istiyoruz. Fakat Visual Studio içerisinde maalesef ki
BirUrun adındaki değişkenle beraber Urun tipine ait Intellisense desteği gelmeyecektir. Aslında bu durumun haklı bir nedeni var. İkinci düğmeye basıldığında
BirUrun adındaki değişkenin tipininin Object mi yoksa
Urun mü olacağı belli değil. İşte tam da istediğimiz ortamı yaratmış olduk. Kullanacağımız nesnenin tipi belirsiz ve biz ona ait bazı özellikleri kullanmak istiyoruz.
Bu durumda ilk olarak ikinci düğmeye basıldığında gerçekten BirUrun değişkeninin tipi
Urun mü yoksa değil mi sorusunu kontrol etmemiz lazım.
[VB]
If TypeOf (BirUrun) Is Urun Then
End If
[C#]
if ((BirUrun) is Urun)
{
}
Buraya kadar her şey çok kolay. Bundan sonra eğer IF kontrollerimize olumlu sonuç dönüyorsa ilk olarak gidip nesnenin
Adi özelliğini bulmamız ve ona bir değer aktarmamız gerekiyor.
[VB]
BirUrun.GetType.GetProperty("Adi").SetValue(BirUrun, "Daron", Nothing)
[C#]
BirUrun.GetType().GetProperty("Adi").SetValue(BirUrun, "Daron", null);
Yukarıdaki kod ile elimizdeki nesnenin tipini bilmeden onun Adi adındaki özelliğini (property) yakalayarak değerini
Daron olarak değiştiriyoruz. Kodumuzu detaylı olarak adım adım bakacak olursak ilk aşamada nesnenin tipini
GetType ile alıyoruz. Sonrasında ise tipini yakaladığımız nesnenin
GetProperty ile Adi adındaki özelliğini alarak
SetValue ile söz konusu özelliğin değerini değiştiriyoruz.
SetValue metodu toplam üç parametre alıyor; bunlardan ilki değer değişikliği yapılacak nesnenin kendisi, ikincisi yeni atanacak olan değer, üçüncüsü ise eğer değiştirilecek olan özellik (property) indeksli ise söz konusu indeks değeri. Bizim örneğimizde indeksli bir özellik olmadığı için bu parametreyi boş geçiyoruz.
Değer atamamızı tamamladığımıza göre bu sefer de sıra geldi BirUrun değişkenimize ait
Uyari metodunu çalıştırmaya. Metodumuz bize bir String döndürecek biz de onu doğrudan bir mesaj kutusu ile kullanıcıya göstereceğiz.
[VB]
BirUrun.GetType.InvokeMember("Uyari", Reflection.BindingFlags.InvokeMethod, Nothing, BirUrun, Nothing)
[C#]
BirUrun.GetType().InvokeMember("Uyari", System.Reflection.BindingFlags.InvokeMethod, null, BirUrun, null).ToString();
Reflection kullanarak türü bilinmeyen bir nesnenin bir metodunu çalıştırmak için
InvokeMember metodundan faydalanmamız gerekiyor. InvokeMember aslında çok geniş kullanımı olan bir metod, biz şimdilik sadece bir çeşit kullanımına değineceğiz. Örneğimizde
InvokeMember bir metod çalıştıracağı için ilk parametresinde
çalıştırılacak olan metodun adını ikincisinde BindingFlags.InvokeMethod ile bir
Metod çalıştırılacağını belirtiyoruz. Üçüncü parametre bizim şimdilik kullanım alanımız dışında kalan Binding’lerle ilgili, aynı şekilde beşinci parametre de boş bırakılarak geçilecek. Dördüncü parametrede ise hedef nesnemiz olan
BirUrun değişkenimizi atayacağız. Böylece metodumuzu da çalıştırmış olduk.
Dinamik DLL Kullanımı
Kabaca Reflection’ın nasıl kullanılabildiğine dair bir örnek yaptıktan sonra
artık sıra geldi harici bir DLL dosyasının çalışma anında programımıza ekleyerek
içerisindeki yapıları kullanmaya. Bu çeşit bir işlevselliği özellikle gerçek
zamanlı DLL derlemesi ile birleştirdiğinizde çok farklı bir dünyaya kapı açmış
olacaksınız. Hedef olarak kullanacağımız DLL dosyasını aşağıdaki kodlardan yaratacağız.
[VB]
Public Class Deneme
Function Metin() As String
Return "Çalışıyor"
End Function
End Class
[C#]
public class Deneme
{
string Metin()
{
return "Çalışıyor";
}
Yarattığımız DLL dosyasını uygulamamız ile aynı konuma yerleştirdikten sonra aşağıdaki kod ile DLL’imizi kullanmaya başlayabiliyoruz.
[VB]
Dim BirAssembly As Reflection.Assembly = Reflection.Assembly.LoadFrom("ornek2.dll")
[C#]
System.Reflection.Assembly BirAssembly = System.Reflection.Assembly.LoadFrom("ornek2.dll");
Artık yukarıda tanımladığımız Assembly üzerinden Reflection kullanarak ilerleyebiliriz. İlk olarak
Deneme adında sınıfımızdan bir instance almamız gerekecek. Bunun için
Deneme tipini bulmamız lazım.
[VB / C#]
BirAssembly.GetModule("Ornek2.dll").GetType("Deneme")
Assembly üzerinden modülümüzü yakalıyor sonra da Deneme adındaki tipinizi buluyoruz. Tabi tipi bulmak yeterli değil, söz konusu tipte bir değişken yaratmamız gerekiyor.
Activator sınıfını kullanarak bu tip üzerinden bir instance yaratarak
Sinif adında bir değişkene aktaracağız.
[VB]
Dim Sinif = Activator.CreateInstance(BirAssembly.GetModule("Ornek2.dll").GetType("Deneme"))
[C#]
object Sinif = Activator.CreateInstance(BirAssembly.GetModule("Ornek2.dll").GetType("Deneme"));
Yarattığımız sınıfın maalesef özellikleri otomatik olarak gelmeyecek. O nedenle
Metin adındaki metodumuzu da elle bularak çalıştırmak zorundayız.
[VB]
BirAssembly.GetModule("Ornek2.dll").GetType("Deneme").GetMethod("Metin").Invoke(Sinif, Nothing)
[C#]
BirAssembly.GetModule("Ornek2.dll").GetType("Deneme").GetMethod("Metin").Invoke(Sinif, null)
Yine Assembly üzerinden yola çıkarak bu sefer daha da ileri gidiyoruz.
Deneme sınıfımızı bulduktan sonra içerisinde Metin adındaki metodumuzu buluyor ve doğrudan
Invoke ile söz konusu metodu çalıştırıyoruz. Invoke metodu bizden iki parametre istiyor; bunlardan ilki ana sınıfın kendisi. Bir önceki adımda yakaladığımız sınıfı buraya parametre olarak aktarıyoruz. Diğeri ise bizim kullanmayacağımız Binding parametresi.
Metin metodumuz çalıştırıldığında geriye bir String değişkeni döndürüyor. Bu değişkeni de bir mesaj kutusu ile kullanıcıya göstermek istersek uygulamamızın tam kodunun aşağıdaki şekilde sonlanması gerekiyor.
[VB]
Public Class Form2
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim BirAssembly As Reflection.Assembly = Reflection.Assembly.LoadFrom("ornek2.dll")
Dim Sinif = Activator.CreateInstance(BirAssembly.GetModule("Ornek2.dll").GetType("Deneme"))
MsgBox(BirAssembly.GetModule("Ornek2.dll").GetType("Deneme").GetMethod("Metin").Invoke(Sinif, Nothing))
End Sub
End Class
[C#]
namespace CSReflection
{
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
System.Reflection.Assembly BirAssembly = System.Reflection.Assembly.LoadFrom("ornek2.dll");
object Sinif = Activator.CreateInstance(BirAssembly.GetModule("Ornek2.dll").GetType("Deneme"));
MessageBox.Show(BirAssembly.GetModule("Ornek2.dll").GetType("Deneme").GetMethod("Metin").Invoke(Sinif, null).ToString());
}
}
}
Böylece harici bir DLL dosyasını yükleyerek istediğimiz metodu dinamik olarak kullanabildik. Farklı durumlarda isterseniz bir DLL içerisinde tüm metod, sınıf ve özelliklerin listelerini alabilir hatta bunları LINQ sorguları ile tarayabilirsiniz.
[VB]
Dim Metodlar = From Gelenler In BirAssembly.GetModule("Ornek2.dll").GetTypes Where Gelenler.GetMethod("Metin") IsNot Nothing
[C#]
var Metodlar = from Gelenler in BirAssembly.GetModule("Ornek2.dll").GetTypes() where Gelenler.GetMethod("Metin") != null select Gelenler;
Örneğin yukarıdaki LINQ sorgumuz ile harici DLL dosyası içerisinde Metin adında metodu olan tüm sınıfların bir listesini alıyoruz.
Hepinize kolay gelsin.
Bir uygulama düşünün kendini programlayabilen. Konumuz “Star Trek” veya “Geleceğe Dönüş” değil. Emin olun gerçek dünyadan ve yapılabileceklerden bahsediyorum. Uygulamalarınızın dış sistemlerle ciddi bir bağlantı içerisinde olduğu durumlarda bazen kendi içlerinde dış sistemlere uygun kodlar üreterek kullanmaları gerekebilir. Bunu bazen uygulamaların kendi içlerindeki yapay zeka ile yapabilecekleri gibi bazen ise başka bir dış kaynaktan aldıkları yeni parametrelerden yola çıkarak kendi kodlarında değişiklik yapabilirler. Eğer bunların hiçbiri size gerçekçi gelmiyorsa başka bir seçenek olarak da harici uygulamaların kullanabileceği DLL dosyaları yaratacak bir uygulama yazmak istediğinizde yapmanız gerekenlerden bahsedebiliriz. Aslında her ikisi de aynı kapıya çıkıyor.
Bize dinamik olarak uygulamalar tarafından kullanılabilecek DLL dosyaları yaratacak bir kod lazım.
Kullanacağımız nesnelerin çoğunun bulunduğu esas namespace System.CodeDom.Compiler olacak. Bunun haricinde C# veya VB için ayrı ayrı uygun namespace’leri kullanmamız gerek. Eğer VB kodu derleyecekseniz VB sınıflarını C# kodu derleyecekseniz tabi ki C# sınıflarını kullanmalısınız. Çapraz işlem yaparak C# kodunuz ile VB kodundan DLL üretme şansınız da var. Biz örneklerimizde C# ile C#’dan derleme, VB kodu ile de VB’den derleme yapacağız.
[VB]
Dim KodUretici As New Microsoft.VisualBasic.VBCodeProvider
Dim Derleyici As System.CodeDom.Compiler.CodeCompiler = KodUretici.CreateCompiler()
Dim Referanslarim As String() = {"System.dll"}
Dim AssemblyAdi As String = "Ornek.dll"
[C#]
Microsoft.CSharp.CSharpCodeProvider KodUretici = new Microsoft.CSharp.CSharpCodeProvider();
System.CodeDom.Compiler.ICodeCompiler Derleyici = KodUretici.CreateCompiler();
String[] Referanslarim = {"System.dll"};
String AssemblyAdi= "Ornek.dll";
Kodumuzun başlangıcında ilk olarak birer CodeProvider nesnesi yaratıyoruz. Elimizdeki hazır kodu derleyecek olan nesneler olarak bu sınıflar VB ve C# için farklılaşıyor. CodeProvider’lar üzerinden birer de derleyici nesnesi aldıktan sonra sıra geliyor derleyeceğimiz kodun referanslarına karar vermeye. Referansları DLL isimleri ile bir
String dizisine aktarmanız şart. Windows uygulamalarında en azından System.dll’in web uygulamalarında da
System.Web.dll’in referans alınmış olması gerekiyor. Son olarak üreteceğimiz DLL dosyasının adını da başka bir değişkene aktararak yolumuza devam edelim.
[VB]
Dim DerlemeParametreleri As New System.CodeDom.Compiler.CompilerParameters(Referanslarim, AssemblyAdi)
DerlemeParametreleri.GenerateExecutable = True
DerlemeParametreleri.GenerateInMemory = False
[C#]
System.CodeDom.Compiler.CompilerParameters DerlemeParametreleri = new System.CodeDom.Compiler.CompilerParameters(Referanslarim, AssemblyAdi);
DerlemeParametreleri.GenerateExecutable = false;
DerlemeParametreleri.GenerateInMemory = false;
Derleme işlemini yaparken yapmamız gereken ayarlar var. Bu ayarları derleyicimize bir
CompilerParameters nesnesi olarak aktaracağız. DerlemeParametreleri değişkenimizi yaratırken referanslarımızı ve DLL adını aktardıktan sonra özel olarak
GenerateExecutable özelliğini false olarak ayarlıyoruz. Böylece derleyicimiz bize tek başına çalışabilir bir dosya yaratmaktansa bir DLL dosyası yaratacak. Bir sonraki adımda da
GenerateInMemory özelliğini false yaparak yaratılacak dosyanın uygulamamız ile aynı konuma, diske yazdırılmasını sağlıyoruz. Aksi halde yaratılan
Assembly sadece hafızada tutulacak ve diske yazılmayacaktır. Sıra geldi dinamik olarak derlemeyeceğimiz kodu bir değişkene aktarmaya.
[VB]
Dim Kodum As String = <Kod>Public Class Deneme
Function Metin() As String
Return "Çalışıyor"
End Function
End Class</Kod>.Value
[C#]
System.IO.StreamReader Okuyucu = new System.IO.StreamReader("Class1.cs");
string Kodum = Okuyucu.ReadToEnd();
Okuyucu.Close();
Bu noktada VB ile C# arasında farklı işlemler yaptım. VB’de doğrudan yaratacağım kodu uygulamanın içerisine gömerken C#’da derleyeceğim C# kodunu harici bir
Class1.cs dosyasından çektim. Siz kendi uygulamalarınızda ister bu kodları farklı dosyalardan çekin ister metin işlemleri ile dinamik kod yaratın. İhtiyaçlarınıza göre uygun çözümü üretmek tamamen size kalmış. Önemli olan tek nokta aslında bu kodlarda hiçbir hatanın olmaması gerektiği, aksi halde derleme işlemi yapılamayacaktır.
[VB]
Dim Sonuc As System.CodeDom.Compiler.CompilerResults = KodUretici.CompileAssemblyFromSource(DerlemeParametreleri, Kodum)
[C#]
System.CodeDom.Compiler.CompilerResults Sonuc = KodUretici.CompileAssemblyFromSource(DerlemeParametreleri, Kodum);
Tüm ayarlarımız tamamlandığında göre doğrudan CodeProvider nesnemizin
CompileAssemblyFromSource metodunu kullanarak derleme işlemini başlatabiliriz. Tabi bu esnada daha önce hazırlamış olduğumuz
DerlemeParametrelerini de metoda parametre olarak aktarıyoruz. Derleme işlemimizi baştan sona tamamlayan kodumuzu bir bütün olarak inceleyelim.
[VB]
Dim KodUretici As New Microsoft.VisualBasic.VBCodeProvider
Dim Derleyici As System.CodeDom.Compiler.CodeCompiler = KodUretici.CreateCompiler()
Dim Referanslarim As String() = {"System.dll"}
Dim AssemblyAdi As String = "Ornek.dll"
Dim DerlemeParametreleri As New System.CodeDom.Compiler.CompilerParameters(Referanslarim, AssemblyAdi)
DerlemeParametreleri.GenerateExecutable = True
DerlemeParametreleri.GenerateInMemory = False
Dim Kodum As String = <Kod>Public Class Deneme
Function Metin() As String
Return "Çalışıyor"
End Function
End Class</Kod>.Value
Dim Sonuc As System.CodeDom.Compiler.CompilerResults = KodUretici.CompileAssemblyFromSource(DerlemeParametreleri, Kodum)
[C#]
Microsoft.CSharp.CSharpCodeProvider KodUretici = new Microsoft.CSharp.CSharpCodeProvider();
System.CodeDom.Compiler.ICodeCompiler Derleyici = KodUretici.CreateCompiler();
String[] Referanslarim = {"System.dll"};
String AssemblyAdi= "Ornek.dll";
System.CodeDom.Compiler.CompilerParameters DerlemeParametreleri = new System.CodeDom.Compiler.CompilerParameters(Referanslarim, AssemblyAdi);
DerlemeParametreleri.GenerateExecutable = false;
DerlemeParametreleri.GenerateInMemory = false;
System.IO.StreamReader Okuyucu = new System.IO.StreamReader("Class1.cs");
string Kodum = Okuyucu.ReadToEnd();
Okuyucu.Close();
System.CodeDom.Compiler.CompilerResults Sonuc = KodUretici.CompileAssemblyFromSource(DerlemeParametreleri, Kodum);
Dinamik olarak DLL dosyası derlemek işte bu kadar kolay. Dinamik kod yaratma araçları son dönemde çok popüler. Veritabanına bağlanarak veritabanındaki nesneleri algılayıp uygun “Veri Katmanı” kodunu dinamik olarak oluşturan hazır uygulamalar olduğu gibi bazı durumlarda özel kodlar yazmak da gerekebiliyor. Böyle bir durumda artık siz de uygulamalarınıza farklı kaynaklardaki şartlara uygun kodu dinamik olarak üretebilir ve bir DLL olarak farklı uygulamalara aktarabileceğiniz gibi kendi uygulamalarınızda da kullanabilirsiniz. Yarattığınız DLL dosyasını hemen uygulamanızda kullanmak isterseniz bu sefer dinamik olarak Assembly kullanımını ve Reflection
konusuna eğilmenizde fayda var.
Hepinize kolay gelsin.
İster VB olsun ister C#, ister web ister Windows uygulaması olsun yazdığımız tüm kodların derlenerek (Compile) bir EXE veya DLL haline dönüştürüldüğünü biliyoruz. Aslında .NET içerisinde yapılan işlem sizin yazdığınız herhangi bir .NET dilindeki kodun
MSIL (Microsoft Intermediate Language)’a çevrilmesidir. İşte tam bu noktada akla gelen ilk soru; acaba bu çeviri işleminin tersini yapmak mümkün mü? Yani elimizdeki DLL veya EXE dosyasından yola çıkarak VB veya C# kodumuzu geri alabilir miyiz? Cevap:
Evet.
Şu andan itibaren yapacaklarımız hedef olarak kullanacağınız uygulamanın lisans sözleşmesine göre yeri geldiğinde suç teşkil edebilir. O nedenle sizi özellikle uyarmak istiyorum. Çoğu zaman De-Compile işlemleri yaparkenki amacımız yazdığımız kodun nasıl derleyici tarafında MSIL’e çevrildiğini incelemek veya kaynak kodunu kaybettiğimiz ve bize ait olan bir uygulamanın kodlarına ulaşmak olacaktır. Diğer yandan lisans sözleşmesi ile aykırı düşmediği sürece farklı uygulamaları da De-Compile ederek arka planda farklı işlemlerin nasıl yapıldığını inceleme şansınız da olabilir.
.NET tarafına geçtiğimizde herhangi bir DLL veya EXE’nin aslında MSIL kodları içerdiğinden bahsetmiştik. Tabi ki bu
MSIL kodları doğrudan bilgisayarlar tarafından çalıştırılabilir kodlar değiller. O nedenle içerisinde MSIL bulunan bir .NET yapısının çalışabilmesi için hedef makinede .NET Framework’ün yüklü olması gerekiyor. .NET Framework içerisindeki
CLR (Common Language Runtime) bizim MSIL kodumuzu makine diline çevirerek çalışmasını sağlayacaktır. Kabaca baktığımızda De-Compile yolunda bizim ilk olarak elimizdeki DLL veya EXE içerisinden MSIL kodunu alarak çıkarmamız gerekecek. Bunun için doğrudan .NET Framework SDK paketi ile beraber gelen
MSIL DisAssembler (ILDASM) uygulamasını kullanabiliriz.
IL DASM Kullanımı
Bilgisayarınıza .NET Framework SDK paketini kurduktan sonra doğrudan “Başlat” menüsünden ulaşabileceğiniz ILDASM programını Visual Studio yükleme konumu içerisinde SDK klasörü altında da bulabilirsiniz. Programı açtıktan sonra “File / Open” menüsünden istediğiniz bir .NET DLL veya EXE dosyasını açma şansınız olacaktır.Deneme amaçlı olarak gelin mini bir Windows uygulaması yazalım ve ILDASM ile açarak alacağımız sonucu görelim.
Uygulamamız içerisinde birer TextBox, Button ve Label bulunacak. Basit bir şekilde düğmeye basıldığında TextBox içerisindeki değeri Label içerisine aktaracağız.
[VB]
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Label1.Text = TextBox1.Text
End Sub
End Class
[C#]
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
label1.Text = textBox1.Text;
}
}
}
Yukarıda yazdığımız kodlar ile oluşturduğumuz uygulamayı ILDASM ile açarak sonucu inceleyelim. Uygulamanın ilk açılan penceresinde bizim EXE’ye ait tüm sınıflar ve namespace’ler gözüküyor olacaktır. Eğer herhangi bir nesnenin tanımı veya metodu ile ilgili MSIL kodunu görmek isterseniz doğrudan çift tıklayarak yeni bir pencerede kodların açılmasını sağlayabilirsiniz.
 ILDASM içerisinde EXE’mizin MSIL kodları açıkça gözüküyor
Hazırladığımız örnek uygulamanın Button_Click durumundaki MSIL kodunu bulduğumuzda aşağıdaki sonuç ile karşılaşıyoruz.
[MSIL]
.method private instance void
Button1_Click(object sender,
class [mscorlib]System.EventArgs e) cil managed
{
// Code size 23 (0x17)
.maxstack 8
IL_0000: ldarg.0
IL_0001: callvirt instance class [System.Windows.Forms]System.Windows.Forms.Label WindowsApplication1.Form1::get_Label1()
IL_0006: ldarg.0
IL_0007: callvirt instance class [System.Windows.Forms]System.Windows.Forms.TextBox WindowsApplication1.Form1::get_TextBox1()
IL_000c: callvirt instance string [System.Windows.Forms]System.Windows.Forms.TextBox::get_Text()
IL_0011: callvirt instance void [System.Windows.Forms]System.Windows.Forms.Label::set_Text(string)
IL_0016: ret
} // end of method Form1::Button1_Click
Yukarıdaki MSIL kodu normal şartlarda CLR tarafından makine koduna çevrilerek hedef ortamda çalıştırılıyor. Artık MSIL kodumuzu aldığımıza göre bu kodu VB veya C# koduna çevirmemiz lazım. Tabi bu iş
o kadar kolay değil ve tek tek elle yapılabilecek bir iş de değil. O nedenle bu sefer de farklı bir araç kullanacağız.
Reflector iş başında
Lutz Roeder tarafından yazılmış bir program olarak Reflector’ı
http://www.red-gate.com/products/reflector/ adresinden bilgisayarınıza indirebilirsiniz. Program aslında bir önceki adımda anlattığım MSIL çözme işlemini de kendi içinde yapabiliyor. Bununla kalmayıp çözdüğü MSIL kodunu istediğiniz .NET diline de çevirebiliyor.
Programı çalıştırdıktan sonra “File / Open” menüsünden istediğiniz bir EXE veya DLL dosyasını seçebilirsiniz. Uygulamanın ana penceresindeki sınıf listesine hemen seçtiğiniz program da gelecektir.
 Reflector ile kaynak kodunu görebiliyoruz.
Ufak bir gezinti ile istediğiniz sınıfın veya metodun koduna doğrudan ulaşabilirsiniz. Reflector arayüzündeki “Programlama Dili” seçeneğinde VB, C#, Delphi ve IL seçenekleri bulunuyor. Bir önceki bölümde hazırladığımız uygulamamızı açarak
Button.Click durumundaki kodu farklı dillerde Reflector ile alıp inceleyelim.
[VB]
Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs)
Me.Label1.Text = Me.TextBox1.Text
End Sub
[C#]
private void Button1_Click(object sender, EventArgs e)
{
this.Label1.Text = this.TextBox1.Text;
}
Yazdığımız kodlar ile Reflector’ın bize verdiği kodlar tam olarak aynı değil. Bu durum zaten çok normal. Çünkü MSIL koduna çeviri esnasında aslında çoğu şey değişiyor. Örneğin tanımladığımız değişkenlerin bize özel olan isimlendirmeleri yok oluyor veya bizim kullandığımız bazı kısa metotlar uzun şekilleri ile yazılabiliyor. Hatta özellikle VB içerisindeki casting kolaylıkları Compile esnasında farklı değişikliklere neden olabiliyor. Bu durumda De-Compile ile aldığımız kod da yazdığımız koddan biraz farklı oluyor. Yine de elimizde çalışır durumda bir kod olduğuna kesin gözü ile bakabiliriz.
Nasıl engelleriz? Obfuscation!
Herhalde çoğunuz “tüm kodlarımız gözler önünde” endişesi içerisindesiniz. Aslında durum gerçekten de öyle. Tabi bu durumun birçok faydası var. Kişisel olarak itiraf etmek gerekirse farklı yazılımları De-Compile ederek çok şey öğrendiğimi söyleyebilirim. Bir defasında da kendi ürettiğimiz bir yazılımı De-Compile etmemiz gerekmişti, gerçekten hayat kurtarmıştı. Peki bunu nasıl engelleyebiliriz?
İlk olarak şunu açıkça belirtiyim, herhangi bir .NET uygulamasından MSIL kodunun alınmasını engellemenin hiçbir yolu yok. Yapabileceğimiz tek şey MSIL kodunun okunabilirliliğini azaltmak için işlevsel olarak aynı işi gören fakat daha karışık bir MSIL kodu yaratmak. Bu işlem
obfuscation olarak adlandırılıyor.
Obfuscation ile ilgili sektörde çok sayıda ücretli yazılım bulabilirsiniz. Biz bunlardan
Xenocode'aait
Postbuild 2008 adındaki ticari yazılımı kullanarak obfuscation ile neler yapabildiğimize bakacağız.
XenoCode’u ilk açtığımızda karşımıza hemen bir uygulama listesi geliyor. Bu listeye bir önceki adımda kendi hazırladığımız EXE dosyasını ekleyerek uygulamanın üst menüsünden “Protect” tabına geçiyoruz. Burada sadece Windows’da çalışacak EXE dosyalarına uygulanabilecek özel bir koruma yöntemi olan “Surpress ILDASM” seçeneğinin işaretini kaldırmamız gerek. Bu seçenek DLL’lere zaten uygulanamayacaktır. Ekranın sağ tarafında korumak istediğimiz sınıfların ve metodların bir listesini işaretleyebiliyoruz. Tüm ayarları tamamladıktan sonra uygulamanın sağ altındaki “XenoCode Application” düğmesine basıyoruz.
 Obfuscation işlemi için yollardayız
Obfuscation işlemini tamamladıktan sonra sıra geldi testlerimizi yapmaya. İlk olarak uygulamamızı ILDASM ile açarak bakalım MSIL kodumuz ne hale gelmiş.
[MSIL] .method private instance void
x44d0c0526a414989(object
xe0292b9ed559da7d,
class [mscorlib]System.EventArgs xfbf34718e704c6bc) cil managed
{
// Code size 23 (0x17)
.maxstack 8
IL_0000: ldarg.0
IL_0001: callvirt instance class [System.Windows.Forms]System.Windows.Forms.Label WindowsApplication1.xaa4f033827d75b4d::get_x029e304eb4c44750()
IL_0006: ldarg.0
IL_0007: callvirt instance class [System.Windows.Forms]System.Windows.Forms.TextBox WindowsApplication1.xaa4f033827d75b4d::get_x77691a2cfb8f8048()
IL_000c: callvirt instance string [System.Windows.Forms]System.Windows.Forms.TextBox::get_Text()
IL_0011: callvirt instance void [System.Windows.Forms]System.Windows.Forms.Label::set_Text(string)
IL_0016: ret
} // end of method xaa4f033827d75b4d::x44d0c0526a414989
Gördüğünüz gibi aslında çok büyük bir değişiklik yok. Sadece sınıfların ve metodların isimleri değiştirilerek karışık isimler verilmiş. Aynı uygulamayı
Reflector ile açtığımızda ise aşağıdaki kodları elde ediyoruz.
[VB]
Private Sub x44d0c0526a414989(ByVal xe0292b9ed559da7d As Object, ByVal xfbf34718e704c6bc As EventArgs)
Me.x029e304eb4c44750.Text = Me.x77691a2cfb8f8048.Text
End Sub
[C#]
private void x44d0c0526a414989(object xe0292b9ed559da7d, EventArgs xfbf34718e704c6bc)
{
this.x029e304eb4c44750.Text = this.x77691a2cfb8f8048.Text;
}
Kodlar epey okunurluluğunu kaybetmiş durumda. Bizim örneğimizde sadece tek bir satır kod bulunduğu için neyin ne olduğunu anlamak çok zor olmuyor. Fakat binlerde satırdan oluşan uygulamaların kodlarından anlaşılabilir bir sonuç çıkarmak neredeyse imkânsız olacaktır.
Hepinize kolay gelsin.
WPF ile beraber özellikle video uygulamalarının programlanmasındaki kolaylık
sonucunda artık Multimedya alanında da sıkça .NET ile programlanmış uygulamalar
görebiliyoruz. Bu yolda WPF içerisindeki MediaElement'in katkısı tabi ki
yadsınamaz. Bu yazımızda WPF içerisinde açtığımız bir video dosyasından bir kare
(thumbnail)
almayı deneyeceğiz.
Bu işlemi yapmak için normal şartlarda C++ ile DirectShow üzerine çalışmak
gerekiyor. Diğer .NET dilleri için Managed Provider'lar bağımsız yazılımcılarca
yazılmış olsa da kolay bir çözüm maalesef ki yok. Bu nedenle biz kendi kodumuzda
MediaPlayer ile bir video dosyasını açacak ve istediğimiz saniyesine giderek o
anki kareyi yakalayacağız. Kodumuz MediaPlayer'in yani uygulamanın çalıştığı
bilgisayarda Media Player'ın oynatabildiği her video ile çalışacaktır, herhangi
bir kodek sınırımız olmayacak.
Dikkat: MediaPlayer / Media Player ve
MediaElement farklı şeylerdir. MediaPlayer doğrudan System.Windows.Media.MediaPlayer
sınıfını tanımlarken, Media Player ise yazı boyunca bir bilgisayarda yüklü olan
uygulama olarak Media Player'ı anlatacaktır. Diğer yandan MediaElement ise
System.Windows.Controls.MediaElement sınıfını
tanımlar. MediaElement ile MediaPlayer sınıfları arasındaki en büyük fark
MediaPlayer'ın görsel olarak bir WPF formunda doğrudan video gösterememesidir.
Videonun ne şekilde nerede gösterileceğine MediaPlayer
için kod ile karar vermek gerekir.
Önce videomuzu bir oynatalım.
Uygulamamızda ilk olarak bir MediaPlayer yaratmamız ve sonrasında da
istediğimiz video dosyasını söz konusu MediaPlayer içerisinde oynatmamız
gerekiyor. Tüm bunları kodlarla yapacağız.
[VB]
Dim birMediaPlayer As New MediaPlayer
birMediaPlayer.Open(New Uri("C:\Users\Public\Videos\Sample Videos\Bear.wmv", UriKind.Absolute))
birMediaPlayer.Play()
birMediaPlayer.IsMuted = True
birMediaPlayer.Position = New TimeSpan(0, 0, 5)
[C#]
MediaPlayer birMediaPlayer = new MediaPlayer();
birMediaPlayer.Open(new Uri(@"C:\Users\Public\Videos\Sample Videos\Butterfly.wmv"));
birMediaPlayer.Play();
birMediaPlayer.IsMuted = true;
birMediaPlayer.Position = new TimeSpan(0, 0, 5);
Yukarıdaki kodumuzda birMediaPlayer adını verdiğimiz
MediaPlayer değişkenimize bilgisayardaki bir video dosyasını
açtırıyoruz. Sonrasında hemen videoyu oynatmaya başlıyoruz aksi halde herhangi
bir görsel elde etme şansımız kalmaz. Bu esnada videodan ses gelmemesi için
sesini de kısıp doğrudan videonun beşinci saniyesine zıplıyoruz.
[VB]
System.Threading.Thread.Sleep(5000)
Dim RenderTarBitmap As New RenderTargetBitmap(1600, 1200, 1 / 96, 1 / 96, PixelFormats.Pbgra32)
Dim DVisual As New DrawingVisual
Dim DContext As DrawingContext = DVisual.RenderOpen
DContext.DrawVideo(birMediaPlayer, New Rect(0, 0, 1600, 1200))
DContext.Close()
RenderTarBitmap.Render(DVisual)
birMediaPlayer.Stop()
Dim BMPFrame As BitmapFrame = BitmapFrame.Create(RenderTarBitmap)
[C#]
System.Threading.Thread.Sleep(5000);
RenderTargetBitmap RenderTarBitmap = new RenderTargetBitmap(1600, 1200, 1 / 96, 1 / 96, PixelFormats.Pbgra32);
DrawingVisual DVisual = new DrawingVisual();
DrawingContext DContext = DVisual.RenderOpen();
DContext.DrawVideo(birMediaPlayer, new Rect(0, 0, 1600, 1200));
DContext.Close();
RenderTarBitmap.Render(DVisual);
birMediaPlayer.Stop();
BitmapFrame BMPFrame = BitmapFrame.Create(RenderTarBitmap);
İşte bu adımda gördüğünüz kod aslında uygulamamızın kalbi. Hemen ilk
satırdaki 5 saniyelik uyku modu dikkatinizi çekmiştir. Maalesef MediaPlayer'ın
içerisinde bir video yükleyip oynatmaya başlamış olsak da bu işlemin tam olarak
gerçekleşip gerçekleşmediğini anlama şansımız yok. Video dosyasının büyüklüğüne
bağlı olarak dosyanın açılması uzun sürebilir. MediaPlayer'In
MediaOpened event'ı ise tam olarak tahmin ettiğiniz şekilde çalışmıyor.
Sonuç olarak en iyi seçecek 5 saniyelik bir bekleme süresi ile disk işlemlerinin
tamamlanmasını beklemek. Tabi unutmamak gerek ki tüm bu yukarıdaki kodları
harici bir Threat içerisinde yapmazsanız bu beş saniyelik sürede programınız
kilitlenecektir.
Sonraki aşamalarda biraz daha karışık bir yapı kullanarak MediaPlayer'ın
içerisinde görselliği almaya çalışıyoruz. RenderTargetBitmap
sınıfı hem oluşturulacak olan görüntünün boyutlarını piksel olarak alıyor, hem
de görüntünün dikey ve yatay olarak DPI (çözünürlük) değerini istiyor.
RenderTargetBitmap'in son parametresi ise oluşturulacak olan görseldeki renk
kanalları ile ilgili, bizim örneğimizde RGB ve Alpha kanallarını tek tek 8bit
toplam 32 bit olarak alıyoruz.
Bir DrawingVisual nesnesi yaratıp Render
işlemini de RenderOpen ile başlatarak o anki
DrawingContext'i ele alıyoruz. DrawingContext'in
DrawVideo metodu doğrudan bir MediaPlayer alarak o anki
görüntüsüyü belirtilen bir alana çizebiliyor. Son olarak
RenderTargetBitmap'in Render metodu ile eldeki
Visual'dan bir bitmap yaratıyoruz. En sonda elde
ettiğimiz BitmapFrame artık videodan almış olduğumuz son görüntüyü temsil
ediyor. Sıra geldi bu görüntüyü JPEG olarak uygun bir dosyaya yazmaya.
[VB]
Dim BMPEncoder As BitmapEncoder = New JpegBitmapEncoder
Dim FStream As New IO.FileStream("C:\Users\Public\Videos\Sample Videos\Butterfly.jpg", IO.FileMode.Create)
BMPEncoder.Frames.Add(BMPFrame)
BMPEncoder.Save(FStream)
FStream.Flush()
FStream.Close()
[C#]
BitmapEncoder BMPEncoder = new JpegBitmapEncoder();
System.IO.FileStream FStream = new System.IO.FileStream(@"C:\Users\Public\Videos\Sample Videos\Butterfly.jpg", System.IO.FileMode.Create);
BMPEncoder.Frames.Add(BMPFrame);
BMPEncoder.Save(FStream);
FStream.Flush();
FStream.Close();
JpegBitmapEncoder sınıfı bizim için JPEG sıkıştırma
işlemlerini halledecektir. Tek yapmamız gereken bir de FileStream
yaratarak Encoder'a elimizdeki BitmapFrame'i
ekleyerek FileStream'e eldeki veriyi Save
metodu ile kaydetmek. Böylece dosyamız artık hazır, videodan karemizi
istediğimiz çözünürlükte alabildik.
ASP.NET ile video dosyasından kare almak?
Konumuzla herhangi bir alakası yok gibi gözükebilir fakat aslında ASP.NET ile
bir video dosyasından kare (thumbnail) alabilmek de bir başka işkencedir. İşin
güzel tarafı .NET Framework içerisindeki tüm sınıflar aslında siz onları
referans olarak almanız şartı ile sizin kullanımınıza açıktır. Özetle,
yukarıdaki kod aynı şekilde ASP.NET'te de çalışır :) Nasıl mı?
Yukarıdaki kodumuz içerisinde kullandığımız sınıflardan MediaPlayer sınıfı
.NET Framework içerisinde PresentationCore.DLL dosyasında
bulunur. Kullandığımız diğer sınıflar ve PresentationCore.DLL'in
Dependecy assembly'si olan bir diğer DLL'te WindowsBase.DLL
dosyasıdır. Tüm bu dosyalar bilgisayarınızda C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0
adresinde bulunur. Yarattığınız herhangi bir ASP.NET sitesine bu DLL'leri
referans olarak ekledikten sonra kodunuz aynı şekilde çalışacaktır.
Hepinize kolay gelsin.
Bugün İzmir'de hosting sağlayıcılar ile bir bir eğitimimiz oldu. Benim için
çok güzel bir fırsattı :) çünkü zaten hali hazırda Türkiye'deki hosting
sağlayıcılar ile ilgili dertliyim. Şirket tarafında müşterilerimize sunduğumuz
içerik yönetim sistemlerini müşterilerimiz hosting sağlayıcılardan aldıkları
alanlara koyduklarına bir çok sorun ile karşılaşıyoruz. Bu sorunların
detaylarına inerek eğitim boyunca ASP.NET hosting yaparken nelere dikkat
edilmesi gerektiğine değindim.
 Microsoft Hosting Çözümleri Eğitimi, İzmir
Seminerlerde özellikle bana "ASP.NET 3.5 destekli hosting nasıl buluruz?"
gibi sorular geliyor. Bu soruları ve arayışı doğrudan hosting firmalarındaki
yetkililere iletme şansım oldu. İlginç bir şekilde sunucularında .NET Framework
3.5 kurulu olduğunu fakat sitelerinde hala 2.0 yazdığını söylediler :) Tabi en
kısa zamanda bu hatayı düzeltecekler. Hatta birkaç gün içerisinde SP1 yüklü
hostinglerimiz bile olacak Türkiye'de.
Bir diğer konu da tabi ki Silverlight'dı :) Silverlight'ın IIS tarafındaki
Mime Type ayarlarından ve detaylarından bahsettik.
Eğitimde kullandığım sunumu aşağıdan indirebilirsiniz.
Hosting Çözümleri Eğitimi Sunumu - 21082008_1.pptx (206,66 KB)
Server 2008 ile beraber IIS 7.0'ın gelmesi özellikle ASP.NET geliştiricileri
için büyük kolaylıklar sunuyor. Bu yazımda sizlere bu kolaylıklardan ufak bir
demet sunarken özellikle HttpModule yazma ve IIS 7.0 tarafında kullanma konusuna
değineceğim.
Web.Config içindeki hazine
Web.Config dosyası normalde biz yazılım geliştiricilerin sadece kendi
uygulamaları ile ilgili ayarları sakladıkları bir yerdi. Oysa artık IIS
içerisinde web uygulamanızın çalıştığı sitenin ayarları ile uygulamanızın
ayarlarına aynı gözle bakabiliriz. Bunun bir sonucu olarak aynı site ile ilgili
hem programatik ayarlar hem de IIS üzerindeki ayarlar artık Web.Config
içerisinde saklanıyor. Gelin Visual Studio 2008 ile yarattığımız yeni bir
ASP.NET sitesinin Web.Config dosyasının ufak bir bölümüne göz atalım.
<!--
The system.webServer section is required for running ASP.NET AJAX under Internet
Information Services 7.0. It is not necessary for previous version of IIS.
-->
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<modules>
<remove name="ScriptModule" />
<add name="ScriptModule" preCondition="managedHandler" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
</modules>
<handlers>
<remove name="WebServiceHandlerFactory-Integrated"/>
<remove name="ScriptHandlerFactory" />
<remove name="ScriptHandlerFactoryAppServices" />
<remove name="ScriptResource" />
<add name="ScriptHandlerFactory" verb="*" path="*.asmx" preCondition="integratedMode"
type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add name="ScriptHandlerFactoryAppServices" verb="*" path="*_AppService.axd" preCondition="integratedMode"
type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add name="ScriptResource" preCondition="integratedMode" verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
</handlers>
</system.webServer>
Gördüğünüz gibi normalden farklı olarak Web.Config içerisinde system.webServer
adında bir tagımız var. Zaten tag ile ilgili gerekli açıklama İngilizce
olarak hemen üstündeki yorum satırlarında yapılmış. system.webServer
tagları arasındaki ayarlar sadece IIS 7.0 içerisinde geçerli olacak ve
burada yapılan ayarlar ile bu uygulamanın çalışacağı IIS içerisinde sitedeki
modüller ve HttpHandler'lar düzenlenmiş olacak. Böylece artık IIS 7.0'a bir site
yükledikten sonra ayarlarını yapabilmeniz için harici bir web paneli kullanmanız
veya sunucuda admin haklarına sahip olmanız gerekmiyor. Doğrudan neredeyse tüm
ayarları Web.Config içerisinde düzenleyebiliyoruz.
Bu sistemin bir diğer avantajı ise kendi bilgisayarınızda çalıştığınız IIS
üzerinde yaptığınız tüm ayarların otomatik olarak sunucuya Web.Config dosyasının
atılması ile karşı tarafa da yansıması. Böylece "Benim bilgisayarımda
çalışıyor ve sunucuya atınca çalışmıyor" şikayetlerine son geliyor
diyebiliriz. Artık web sitenizi sunucuya yüklediğinizde tüm ayarlarını da karşı
tarafa aktarmış oluyorsunuz.
Ufak bir örnek...
IIS içerisinde her web sitesinin otomatik olarak açılmaya ayarlı sayfaları
vardır. Genelde bunlar default.htm, default.aspx gibi sayfalardır ve varsayılan
ayarlar ile karşımıza çıkarlar. Böylece sunucuya bir site yüklediğinizde ilk
olarak hangi sayfanın açılması gerektiği belirtilmiş olur. Eğer bu ayarı IIS
6.0'da değiştirmek isterseniz ya hosting sağlayıcınızın size bir yönetim paneli
sunması lazım ya da yine size özel script hakları ayarlaması gerekir. Oysa IIS
7.0 içerisinde bu ayar Web.Config içerisinde saklanıyor. Nasıl mı?
Bilgisayarınızda IIS 7.0 Manager'ı açarak ASP.NET web sitenizi seçin ve IIS
Manager içerisinde "Default Document" kısmına
giderek yeni bir doküman ismi ekleyin.
 IIS 7.0 içerisinde "Default Document" ayarı.
Bu yaptığınız ayarı kendi bilgisayarınıza yaptınız ve sitenizi sunucuya
yüklediğinizde tekrar yapmanız gerekecek! dersem de inanmayın. Çünkü IIS 7.0
içerisindeki bu ayar aslında söz konusu web sitesindeki Web.Config dosyasına
yazıldı, aynen aşağıdaki gibi;
<system.webServer>
<defaultDocument>
<files>
<add value="ornek.aspx" />
</files>
</defaultDocument>
</system.webServer>
Gördüğünüz gibi IIS içerisinde yeni bir "Default Document" eklemek için
aslında tek yapmanız gereken Web.Config'de gerekli tanımlamaları yapmak. Bunun
gibi daha birçok ayar tamamen Web.Config içerisine hapsedilmiş durumda. Böylece
çoğu sorundan kolayca kurtulmak mümkün.
HttpModule yazalım...
IIS 7.0'ın çalışma yapısı ile IIS 6.0'ın yapısı arasında büyük fark var. IIS
6.0'da ISAPI önünde HttpModule yazabilirken IIS 7.0'da aslında
çok daha düşük seviyelere inebiliyoruz. Örneğin ASP.NET ile yazdığınız bir
HttpModule otomatik olarak sitenizdeki tüm HTML dosyalarını ve PHP sayfaları
bile etkileyebiliyor. Bunun nedeni HttpModule'ün doğrudan IIS'in ana motoru
üzerinde çalışıyor olması, yani tam bir entegrasyon söz konusu.
Bir HttpModule yazmak için basit bir şekilde yeni bir sınıf oluşturarak
iHttpModule interface'ini implemente etmek yeterli olacaktır.
Bu işlemi yaptıktan sonra HttpApplication üzerinden bir Request işleminin tüm
event'larına ulaşabilirsiniz. Örneğin aşağıdaki gibi bir HttpModule web sayfası
içerisinde açılan her sayfanın başına bir metin ekleyecektir.
[VB]
Imports Microsoft.VisualBasic
Public Class Class2
Implements IHttpModule
Public Sub Dispose() Implements System.Web.IHttpModule.Dispose
End Sub
Public Sub Init(ByVal context As System.Web.HttpApplication) Implements System.Web.IHttpModule.Init
Dim myapp = CType(context, HttpApplication)
AddHandler myapp.BeginRequest, AddressOf myapp_BeginRequest
End Sub
Private Sub myapp_BeginRequest(ByVal sender As Object, ByVal e As System.EventArgs)
Dim myapp = CType(sender, HttpApplication)
myapp.Context.Response.Write("Deneme")
End Sub
End Class
[C#]
public class Class1 : IHttpModule
{
public Class1()
{
}
public void Dispose()
{
throw new NotImplementedException();
}
public void Init(HttpApplication context)
{
HttpApplication myapp = (HttpApplication)context;
myapp.BeginRequest += new EventHandler(myapp_BeginRequest);
}
void myapp_BeginRequest(object sender, EventArgs e)
{
HttpApplication myapp = (HttpApplication)sender;
myapp.Context.Response.Write("Deneme");
}
}
Tabi bu gibi bir HttpModule'ü kullanabilmeniz için Web.Config içerisinde
gerekli ayarlamayı da yapmanız gerekir.
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules>
<remove name="WindowsAuthentication" />
<remove name="UrlMappingsModule" />
<remove name="UrlAuthorization" />
<remove name="StaticFileModule" />
<remove name="StaticCompressionModule" />
<remove name="Session" />
<remove name="ServiceModel" />
<remove name="RoleManager" />
<remove name="RequestMonitorModule" />
<remove name="RequestFilteringModule" />
<remove name="ProtocolSupportModule" />
<remove name="Profile" />
<remove name="OutputCache" />
<remove name="IsapiModule" />
<remove name="IsapiFilterModule" />
<remove name="HttpLoggingModule" />
<remove name="HttpCacheModule" />
<remove name="FormsAuthentication" />
<remove name="FileAuthorization" />
<remove name="DirectoryListingModule" />
<remove name="DefaultDocumentModule" />
<remove name="DefaultAuthentication" />
<remove name="CustomErrorModule" />
<remove name="ConfigurationValidationModule" />
<remove name="AnonymousIdentification" />
<remove name="AnonymousAuthenticationModule" />
<remove name="ScriptModule" />
<add name="DefaultDocumentModule" />
<add name="AnonymousAuthenticationModule" />
<add
name="YeniModul"
type="Class12 />
</modules>
</system.webServer>
Yukarıdaki kod içerisinde IIS 7.0'ın mödüllerini düzenliyoruz. İlk olarak tüm
modülleri pasif hale getirerek kullanmayacağımız işlemleri iptal ediyoruz.
Sonrasında da sadece üç modül istiyoruz. Bunlardan DefaultDocumentModule
otomatik olarak varsayılan dokümanın açılmasını sağlıyor. AnonymousAuthenticationModule
ise anonim ulaşımı sağlıyor. Sonrasında da bizim yazdığımız
HttpModule'ün sınıf ismini taşıyan yeni modülümüzü ekliyoruz. Böylece
artık bu web sitesi içerisindeki tüm isteklerde bu modül de çalışacak.
İsterseniz tüm bu modül ayarlarını otomatik olarak IIS Manager içerisinde de
yapabilirsiniz. Ayarlamaları yapacağınız web sitesini seçtikten sonra "Modules"
kısmına geçerek tüm modülleri silebilir, sağ menüden "Add Managed Module"
diyerek site içerisinde yazılmış modülleri bularak ekleyebilirsiniz.
Başka neler var?
IIS 7.0 içerisinde FastCGI ile PHP desteği geliyor. Hatta PHP tarafında da
yukarıdaki HttpModule'lerin çalıştığını düşünürseniz PHP ile tüm bu modülleri
kullanabileceğiniz sonucuna varabilirsiniz. Örneğin ASP.NET Forms Authentication
modülünü PHP ile kullanabilirsiniz hatta böylece yarısı PHP yarısı ASP.NET ile
yazılmış bir sitede global Authentication sistemi bile kurmuş olursunuz. Daha bu
gibi bir çok esnekliğe sahip olan IIS 7.0 ile yazılım geliştirme ortamı
arıyorsanız Vista ile beraber IIS 7.0'ın geldiğini de hatırlatmak isterim.
Hepinize kolay gelsin.
Çok önceleri İngilizce bloguma yazdığım fakat ilginç bir şekilde Türkçe'ye
yazmadığım bir araçtan bahsetmek istiyorum. Özellikle sunumlarda çok işime
yarıyor ve sıkça kullanıyorum. En son
Soru
Merkezi'nde de bir arkadaşımız sorduğu için buraya hemen yazmaya karar
verdim.

Gördüğünüz gibi aslında araç çok basit bir iş yapıyor. Sisteminizde herhangi
bir klasöre sağ tuş ile tıkladığınızda karşınıza gelen menüden doğrudan
ASP.NET Development Server çalıştırabiliyorsunuz. Bu da ortalama 3
saniye içerisinde o klasörün içeriğini gösteren bir IIS anlamına geliyor.
Özellikle hızlı bir şekilde örnekleri veya uygulamaları incelemek için çok
başarılı bir araç. Visual Studio ile projeyi açıp F5'e basmaktan veya klasör
için IIS üzerinde ayar yapmaktan pratik olduğu kesin.
ASP.NET Development Server Kısayol Aracı - 19062007_1.msi (355 KB)
Uygulamayı yazan Infragistics'ten J. Ambrose Little'a
buradan teşekkürlerimizi de yolluyoruz ;)
WPF teknolojisi Windows uygulamalarında bize iki ve üç boyutlu animasyonlarla
zengin kullanıcı arayüzleri hazırlama şansı tanırken WPF Browser
Application (XBAP) yapısı ile beraber bu uygulamaları istersek İnternet
Tarayıcısı içerisine de taşıyabiliyoruz. Tabi bu noktada istemci tarafında ufak
ve sıkıcı bir ihtiyacımız var; .NET Framework. WPF Browser Application projenizi
geliştirirken kullanmış olduğunuz .NET Framework sürümünün istemcilerde de yüklü
olması şart. Browser Application şablonu Expression Blend ile beraber gelmese de
Visual Studio içerisinde böyle bir proje yaratılarak aynı proje rahatlıkla
Expression Blend ile beraber açılabiliyor.
Örneğimizde basit bir uygulama yaparak iki metin kutusu, bir düğme ve bir de
etiket (TextBlock) kullanacağız. TextBox'lar içerisine yazılan değerler bir
web
servisine gönderilecek ve web servisi söz konusu değerlerin toplamını alarak
uygulamamıza geri verecek. Normalde tabi ki çok basit bir şekilde bu işlem
istemci tarafında WPF ile halledilebilir fakat bizim amacımız bir web servisi
kullanarak WPF Browser Application içerisinden sunucuya veri
göndererek veri alabiliyor olmak. Böylece rahatlıkla sunucu tarafındaki uygulama
da kendisine gelen verilere göre herhangi bir veritabanı sistemini sorgulayarak
uygun bilgileri geri döndürebilecektir.
WPF Browser Application'ı tasarlayalım...
İlk olarak uygulamamızı Visual Studio içerisinde "File / New Project"
menüsünden "WPF Browser Application" proje şablonunu seçerek
yarattıktan sonra görsel tasarımını tamamlayalım. Uygulama içerisine otomatik
olarak yerleştirilecek olan ana sayfamız "Page1.XAML" dosyasını doğal olarak
Expression Blend ile düzenlememiz gerekiyor. Bunun için Visual Studio içerisinde
yarattığımız bu projeyi Expression Blend ile de açarak XAML dosyasını
düzenlememiz gerek.
<Page x:Class="Page1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Page1">
<Grid Width="250" Height="400">
<Grid.RowDefinitions>
<RowDefinition Height="0.168*"/>
<RowDefinition Height="0.155*"/>
<RowDefinition Height="0.132*"/>
<RowDefinition Height="0.545*"/>
</Grid.RowDefinitions>
<TextBox Text="TextBox" TextWrapping="Wrap" x:Name="Kutu1"/>
<TextBox Grid.Row="1" Text="TextBox" TextWrapping="Wrap" x:Name="Kutu2"/>
<Button Grid.Row="2" Content="Button" HorizontalAlignment="Center" Width="100" Height="40" x:Name="Dugme"/>
<Label Margin="8,8,8,0" VerticalAlignment="Top" Height="27" Grid.Row="3" Content="Label" x:Name="Etiket"/>
</Grid>
</Page>
Hazırlamış olduğumuz uygulamanın yukarıdaki XAML kodunu incelediğinizde
ekranda iki adet metin kutusu, bir düğme ve bir de TextBlock olduğunu
göreceksiniz. Tüm bu kontrolleri bir Grid içerisine yerleştirerek ekranda sabit
bir şekilde görünmelerini sağlıyoruz.
Web servisimizi hazırlayalım
Sıra geldi web servisimizi hazırlamaya. Bunun için Visual Studio içerisinde
üzerinde çalıştığımız Solution yapısına yeni bir ASP.NET 3.5 web projesine
ekleyeceğiz. "File / Add / New Project" menüsünden "ASP.NET Web Application"
seçeneğinden ilerleyebilirsiniz. Yarattığımız web sitesine "WebService1.asmx"
adında yeni bir web servisi
ekleyerek aşağıdaki şekilde kodumuzu yerleştirelim.
[VB]
Imports System.Web.Services
Imports System.Web.Services.Protocols
Imports System.ComponentModel
<System.Web.Services.WebService(Namespace:="http://tempuri.org/")> _
<System.Web.Services.WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<ToolboxItem(False)> _
Public Class WebService1
Inherits System.Web.Services.WebService
<WebMethod()> _
Public Function
Topla(ByVal x As Integer, ByVal y As Integer) As Integer
Return x + y
End Function
End Class
[C#]
using System;
using System.Collections;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml.Linq;
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class WebService : System.Web.Services.WebService
{
public WebService()
{
}
[WebMethod]
public int Topla(int x, int y)
{
return x + y;
}
}
Sıra geldi bu web servisini WPF Browser Application içerisinde kullanmaya.
Reference ekleyelim
Web servisinizi hazırladıktan sonra rahatlıkla WPF Browser Application
projenize sağ tıklayarak ve "Add Service Reference" diyerek web servisinizi
bulup referans olarak ekleyebilirsiniz. Sonrasında normal bir Winforms
uygulamasında olduğu gibi uzaktaki servisi kullanabilirsiniz.
[VB]
Class Page1
Private Sub Dugme_Click(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Dugme.Click
Dim Servis = New ServiceReference1.WebService1SoapClient
Etiket.Content = Servis.Topla(Kutu1.Text, Kutu2.Text)
End Sub
End Class
[C#]
public partial class Page1 : Page
{
private void Dugme_Click(object sender, RoutedEventArgs e)
{
ServiceReference1.WebServiceSoapClient Servis = new WpfBrowserApplication1.ServiceReference1.WebServiceSoapClient();
Etiket.Content = Servis.Topla(int.Parse(Kutu1.Text), int.Parse(Kutu2.Text)).ToString();
}
}
Yukarıdaki kodumuzda basit bir şekilde ServiceReference1
üzerinde servisimizi tanımlayarak içerisindeki Topla metodunu
kullanıyoruz. Sonucu da WPF uygulamasında Etiket adındaki
TextBlock içerisine yazdırıyoruz.
Sorunlar baş gösteriyor...
Fakat ufak bir sorun var. WPF Browser Application'ı Visual Studio içerisinden çalıştırdığınızda doğrudan dosya sistemi
üzerinden çalıştırılacaktır, yani IIS veya ASP.NET Development Server devreye
girmeyecektir. Oysa bizim web servisi ASP.NET Development Server üzerinde
çalışmak zorunda. Visual Studio'nun web servisini ASP.NET Development Server
üzerinden çalıştırırken WPF Browser Application'ı dosya sisteminden çalıştırması
bizi büyük bir sorunla baş başa bırakacak; "Güvenlik".
Artık hem AJAX hem de Silverlight nedeniyle çoğumuzun bildiği üzere istemci
tarafında bir alan adından yola çıkarak başka bir alan adına bağlanıp veri alımı
veya gönderimi yapamazsınız. WPF Browser Application dosya sisteminden
başlatıldığında maalesef web servisini "başka bir alan adında" olarak
algılayacağı için veri trafiği gerçekleşmeyecektir. Bu durumda yapılacak şey
belli; WPF Browser Application'ı bizim web servisi ile aynı projeye "output"
ettirmemiz, aslında Publish etmemiz gerek.
WPF Browser Application projenize sağ tuş ile tıklayın ve "Publish" komutu
verin. Yayınlanacak konum olarak web servisinize ait dosyaların bulunduğu
ASP.NET sitenizin ana klasörünü gösterin. Böylece WPF Browser Application
hazırlanarak web sitenize yerleştirilmiş olacak. Şimdi ASP.NET Development
Server üzerinden XBAP dosyasını açabilir ve uygulamanızı gönül rahatlığı ile
kullanabilirsiniz.
Hepinize kolay gelsin.
Bugün Edirne M.P. Anadolu Ticaret Meslek ve Ticaret Meslek
Lisesi'nin organizasyonunu üstlendiği Edirne'deki meslek liseleri'nin
yer aldığı bir seminer serisindeydim. Semineri Trakya Birlik Genel
Müdürlüğü Konferans Salonu'nda yaptık. Salon şu ana kadar gördüğüm en
ilginç ve güzel salonlardan biriydi. Balkonuyla beraber iki katlı seminer
salonunda alt kattaki ve üst kattaki dinleyiciler için ayrı projeksiyon
sistemlerinin bulunması dinleyici için çok ergonomik bir ortam sağlıyor.
 Edirne'ye gidip Selimiye Cami fotoğrafı çekmemek olmaz :)
Sabah 09.00 gibi seminerlere başladığımız için bir gün önceden Edirne'ye
gitmek durumunda kaldım. Dün akşam 20.00 gibi Edirne'deydim, Meriç kenarında bir
yemek yeme şansına sahip olmak muhteşemdi. Aslında otobüsle iki buçuk saat gibi
kısa bir sürede gidilebilen Edirne'yi (kendi adıma konuşayım) sanki biraz
farkında değiliz veya unutmuşuz gibime geldi. Rahatlıkla günübirlik gidip
gezilebilecek bir şehir.
 Selimiye Kubbesi İç Motifler
09.00'da başladıktan sonra öğleden sonra 18.00'a kadar WPF,
Silverlight ,AJAX ve LINQ konularına değindik. Bu benim ikinci Meslek
Lisesi deneyimim oldu. Lise çağındaki gençlere hitap edebilmek adına daha çok
çalışmam gerektiğini açıkça itiraf edebilirim :) Yine de aldığım tepkilere göre
faydalı bir gün geçirdik, parıldayan genç gözler gördüm.
 Edirne, MP (Anadolu) Ticaret Meslek Lisesi, WPF, Silverlight, AJAX, LINQ Seminerleri
Aktivite boyunca Edirne TV :) de oradaydı. Hatta sitelerinde de
aktiviteyi haber yyapmışlar. Özellikle sitedeki fotoğrafta biraz çok agresif
çıkmışım :) Zaten herkes sahnede rahat durmadığım için fotoğraf çekememekten
şikayetçi :)
Organizasyondaki emeklerinden dolayı sevgili Serdar Daloğlu'na
, Aziz Bayıroğlu ve Oğuzcan Şahin'e burada bin bir teşekkür ediyorum. Beni
muhteşem bir şekilde ağırlamanın yanı sıra organizasyondaki her tür detayı çok
başarılı bir şekilde yürüttüler.
Varsayalım ki web sitenizde belirli aktiviteleri paylaşıyorsunuz veya belki
de toplantıları. İnsanların buluşma tarihlerini bir kenara not almalarını ve
sonra da günü geldiğinde hatırlamalarını istiyorsunuz. Artık çoğu kullanıcının
bir şekilde dijital ortamda takvim tuttuğunu varsayarsak neden onlara söz konusu
aktivitelerini hızlı bir şekilde takvimlerine ekleme olanağı tanımlayalım? Şükür
ki bu konuda genel geçer bir standart var; VCalendar!
VCalendar standardı çoğu dijital takvim uygulaması ile uyumlu bir standart.
Yapacağımız örnekte bir Generic Handler (ashx) kullanacağız. Söz konusu handler
bize VCalendar davetiye dosyaları oluşturarak verecek. Siz
uygulamalarınızda ashx dosyasına QueryString üzerinden parametreler göndererek
farklı VCalendar dosyaları oluşturabilirsiniz.
context.Response.ContentType = "application/download"
İlk olarak yukarıdaki şekilde istemciye göndereceğimiz verinin download
edilmesi gereken bir uygulama dosyası olduğunu belirtelim. Böylece istemcideki
tarayıcı bir download penceresi açacaktır. VCalendar dosyaları vcs uzantılıdır,
istemciye doğrudan gönderdiğimiz istemcide kullanıcı bunu ister Outlook ile açar
ister farklı bir uygulama ile kullanır, karar tamamen kullanıcıya kalmış.
[VB]
Dim BasTarih As Date = Date.Now
Dim SonTarih As Date = Date.Now.AddDays(1)
Dim Konum As String = "İstanbul - MS Binası"
Dim Konu As String = "VCalendar Toplantısı"
Dim Detay As String = "Toplantı VCalendar standartları görüşülecek. "
[C#]
System.DateTime BasTarih = System.DateTime.Now;
System.DateTime SonTarih = System.DateTime.Now.AddDays(1);
string Konum = "İstanbul - MS Binası";
string Konu = "VCalendar Toplantısı";
string Detay = "Toplantı VCalendar standartları görüşülecek. ";
Bir sonraki adımda yukarıdaki şekilde parametrelerimizi tanımlayalım. Bu
parametreleri siz uygulamalarınızda veritabanına bağlayabilirsiniz.
Yaratacağımız VCalendar dosyası buradaki bilgileri içerecek.
[VB]
Dim BirStream As New IO.MemoryStream()
Dim Yazici As New IO.StreamWriter(BirStream)
Yazici.AutoFlush = True
[C#]
System.IO.MemoryStream BirStream = new System.IO.MemoryStream();
System.IO.StreamWriter Yazici = new System.IO.StreamWriter(BirStream);
Yazici.AutoFlush = true;
VCalendar dosyaları özünde text (metin) bazlı dosyalardır. O
nedenle aslında sunucu tarafında bir metin yaratarak Binary
olarak istemciye göndereceğiz. Bu nedenle istemciye göndereceğimiz tüm içeriği
oluştururken elimizde bir Stream ve StreamWriter
olması gerekiyor. Söz konusu Stream herhangi bir konuma yazdırılmayacağı için
havada bir MemoryStream yaratarak ilerliyoruz. Söz konusu
StreamWriter'ın AutoFlush özelliğini True
olarak aktardığımızda artık tüm içerik otomatik olarak Stream'e aktarılıyor
olacak.
Yazici.WriteLine("BEGIN:VCALENDAR")
Yazici.WriteLine("PRODID:-//daron.yondem.com")
Yazici.WriteLine("BEGIN:VEVENT")
Yukarıdaki VCalendar standartlarına uygun dosyamızı yaratmaya başladık.
PRODID özelliğine aktardığınız değer çok önemli değil. Aslında bu VCalendar
dosyasını yaratan programın adını içermesi yeterli.
[VB]
Yazici.WriteLine("DTSTART:" & BasTarih.ToUniversalTime.ToString("yyyyMMdd\THHmmss\Z"))
Yazici.WriteLine("DTEND:" & SonTarih.ToUniversalTime.ToString("yyyyMMdd\THHmmss\Z"))
Yazici.WriteLine("LOCATION:" & Konum)
Yazici.WriteLine("DESCRIPTION;ENCODING=QUOTED-PRINTABLE:" & Detay)
Yazici.WriteLine("SUMMARY:" & Konu)
[C#]
Yazici.WriteLine("DTSTART:" + BasTarih.ToUniversalTime().ToString("yyyyMMdd\\THHmmss\\Z"));
Yazici.WriteLine("DTEND:" + SonTarih.ToUniversalTime().ToString("yyyyMMdd\\THHmmss\\Z"));
Yazici.WriteLine("LOCATION:" + Konum);
Yazici.WriteLine("DESCRIPTION;ENCODING=QUOTED-PRINTABLE:" + Detay);
Yazici.WriteLine("SUMMARY:" + Konu);
Gördüğünüz gibi neredeyse tüm parametrelerimizi burada dosyamıza ekledik.
Önemli olan noktalardan biri tüm tarih bilgilerinin ilk olarak
UniversalTime'a yani global olarak geçerli zaman dilimine uyarlanması
gerektiği. İkincisi ise tarih dosyaya yazdırılırken uyulması gereken format.
Sonraki satırlarda diğer parametrelerimizi de aktardıktan sonra devam
edebiliriz.
[VB]
Yazici.WriteLine("PRIORITY:3")
Yazici.WriteLine("BEGIN:VALARM")
Yazici.WriteLine("TRIGGER:-PT30M")
Yazici.WriteLine("ACTION:DISPLAY")
Yazici.WriteLine("DESCRIPTION:" & Konu)
Yazici.WriteLine("END:VALARM")
Yazici.WriteLine("END:VEVENT")
Yazici.WriteLine("END:VCALENDAR")
[C#]
Yazici.WriteLine("PRIORITY:3")
Yazici.WriteLine("BEGIN:VALARM")
Yazici.WriteLine("TRIGGER:-PT30M")
Yazici.WriteLine("ACTION:DISPLAY")
Yazici.WriteLine("DESCRIPTION:"
+ Konu)
Yazici.WriteLine("END:VALARM")
Yazici.WriteLine("END:VEVENT")
Yazici.WriteLine("END:VCALENDAR")
Kodumuzun ilk satırında bu aktivitenin ne kadar önemli olduğuna dair bir
değer aktardıktan sonra aktivite ile ilgili bir alarm ayarlıyoruz. PT30M ayarı
ile aktiviteden yarım saat önce kullanıcının uyarılması gerektiğini belirtmiş
olduk. Siz bu ayarları istediğiniz gibi değiştirebilirsiniz. Son olarak hem
VEVENT gem de VCALENDAR'ı kapatarak dosyamızı sonlandırıyoruz.
[VB]
context.Response.AppendHeader("Content-Disposition", "attachment; filename=aktivite.vcs")
context.Response.AppendHeader("Content-Length", BirStream.Length.ToString())
context.Response.BinaryWrite(BirStream.ToArray())
[C#]
context.Response.AppendHeader("Content-Disposition", "attachment; filename=aktivite.vcs");
context.Response.AppendHeader("Content-Length", BirStream.Length.ToString());
context.Response.BinaryWrite(BirStream.ToArray());
Sıra geldi oluşturduğumuz dosyayı istemciye göndermeye. İlk olarak istemciye
gönderdiğimiz HTTPResponse'a bazı header bilgileri eklememiz gerekiyor.
Bunlardan ilki istemcinin aldığı dosyayı hangi isimle açacağı. Bizim örneğimizde
dosya adı aktivite.vcs şeklinde yer alıyor. İkincisi ise
oluşturduğumuz dosyanın boyutu. Son olarak Response.BinaryWrite
ile elimizdeki Stream'i istemciye gönderiyoruz.
Eğer istemci bu adresi doğrudan açarsa karşısına bir VCalendar download
penceresi gelecektir. Yarattığımız ashx dosyasını farklı aspx dosyaları
içerisinde linkleyerek kullanıcıların linklere bastıklarında VCalendar
dosyalarını indirebilmelerini sağlayabilirsiniz.
Generic Handler'ımızın son hali ile aşağıdaki şekilde;
[VB]
<%@ WebHandler Language="VB" Class="vcalendar" %>
Imports System
Imports System.Web
Public Class vcalendar : Implements IHttpHandler
Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
context.Response.ContentType = "application/download"
Dim BasTarih As Date = Date.Now
Dim SonTarih As Date = Date.Now.AddDays(1)
Dim Konum As String = "İstanbul - MS Binası"
Dim Konu As String = "VCalendar Toplantısı"
Dim Detay As String = "Toplantı VCalendar standartları görüşülecek. "
Dim BirStream As New IO.MemoryStream()
Dim Yazici As New IO.StreamWriter(BirStream)
Yazici.AutoFlush = True
Yazici.WriteLine("BEGIN:VCALENDAR")
Yazici.WriteLine("PRODID:-//daron.yondem.com")
Yazici.WriteLine("BEGIN:VEVENT")
Yazici.WriteLine("DTSTART:" & BasTarih.ToUniversalTime.ToString("yyyyMMdd\THHmmss\Z"))
Yazici.WriteLine("DTEND:" & SonTarih.ToUniversalTime.ToString("yyyyMMdd\THHmmss\Z"))
Yazici.WriteLine("LOCATION:" & Konum)
Yazici.WriteLine("DESCRIPTION;ENCODING=QUOTED-PRINTABLE:" & Detay)
Yazici.WriteLine("SUMMARY:" & Konu)
Yazici.WriteLine("PRIORITY:3")
Yazici.WriteLine("BEGIN:VALARM")
Yazici.WriteLine("TRIGGER:-PT30M")
Yazici.WriteLine("ACTION:DISPLAY")
Yazici.WriteLine("DESCRIPTION:" & Konu)
Yazici.WriteLine("END:VALARM")
Yazici.WriteLine("END:VEVENT")
Yazici.WriteLine("END:VCALENDAR")
context.Response.AppendHeader("Content-Disposition", "attachment; filename=aktivite.vcs")
context.Response.AppendHeader("Content-Length", BirStream.Length.ToString())
context.Response.ContentType = "application/download"
context.Response.BinaryWrite(BirStream.ToArray())
End Sub
Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
Get
Return False
End Get
End Property
End Class
[C#]
<%@ WebHandler Language="C#" Class="Handler" %>
using System;
using System.Web;
public class Handler : IHttpHandler {
public void ProcessRequest (HttpContext context) {
context.Response.ContentType = "application/download";
System.DateTime BasTarih = System.DateTime.Now;
System.DateTime SonTarih = System.DateTime.Now.AddDays(1);
string Konum = "İstanbul - MS Binası";
string Konu = "VCalendar Toplantısı";
string Detay = "Toplantı VCalendar standartları görüşülecek. ";
System.IO.MemoryStream BirStream = new System.IO.MemoryStream();
System.IO.StreamWriter Yazici = new System.IO.StreamWriter(BirStream);
Yazici.AutoFlush = true;
Yazici.WriteLine("BEGIN:VCALENDAR");
Yazici.WriteLine("PRODID:-//daron.yondem.com");
Yazici.WriteLine("BEGIN:VEVENT");
Yazici.WriteLine("DTSTART:" + BasTarih.ToUniversalTime().ToString("yyyyMMdd\\THHmmss\\Z"));
Yazici.WriteLine("DTEND:" + SonTarih.ToUniversalTime().ToString("yyyyMMdd\\THHmmss\\Z"));
Yazici.WriteLine("LOCATION:" + Konum);
Yazici.WriteLine("DESCRIPTION;ENCODING=QUOTED-PRINTABLE:" + Detay);
Yazici.WriteLine("SUMMARY:" + Konu);
Yazici.WriteLine("PRIORITY:3");
Yazici.WriteLine("BEGIN:VALARM");
Yazici.WriteLine("TRIGGER:-PT30M");
Yazici.WriteLine("ACTION:DISPLAY");
Yazici.WriteLine("DESCRIPTION:" + Konu);
Yazici.WriteLine("END:VALARM");
Yazici.WriteLine("END:VEVENT");
Yazici.WriteLine("END:VCALENDAR");
context.Response.AppendHeader("Content-Disposition", "attachment; filename=aktivite.vcs");
context.Response.AppendHeader("Content-Length", BirStream.Length.ToString());
context.Response.BinaryWrite(BirStream.ToArray());
}
public bool IsReusable {
get {
return false;
}
}
}
Hepinize kolay gelsin.
ASP.NET uygulamalarında Date.Now() gibi çoğu sınıf o anki
CurrentCulture
üzerinden gerekli bilgileri alarak çalışır. Yani uygulamanın çalıştığı makinen
Regional Settings'i Türkiye'ye göre ayarlanmış ise tarih bilgisi ona göre
gelecektir. Bu durum genelde sıkıntı yaratmasa da özellikle yurt dışından
hosting (barındırma) hizmeti aldığınızda sıkıntılar baş göstermeye başlar. Eğer
uygulamanız farklı ülkelere ve dillere hizmet edecek şekilde bir altyapıya sahip
değilse veya buna gerek yoksa aslında uygulamanın her şart altında belirli bir
CurrentCulture ile çalışmasını isteyebilirsiniz.
Varsayalım satın aldığınız hosting firması yurt dışında olduğu için
sunucularını yüklerken "Regional Settings"de sunucu ayarı olarak İngilizceyi
seçtiler. Bu durumda Date.Now() dahil kullandığınız çoğu sınıf geriye farklı
formatlarda değerler döndürecektir. Örneğin bizde sıfırdan küçük sayılar virgül
ile ayrılırken İngilizce ayarlanmış bir sunucuda nokta ile ayrılacaktır. Bu gibi
sıkıntıları toptan çözmek için Web.Config içerisinde yapabileceğiniz bir ayar
var.
<system.web>
<globalization culture="tr-TR" uiCulture="tr-TR" />
</system.web>
Yukarıdaki şekilde Web.Config içerisindeki System.Web tagları arasına uygun
satırı yerleştirmeniz yeterli. Artık tüm uygulama herşeyden bağımsız olarak
Türkiye'ye ve Türkçe'ye göre çalışacaktır.
<%@ Page UICulture="tr-TR" Culture="tr-TR" %>
Ayrıca isterseniz bu ayarı her aspx (web form) için ayrı ayrı da
yapabilirsiniz. Yukarıdaki şekilde herhangi bir web forumun mark-up kısmına
Page için UICulture ve Culture
ayarlarını tanımlayabilirsiniz.
Hepinize kolay gelsin...
Herhangi bir web sitesine bir ASP.NET uygulaması yerleştirdiğinizde otomatik olarak uygulama
ile beraber Web.Config dosyasını da sunucuya yerleştirmiş olursunuz. Bazı
durumlarda (benim blogda olduğu üzere) birden çok ASP.NET uygulamasını tek bir
alan adı altında çalıştırmanız gerekebilir. Bu uygulamaları iç içe klasörlerle
ayırmak vs pek işe yaramaz çünkü kök klasörde bulunan Web.Config içerisinde tüm
ayarlar alt klasörleri de otomatik olarak etkiler. Yani bir "inheritance" durumu
söz konusudur.
Kök dizindeki Web.Config içerisindeki tüm ayarları tek tek iç dizinlerdeki
Web.Config'ler içerisinde "remove" etmek mümkün fakat çok zahmetli bir iş. Diğer
yandan bazı durumlarda farklı ASP.NET sürümlerini de aynı site içerisinde
kullanmak isteyebilirsiniz, örneğin benim blog ASP.NET 2.0 kullanırken aktivite
kayıt uygulamam ASP.NET 3.5 ile hazırlandı.
İşin kolayı!
Herhangi bir Web.Config dosyası içerisindeki ayarları "inheritance" ile alt
klasörlerini geçmesini istemiyorsanız aslında yapacağınız çok ufak bir ayar var.
<location path="." inheritInChildApplications="false">
<system.web>
<!--Tüm ayarlar burada-->
</system.web>
</location>
Web.Config dosyanız içerisinde tüm ayarların bulunduğu
System.Web taglarını
ayrıca bir location tagı içerisine alarak söz konusu location tagının da
inheritInChildApplications özelliğini False
olarak ayarlarsanız artık kök dizindeki ayarlarınız diğer dizinler tarafından
kullanılmayacaktır. Böylece rahatlıkla yeni uygulamalarınızı aynı alan adına
yükleyebilirsiniz.
Hepinize kolay gelsin...
.NET Framework 3.0 ile beraber gelen WPF, WCF ve WF sonrasında VS 2008 ve
.NET Framework 3.5 derken aslında epey bir yenilik ile karşı karşıya kaldık. Bu
konularda Microsoft'un sertifikasyonlarında şu ana kadar yeni bir sistem
oluşturulmamıştı, zaten bu konularda sertifikasyon sınavları da yoktu. Oysa
artık sizlere güzel haberlerim var; Visual Studio 2008 ile beraber yeni
sertifikasyonlar ve sınavlar tam olarak belli oldu.
 Visual Studio 2008 MCTS Sertifikasyon Sınavları
Yukarıdaki görselde de görebileceğiniz üzere toplam altı adet yeni MCTS
sertifikasyonu söz konusu. Her biri özellikle .NET Framework 3.5 olarak
isimlendirimiş durumda. WPF, WCF ve WF'i görmek gerçekten hoş. Diğer yandan
ADO.NET'in ayrı bir sertifikasyon yolu olarak seçilmesi ise gerçekten ilginç.
Yukarıdaki sınavlardan 70-502,503 ve 504 şu an açık durumda. Diğerleri
önümüzdeki aylarda açılacak.
 Visual Studio 2008 MCPD Sertifikasyon Sınavları
MCPD yolunda da ilginç gelişmeler var. Windows Developer ve EA Developer'ın
sonuna .NET Framework'ün sürüm numarası eklenmiş. Böylece hangi sürümün yazılım
geliştiricisi olduğunuz doğrudan belli olacak. Web Developer sertifikasyonu ise
artık yok, onun yerine ASP.NET Developer 3.5 şeklinde yeni bir sertifikasyon
var. Aslında bu çok doğru bir adım olmuş. Çünkü Web Developer adı çok daha geniş
kapsamlı, oysa sınavlarda doğal olarak sadece Microsoft ürünleri soruluyor. O
nedenle ASP.NET Developer adı bence çok daha uygun olmuş.
 Visual Studio 2008'e Upgrade Sertifikasyon Sınavları
Her zamanki gibi eski sertifikalı uzmanlar için "upgrade" sınavları da
olacak. Yükseltme sınavları ile ilgili detayları yukarıdan inceleyebilirsiniz.
Bu sınavların da daha hiçbiri yayında değil.
Yeni sertifikasyonlar ve sınavlar gerçekten güzel organize edilmiş. Ben
heyecanla Expression ürün ailesi ve Silverlight sınavlarını bekliyorum. Umarım
WPF, WCF ve WF için beklediğimiz kadar beklemek zorunda kalmayız.
Hepinize kolay gelsin.
PCnet'in Nisan sayısındaki yazılarımı her ay olduğu gibi yine buradan sizlere duyurmak
istiyorum :) Derginin
OKUL bölümünde AJAX, ASP.NET 3.5,
Expression Blend ve Silverlight ile ilgili yazılarım yer alıyor.
AJAX : ASP.NET AJAX İstemci Özellikleri
Expression Blend : WPF ile zengin doküman uygulamaları
Silverlight: Silverlight ve video dünyası
ASP.NET 3.5 : Bir sitenin ekran görüntüsünü ASP.NET ile nasıl
alırsınız? Hepinize sevgiler.
Son iki gündür Isparta, Süleyman Demirel Üniversitesi'ndeydim.
İki gün boyunca Silverlight, WPF, ASP.NET 3.5 AJAX ve LINQ
konularına değindik. SDÜ zaten daha önce de öğrencilerinden bana gelen soru
mailleri ile beni şaşırtan bir üniversite olmuştu. Bu ziyaretimde de epey şaşkın
anlar yaşadım. Peki neye şaşırdım? SDÜ'de şu an Silverlight ve WPF konularında
bitirme projeleri hazırlayan kardeşlerimiz var. Daha çoğu üniversitede bu
konuların birer mistik ütopya olarak dolaştığını düşünürsek SDÜ öğrencileri
ciddi şanslı. Seminerler boyunca gelen sorular ortalamanın çok üstünde bir
seviyeye sahipti.
 Süleyman Demirel Üniversitesi, Isparta
Buradan özellikle SDÜ'den sevgili Eğitim Görevlisi dostum Mehmet
Albayrak'a ilgisi, misafirperverliği ve organizasyondaki katkısı için
çok teşekkür ediyorum. Ayrıca tabi ki güler yüzleri ve teknoloji aşkları ile
beni hem şaşırtan hem de sevindiren katılımcılara, SDÜ öğrencilerine de çok
teşekürler. Kısa zamanda yakaladığım ufak bir manzara fotoğrafı ile buradan
Ispartaya tekrar selamlar.
 Eğirdir Gölü Tepesi, Isparta
Dün INETA ve TBD işbirliği ile düzenlediğimiz
"4 Konu 4 Gün" eğitim serisinin
ilk gününü tamamladık. "ASP.NET 3.5 AJAX" konusunu ele aldığımız gün boyunca
teknik detaylara boğulmanın yanı sıra bir "Pazar" gününün şanına değer bir
şekilde eğlenmeyi de unutmadık :) Özellikle öğle yemeği araları muhteşem :)
Eğitim ortamımızı size biraz anlatmam gerekirse, "çantasından çikolatasını
çıkartarak sınıfıyla paylaşan" arkadaşlarımızdan, "herkes açlıktan ölürken
(sadece ben değil) sadece bir tabak çorba içip, Ben Doydum diyebilen
arkadaşlarımıza kadar renkli bir perspektife sahiptik :) Hah bir de okuldaki
derslerini düşünen "dertli kerime"miz vardı :) Sanırım bir pazar gününü hem bu
kadar eğlenceli hem de verimli geçirmek adına ciddi bir başarı sağladık.
 ASP.NET 3.5 AJAX Günü
Katılan herkese çok teşekkür ediyorum. Büyük zevk aldım. Fotoğraf çekilmeye
kadar kalamayan ve bir saat öncesinde kaçan arkadaşları da şiddetle kınıyoruz :)
Gün boyunca yaptığımız bazı örnekleri aşağıdan indirebilirsiniz.
Örneklere ait kaynak kodları - 24032008_1.zip (26,94 KB)
Ücretsiz eğitim konseptinde düzenlediğimiz INETA ve NETRON sponsorluğundaki
Silverlight 1.0 eğitimine gelen ve gelmeye devam eden büyük ilgi daha önce de
tahmin ettiğim bir durumdu. Bu konuda maalesef "talihli" olamayıp seçilemeyen
arkadaşlar haklı olarak sitemkar mailler gönderiyorlar. Emin olun bu tarz
aktivitelere devam edeceğiz, mekan sponsorları aramaya devam ediyorum.
Bundan yaklaşık bir ay kadar öncesinde sevgili Burcu Kutlu
ile temellerini attığımız bir diğer etkinliği bugün sizlere duyurmak istiyorum.
Bu sefer de INETA ve TBD Genç işbirliği ile
birer tam günlük dört farklı konuda bilgisayar başında eğitimler açıyoruz. "Bir
günlük eğitim mi olur?" derseniz aslında haklısınız ama en azından kendi
adıma düşündüğümde 3 saatlik seminerlerimden sonraki adım diyebilirim. Diğer
Silverlight eğitimini 3 gün olarak tasarlamıştık. Umarım yakında bu gibi
ücretsiz eğitimlerin sayısını arttıracağız. Bu seferlik dört konu, dört gün ;)
23 Mart - ASP.NET 3.5 AJAX
30 Mart - Silverlight
6 Nisan - Expression Blend ve WPF
13 Nisan - ASP.NET 3.5 ve LINQ
Eğitim saatleri her gün 10.00-18.00 arasında, eğitim yeri
TBD İstanbul (Ali Ruhi Sok. No:2, K.3, Hasanpaşa/ Kadıköy).
Kayıt için bu adresi kullanabilirsiniz;
http://www.tbdgenc.org/index.php?page=activityjoin&lang=tr&id=29
Buradan özellikle tekrar sevgili Burcu Kutlu'ya aktivitenin
organizasyonundaki yoğun emekleri için çok teşekkür ediyorum.
PCnet'in Mart sayısındaki yazılarımı her ay olduğu gibi yine buradan sizlere duyurmak
istiyorum :) Derginin
OKUL bölümünde AJAX, ASP.NET 3.5,
Expression Blend ve Silverlight ile ilgili yazılarım yer alıyor.
AJAX : İnce ayar AJAX.
Expression Blend : WPF tasarımında görsel kaynaklar
Silverlight: Silverlight projelerinin bileşenleri
ASP.NET 3.5 : ASP.NET 3.5 Veri Kontrolleri Hepinize sevgiler.
Dün verdiğim sözü tutmanın zamanı geldi. Sizlerle kodlarını paylaştığım
mini projenin içerisindeki önemli birkaç noktayı öne çekerek mini bir XLINQ ve VB
şovu yapmak istiyorum :) Üzgünüm C# cılar .Element veya
.Elements gibi metodlarla uğraşmak zorunda kalacaklar ve benim güzel
VB'mi bırakarak ek metotlar kullanmaya niyetim yok :) Ayrıca paylaştığım proje
de VB ile yazılmış durumda o nedenle bu yazı da full VB olacak.
(Sektörde benim kadar agresif C#'a saldıran yok :)
Allah sonumu hayır etsin:) Bu arada C#'ı severim yani ama herkes yerinde sağ
olsun ;))
Kodlara geçmeden önce gelin projenin kullandığı XML dosyalarının yapısına bir
göz atalım.
<?xml version="1.0" encoding="utf-8"?>
<Olay>
<Tag>223257</Tag>
<Icerik>1112567</Icerik>
<Katilimci>0</Katilimci>
<Katilan Adi="Ercan
Altuğ Yılmaz" Mail="hebele@gubele.com" Tel="0900900900:)" />
<Katilan Adi="İbrahim
Demir" Mail="hebele@gubele.com" Tel="0900900900" />
</Olay>
Projedeki her bir aktivite için aktivitenin TAG ozelliği ile
aynı isme sahip bir XML dosyası oluşturuluyor. Ayrıca TAG
bilgisi neden dosyanın içerisine de kaydetmişim bilmiyorum :) Şimdi kodumu
okurken saçma olduğunu gördüm. Neyse gece yarısı aceleyle herhangi bir planlama
olmadan kod yazılırsa böyle olur :) Yukarıdaki gibi yaratacağımız XML
dosyalarında Olay kök elementinin içerisinde Icerik
kısmına söz konusu aktivite ile ilgili açıklamaları içerecek olan HTML kodları
yerleştirilecek. Maksimum katılımcı sayısı Katilimci tagları
arasına yazılacak. Sonrasında aktiviteye kayıt olan herkesin bilgisi
Katilan taglarındaki gibi bu dosyaya eklenecek.
kayit.aspx
Bu dosyayı herhangi bir kaydı göstermek veya düzenlemek için kullanacağız.
Eğer bu dosyaya herhangi bir aktivitenin tag bilgisi adres üzerinden ?tag=aktivite
şeklinde aktarılmış ise söz konusu aktivitenin bilgileri gelecek ve sonrasında
değiştirilebilecek. Aksi halde yeni bir aktivite yaratılacak. Önemli olan
birinci nokta yeni bir aktivite için yeni bir XML dosyası yaratarak içerisine
gerekli bilgileri ekleyebilmek.
Dim Belge As New
XDocument
Dim root As New
XElement("Olay")
root.Add(New XElement("Tag", TextBox2.Text))
root.Add(New XElement("Icerik", TextBox1.Text))
root.Add(New XElement("Katilimci", TextBox3.Text))
Belge.Add(root)
Belge.Save(Server.MapPath("App_Data") & "\" & TextBox2.Text & ".xml")
Yukarıdaki kodda bir XDocument yaratarak içerisine XElement'ler ekliyoruz.
Elementleri eklerken isterseniz değerlerini de ikinci parametre olarak
verebiliyorsunuz. Son olarak da XDocument'ın Save metodu ile dosyayı
kaydediyoruz. Olay aslında bu kadar basit. Kullanıcının kutulara girdiği
metinleri herhangi bir kontrolden geçirmiyoruz, çünkü birincisi yönetim
panelindeyiz. Yani güvenli bir yerdeyiz, ikincisi bu projede buna zamanımız yok
:D Ama aklınızda olsun halka açık sitelerde böyle girişleri script
injection için kontrol etmek gerek.
Peki var olan bir dosyayı okuyup ekranda nasıl gösteririz?
Dim Belge = XDocument.Load(Server.MapPath("App_Data") & "\" & Request.QueryString("tag") & ".xml")
TextBox2.Text = Belge.<Olay>.<Tag>.Value
TextBox3.Text = Belge.<Olay>.<Katilimci>.Value
TextBox1.Text = Belge.<Olay>.<Icerik>.Value
GridView1.DataSource = From Gelenler In Belge.<Olay>.<Katilan> Select Gelenler.@Adi, Gelenler.@Mail, Gelenler.@Tel
GridView1.DataBind()
İlk satırda gördüğünüz üzere XDocument sınıfının
Load metodu ile dosyamızı okuyarak Belge değişkenine
aktarıyoruz. Bu noktada özellikle VB ile ilgili late-binding olayından bahsetmek
istiyorum. Dikkatinizi çektiyse Belge değişkenini tanımlarken herhangi bir
değişken tipi belirtmedim. Bu durum kod çalışırken run-time esnasında değişkenin
tipi belli olacak şeklinde çalışmıyor. Eğer böyle çalışsaydı yıllar önceki
VB'deki performans kaybını yaşamış olurduk. Tam tersine biz bu kodumuzda
Belge değişkeninin tipini belirtmesek de compiler bunu algılayarak
gerekli tanımlamaları yapacaktır. Zaten yukarıdaki manzarada bile Visual Studio
içerisinde Belge değişkeninin üzerine fare ile geldiğimizde
değişkenin tipinin algılandığını görebiliyoruz. Buradan yola çıkıp "hiçbir
değişkenin tipini tanımlamayın" diye bir şey söylemiyorum, bu büyük bir
hata olur fakat tipi belli bir şey için de uğraşmaya gerek yok :) (VB'cilerdeki
bu tembellik nedir ya :D)
GridView ile ilgili kısma geçerken bu Grid'in ne işe
yarayacağını baştan söyliyeyim. Tüm kolonları otomatik yaratılmak üzere ayarlanmış
bir Grid olarak bu arkadaşımızın görevi aktiviteye kayıt olanların bilgilerini
göstermek. Bunun için doğrudan Belge değişkenimize bir LINQ sorgusu göndererek
istediğimiz bilgileri kolonlar şeklinde alıyoruz. Ne kadar kolay değil mi?
default.aspx
Proje içerisinde değinmek istediğim bir diğer dosya da ana kayıt sayfası. Bu
sayfada ilk olarak söz konusu aktiviteye kayıt olan kişi sayısını bularak
maksimum sayının altında olup olmadığını kontrol etmemiz gerekiyor. Yani XML
dosyası içerisinde Katilan taglarını saymamız gerek.
If Belge.<Olay>.<Katilimci>.Value <=
Belge.<Olay>.<Katilan>.Count And Belge.<Olay>.<Katilimci>.Value <> 0 Then
Label1.Text = "Aktivite için maksimum kayıt sayısına ulaşıldı. Üzgünüz, bir dahakine."
kayittablo.Visible = False
Else
Belge değişkenimize XML dosyasını yükledikten sonra doğrudan Olay'ın
Katilimci değerinden maksimum katılımcı sayısını alabiliyoruz. O
ana kadar toplam kaç kişinin kayıt olduğunu, yani Katilan
taglarının sayısını da doğrudan Count metodu ile alabiliyoruz.
XLINQ cidden süper bir şey, eskiden ömür tüketirdi bu işler.
Dim Belge = XDocument.Load(Server.MapPath("App_Data") & "\" & Request.QueryString("event") & ".xml")
Belge.<Olay>.SingleOrDefault.Add(New XElement("Katilan",
New XAttribute("Adi", TextBox1.Text), New XAttribute("Mail", TextBox2.Text), New XAttribute("Tel", TextBox3.Text)))
Belge.Save(Server.MapPath("App_Data") & "\" & Request.QueryString("event") & ".xml")
Son olarak gelelim kayıt olan ziyaretçinin bilgilerini XML dosyasına
eklemeye. XML dosyasını okuyarak içerisinde Olay kök elementini
buluyoruz. Normalde elementler liste olarak döndürüldüğü için bizim bu listeyi
tek bir elemente çevirmemiz lazım. Olay elementinin zaten XML
dosyasında bir adet olabileceğini biz biliyoruz, çünkü kök element. O nedenle
Olay'ı yakaladıktan sonra .SingleOrDefault
diyerek bunu tek bir element olarak alıyoruz ve içerisine Katilan
elementi ekliyoruz. Katilan elementini XElement
olarak yaratırken birinci parametrede elementin adını verdikten sonra
istediğiniz kadar başka XElement'ler veya
XAttribute'ler ekleyebilirsiniz. Bizde katılımcının adı, telefonu ve
maili yeterli olacak. Son olarak dosyayı diske kaydediyoruz.
XLINQ ile XML uygulamaları "bebelere balon" kıvamında!
Eski günlerde olsak yukarıdaki işlemleri yapabilmek için XSLT, XPATH bilmenin
yanı sıra bolca da XML okuma ve yazma için kod yazmanız gerekirdi. Oysa bugün iş
gerçekten çocuk oyuncağı da olmanın ötesinde "bebelere balon" kıvamına gelmiş
durumda. Umarım bu projeyi sizlerle paylaşmam XLINQ'nun kullanımı ile ilgili
ufak da olsa bir fikir verip bu dünyaya giriş yapmanıza yardımcı olur.
Hepinize kolay gelsin.
Ücretsiz 24 saatlik Silverlight eğitimi ile ilgili duyuru içerisindeki kayıt
formunu görmüşsünüzdür. Maalesef bu form sistemini yapmamı bekleyerek duyuruyu
üç gün kadar geç yapabildik :) Bu aralarda ciddi çok yoğun.
Peki böyle bir formu yapmak ne kadar sürebilir ki? Ortalama 15 dakikamı aldı,
ama sadece bir mailform değil :) Hazır yapmışken ileriki aktiviteler için de
kullanabileceğim bir sistem yapmak istedim. Hedefim mini-iğrenç :) bir yönetim
panelinden en azından aktivite yaratıp kapatabilmekti, tabi kayıt olan kişilerin listesini de alabilmem gerekiyordu. Neden iğrenç dediğimi de
açıklıyım. Sadece ben kullanacağım için yönetim panelinin güzelliği ile vs hiç
mi hiç uğraşmadım :) iş görsün yeter.
Konuyu uzatmadan, bütün bunları neden size anlattığımı da söylemekte fayda
var. Hazırlamış olduğum sistemi tüm kodları ile sizlerle paylaşmaya karar
verdim. Evet, birazdan indirebileceksiniz :)
Sistem aslında çok basit bir mantıkla çalışıyor. Yönetim panelinden bir
aktivite yaratıyorsunuz aktiviteye verdiğiniz TAG özelliği o aktivitenin kodu
oluyor. Bu kod üzerinden default.aspx?event=kod gibi adreslerle insanlar bu
aktivitelere kayıt olabiliyorlar. Her bir aktivitenin kodu, aciklamasi ve
maksimum katılımcı sınırı var. Aciklama kısmı aktivite ile ilgili sayfadaki kayıt
formunun üzerindeki HTML kısmı içeriyor. Makimum katılımcıyı isterseniz 0 vererek
sınırsız hale getirebiliyorsunuz. Her bir aktivite ile ilgili tüm bilgiler ayrı
ayrı XML dosyalarında App_data klasöründe saklanıyor.
Uyarılar
Arkadaşlar birazdan projenin kodlarını indirip incelerken bu
projeyi bir gece yarısı saat 01.00 ile 01.15 arasında yaptığımı aklınızın bir
köşesinde bulundurun :) Hatta bu projeyi paylaşıyorum diye içerisinde herhangi
bir değişiklik vs de yapmadım. Yalan olmasın login.aspx deki şifreyi
değiştirdim. O nedenle aşağıda bahsettiğim noktalarla ilgili bu projeyi örnek
almayın!
Bunları örnek almayın!
-Authentication yapısı rezalet. Zaten login.aspx de kullanıcı adı bile yok,
sadece şifre soruyor :) Şifreyi sorduğu metin kutusunun tipi bile Password değil
:) Bir ara düzeltmek lazım. Forms Authentication kurmaya üşendim.
-XML dosyalarının okunması ve yazılması arasında aslında application.lock
kullanmak lazım. Aynı salisede 2 kişi formu göndermeye kalkarsa biri karambole
gidecektir. Allahtan bizde pek böyle bir ihtimal yok gibi :) (Umarım)
İncelenmesi gereken kısımlar (Projenin kodunu
paylaşmaktaki amacım)
XLINQ ile yazılmış kısımlara özellikle dikkat etmenizde fayda var. XML
dosyalarının yaratılmasındaki kolaylık, okunmasındaki rahatlık özellikle dikkat
çekici. Bu kodu sizlerle paylaşmanın birinci nedeni XLINQ örneği olarak
incelemeniz ikincisi ise böyle bir mini sisteme ihtiyacı olan varsa alsın rahat
rahat kullansın :)
LINQ'den bahsettiğimize göre unutmamak gerek ki bu site ASP.NET 3.5 ile
hazırlanmıştır. Projedeki bazı kodlarla ilgili yarın bazı açıklamalar da
yayınlayacağım.
Hepinize kolay gelsin. Aktivite Kayıt Sistemi Kaynak Kodları - 28022008_1.zip (7.5 KB)
Bu aralar karşılaştığım ilginç sorulardan biri de URL Mapping hakkında.
İnternette gezerken dikkatinizi çekmiştir, bazı sitelerde
www.adres.com/bu+bir+makale/default.aspx gibi adresler kullanılıyor. İşte
buna URL Mapping deniyor. Bu işlemi, aslında var olmayan bir
adresi varmış gibi kullanarak esasen var olan başka bir adrese arka planda
yönlendirmek şeklinde tanımlayabiliriz.
Örneğin:
www.ornek.com/urunler.aspx?ID=5
gibi bir adres yerine
www.ornek.com/5/default.aspx
şeklinde adresler kullanabiliyorsunuz.
Biz de bu konuda bir örnek yaparak yukarıdaki gibi bir adresi dönüştürmeyi
deneyelim. Örneğimizde kullanmak üzere bir default.aspx yaratıyoruz ve basit bir
şekilde sayfaya bir adet yerleştirerek QueryString üzerinden
gelecek ID bilgisini Label içerisine yazdıracağız.
[default.aspx]
<%@ Page Language="VB" AutoEventWireup="false" CodeFile="Default.aspx.vb" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
</div>
</form>
</body>
</html>
[default.aspx.vb]
Partial Class _Default
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Label1.Text = Request.QueryString("ID")
End Sub
End Class
Sayfamızı hazırladığımıza göre sıra geldi mapping işlemini yapmaya. Projemize
bir adet Global.asax (Global Application Class) eklememiz
gerekiyor. Projeye "Solution Explorer" içerisinde sağ tuş tıklayarak "Add new
item" diyerek söz konusu dosyayı ekleyebilirsiniz. Sonrasında Global.asax
içerisinde Application'a ait BeginRequest
durumunu yakalayarak mapping kodumuzu yazacağız.
<%@ Application Language="VB" %>
<script runat="server">
Protected Sub Application_BeginRequest(ByVal sender As Object, ByVal e As System.EventArgs)
Dim GelenAdres As String = Context.Request.Url.AbsolutePath
Dim GelenID As String = GelenAdres.Substring(GelenAdres.IndexOf("/", GelenAdres.IndexOf("WebSite15")) + 1, GelenAdres.IndexOf("default.aspx") - GelenAdres.IndexOf("/", GelenAdres.IndexOf("WebSite15")) - 2)
Context.RewritePath("../default.aspx?ID=" & GelenID)
End Sub
</script>
Gelelim yukarıda neler yaptığımıza. İlk satırda GelenAdres adında bir
değişken yaratarak buraya kullanıcının talepte bulunduğu adresin yolunu
kopyalıyorum. Bu adres metni içerisinde /5/ gibi duran ID bilgisini almam
gerekiyor. Ben bu işlemi standart String işlemleri ile yaptım, oysa güzel bir
RegularExpression çok daha hoş durabilir. İhtiyaçlarınıza göre istediğiniz
metodu kullanabilirsiniz. ASP.NET Development Server kullandığım için benim
sitem bir WebSite15 denen bir klasör içerisinde açıldı. O nedenle string
işlemlerimi şimdilik ona göre yazdım. Son olarak da Context
nesnesine ait RewritePath metodu ile esas açılacak olan adresi
belirtiyorum. Yakalamış olduğum ID bilgisini adresin sonuna ekliyorum.
Artık
www.ornek.com/5/default.aspx adresine giden kullanıcılar için aslında
www.ornek.com/default.aspx?ID=5
adresi açılıyor ama bunu hiçbir kullanıcı görmüyor. Örneği bir adım ileri
taşıyarak
www.ornek.com/Bu+bir+metin/default.aspx şeklindeki adreslerin de
www.ornek.com/default.aspx?ID=5
şekline dönüşmesini sağlayabilirsiniz. Tek yapmanız gereken gelen başlik
bilgisini alip ona uygun ID'yi veritabanından çekerek yeni adrese aktarıyor
olmak.
Mapping yaptığımız tüm adreslerin sonunda .aspx uzantılı bir dosya adresi
kullandık. Bunun nedeni sadece .aspx uzantılı dosyaların IIS 6.0 üzerinde asp.net
motoruna bağlı olması. Bu durum IIS'e admin erişiminiz varsa özel ayarlarla tabi
ki değiştirilebilir. Yakın zamanda Server 2008 lansmanı ile IIS7.0 da kullanıyor
olacağız. IIS7.0'ın mimari yapısındaki değişiklikler sonucu yukarıdaki kodu IIS
7.0 üzerinde çalıştırdığınızda tüm istekler dosya uzantısına bakılmadan map
edilebilecektir.
Yukarıdaki taktiğin yanı sıra HttpModule yazarak URL Mapping
işlemini daha performanslı bir hale getirmek de mümkün. Umarım o konuda da
yakında uzun bir makale yazma şansım olur :)
Hepinize kolay gelsin.
PCnet'in Şubat sayısındaki yazılarımı her ay olduğu gibi yine buradan sizlere duyurmak
istiyorum :) Derginin
OKUL bölümünde AJAX, ASP.NET 3.5,
Expression Blend ve Silverlight ile ilgili yazılarım yer alıyor.
AJAX : Zaman doluyor, AJAX istekleri yolda.
Expression Blend : WPF Uygulamalarında internette
Silverlight: Silverlight ve JavaScript
ASP.NET 3.5 : ASp.NET 3.5 ve LINQ2SQL Tüm bu yazılara ek olarak
Şubat sayısına özel ".NET Framework 3.5'in Yıldızı: LINQ"
makalem de OKUL bölümünde yer alıyor :)
Hepinize kolay gelsin.
Budan bir süre önce Windows Server 2008 sertifikasyonlarından bahsetmiştim.
Bugünlerde Visual Studio 2008 için planlanan sertifikasyonların da bir kısmı
duyurulmaya başlandı.
Visual Studio 2005'de olduğu gibi 2008 ile beraber de MCTS ve
MCPD ünvanlarına "competency" ler ekleniyor olacak. Şu an için MCTS tarafı
belirlenmiş durumda ve öngörülen MCTS'lerin listesi şöyle;
- Windows Forms Applications
- ASP.NET Applications
- Windows Communication Foundation Applications
- ADO.NET Applications
- Windows Workflow Foundation Applications
- Windows Presentation Foundation Applications
Visual Studio 2005 serisi ile beraber girdiğimiz 70-536
sınavı hala geçerli olan ve yeni başlayanların Visual Studio 2008 için de girmek
zorunda olacağı bir sınav olacak. Yani bugün yola çıkacak olanların hemen
girebileceği bir sınavdan bahsediyoruz :) Yukarıdaki konulardaki sınavlar Mart
ayından başlayarak Mayıs sonuna kadar farklı tarihlerde yayınlanmaya başlayacak.
Yeni haberler duyuruldukça sizlere de ulaştırıyor olacağım.
Bundan bir süre önce .NET Framework 3.5'in açık kaynak
kodlarının Microsoft tarafından dağıtılacağını sizlere duyurmuştum. Bu gibi bir
dağıtımın özellikle Framework içerisinde hataların hızlıca giderilebilmesine ve
biz programcıların arka planda nelerin çalıştığını görerek yerine göre daha
performanslı uygulamalar hazırlayabilmemize yardımcı olacağı kesin. İşte o gün
bugün :)
Framework içerisindeki aşağıdaki kütüphanalerin açık kaynak kodları
yayınlandı.
- .NET Base Class Kütüphanaleri (System, System.CodeDom,
System.Collections, System.ComponentModel, System.Diagnostics, System.Drawing,
System.Globalization, System.IO, System.Net, System.Reflection, System.Runtime,
System.Security, System.Text, System.Threading, vs).
- ASP.NET (System.Web, System.Web.Extensions)
- Windows Forms (System.Windows.Forms)
- Windows Presentation Foundation (System.Windows)
- ADO.NET ve XML (System.Data ve System.Xml)
Çok yakında diğer sınıfların da zaman içerisinde paylaşıma açılacağı ayrıca
duyuruldu.
Yükleme başlıyor...
Visual Studio'nun .NET Framework açık kaynak koduna online olarak
ulaşabilmesi için aşağıdaki adresten gerekli paketi bilgisayarınıza yüklemeniz
şart. Maalesef söz konusu paket Express sürümlerle
çalışmayacaktır.
https://connect.microsoft.com/VisualStudio/Downloads/DownloadDetails.aspx?DownloadID=10443&wa=wsignin1.0
Yükleme işlemi tamamlandıktan sonra Visual Studio 2008 içerisinde Tools > Options > Debugging > General tabına
giderek "Enable Just My Code"" seçeneğini OFF ve "Enable Source Server Support" seçeneğini
ON
olarak değiştirmeniz gerekiyor.
 Açık kaynak koduna yolculuk : Adım 1
Bir sonraki adımda yine "Options" içerisinde "Symbols"
bölümüne "http://referencesource.microsoft.com/symbols
" adresini ekledikten sonra internetten indirilen kaynakların önbelleklenmesi
için de bir klasör belirtmeliyiz. Klasör olarak kullanıcınızın yazma hakkına
sahip olduğu bir yol göstermenizde fayda var. Özellikle Vista kullanıcılarına
tavsiyem kendi kullanıcı klasörleri içerisinde bir adres vermeleri. "Search the above locations only when symbols are loaded manually" işaretini
de işaretleyerek işlemimizi tamamlıyoruz.
 Açık kaynak koduna yolculuk : Adım 2
İşlemleri tamamlamak için "OK" düğmesine bastığınızda Visual Studio size harici
bir kaynaktan kaynak kodu yüklemenin tehlikeli olabileceğine dair bir uyarı
gösterecektir. Söz konusu uyarıya "Yes" diyerek kaynağa
güvendiğinizi belirtebilirsiniz.
Peki NASIL kullanacağız?
Şimdi hemen bir Winforms projesi başlatarak bir uyarı mesajı gösterelim. Uyarı
mesajımı gösterecek koda "breakpoint" ekledikten sonra projeyi
çalıştırarak "breakpoint" noktasına geldiğinde "Call Stack"
penceresinden istediğimiz sınıfı seçerek sağ tuş ile gelen menüden "Load
Symbols" komutu veriyoruz.
 Açık kaynak koduna yolculuk : Adım 3
Yükleme işlemi internet üzerinden yapılacağı için tabi ki "Load Symbols"e
tıklamadan önce internete bağlı olduğunuzdan emin olmanız gerekiyor. İşlem
bittiğinde "Call Stack" içerisinde gri satırlar artık siyah olacak ve her
satırın sonunda kaynak koddaki satır numaralı da gözükecektir.
 Açık kaynak kodu bilgisayarımızda.
İncelemek istediğiniz koda karar verdikten sonra çift tıklayarak kaynak
dosyasının açılmasını sağlayabilirsiniz. Kaynak açılmadan önce size lisans
sözleşmesi de gösterilecektir, sözleşmeyi okuyup kabul ettikten sonra kaynak
kodu bilgisayarınıza indirilecektir. Daha sonraki denemelerinizde sözleşme bir
daha gösterilmeyecektir.
 .NET Framework açık kaynak kodu VB :)
İşte açık kaynak kodu karşımızda. Unutmayalım bu kod bizler için hazırlanmış
bir kod. Yani içerisinde bize özel yorumlar var. Karşılaşacağımız bazı sınıflar
VB bazıları ise C# ile yazılmış durumda. Maalesef şimdilik istediğimiz dilde
inceleme gibi bir şansımız yok.
Hepimize hayırlı, uğurlu olsun :)
PCnet'in
Ocak sayısındaki yazılarımı her ay olduğu gibi yine buradan sizlere duyurmak
istiyorum :) Derginin
OKUL bölümünde AJAX, ASP.NET 3.5,
Expression Blend, Expression Design, Silverlight ve
Expression Web ile ilgili yazılarım yer alıyor.
AJAX : UpdateProgress ile asenkron yüklemelerin takibi
Expression Blend : Animasyonlar ve Tetikleyiciler
Expression Web: Expression Web ile Veri Oyunları
Expression Design : Vektörel Çizim Araçları
Tüm bu yazılara ek olarak Ocak sayısına özel sürpriz makalelerim :)
FaceBook uygulamanızı geliştirin ! :
ASP.NET bilgisiyle kolay yoldan FaceBook uygulamaları geliştirmenin yollarını inceliyoruz.
Visual Studio 2008 Bilgisayarlarımızda! : Visual Studio 2008 ve ücretsiz Express sürümleri bilgisayarlarımıza girdi. Peki yeni neler geldi?
Hepsi PCnet Ocak sayısında! :)
Hepinize kolay gelsin.
2008'in ilk aktivitesini
CETURK.com organizasyonunda Microsoft, İstanbul / Dikilitaş binasında
gerçekleştiriyoruz. "2008 Microsoft Vizyonu ve Yeni Teknolojileri
Semineri" olarak adlandırdığımız güne hepiniz davetlisiniz :)
12 Ocak, Cumartesi günü sabah 10'dan başlayarak
17.30'a kadar sürecek olan seminerlerin konuları arasında
Expression Web, Design, Blend, Silverlight, Visual Studio 2008, LINQ
bulunuyor. Expression Blend ile WPF Animasyonları ve
Silverlight 1.0, 2.0 Uygulamaları bölümünü 12.30-14.30
arasında ben sunuyor olacağım.
Programın detayları ve seminere kayıt için aşağıdaki linki kullanabilirsiniz.
http://www.ceturk.com/etkinlikkayit.asp?id=35
.NET Framework 3.5 ile beraber ASP.NET 3.5'i de kullanmaya başladığımız
bugünlerde artık projelerimizi yavaş yavaş sunuculara aktarmaya doğru da
yaklaşıyoruz. Peki sunucuda neler yapmamız gerekiyor? Aslında durum daha önceki
.NET Framework sürümlerinden pek farklı değil. .NET Framework 3.5'i direk
sunucunuza kurmanız gerekiyor fakat öncesinde kesinlikle .NET Framework 2.0'ın
kurulmuş olması şart. Malum 3.5 sürümü 2.0 üzerine gelen eklentilerden oluşuyor
ve hala 2.0 sürümündeki sınıflar 3.5 içerisinde de kullanılıyor.
Kurulumu tamamladıktan sonra akla gelecek ikinci bir soru ise IIS içerisinde
nasıl bir ayar yapmamız gerektiği. Hatırlarsanız .NET Framework 2.0 ile beraber
IIS içerisinde artık her bir web sitesi için 1.0 ve 2.0 arasında bir seçim
yapabildiğimiz ayarlar gelmişti. Bu ayarlara baktığınızda 3.5 seçeneğini
göremezseniz şaşırmayın çünkü ASP.NET 3.5 siteleri IIS'de 2.0 siteleri gibi
çalışıyor. Yani söz konusu siteyi IIS içerisinde .NET Framework 2.0 ile
çalışacak şekilde ayarladıysanız hiçbir sorunla karşılaşmazsınız.
O zaman ne farkı kaldı? Fark aslında projenizin Web.Config dosyası içerisinde
yer alıyor.
<system.codedom>
<compilers>
<compiler language="c#;cs;csharp" extension=".cs" warningLevel="4"
type="Microsoft.CSharp.CSharpCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<providerOption name="CompilerVersion" value="v3.5"/>
<providerOption name="WarnAsError" value="false"/>
</compiler>
<compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" warningLevel="4"
type="Microsoft.VisualBasic.VBCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<providerOption name="CompilerVersion" value="v3.5"/>
<providerOption name="OptionInfer" value="true"/>
<providerOption name="WarnAsError" value="false"/>
</compiler>
</compilers>
</system.codedom>
İşte Web.Config içerisinde yer alan yukarıdaki bölüm projenizin ASP.NET 3.5
projesi olduğunu ve .NET Framework 3.5 özelliklerini kullanabileceğini
belirtiyor. Böylece gerekli referanslar ile artık web siteniz LINQ ve entegre
AJAX gibi özelliklerden faydalanabilecek. Visual Studio 2008 ile yarattığınız
ASP.NET 3.5 sitelerinde Web.Config dosyalarına bu kod otomatik olarak ekleniyor.
Hepinize kolay gelsin.
Bugün sizlere biraz Refactoring'den bahsetmek isriyorum. Refactoring'i kaba
bir şekilde tanımlamak gerekirse herhangi bir kodun işlevini değiştirmeden
yazılışı değiştirmek ve hedef olarak da kodun okunuşu kolaylaştırmaktır
diyebiliriz. Refactoring konusunda sektörde bir çok araç, üçüncü parti
uygulamalar satılıyor. Visual Studio içerisinde de C# için hazır bazı ufak
tefek Refactoring araçları bulunuyor. Tabi ben bir VB programcısı olarak olayın
VB kısmından bahsedeceğim ve sizlere ücretsiz bir Visual Studio eklentisi olan
Refactor'u tavsiye edeceğim.
http://msdn2.microsoft.com/en-us/vbasic/bb693327.aspx
Yukarıdaki adresten indirebileceğiniz yazılımın normal sürümü ücretsiz ve hem
Visual Studio 2005 hem de 2008 ile uyumlu. Yazılımın daha çok özelliklere sahip
bir sürümü de "Refactor Pro" adı altında satılıyor. Biz şimdilik ücretsiz
sürümle yetinelim :)
Hemen bir iki örnek ile neler yapabileceğimize bakalım.
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim ds As New Data.DataSet
Using cnn As New SqlConnection(ConfigurationManager.ConnectionStrings("CNN").ConnectionString)
Using cmd As New SqlCommand("SELECT * from TABLO", cnn)
Dim da As New SqlDataAdapter(cmd)
da.Fill(ds)
End Using
End Using
GridView1.DataSource = ds
GridView1.DataBind()
End Sub
Yukarıdaki kod herhangi bir asp.net web sayfasının Page.Load durumunda
çalışıyor olsun. Gördüğünüz gibi veritabanına bir Select göndererek gelen veriyi
GridView'e bağlıyoruz. Eğer Select ile aldığımız veriyi sayfada başka yerlerde
de almamız gerekecekse aslında bunu harici bir function olarak yazmamız daha
faydalı olacaktır. Hemen aşağıdaki şekilde function içerisine almak istediğim
bölümü seçiyorum.
 Kodumuzu harici bir function içerisinde alıyoruz.
"Extract Method" komutu verdiğimizde Refactor bize kodu
class yapısı
içerisinde nereye yazdırmak istediğimizi soruyor sonrasında da Function'ımızı
aşağıdaki gibi otomatik olarak yaratıyor.
Partial Class _Default
Inherits System.Web.UI.Page
Private Shared Sub
Page_LoadExtracted(ByVal ds As Data.DataSet)
Using cnn As New SqlConnection(ConfigurationManager.ConnectionStrings("CNN").ConnectionString)
Using cmd As New SqlCommand("SELECT * from TABLO", cnn)
Dim da As New SqlDataAdapter(cmd)
da.Fill(ds)
End Using
End Using
End Sub
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim ds As New Data.DataSet
Page_LoadExtracted(ds)
GridView1.DataSource = ds
GridView1.DataBind()
End Sub
End Class
Gördüğünüz gibi artık aynı Function'ı kullanarak sürekli aynı datayı
istediğimizde bir DataSet içerisine doldurtabiliyoruz. Fakat burada sizi
rahatsız edeceğinden emin olduğum bir şey var; Refactor'un yarattığı function'ın
adı çok anlamsız :) Visual Studio içerisinde yaratılan fonksiyonun adını
değiştirirseniz Refactor sizin için söz konusu fonksiyonun kullanıldığı
yerlerdeki referansları da otomatik olarak değiştirecektir.
Gelelim bir diğer örneğe. Varsayalım ki yeni bir sınıf yapısı oluşturmaya
başladınız. Oluşturduğunuz ilk sınıfın bir sürü Private değişkeni var ve bunlara
da uygun Property'lerin tanımlanması gerekiyor. Set ve
Get leri tek tek her biri
için ayarlıyor olmak gerçekten işkenceye dönüşebilir. Gelin aşağıdaki koda bir
bakalım.
Public Class Deneme
Private Ozellik As Integer
Private Ozellik2 As Integer
Sub New()
End Sub
Sub New(ByVal Ozellik As Integer, ByVal Ozellik2 As Integer)
Me.Ozellik = Ozellik
Me.Ozellik2 = Ozellik2
End Sub
End Class
Yukarıdaki sınıfımızda sadece iki adet özellik bulunuyor bunların Property'lerini oluşturmamız gerekiyor.
Private değişkenlerin üzerine sağ tuşu
ile tıkladıktan sonra "Refactor / Encapsulate Field" komutu veriyorum ve kodun
yerleştirileceği yeri de seçtikten sonra Refactor benim için Property kodlarını
otomatik olarak yazıyor.
Public Class Deneme
Private Ozellik As Integer
Private Ozellik2 As Integer
Sub New()
End Sub
Sub New(ByVal Ozellik As Integer, ByVal Ozellik2 As Integer)
Me.Ozellik1 = Ozellik
Me.Ozellik21 = Ozellik2
End Sub
Public Property Ozellik1() As Integer
Get
Return Ozellik
End Get
Set(ByVal value As Integer)
Ozellik = value
End Set
End Property
Public Property Ozellik21() As Integer
Get
Return Ozellik2
End Get
Set(ByVal value As Integer)
Ozellik2 = value
End Set
End Property
End Class
Refactor tarafından tamamlanan yukarıdaki kodda dikkatinizi çektiyse
Sub New kodundaki değerlerin aktarıldığı değişkenlerin isimleri de
otomatik olarak Property isimleri ile değiştirilmiş durumda.
Bir önceki örnekte olduğu gibi burada da eğer elle Property
isimlerini değiştirirseniz Refactor otomatik olarak sınıf içerisinde diğer
referansları da değiştiriyor.
Tüm bu işlemleri kod yazarken yapıyor olmak kolaylık sağlayabilir fakat esas
mesele elinizde hazır kodları tamamlanmış bir proje varsa gerçekleşiyor. Projeyi
inceleyerek sadece Refactoring araçlarını kullanarak daha
okunabilir bir kod yaratmaya çalışıyorsunuz, hatta çoğu zaman kodun işleyişini
değiştirmeden kodu kısaltabiliyorsunuz bile.
Refactoring'e giriş yapmanızı sağlayacak Refactor eklentisi ne kadar ücretsiz
olsa da daha fazla reklamını yapmayacağım :) Refactoring
dünyasını keşfetmek artık size kalmış.
Hepinize kolay gelsin.
PCnet'in
Aralık sayısı yine dopdolu :) Derginin
OKUL bölümünde AJAX, Silverlight,
Expression Web, Expression Blend, Expression Media ve Expression Design ile ilgili
yazılarım yer alıyor. Ayrıca Aralık sayısından itibaren dünyada ilk defa :) ASP.NET 3.5
bölümü PCnet'te!
ASP.NET 3.5 : ASP.NET 3.5 Geliyor!
AJAX : UpdatePanel uzmanlığı
Silverlight : Kolay Yoldan Silverlight Animasyonları
Expression Blend : MediaElement ile Video Sihirleri
Expression Web: Expression Web ile yolculuğa devam
Expression Design : İlk Windows Programımızı Tasarlayalım
Expression Media : Mültimedya Dosya Yönetimi
Tüm bu yazılara ek olarak Aralık sayısına özel sürpriz makalem :)
Yeni nesil MashUP uygulamaları :
MashUp uygulamaları hazırlamanın zevki Microsoft Popfly ile kat kat arttı.
Hepsi PCnet Aralık sayısında! :)
Daha fazlasını mı istiyorsunuz? PCnet ile beraber Expression Studio paketinden Blend, Web, Design, Encoder, Media'nın deneme sürümleri de DVD olarak geliyor.
Hepinize kolay gelsin.
Yazımın tamamen "yıkama yağlama" kokacağının farkında olarak başlıyorum bu
cümlelere. Ben böyle bir yazı okuyacak olsam kesinlikle "yağcılık yapmış" derim
:) Umarım sizler demezsiniz. En azından blogumu bir süredir takip edenler veya
benle karşılaşmış olanlar beni daha net anlayacaktır diye ümit ediyorum. Bu
temkinli girişten sonra konuya geçiyim.
Gelelim esas yazımın girişine :)
İlk olarak PCWorld Türkiye'de kapak konusu yazdığımda Lise 2'deydim. O
günlerden bugüne bilişim teknolojiler üzerine çalışan birçok şirkette görev
aldım, birçok şirketle kurumsal olarak çalıştık. Özetle, yaşımın yettiği ölçüde
çok BT çalışanı ve çok BT yöneticisi gördüm. İngilizce blog sitemi de katarsak
iki yıldır blog yazıyorum. Tüm bu bilgiler ışığında ilk defa böyle bir yazı
yazma ihtiyacı hissettim. Peki ne yazacağım? :) Sabır.
Bundan yaklaşık üç ay önce PCnet ekibinden sevgili dostum, adaşım :) Daron
Dedeoğlu'nun MSN'den gönderdiği titreşim ile başlayan dalgalanma bakın nerelere
geldi. İlk olarak PCnet Ekim sayısında AJAX ve Silverlight içeriği sunmanın
Türkiye'de bir ihtiyaca cevap olacağını söylediğimde gelen olumlu tepki beni
biraz şaşırttı. Malum Silverlight yeni release olmuştu. Sevinçle yazılarımı
hazırladım. Bir sonraki ay, Kasım ayı için içerik toplantısına Expression Blend,
Web ve Design ile ilgili Türkçe içerik eksikliği olduğundan bahsederek dergide
yer verilirse yararlı olacağını dile getirdim. Aslında epey ümitsizdim, çünkü
ürünler yeni olmakla beraber sundukları teknolojiler de kısmen çok yeniydi. Yine
"OK" dendi ve havalara uçarak Kasım sayısına da yazılarımı hazırladım ve bir
anda PCnet'te her ay bu yepyeni ürünleri, teknolojileri yazıyor olduk.
Bu noktaya kadar yaşananlar beni şaşırtmakla beraber "Bravo! Vizyonları
genişmiş!" diyerek haddim olmadan içten içe değerlendirmeler de yaptım.
Daha bundan üç gün önce
bloguma Visual Studio 2008'in RTM sürümünün bu ay sonunda çıkacağı ile
ilgili Microsoft'un basın açıklamasını taşıdım. Böylece partnerlar Visual Studio
2008 kullanarak ürün geliştirebilecekler. Şubat ayında beklenen resmi lansmanın
da gecikmeyeceği ortaya çıktı. Hemen kolları sıvayıp tabiri caiz ise yüzsüzlük
yaparak PCnet Yayın Yönetmeni Barış Nevreş'e çok kısa bir mail yazdım.
http://www.microsoft.com/presspass/press/2007/nov07/11-05TechEdDevelopersPR.mspx
VS 2008 ve .NET Framework 3.5 bu ay çıkıyor.
Aralık sayısında OKUL bölümüne ASP.NET 3.5 bölümü eklemeyi teklif ediyorum? Pazartesiye yetiştirebilirim yazısını.
Yukarıdaki maile daha kısa ama daha değerli bir cevap geldi.
Ekleyelim.
İnanamadım! Aslında daha doğrusu "gözlerime inanamadım" çünkü daha önce
yaptığım yüz yüze görüşmelerde edindiğim izlenimden yola çıkarak ümitliydim ama
gözlerim :) inanmakta zorlandı. Bahsettiğimiz durum daha release olmamış bir
teknoloji ile ilgili release olma tarihi basın açıklamasında duyurulduğu anda
konuyla ilgili Türkçe kaynak yayınlamayı uygun gören bir VİZYON'a sahip
olmaktır. PCnet'in böyle bir vizyona sahip olması hem PCnet adına, hem Türkiye
adına beni sevindirdi, hem de bir PCnet yazarı olarak kendim için sevindim :)
Yukarıda bahsettiğim vizyon bugün çok az kurumda vardır diye tahmin ediyorum.
Ben ilk defa karşılaşıyorum. O nedenle buradan PCnet'e ve Yayın Yönetmeni Barış
Nevreş'e teşekkür ediyorum. Ben lisedeyken yeni çıkan bir teknolojiyle ilgili
yazıları dergilerde bulamıyordum. Şimdiki gençler şanslı :)
SSS
Soru:Bu bir reklam mıdır?
Cevap:Amaç değil fakat araç olabilir.
Soru:PCnet ve Microsoft kanki midir?
Cevap:Çok da güzel Linux yazıları var dergide :) Dergininin
Yazılım Editörü Daron Dedeoğlu Pardus programlama ekibindedir.
Soru:Bugün teknik bir makale yok mu blogda?
Cevap: Eeee.... Yok :)
|
Copyright © 2010 Daron Yöndem.
Tüm hakları saklıdır.
|
|