daron yöndem | Microsoft Regional Director | Silverlight MVP
Microsoft Regional Director | Nokia Developer Champion | Azure MVP

Mvc website ile application arasındaki fark nedir?

Geçenlerden twitter üzerinden gelen sorulardan biriydi bu malum :) Twitter'dan cevaplamak için uzun bir konu olmanın yanı sıra bloga yazarsam daha faydalı olur diye düşündüm. O zaman gelin şu olaya bir göz atalım. Neymiş bakalım "Web Application" ile "Web Site" arasındaki fark.

Aslına bakarsanız ilk olarak aklıma gelen cevap "proje şablonu farkından başka bir şey değil" şeklinde oldu. Ama sonrasında tabi ki başka soru işaretleri de söz konusu olabilir. Yani, anladık proje şablonu farklılığı :) ama nedir bu farklılıklar? Veya neden var bu farklılıkar? Konuya sadece MVC gözü ile bakmayacağım bu arada çünkü soru aslında doğrudan MVC ile alakalı değil. Web Application ve Web Site arasındaki farklılık MVC seçmeseniz ve WebForms ile gitseniz de karşınıza çıkacaktır.

Source code nerede olsun?

İlk olarak bu iki şablon konsepti arasında bir compiler davranış farklılığı var. Zaten her şey de buradan çıkıyor :) Eğer web site ile devam ederseniz compiler sadece validasyon amaçlı projenizi compile eder ve sunucuya elinizdeki tüm source code'u atmanız gerekeir. Web project tarafında ise deployment öncesinde compiler tüm dosyaları bir DLL'e dönüştürür ve bu şekilde deployment yapılır. Bu iki yaklaşım arasında ciddi farklılıklar var özünde. Birinde sunucudaki IL kodunuz Runtime tarafından çalıştırılırken diğerinde doğrudan source code'unuz Runtime tarafından compiler'lara sunucuda gönderilerek (Dynamic Compilation) çalıştırılır. Bunun uygulamanın ilk açılışında küçük bir performans farkı yaratacağı malum ama tabi ki bunu önemsemeyebilirsiniz de. Esas büyük farklılık aslında yazılım geliştirme süreçlerinizin tanımı ile alakalı. Eğer "sunucuya bağlanıp orada kod editlediğim oluyor" diyorsanız işte o zaman Web Site ile devam etmeniz gerek. Malum Web Application'da source code sunucuda bulunmuyor.

Yukarıda bahsettiğimiz karar aslında çok kritik bir karar. Olaya sadece kendi açınızdan bakmayın. Eğer WebSite ile devam ederseniz, yani sunucuya source code'ları atarsanız sunucuya erişimi olan herkesin o kodları düzenleyebilmesine de olanak vermiş olursunuz. Bu sizin şartlarınıza göre iyi veya kötü bir durum olabilir. Kararı verecek olan sizsiniz. Bir diğer örnek de "ben sadece bir dosyayı değiştirip sunucya atmak istiyordum" senaryosu :) Web Site'da bunu yapabilirsiniz çünkü compile işlemi sunucuda gerçekleşir ama WebApplication'da tüm projeyi tekrar compile edip atmak durumundasınız. Tabi projenizi farklı assemblylere compile olacak şekilde bölüştürebilirsiniz ama o da apayrı uzun bir hikaye.

Hem CS hem VB aynı projede!

Ben pek böyle bir senaryo görmedim :) ama olur ya aynı projede bir code-behind dosyası VB diğer CS ile yazılır :) işte bunu ancak WebSite'da yapabilirsiniz. Aslında tüm bunların nedeni yine compile işleminin nerede nasıl yapıldığı ile alakalı. Zaten WebProject'te proje dosyasına göre compiler seçilir ve bu da kafadan farklı dil kullanımını engeller. Tabi ki harici kütüphaneler ekleyip solution içerisinde farklı diller kullanabilirsiniz amma illa ki aynı web site içerisinde olacak diyorsanız WebSite kullanmalısınız. WebSite'lar için her dosya için ayrı ayrı request üzerine dosya uzantısına göre compiler ile eşleştirilebilir.

Kullandığınız Microsoft dışı araçlardan ne haber?

Microsoft ürünleri dışında bir şeyler kullanıyorsanız, örneğin NUnit, Cruise Control.NET hatta klasik bir TFS bile Web Site projelerinde Continious Integration'da canınızı sıkabilir. Bugünlerde TFSLive ile işler ciddi kolaylaşmış olsa da WebProject tarafında CI implementasyonlarında çok daha rahat edersiniz. WebProject'ler MSBuild ile çalışır ve MSBuild entegrasyonu olan her türlü araçta çok daha rahat edersiniz. Zaten MSBuild normalde WebSite'da çalışmıyor :) Build edip deploy etmiyoruz malum ama zorlayıp etrafından dönüp çalıştırabilirsiniz. Zor işler bu işler. Ayrıca gerek yok. Eğer gerekiyorsa WebApplication kullanın zaten. :) CI derdiniz yoksa bu problemleri yaşamanız pek de olası değil. Ama örneğin hatırlıyorum.. Azure SDK ilk zamanlarda Deployment Package yaratırken bile Web Sites projeleri ile seksen takla atmamız gerekiyordu (eskiden).

Edit & Continue sadece WebApplications'da var!

Sanırım başlık kendini açıklıyor zaten değil mi? Eğer Edit&Continue ile debugging esnasından özgürce takılmayı seviyorsanız zaten WebSites kullanmıyorsunuz demektir :)

Başka başka....

  • WebApplication'da birden çok web projesi arasında dependency yaratabilirsiniz.
  • Dışarıdan assemblye ulaşıp farklı araçlarla UnitTest yapabilirsiniz. Web Sites ile de tabi ki UnitTest yaparsınız ama biraz daha takla atmak gerekir çünkü her sayfa assembly'de bir sınıfla eşleşmez.
  • Assembly versioning olayını WebSites'da doğal olarak yapamazsınız. Assembly delivery yok zaten.
  • PreBuild-PostBuild gibi olaylarınız sadece WebProject'lerde olabilir.
  • Tabi ki ek olarak Visual Studio'nın şablona göre içeri attığı farklı dosyalar ve klasör yapıları da var ama onlar pek de kritik değil. Sanırım hepsi bu kadar :) Atladıklarım varsa yorum olarak beklerim ;)

    Görüşmek üzere.

    ASP.NET'te OutputCaching olayını bilmeyen yoktur diye tahmin ediyorum. Kabaca herhangi bir sayfanın çıktısının cache'e alınmasını sağlayan bu özellik ile isterseniz PartialCaching de yapabilirsiniz. Yani bir sayfanın tamamı cache'e alınmazken içindeki bir UserControl alınabilir. Tüm bunların epey detaylıca ayarlarını yapmak da mümkün. Örneğin Cache'in ne şekilde oluşturulacağını belirlemek için VaryByParam ile GET/POST ile gelen parametrelerdeki değişiklikleri baz alabiliyoruz. Buna ek olarak VaryByControl ile de sayfadaki herhangi bir ASP.NET kontrolündeki değişikliğin Cache'i valide etmesini de sağlayabiliyoruz. Böylece tek bir sayfa URL'den gelen bir ID'ye göre birden çok defa cache'e alınabiliyor veya sayfadaki bir kontroldeki her state için ayrı ayrı cache'lenebiliyor.

    VaryByCustom

    İşte şimdi size bir VaryByCustom hikayesi anlatacağım :) Çoğumuzun bilmediğini tahmin ettiğim VaryByCustom aynı VaryByParam ve VaryByControl'de olduğu gibi OutputCaching'de variyasyonların nasıl yaratılacağını belirliyor. Fakat adından da anlaşılacağı üzere bu işlemi olabildiğince özelleştirilebilir bir şekilde yaparak bize esneklik sağlıyor. Esasında benim tüm bu makaleyi yazmama neden olan ihtiyaç şöyle bir ihtiyaçtı. ASP.NET'te bir sayfada yer alan UserControl'üm dışarıdan aldığı bir parametreye göre içerik gösteriyor. Bu parametre hep değişebiliyor ve tabi ki farklı parametreler için farklı cache'ler şart. Bu noktaya kadar sanırım "VaryByControl" yeter de artar. UserControl'ün içinde dışarıdan parametreyi aldığı bir property var ve bu Property'yi VaryByControl ile OutputCache'e vermemiz bu noktaya kadar ihtiyacımızı giderecek.

    [ASP.NET]

    <%@ Control Language="vb" AutoEventWireup="false" CodeBehind="ornek.ascx.vb" Inherits="site.ornek" %>
    <%@ OutputCache Duration="160" VaryByControl="ornek.birID" Shared="true" %>

    Yukarıdaki manzarada 160 saniyelik bir OutputCache'i UserControl'e verdik. Farklı sayfalarda bu UserControl aynı parametrelerle kullanılırsa tek bir defa Cache'lenmesi için Shared özelliğini de True olarak set ettik. Son olarak da ornek adındaki UserControlümüzün birID adındaki Property'sini VaryByControl diyerek tüm cache'lerin bu property'ye gelen değerler etrafında oluşturulmasını sağladık. Bir sonraki adıma geçecek olursak esas ilginç noktaya gelmiş olacağız. Tüm cachle'lerin session based olmasını istiyoruz :) Evet, bir nefes alalım... Biliyorsunuz ASP.NET'teki OutputCache Session based değil. Yani bir kullanıcı siteye gelip Cache'lenmeye sebep oldu ise diğer kullanıcı geldiğinde Cachelenmiş içeriği görür. Aslında bu tam da OutputCache'in yapması gereken şey. Ama benim ihtiyacım olan bu değildi :) İstediğim şey siteye gelen her kullanıcının kendi cache'ine sahip olması. Böylece her kullanıcı siteye geldiği anda taze veri alacak ve kendi session'ı boyunca cachelenmiş veri görecek. Bunu yapabilmek için VaryBySession gibi bir şey lazım ki böyle bir şey yok. O yüzden ben de VaryByCustom'a başvurma kararı aldım.

    [ASP.NET]

    <%@ Control Language="vb" AutoEventWireup="false" CodeBehind="ornek.ascx.vb" Inherits="site.ornek" %>
    <%@ OutputCache Duration="160" VaryByControl="ornek.birID" VaryByCustom="sessionlifetime" Shared="true" %>

    İlk olarak yukarıdaki gibi OutputCache'e VaryByCustom özelliği veriyoruz. Buraya ne yazdığınız önemli değil. Yeter ki Browser yazmayın :) çünkü o şekilde tanımlı hazır bir yapı zaten var. Onun yerine ben kendi örneğimde "sessionlifetime" dedim. Dediğim gibi buraya herhangi bir string değer verebilirsiniz. Bir sonraki adımda bu değeri yakalayan yine biz olacağız.

    [Global.asax / VB]

    Public Overrides Function GetVaryByCustomString(context As HttpContext, arg As StringAs String
        If (arg = "sessionlifetime"Then
            Return context.Session.SessionID
        Else
            Return ""
        End If
    End Function

    Global.asax içerisinde Override edebileceğiniz GetVaryByCustomString adında bir fonksiyon var. Bu arkadaşa context olarak HttpContext ile beraber bir de args parametresi geliyor. Koddan da anlayabileceğiniz üzere args zaten bizim VaryByCustom'a verdiğimiz değer. Eğer farklı sayfalarda farklı VaryByCustom değerleriniz varsa buradaki fonksiyonu bir Switch koyarak ilerlemeniz gerekecek. Ben Session based caching istediğim için Cache Validasyonu adına SessionID'yi kullanmak mantıklı oldu. Buradan geri döndüğünüz her farklı değer OutputCache için bir input olacak ve eğer yeni farklı bir değer gelmiş ise hemen yeni bir Cache yaratılacak. Eğer değer daha önce geri gönderilmiş ise bu sefer söz konusu kontrolün içeriği Cache'den stream edilecek.

    İşte bu kadar basit. Böylece hem UserControl'e gelen parametreye göre hem de Session based bir OutputCaching'im olmuş oldu :) Ben mutluyum, umarım sizin de işinize yarar.

    Kolay gelsin.

    Blogu yazarken kullandığım bir ufak taktiği daha sizlerle paylaşmak istiyorum :) Özellikle blogun arama ve arşiv kısımlarında süper işime yarayan bu taktik IIS'ten response'un sıkıştırılarak gönderilmesi. Konuya geçmeden önce sizden blogun arama ve arşiv kısımlarını bir ziyaret etmenizi istiyorum. Sayfaların açılış hızından tutun özellikle arama kısmındaki aramanın hızına kadar sanırım tüm bu performans öğeleri dikkatinizi çekecektir. Sayfaların hızlı açılması adına birer günlük output caching koyduğumu itiraf etmem gerek. Bu bölümlerde blogun son bir günündeki değişikliklerin yansımamasını göze alarak böyle bir caching stratejisinin doğru olacağını düşündüm.

    [HTML]

            <%@ OutputCache Duration="86400" VaryByParam="lang" %>

    Konumuz olmasa da yukarıdaki ayarlama hemen bir paylaşiyim istedim. Bu arada unutmadan VaryByParam cachlemenin bir değişkene göre farklılaştırılabilmesini sağlıyor. Örneğin benim blogda İngilizce ve Türkçe sayfalarda arama sayfaları aslında aynı sadece URLReWriting üzerinden gelen Lang parametresine göre sayfa kendisini şekillendiriyor. Bu parametreye göre iki farklı cache alınıp kullanılabilmesi için VaryByParam'ı da set edebiliyoruz. Bu kısa Cache hatırlatmasından sonra gelelim esas meseleye, arama sayfası.

    gzip veya deflate

    Hem arama hem de arşiv sayfasında sayfanın outputu çok büyük. Arşiv sayfasında tüm makaleler ve linkleri olduğu için HTML çok şişti. Arama sayfasında ise başka bir nedenle şişme oldu :) O neden ne mi? Bloga arama özelliğini eklerken düşündüm ve aslında postların başlıkları ve tagleri dışında bir aramanın gerekmediğini düşündüm. Yani postların metinlerinin içinde bir arama çok anlamlı değil. Sonrasında aklıma gelen fikir şu oldu; acaba dedim 3000 tane postun başlıkları ile taglerini direk sayfa ilk açılışında JSON olarak outputa eklesem sayfa çok mu şişer? Düşündüğüm şey herşeyi sayfa ilk açılırken içine eklemek sonra da arama işleminini tamamen JavaScript ile istemcide yapmaktı. Böylece süper bir performans elde edecektim. Yaptığım testlerde 3000 makalenin başlık ve tag bilgilerinin ortalam 120 KB tuttuğunu gördüm. Ortalama bir ADSL bağlantısında bunun 1sn'de download olacağını düşünürsek aslında uzun bir süre sayılmaz ama yine de plain-text bir içeriği böyle bulk göndermek söz konusu olunca bunu ziplesem ne olur diye düşünmeye başladım ve....

    [VB]

            Public Shared Sub GZipEncodePage()
                If IsGZipSupported() Then
                    Dim Response As HttpResponse = HttpContext.Current.Response

                    Dim AcceptEncoding As String = HttpContext.Current.Request.Headers("Accept-Encoding")
                    If AcceptEncoding.Contains("gzip"Then
                        Response.Filter = New System.IO.Compression.GZipStream(
                            Response.Filter, System.IO.Compression.CompressionMode.Compress)
                        Response.AppendHeader("Content-Encoding""gzip")
                    Else
                        Response.Filter = New System.IO.Compression.DeflateStream(
                            Response.Filter, System.IO.Compression.CompressionMode.Compress)
                        Response.AppendHeader("Content-Encoding""deflate")
                    End If
                End If
            End Sub

    İşte ortaya yukarıdaki kod çıktı. Bu kod ilk olarak sayfayı açan istemcinin Encoding destekleyip desteklemediğine göz atıyor. Sonra da desteklenen encoding seçeneğine göre uygun gzip veya deflate encoding'i kullanıyor. Bu teknik sunucunuzun durumuna göre hafiften ek yük yaratabilir. Özellikle dinamik sayfaları sürekli zipliyor olmak tabi ki request yükünü etkileyecektir. Fakat benim senaryomdaki gibi zaten günlük cachelenen bir içeriği ziplemenin hiçbir zararı olmaz. Sözün özü 120 KB'lık output 30KB civarına indi. Özetle 35 KB'lık bir arama sayfası 3000 makalenin başlık ve taglerini de download etmiş şekilde istemciye gönderiliyor. Hiç fena değil!

    gzip ve deflate gibi output compression site genelinde IIS'ten de ayarlanabilir ama sitenizin yüküne göre çalışma zamanında kapatıp açmak veya sayfa bazında kapatıp açmak isterseniz yukarıdaki kod işinizi görecektir.

    Hepinize kolay gelsin ;)

    Blog yazmak ciddi ciddi apayrı bir işmiz :) Örneğin ben hiç düşünmemiştim ki bloguma yazı eklediğimizde nasıl hemen FeedBurner bunu görüyor. Nasıl oluyor da çat çat her tarafa otomatik publish oluyor. Feedburner çılgın çılgın gelip bakıyor sürekli sanarken aslında durumun pek de öyle olmadığını öğrendim :) Aslında blog sistemlerinin hepsi gidip bu üçüncü parti yerlere XML-RPC ile Ping atıyorlarmış. Hatta bunu otomatik hale getiren http://pingomatic.com/ gibi yerler var. Tamam da tüm bunları nasıl otomatik hale getireceğiz? Yani bloga bir yazı girdiğimde veya yazıyı değiştirdiğimde nasıl olacak da tüm bu servisleri haberdar edeceğim?

    [VB]

            Public Shared Sub Send()
                Execute("http://ping.feedburner.com")
                Execute("http://rpc.pingomatic.com/RPC2")
            End Sub

            Private Shared Sub Execute(url As String)
                Try
                    Dim request As HttpWebRequest = DirectCast(WebRequest.Create(url), HttpWebRequest)
                    request.Method = "POST"
                    request.ContentType = "text/xml"
                    request.Timeout = 3000

                    AddXmlToRequest(request)
                    Dim Res = request.GetResponse()
                    Dim Reader As New StreamReader(Res.GetResponseStream())
                    Dim Final = Reader.ReadToEnd
                Catch generatedExceptionName As Exception
                    Helpers.ErrorReport(generatedExceptionName.Message, generatedExceptionName.StackTrace)
                End Try
            End Sub

    İşte yukarıdaki kod işinizi görecektir. Basit bir POST işlemi ile Ping yapılabiliyor. Catch'deki gereksiz loglama benim blogla alakalı :) onu kaldırdım oradan. Şimdi kodu okuyanlarınız tabi AddXmlToRequest nerede diye soracaklar. İşin sırrı da biraz orada zaten.

    [VB]

            Private Shared Sub AddXmlToRequest(request As HttpWebRequest)
                Dim stream As IO.Stream = DirectCast(request.GetRequestStream(), IO.Stream)
                Using writer As New XmlTextWriter(stream, Encoding.ASCII)
                    writer.WriteStartDocument()
                    writer.WriteStartElement("methodCall")
                    writer.WriteElementString("methodName""weblogUpdates.ping")
                    writer.WriteStartElement("params")
                    writer.WriteStartElement("param")
                    writer.WriteElementString("value""Daron Yöndem")
                    writer.WriteEndElement()
                    writer.WriteStartElement("param")
                    writer.WriteElementString("value""http://feeds2.feedburner.com/daronyondem")
                    writer.WriteEndElement()
                    writer.WriteEndElement()
                    writer.WriteEndElement()
                End Using
            End Sub

    Benim blogda ping ile beraber "Hey burada değişiklik var!" dediğim tek yer feedburner RSS linkim olduğu için onu direk kodun içine gömdüm. Sizin kodunuzda parametrik olabilir bu kısım tabi ki :) Kabaca yolladığım XML aşağıdaki şekilde;

    [XML]

    <?xml version="1.0"?>
    <methodCall>
      <methodName>weblogUpdates.ping</methodName>
      <params>
        <param>
          <value>Hoboloy</value>
        </param>
        <param>
          <value>http://www.hoyhoy.com/</value>
        </param>
      </params>
    </methodCall>

    Buradaki methodName önemli, geri kalanlar ise sizin istediğiniz şekilde değiştirebileceğiniz şeyler. Unutmayın bunu sadece yeni içerik eklendiğinde değil içerik değişikliğinde de yapmanız gerekiyor.

    Hepinize kolay gelsin ;)

    Şimdi efendim :) uzun zaman oldu blogdan böyle bir derleme toplamı maili atmayalı. O nedenle bugün öyle bir post yaziyim dedim. İlk olarak sürekli "Hocam gelmişsin haberimiz olmadı" sorununu çözelim :) Bir yere gideceksem, bir yerde etkinlik oluyorsa nasıl haberdar olabilirsiniz?

    Benim birinci tavsiyem ilk aşamada tabi ki blogu takip etmeniz. Bunu ister RSS üzerinden yapın ister buradan mail ile kayıt olun her post mail gelsin. Bu işlemi yerine getirdikten sonra geriye kalıyor twitter, facebook, friendfeed konuları :)

    Şimdi bazı duyuruları bloga yazmıyorum. Kısa kısa geçmek istediğim şeyleri genelde twitter üzerinden geçiyorum. O nedenle eğer varsa bir twitter hesabınız ve kullanıyorsanız :) www.twitter.com/daronyondem doğru adres olacaktır. Twitter'a attığım herşeyi Facebook'a da atıyorum. http://www.facebook.com/daronyondemtr adresindeki "Beğen / Like" :) düğmesi takip için yeterli olur. Şu sıralar gittiğim geldiğim aktiviteleri de Facebook Fan Page üzerinde yaratıyorum ki toplu olarak bir yerde bir aktivite listesi görme şansınız da olsun.

    Son olarak Friendfeed kullananlar da www.friendfeed.com/daronyondem buradan takip edebilirler.

    Görüldüğü üzere manzara açık ve net :)

    Son zamanlarda bir de GoodReads kullanmaya başladım :) Hani ilgilenenlere ....

    Bu aralar neler var?

    Önümüzdeki hafta Microsoft Istanbul ofisinde "Silverlight UI Ninja Eğitimi" var :) Kesinlikle kaçırmamanızı tavsiye ederim :) Sonrasında Mayıs başında ise Ankara'da Silverlight 5 ve ASP.NET MVC3+HTML5 oturumlarım var. "Ankara'ya gelmiyorsunuz" gerçek dışı söylemleri üreten arkadaşlara duyurulur :D

    Yurt dışında ise Dubai, Ürdün, Mısır, Suudi Arabistan'a uğrayacağım Mayıs ayı içerisinde. Oralarda olan Türk kardeşlerimiz varsa görüşmek isteyenler bana mail atabilirler ;) Dubai'de Multitouch, Mısır ve Suudi Arabistan'da Azure, Ürdün'de ise Windows Phone 7 anlatacağım.

    Uzun zaman olmuştu şöyle bir güncelleme yazısı yazmayalı :) En kısa zamanda görüşmek üzere!

    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.
    Ö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.
    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
    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
    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
    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
    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...

    Twitter
    RSS
    Youtube
    RSS Blog Search
    Arşiv'de tüm yazıların listesi var. Yine de blog'da arama yapmak istersen tıkla!
    Instagram Instagram