Kimi zaman bir Web Site (Application değil) kodlaması yaparken (Class LibrarySınıf Kütüphanesi değil) birden fazla .Net Framework dilini kullanmak durumda kalınabilir.
Örneğin; Projede dil değişikliğine gidilebilir. Vb.Net dilinden C# diline geçmek gibi. Bu durumda adım adım ilerlermek daha mantıklı olacaktır. Lakin Web Site ŞablonuTemplate ile uygulama geliştirirken tüm classsınıf lar App_Code klasöründe olmalı ve klasör içinde tek dil uzantılı class dosyaları bulunmalıdır.
Peki böyle bir sorunu nasıl çözebiliriz.
İlk önce; App_Code klasörü her bil dil için alt klasörlere ayırılır. Kaç farklı dil kullanılacaksa o kadar klasör olmalı.
Daha sonra ise; Derleyicicompiler ye gerekli bilgileri web.config dosyası ile belirtmek yeterli olacaktır.
<configuration> <system.web> <compilation debug="false" targetFramework="4.0"> <codeSubDirectories> <add directoryName="vb-codes"/> <add directoryName="cs-codes"/> </codeSubDirectories> </compilation> </system.web> </configuration>
Ctr + Shft + B
Geçenlerde bir takım verileridata WebForm' unda görüntülememView ve filtrelememFilter|Search gerekti (zaman da dar bu arada).
Bakın ne yaptım;
<asp:QueryExtender ID="QueryExtender1" runat="server" TargetControlID="EntityDataSource1"> <asp:SearchExpression DataFields="ProductName" SearchType="StartsWith"> <asp:ControlParameter ControlID="productname" /> </asp:SearchExpression> </asp:QueryExtender>
protected void Button1_Click(object sender, EventArgs e) { QueryExtender1.DataBind(); }
Alternatif olarak; TextBox kontrolünün Autopostback özelliğini True olarak ayarlanırsa Button kontrolüne ihtiyaç kalmadan da filtrelemeyi tetiklemek mümkün olur.
Biraz açıklama: QueryExtender, Framework 4.0 bileşenidir. LINQ ifadeleri için geliştirilmiş Expressionlaraİfade sahiptir. Örneğimizde SearchExpression kullandık. Nasıl kullandık? DataFields özelliği ile filtre uygulanacak alanı belirledik.(Daha fazla alan virgül ile belirtilebilir) Bu özellik klasik Sql sorgusunda where ifadesinden sonra kullanılan fieldAlan tanımlaması gibi düşünebilir. SearchType özelliği ise like ifadesinin karşılığıdır. StartsWith 'parametre%', EndsWith '%parametre' ve Contains '%parametre%' gibi çalışır. Son olarak filtreleme için kullanılacak parametre kaynağını belirtmek. Bu bir kontrol olabileceği gibi session, cookie gidi kaynaklar da olabilir.
Projeyi indirmek için tıklayın.
Repeater ile verileri listemek yada sıralamaksort mümkün. Peki sıralamasını manuel nasıl yaparız?
Bunu gerçekleştirmek için taşıma yapmak istediğimiz tablomuza RowNumber adlı bir kolonfield ekliyoruz. Bu kolondaki değer verinin sıra numarasını temsil edecek. Taşıma işlemi ise bu numaraları değiştirmekten ibaret olacaktır.
Repeater içine sıralama olayını gerçekleştirmek için iki adet ImageButton kontrolü ekliyoruz. CommandArgument özelliğineproperty taşınacak satırın Id değerini atıyoruzset. CommandName özelliğine atanan up ve down değerleri ile de taşıma yönünü bildiriyoruz.
<td style="width: 24px; text-align: center;"> <asp:ImageButton runat="server" ID="moveup" ImageUrl="~/Images/up.png" ToolTip="Yukarı Taşı" CommandArgument='<%# Eval("Id")%>' CommandName="up" /> </td> <td style="width: 24px; text-align: center;"> <asp:ImageButton runat="server" ID="movedown" ImageUrl="~/Images/down.png" ToolTip="Aşağı Taşı" CommandArgument='<%# Eval("Id")%>' CommandName="down" /> </td>
Repeater kontrolünün ItemCommand olayıevent na aşağıdaki kodları yazarak taşıma işlemini gerçekleştiriyoruz.
using (NorthwindDataContext db = new NorthwindDataContext()) { //taşınacak verinin Id bilgisi alınıyor Guid Id = new Guid(e.CommandArgument.ToString()); //taşınacak veri OrderedProduct moveproduct = db. OrderedProducts. FirstOrDefault(p => p.Id == Id); //yeni numara hesapla int RowNumber = e.CommandName == "up" ? moveproduct.RowNumber - 1 : //yukarı ise moveproduct.RowNumber + 1; //aşağı ise //yeri değişecek veri OrderedProduct targetproduct = db. OrderedProducts. FirstOrDefault(p => p.RowNumber == RowNumber); if (e.CommandName == "up") { //yukarı taşı moveproduct.RowNumber -= 1; targetproduct.RowNumber += 1; } else if (e.CommandName == "down") { //aşağo taşı moveproduct.RowNumber += 1; targetproduct.RowNumber -= 1; } //değişiklikleri yap db.SubmitChanges(); } //tekrar listele BindData();
Daha sonra ise, ilk satırdaki Yukarı Ok u ve en alt satırdaki Aşağı Ok ImageButton'larını basit bir script kodu ile kaldırıyoruz. Bu kod sayesinde sunucuserver tarafındaki ilk kayıt mı son kayıt mı kontrolünü yapmaktan yırtıyoruz :)
<script src="Scripts/jquery-1.4.1-vsdoc.js" type="text/javascript"></script> <script type="text/javascript"> $(document).ready(function () { $("table tbody tr:first td:eq(3)").empty(); $("table tbody tr:last td:eq(4)").empty(); }); </script>
Repeater kontrolü renderHtml koduna dönüşmek edildiğinde aşağıdaki görüntü oluşacaktır. Kullanıcı yukarı aşağı ok tuşları ile satırları manuel olarak sıralayabilecek.
Projeyi indir.
Geçenlerde bir uygulama için Captcha örneği hazırlıyoruz. Test aşamasında iken güvenilirliğini nasıl test edebiliriz diye düşündüm. Akabinde aklıma MS OneNote uygulaması geldi. Ms Outlook'tan sonra en sık kullandığım ikinci MS Office uygulamasıdır. Uygulamanın özellikleri saymakla bitmez ama bizi ilgilendiren ise bir çeşit OCR özelliği barındırmasıdır. Bu özellik sayesinde resimlerin içindeki metinleri ayrıştırabiliryorsunuz.
Resime sağ tıkla ve metni ayrıştır.
Basit bir örnek ile başlayalım.
Arial 14 gri üzerine siyah metin. Sonuç -> 5TSRB5
İki çizgi atalım Sonuç - > KW4
Arka planı HatchBrush ile değiştirelim Sonuç -> String.Empty :)
Not: Bu test 100% güvenilir değildir. Daha iyi algoritmalar ile ayrıştırma daha başarılı olabilir.
Örnek proje.
Geçenlerde herhangi bir uygulama geliştiriyordum ki aniden bir kontrol ihtiyacım oldu. Söyle ki;
Bir Classnesne oluşturdum.
public class Employee { public int ID { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public decimal Salary { get; set; } public DateTime HireDate { get; set; } }
Daha sonra kopyasınıinstance çıkarıp özelliklerine değer atadım. Buraya kadar herşey normal. Peki dedim şunu birde WebForm'unda zahmetsiz bir şekilde gösterebilsem ne süper olur. Böyle durumda akla en yatkın DetailsView veri kontrolü kullanmaktır. Lakin kontrolün DataSource özelliğine herhangi bir nesneyi zart diye atayamazsınız. Eğer atarsanız şöyle bir hata alırsınız
Hoş değil :(
Bu gibi durumlarda olmasa ne zaman kontrol geliştireceğiz ki :) Peki ne yapmak lazım; Mantık basit. Reflection ile nesne özelliklerini okumak, kontrolün ihtiyaç duyabileceği ekstra bilgileri Attributenitelik yardımı ile iletmek.
[Serializable] public class Employee { [FieldAttributes(IsVisible = false)] public int ID { get; set; } [FieldAttributes(FieldHead = "Ad")] public string FirstName { get; set; } [FieldAttributes(FieldHead = "Soyad")] public string LastName { get; set; } [FieldAttributes(FieldHead = "Maaş", Format = "N2")] public decimal Salary { get; set; } [FieldAttributes(FieldHead = "İşe Başlama Tarihi", Format = "dd.MM.yyyy")] public DateTime HireDate { get; set; } }
Kullanımın kolay olması için SmartTag ve DesignTimeSupport gibi atraksiyonlar.
Sonuç;
Proje dosyası.
Web.config dosya tanımlamalarında bulunan configSource özelliği ile verileri birden fazla dosyaya dağıtarak yönetimi daha rahat bir hale getirebiliriz. Burada dikkat edilmesi gereken nokta; yeni eklenen config dosyasında xml bildirimi ve configuration kök düğümünün olmaması gerekir.
Web.config dosyası. configSource ile diğer config dosyalarını kendine bağlıyor.
<?xml version="1.0"?> <configuration> <appSettings configSource="Applications.config"/> <connectionStrings configSource="Connections.config"/> <system.web> <compilation debug="true" targetFramework="4.0" /> </system.web> </configuration>
Tüm appSettings değerleri Applications.config dosyasında.
<appSettings> <add key="SendMail" value="True"/> <add key="ErrorMessage" value="Hata Oluştu."/> <add key="LogOffPath" value="~/Logoff.aspx"/> <add key="Logo" value="~/Images/NWTraders.png"/> </appSettings>
Tüm connectionStrings ifadeleri Connections.config dosyasında.
<connectionStrings > <clear/> <add name="DB1" connectionString="Data Source=.;Initial Catalog=db1;Integrated Security=True;" /> <add name="DB2" connectionString="Data Source=.;Initial Catalog=db2;Integrated Security=True;" /> <add name="DB3" connectionString="Data Source=.;Initial Catalog=db3;Uid=sa;Pwd=123456;" /> <add name="DB4" connectionString="Data Source=.;Initial Catalog=db4;Uid=sa;Pwd=123456;" /> </connectionStrings>
Repeater, veri kontrolleri içinde en sevdiğimdir. Onu esnek hale getiren basit yapısı da ben en cezbeden özelliğidir. Basit olduğundan dolayı görevi sadece veri göstermek. Peki sıralama yapmak istersek ne yapmalıyız? Aslında cevap basit; HeaderTemplate içine LinkButton kontrolü yerleştirip, sıralama bilgilerini de ViewState içinde tutacağız.
Burada tablotable başlıklarına birer LinkButton ve Image kontrolü koyuyoruz. LinkButton sıralama komutunu işlerken, Image kontrolleri de sıralama yapılan satırları işaret edecek.
<HeaderTemplate> <table> <tr class="head"> <th style="width: 65%"> <asp:LinkButton ID="h1" runat="server" Text="Product Name" CommandName="name" CommandArgument="ProductName" /> <asp:Image ID="ProductName" runat="server" ImageAlign="AbsMiddle" /> </th> <th style="width: 20%"> <asp:LinkButton ID="h2" runat="server" Text="Unit Price" CommandName="price" CommandArgument="UnitPrice" /> <asp:Image ID="UnitPrice" runat="server" ImageAlign="AbsMiddle" /> </th> <th style="width: 15%"> <asp:LinkButton ID="h3" runat="server" Text="Unit Stok" CommandName="stock" CommandArgument="UnitsInStock" /> <asp:Image ID="UnitsInStock" runat="server" ImageAlign="AbsMiddle" /> </th> </tr> </HeaderTemplate>
Sıralama sırasından iki adet bilgiye ihtiyaç var. Sıralanacak veri kolonu ve sıralama yönü. Bu bilgileri ViewState içinde saklıyoruz. Kullanım kolaylığı olması için Propertyözellik olarak tanımlıyoruz.
public string SortOrder { get { if (ViewState["SortOrder"] == null) ViewState["SortOrder"] = "Asc"; return ViewState["SortOrder"].ToString(); } set { ViewState["SortOrder"] = value; } } public string SortColumn { get { if (ViewState["SortColumn"] == null) ViewState["SortColumn"] = "ProductName"; return ViewState["SortColumn"].ToString(); } set { ViewState["SortColumn"] = value; } }
Sıralama komutu için yazılacak Ado.Net kodları.
"Kolon adı parametre olmadığı için String nesnedinin Format metotunu kullandım."
void GetData() { SqlConnection con = new SqlConnection( "Data Source=.;Initial Catalog=Northwind;Integrated Security=True"); string query = string.Format( "Select ProductName,UnitPrice,UnitsInStock From Products Order by {0} {1}", SortColumn, SortOrder); SqlCommand com = new SqlCommand( query, con); con.Open(); rpt1.DataSource = com.ExecuteReader(); rpt1.DataBind(); con.Close(); }
Uygulama sonunda elde edeceğimiz veri listesi.
Kalan detaylara projeyi indirip bakabilirsiniz.
Öyle bir tablotable olsun ki sınırsız kategori ve alt kategori ekleyebileyim. Neden bahsettiğimi anladınız sanırım :) Halk arasında Sınırsız Ağaç Yapısı denilen tablo çeşidi.
Örnek tablo:
Yapı şöyle olacak; Kategori, hiyerarşinin en üstünde ise alt kategori değeri 0sıfır değilse üst kategorinin id değeri yer alacak. Örneğin; Kitap, kendi kategorisinde en tepede yani alt kategori değeri 0. Dünya Klasikleri ise Kitap kategorisinin altında olduğu için alt kategori değeri Kitap kategorisinin CategoryID değeri olacak yani 1 gibi ...
Azıcık kod yazalım. Kategori tablosunu DataTable nesnesine doldurarak başlayalım. Bu hamle işimizi bi hayli kolaylaştıracaktır. Daha sonra recursiveyinenelen bir metot yardımıyla kategori ve alt kategori bitinceye kadar dönelim. Son olarak ta elde ettiğimiz değerleri Treeview controlülüne nodedüğüm olakarak ekleyelim.
"Eğer karışık geldi ise biraz recursive çalışın."
DataTable dt = new DataTable(); protected void Page_Load(object sender, EventArgs e) { SqlConnection con = new SqlConnection( "Data Source=.;Initial Catalog=Ordek;Integrated Security=True"); SqlDataAdapter dap = new SqlDataAdapter( "select * from Category order by SubCategoryID", con); dap.Fill(dt); populateData(TreeView1.Nodes[0], getrows("0")); } DataRowCollection getrows(string id) { DataView dw = new DataView(dt); dw.RowFilter = "SubCategoryID=" + id; return dw.ToTable().Rows; } void populateData(TreeNode node, DataRowCollection col) { foreach (DataRow row in col) { TreeNode n = new TreeNode(row[1].ToString()); node.ChildNodes.Add(n); populateData(n, getrows(row[0].ToString())); } }
Geçenlerde Asp.Net sunucuserver kontrollerinden TakvimCalendar üzerine uygulama geliştiriyorduk. Önemli günleri vurgulamak çok klasik bir örnektir. Bizde bu örnek üzerinden yola çıktık. Farklı olarak, gün seçildiğinde sonuçları popup pencere ile göstermeye karar verdik.
Örneği besleyecek basit bir xml verisi hazırladık ve veriyi kod içinde kullanmayı sağlayan basitte bir classnesne yazdık. Gerisi Takvim kontrolünü kullanamaya kaldı.
Sonuçları popup pencerede nasıl göstereceğimizi anlamak için Takvim kontrolünü biraz irdelemek gerekir. Kontrol tarayıcı penceresine basıldığındaRender html tarafında bir table etiketine karşılık gelir. Varsayılan olarakta herbir hücredekitd gün ifadesi anchorçapa etiketitag içinde gösterilir. Hücerelere tıklandığında ise dopostback fonksiyonu tetiklenerek işlem yapılır. Fakat bizim uygulamamızda anchor' a ihtiyaç yok.
O yüzden kontrolün SelectionMode özelliğini None olarak ayarlıyoruz. Böylece hücre içlerine sadece gün değerleri eklenir.
<form id="form1" runat="server"> <div> <asp:Calendar runat="server" OnDayRender="Unnamed1_DayRender" BackColor="White" BorderColor="#999999" CellPadding="4" DayNameFormat="Shortest" Font-Names="Verdana" Font-Size="8pt" ForeColor="Black" Height="180px" Width="200px" SelectionMode="None"> <DayHeaderStyle BackColor="#CCCCCC" Font-Bold="True" Font-Size="7pt" /> <NextPrevStyle VerticalAlign="Bottom" /> <OtherMonthDayStyle ForeColor="#808080" /> <SelectedDayStyle BackColor="#666666" Font-Bold="True" ForeColor="White" /> <SelectorStyle BackColor="#CCCCCC" /> <TitleStyle BackColor="#999999" BorderColor="Black" Font-Bold="True" /> <TodayDayStyle BackColor="#CCCCCC" ForeColor="Black" /> <WeekendDayStyle BackColor="#FFFFCC" /> </asp:Calendar> </div> </form> <script type="text/javascript"> function openPen(id) { window.open("showIT.aspx?id=" + id, "show", "width=300px,height=200px"); } </script>
Detayları göstereceğimiz popup penceresini açmak için basit bir JavaScript fonksiyonu hazırlıyoruz.
protected void Unnamed1_DayRender(object sender, DayRenderEventArgs e) { foreach (Day day in DayProvider.GetDays()) { if (day.Date.ToString("dd.MM") == e.Day.Date.ToString("dd.MM")) { e.Cell.Controls.Clear(); HyperLink link = new HyperLink(); link.Text = e.Day.Date.Day.ToString(); link.NavigateUrl = string.Format("javascript:openPen('{0}')",day.Id); e.Cell.Controls.Add(link); } } }
Önemli günleri vurgulayacak kodlarımızı Takvim kontrolünün DayRender adlı olayınaevent yazıyoruz. Bu olay, her bir gün için bir kez tekrarlanır. Uygun günü yakaladığımızda, hücre içini temizleyip yerine openPen JavaScript fonksiyonunu çağıran bir HyperLink kontrolü ekliyoruz. Bundan sonra çeşitlendirmek mümkün.
Uygulamayı daha iyi anlamak için aşağıdaki projeyi indirip bakmanızda fayda var.
Proje
Geçen hafta 1. bölümü biten site yayınlama konusunun devamı.
Bu bölümde, uygulama için tasarlanmış veritabanıdatabasenı uzak sunucuya nasıl aktarılacağına bakacağız. Burada ki söz konusu veritabanı MS Sql Server 2000 yada daha yeni bir sürüm olacak.
Tabiki de bu işlemleri yaparken hizmeti aldığımız hosting firmasının bize sunduğu imkanlar çok önemli. Biz olayı, bakup-restore imkanı vermeyen hosting firmalar için ele alacağız.
Hosting firması, bir arayüz ile backup/restore hizmeti vermiyor yada uyumsuzluklardan dolayı işlemi gerçekleştiremiyorsanız yapmanız gereken; Önce veritabanının DDLCreate scriptini oluştumanız daha sonra bunu çalıştırmalısınız. İskeleti oluşturduktan sonra DMLInsert scriptlerini (ki bu çok zahmetli bir işlemdir) oluşturup yine sunucuda çalıştırmanız gerekmektedir. Klasik MS Sql Server Management Studio sadece DDL scriptleri oluşturabilir. İşte tam burada Sql Publish Wizard uygulaması devreye girip hayatımızı kurtarıyor.
VS2008 kurulu ise SWP uygulamasını şu dizin altından bulabilirsiniz; 64 bit işlemciler için C:\Program Files (x86)\Microsoft SQL Server\90\Tools\Publishing\1.2 32 bit işlemciler için C:\Program Files\Microsoft SQL Server\90\Tools\Publishing\1.2
Başlamadan önce belirtmeliyim ki, SPW ile oluşturulan scriptler var olan bir veritabanı üzerinde işlem yapar. Öncelikle sunucu üzerinde aynı adlı bir veritabanı oluşturmuş olmanız gerekmektedir.
Kendi bilgisayarınızda kurulu olan Ms Sql Server' a bağlantı kuruyoruz.
Publish edilecek veritabınını seçiyoruz. Script all objects in the selected database seçeneği seçildiği takdirde, adım sayısı azalacak ve gerekli olan tüm DDL ve DML scripleri direk oluşacaktır.
İhtiyaç duyduğumuz nesneleri (Table,View,Procedure vs) seçiyoruz.
Alt nesneleri seçiyoruz.
Oluşacak script için dosya adı ve yolu belirliyoruz.
Uygun Ms Sql Server versiyonu seçillir.
Özet bilgisi ve ardından scriptimiz oluşturulur.
Bu işlemlerden sonra yapmanız gereken tek şey, oluşan script içeriğini host firmasının size verdiği arayüz de çalıştırmak olacaktır.
İkinci bölümün sonu...
Asp.Net eğitimi alan hemen hemen tüm öğrencilerin sıkıntılarından biri de, yapılan uygulamaların gerçek sunucuda nasıl yayınlanacağıdır. İşi bilenler için gayet basit gibi görünse de tecrübesi olmayan kişiler için ızdırap haline dönüşebilir. Hal böyle olunca bu konu ile ilgili tecrübelerimi aktaracağım küçük bir yazı dizisi hazırladım.
Konuyu üç bölüm halinde işleyeceğim. İlk bölüm, uygulamanın ftp ile sunucuya yüklenmesi. İkinci bölüm, uygulamanın (varsa) kullandığı veritabanının sunucuya yüklenmesi. Son ve üçüncü bölüm ise bir takım ipuçları içerecektir.
Bu bölümde, resimde görülen örnek projeyi sunucuya yüklenecek hale getireceğiz. Bunu göstermemim sebebi, uygulamanın çalışması için sunucuya herşeyi yüklenmesine gerek olmadığıdır.
Yayınlamadan önce bir iki ayar yapmamız gerekiyor. Web.config dosyasını açıp, compilation -> debug özelliğinin degerini false olarak ayarlıyoruz. Bu performans açısından önemli. Bu konu ile ilgili daha fazla bilgi edinmek isterseniz Scott Guthrie's şu yazısını okumanızı tavsiye ederim. Daha sonra, çalışma zamanıruntime nda ki olası hataları daha ayrıntılı görmek için customError -> mode özelliğinin değerini false olarak ayarlıyoruz. Bunu yapmanızı özellikle tavsiye ederim. Genelde ilk denemelerde hata alma olasılığı yüksektir. Detay görmek problemleri çözmekte çok faydalı olacaktır. Her şey yoluna girdiğinde şu yazıdaki gibi bir hata yönetimi yapmak işinize yarayabilir.
Yayın öncesi ayarları yaptıktan sonra sıra geldi uygulamanın sunucuya gönderilecek çıktısının alınması. Bunun için Projeye sağ tıklayıp Publish komutunu veriyoruz. Bu komut ile proje önce derlenir, hataerror alınırsa işlem iptal olur. Kimi zaman ikazlarwarnings alabilirsiniz ve genelde de size nerede olduğu konusundan bilgi vermez. Bu gibi durumlarda aklıma gelen olası sorun, projenin ihtiyaç duyduğu bir kaynağı (resim, script vs) bulamamasıdır. Asp.Net projeleri için birden fazla Publish seçeneği bulunmaktadır. Varsayılan seçenek, belirtilen bir klasöre sadece sunucuya gitmesi gereken dosya va klasörlerin çıktısını oluşturur. Zaten bu da bizim istediğimiz seçenek. Diğer seçenekleri görmek yada kullanmak için (Örneğin local sunucuya yayınlamak gibi) üzerinde üç nokta bulunan düğme işinizi görecektir. Herhangi bir değişiklik yapmadan çıktılar için bir yol belirliyoruz. İşlem başarılı bir şekilde tamamlandığında aşağıdaki gibi bir klasör çıktısı olacaktır. Bunlar sunucuya gitmesi gereken dosyalardır.
Bin klasöründeki dll dosyaları ve config uzantılı dosyalar sunucuya yüklendiğinde uygulamanız sonladırılır ve ilk çağrıda yeniden başlar. Bu durumda uygulama içindeki tüm oturumsession vs yok olacaktır. Size tavsiyem bakım zamanlarını geç saatlerde yapın ve app_offline.htm adında bir dosya oluşturup sitenin kök klasörüne koyun. Uygulama erişimini engelleyecektir.
Geriye son bir işlem kaldı. Çıktıların sunucuya yüklenmesine. Bunun için bir ftp uygulamasına ihtiyac var. Bir çok paralı yada parasız alternatif olmasına karşın benim tavsiye Total Commander adlı uygulamayı kullanmanız. Resimde görüldüğü gibi ftp sunucunuzu uygulamaya kayıt edin. Publish klasöründeki tüm dosyaları sunucu bilgisayarında size verilen (bu genelde ya wwwroot yada httpdocs adında bir klasör olur) klasöre kopyalayın.
Enterprise Library, Linq yada EntityFramework gibi yapılar kullanacaksanız, hosting paketinizin size vermiş olduğu Trust Level' ın medium yada full olduğundan emin olun. MVC gibi OutOfBand (şimdilik) denilen framework'lerinde direk çalışmadığını belirtmek isterim . Bunun için sunucunuzdan destek almalısınız.
Artık (veritabanı kullanmıyorsanız) uygulamayı test edebilirsiniz. Olası durumalara karşı problemleri çözüp yukarıda gerekli adımları tekrar etmeniz yeterli olacaktır.
Birinci bölümün sonu ...
"Hatasız bir uygulama yazmak için kullanıcıyı ortadan kaldırmaktır" (sanırım buna benzer bir şeydi) diye duymuştum bir zamanlar. Yazılımlarımızda hatalar olacak. Bu kaçınılmaz ama en aza indirmek içinde çaba sarfetmek te bizim görevimiz. Lakin bunun için her yere try cacth blokları da koymak pek mantıklı bir yaklaşım değil:) Bu durumlar için, özellikle web uygulamalarında Error Feedback denilen bir yöntem çok sık kullanılır. Amaç; çalışma zamanı bir sayfada ya da ona bağlı bir uygulamada hata oluştuğunda, hata ile ilgili detayların geliştiriciye e-mail olarak gönderilmesi daha sonra da kullanıcıya hata mesajı yerine basit bir html sayfası gösterilmesinden ibaret.
Error isiminde bir classnesne oluşturalım. Oluşan hata ile ilgili gerekli bilgileri birer özellikproperty olarak belirleyelim. Time : Hata ne zaman oluştu? Message : Oluşan hata nedir? -> Exception.Message Ip : Hataya maruz kalan kullanıcı Ip adresi nedir? Page : Hatanın oluştuğu sayfa hangisi? Details : Oluşan hatanın detayları? -> Exception.Source
public class Error { public DateTime Time { get; set; } public string Message { get; set; } public string Ip { get; set; } public string Page { get; set; } public string Details { get; set; } }
Gönderilecek Feefback için güzle bir html şablonu oluşturalım. Şablon içinde bilgi gireceğimiz alanları küme parantez parametreleri ile işaretleteyim ki String nesnesini Format metotu ile rahatça kullanabilelim. Oluşan şablonu App_Data klasörünün altına koyuyoruz.
Error nesnesine hizmet edecek ErrorProvider adında yardımcı bir nesne daha oluşturuyoruz. Nesneye CreateMessage adında static bir metot ekliyoruz. Metotun görevi; daha önce hazırladığımız şablonu okumak ve parametre olarak verilen error nesnesinden gelen bilgileri şablondaki gerekli yerlere yerleştirmek. Son olarakta oluşan bilgiyi e-mail olarak göndermek. (SendMail metotu için projeye bakınız)
public class ErrorProvider { public static void CreateMessage(Error error) { string content = File.ReadAllText( HttpContext.Current.Server.MapPath("App_Data/error.txt")); content = string.Format( content, error.Time.ToString("dd.MMM.yyyy HH:mm"), error.Page, error.Ip, error.Message, error.Details); SharedClass.SendMail( "developer@domain.com", "Raise Error", content); } }
Herşey tamam gibi. Sırada oluşabilecek hataları elde elebileceğimiz Global Application Class' ından yardım almaya geldi. Global.asax ' ın Application_Error adlı metotu, uygulama içinde hata oluştuğunda otomatik devreye girer. Bizde burada devreye girip ihtiyacımız olab kodları yazıyoruz.
protected void Application_Error(object sender, EventArgs e) { Exception exteption = Server.GetLastError(); Error error = new Error(); error.Message = exteption.Message; error.Details = exteption.Source; error.Time = DateTime.Now; error.Page = Request.UrlReferrer.AbsoluteUri; error.Ip = Request.ServerVariables["HTTP_X_FORWARDED_FOR"]; if (error.Ip == null || error.Ip == string.Empty || error.Ip == "unknown") error.Ip = Request.ServerVariables["REMOTE_ADDR"]; ErrorProvider.CreateMessage(error); Server.ClearError(); }
Son bir adım kaldı. Kullanıcı hata mesajları yerine bizim belirlediğimiz sayfaları görsün.
<customErrors mode="On" defaultRedirect="~/Error/GenericErrorPage.htm"> <error statusCode="403" redirect="~/Error/NoAccess.htm"/> <error statusCode="404" redirect="~/Error/FileNotFound.htm"/> </customErrors>
web.config dosyası içindeki customError -> mode özelliğini On olarak değiştiriyoruz. Daha sonra error alt düğümleri ile olası hatalar için uygun sayfaların yollarını redirect özellikleri ile belirttikten sonra uygulamada bitmiş oluyor.
Dataveri kaynağınız xml olduğunda içindeki verileri okumak veritabanındandatabase okumak kadar kolay olmayabilir. XmlDataSorce nesnesiclass ile bu işlemi basit bir hale getirebilir.
<asp:Repeater ID="Repeater1" runat="server" DataSourceID="XmlDataSource1"> <HeaderTemplate> <table style="font-family:Verdana;font-size:11px;"> </HeaderTemplate> <ItemTemplate> <tr> <td> <a href='<%# XPath("link") %>'> <%# XPath("title") %> </a> </td> </tr> <tr> <td style="text-align:right;font-style:italic;"> <%# XPath("pubDate")%> </td> </tr> <tr> <td> <%# XPath("description")%> </td> </tr> </ItemTemplate> <FooterTemplate> </table> </FooterTemplate> </asp:Repeater> <asp:XmlDataSource ID="XmlDataSource1" runat="server" DataFile="http://www.ayrilmaz.com/rss" XPath="rss/channel/item"></asp:XmlDataSource>
Kodu biraz incelersek; XmlDataSource nesneclass sinin DataFile özelliğiproperty xml dosyasının yolunu ister. Bu disk üzerinde bir dosya olabileceği gibi bir rss dökümanı da olabilir. Burada önemli olan DataFile ile belirttilen verinin nasıl gösterileceğidir. Bunu yapmanın en pratik yolu ise xpath özelliğini kullanmaktır.
Veri kaynağını belirttikten sonra bunu gösterecek bir kontrole ihtiyaç var. Benim seçimim Repeater olacak. (DataList yada Grid de kullanılabilir). ItemTemplate içinde göstermek istenilen node adı XPath metoduna parametre olarak verilir ve değeri gösterilir.
Asp.Net sunucuserver kontrollerinden TextBox kontrolünü TextMode="Multiline" ayarlanarak kullanıldığında MaxLength özelliğiproperty çalışmamaktadır. Buraya çözüm için alternatif yöntemler yazacağım zaman zaman.
İlk çözüm yine sunucu kontrollerinden CustomValidator ile olacak.
<asp:TextBox ID="mesaj" runat="server" TextMode="MultiLine" Rows="6" Columns="40" /> <asp:CustomValidator ID="cvM" runat="server" ErrorMessage="En fazla 400 karakter." ForeColor="Maroon" ClientValidationFunction="Max400" ControlToValidate="mesaj" ValidationGroup="g1" /> <script type="text/javascript"> function Max400(source, arguments) { if (arguments.Value.length <= 40) arguments.IsValid = true; else arguments.IsValid = false; } </script>
devam edecek...
Geçenlerde bir web proje için resim kırpmacrop ve yeniden boyutlandırmaresize gibi işlemleri yapmam gerekti. Asp.Net'in yapısı gereği illaki JavaScript kullanmak kaçınılmaz bir durum. Günümüzde de oturup deli gibi JavaScript yazılmaz. O yüzden JQuery' den yardım almaya karar verdim.
ClientSide işlemler için Jquery eklentisi olan Jcrop kullandım. Diğer eklentiler arasından en beğendiğim bu oldu. Geri kalan kısımları ile GDI+ ile hallettim.
Uygulama.
Asp.net sunucu kontrollerinden Panel'in GroupingText özelliğini kullanarak html çıktısı olarak Fieldset etiketi (etkisi) elde edilebilir.
<asp:Panel ID="pnlLogin" runat="server" BorderStyle="None" GroupingText="Login" Height="123px" Width="280px"> <asp:Label ID="lblUsername" runat="server" Text="Username" /> <asp:TextBox ID="txtUsername" runat="server" /> <br /> <asp:Button ID="btnSubmit" runat="server" Text="Enter" />
Ben veri kaynağı olarak Xml kullanması severim de herkes sevmek yada bilmek zorunda değil. Xml ile yaptığım anket uygulamasını Sql ve Ado.Net kullanarak tekrar yaptım.
Veritabanı şeması aynen aşağıdaki gibi;
Uygulamada kullanılan nesneclass diyagramı;
Uygulamada kullanılan örnek kod;
public void OyVer(int AnketSoruID) { using (SqlConnection con = new SqlConnection( "Data Source=.;Initial Catalog=calismalar;Integrated Security=True;")) { using (SqlCommand com = new SqlCommand( "update AnketSorular set AnketOy += 1 where AnketSoruID = @AnketSoruID", con)) { com.Parameters.AddWithValue("@AnketSoruID", AnketSoruID); con.Open(); com.ExecuteNonQuery(); } } }
Uygulama kaynak kodları da burada. Sql script ise burada.
Zon zamanlarda Asp.Net Mvc ile uğraşıyorum. Asp.Net uygulamaları geliştiriken code-behind çalışan biriyseniz ilk etapta belli alışkanlıkları değiştirmeniz gerekiyor. Bunun yanısıra alışkanlık kazanmış olduğunuz bazı kontrolleride yer yer kullanamamakta ayrı bir problem teşkil ediyor. Buna örnek olarak WYSIWYG editorleri gösterilebilir.
Fck ve TinyMCE olmak üzere sürü ile editör mevcut fakat basit ve hafif bir editör ihtiyacınız varsa htmlArea benim favorim.
Editör dosyalarını buradan örnek projeyi şuradan indirebilirsiniz.
Gelelim projeye adapte etme kısmına; - Öncelikle editor klasörünü Content klasörüne kopyalıyoruz.
- creator.js dosyasında ki 2. satırı şu şekilde değiştiriyoruz.
_editor_url = "/Content/editor/";// editörün dosyalarının bulunduğu yol
- creator.js dosyasını editörü kullanacağımız sayfaya link verdikten sonra sayfaya 1 adet texteara ekliyoruz.
<textarea name="content" id="content" style="width: 500px; height: 250px;"> <%= ViewData["Data"] %></textarea> <script language="javascript1.2"> editor_generate('content'); </script>
artık sayfamızı test edebiliriz.
Bir WebFormu içerisinde birden fazla Default Button kullanmak için birden çok form etikettagi kullanmak bir çözüm olabilir. Alternatif bir çözüm ise Panel kontrolünü kullanmaktır. Panel kontrolünün de form etiketinde olduğu gibi DefaultButton özelliği bulunmaktadır. Bu özellik sayesinde bir WebFormu içinde istediğiniz kadar DefaultButton kullanabilirsiniz. Örnek;
<form id="form1" runat="server" defaultbutton="btnAd_1"> <div> <asp:Label ID="lblAd_1" runat="server" Text="Adınız" /> <asp:TextBox ID="txtAd_1" runat="server" /> <br /> <asp:Button ID="btnAd_1" runat="server" Text="Gönder" onclick="btnAd_1_Click" /> <br /> <br /> <asp:Panel ID="Panel1" runat="server" Height="86px" Width="173px" BorderStyle="Solid" BorderWidth="1" DefaultButton="btnAd_2"> <asp:Label ID="lblAd_2" runat="server" Text="Adınız" /> <asp:TextBox ID="txtAd_2" runat="server" /> <br /> <asp:Button ID="btnAd_2" runat="server" Text="Gönder" onclick="btnAd_2_Click" /> <br /> </asp:Panel> <br /> <asp:Label ID="sonuc" runat="server"></asp:Label> </div> </form>
Çok yakın ve kadim bir dostum için araştırırken farkettim ve paylaşmak istedim. ListView kontrolü içinde ki verileri gruplayarak göstermek. DataList kontrolündeki RepeatColums özelliğini kullanmak gibi fakat birazcık farklı :)
Div etiketleriyle Listview'e şablon hazırlamak yeterli.
<asp:ListView ID="Listview1" runat="server" GroupltemCount="S" EnableViewState="false"> <ItemTemplate> <div style="width: 200px; float: left; font-family: Verdana; font-size: l0px; margin-bottom: l0px;"> <asp:Image ID="Imagel" runat="server" ImageUrl='<%# "image.aspx?path=" + Eval("FullName") %>' /> <br /> <strong>Dosya Adi:</strong> <%# Eval("Name")%> <br /> <strong>Uzunluk: </strong> <%# Eval("Length")%> <br /> <strong>Özellikler : </strong> <%# Eval("Attributes")%> </div> </ItemTemplate> <LayoutTemplate> <div id="groupPlaceholderContainer" runat="server"> <div id="groupPlaceholder" runat="server"> </div> </div> </LayoutTemplate> <GroupTemplate> <div id="itemplaceholdertontainer" runat="server" style="width: l000px;"> <div id="itemPlaceholder" runat="server"> </div> </div> </GroupTemplate> </asp:ListView>
Veri kaynağı için basit ve hızlı bir çözüm, dosyalar.
Listview1.DataSource = from file in new DirectoryInfo("C:\\windows").GetFiles() orderby file.Name select new { file.Name, file.Length, file.FullName, file.Attributes }; Listview1.DataBind();
Dosyaları biraz süslü gösterelim.
string path = Request["path"]; Icon ico = Icon.ExtractAssociatedIcon(path); Bitmap bmp = new Bitmap(ico.Width, ico.Height); Graphics g = Graphics.FromImage(bmp); g.DrawIcon(ico, new Rectangle(0, 0, ico.Width, ico.Height)); bmp.Save(Response.OutputStream, ImageFormat.Png); g.Dispose(); bmp.Dispose(); ico.Dispose();
Daha önceki "Web Sitemiz .." başlıklı bir kaç yazımda Web Part' lar hazırlamıştım. Yeni bir kontrol daha; Tcmb günlük döviz bilgileri.
Uygulamayı indirmek için tıklayın.
Kullanım kolaylığı için 2 adet özellik eklendi.
Bu tip uygulamaları yaparken kaynağın kopyası üzerinde çalışmayı tercih ederim. Hız açısından.
public static string[] dovizBilgisi(DovizTipleri tip) { if (HttpContext.Current.Cache[tip.ToString()] == null) { XmlDocument xDoc = new XmlDocument(); // local -> test xDoc.Load(HttpContext.Current.Server.MapPath("App_Data/doviz.xml")); // online -> application // xDoc.Load("http://www.tcmb.gov.tr/kurlar/today.xml"); string[] doviz = { xDoc.SelectSingleNode(string.Format( "Tarih_Date/Currency[@Kod='{0}']/ForexBuying", tip.ToString())).InnerText.Replace('.', ','), xDoc.SelectSingleNode(string.Format( "Tarih_Date/Currency[@Kod='{0}']/ForexSelling", tip.ToString())).InnerText.Replace('.', ',') }; HttpContext.Current.Cache.Insert( tip.ToString(), doviz, null, DateTime.Now.AddHours(2), TimeSpan.Zero); } return (string[])HttpContext.Current.Cache[tip.ToString()]; }
Bir önceki yazımda Fck Editor'ü Asp.net projelerinde daha rahat kullanılabilecek hale getirdiğimden bahsetmiştim. Sanırım bir şey eksik kalmış, Fck Editor'ü bir projeye nasıl entegre ederimi unutmuşuz :)
Adım adım ilerleyelim;
1. Gerekli dosyaları buradan indirelim.
2. Resimde işaretli klasörleri projeye ekleyelim.
3. Eklediğimiz dosyalar içerisinde işaretli olan ascx dosyasını düzenleyerek upload edeceğimiz kaynakların yollarını belirleyebiliriz.
4. FredCK.FCKeditorV2.dll dosyasını Toolbar' a ekleyelim. Bunu yapmak için dll dosyasını Toolbar'a sürükleyip bırakabilir yada Toolbar'a sağ tıklayıp Choose Items.. komutunu kullanabiliriz.
Artık Fck Editor kontrolünü Textbox kullanır gibi WebForm'larımızda kullanabiliriz.
Ara ara web tabanlı WYSIWYG editorleri incelerim. GeçenlerdeFck Editor ile oyalandım. Gerçekten de çok başarılı bir editor olduğunu rahatlıkla söyleyebilirim. Gerçi indirip hemen kullanamıyorsunuz ama biraz ilgi ve alaka ile bunu başarıyorsunuz.
Azıcık araştırdım birazcık kurcaladım ufak tefek te eklemeler yaptım. Amacım Asp.Net Web Form' larında hızlı bir şekilde kullanmak.
Neler yaptım bir bakalım;
Proje dosyası, fckApplication.
Resimler
Toolbar optimizasyonu
Dosya gösterimi için alternatif satır rengi
Resimler için ön izleme
Xslt ile çalışıyorsanız bir kaç küçük ayrıntı. - Xml verilerini sıralamak için for-each kalıbına
<xsl:sort select="." order="ascending"/>
yazmak yeterli. - Satırları ardışık olarak renklendirmek için de mod operatörü ve position() fonksiyonu bu işin üstesinden gelecektir.
<xsl:variable name=mod1 select="position()"/> <xsl:if test="$modi mod 2 = 1">
Kodun tamamı;
<?xml version="1 .0" encoding="utf-8" ?> <Sehirler> <Sehir>Istanbul / Ataturk</Sehir> <Sehir>Ankara / Esenboga</Sehir> <Sehir>Ankara / Etimesgut</Sehir> <Sehir>Murted Tur—Afb</Sehir> <Sehir>Adana / Sakirpasa</Sehir> <Sehir>Adana / Incirlik</Sehir> <Sehir>Atyon</Sehir> <Sehir>Antalya</Sehir> <Sehir >Gaziantep</Sehir> <Sehir>Iskenderun</Sehir> <Sehir>Konya</Sehir> <Sehir>Merzifon</Sehir> <Sehir>Samsun</Sehir> <Sehir>Sivas</Sehir>
Xml verisinin devamı için tıklayın...
<xsl:template match="/"> <table style="width :200px;color:#333333;border-collapse:collapse;font-family:verdana;font-size : 10px;" cellspacing="0" cellpadding="4" border="0"> <tr style="color:White;background-color:#5D7B9D;font-weight:bold;"> <th scope="col">Şehirler</th> </tr> <xsl:for-each select="Sehirler/Sehir"> <xsl:sort select="." order="ascending"/> <xsl:variable name="modi" select="position()"/> <xsl:if test="$modi mod 2 = 1"> <tr style="color:#333333;background-color:#F7F6F3;"> <td> <xsl:value-of select="." /> </td> </tr> </xsl:if> <xsl:if test="$modi mod 2 = 0"> <tr style="color:#284775;background-color:White;"> <td> <xsl:value-of select="."/> </td> </tr> </xsl:if> </xsl:for-each> <tr style="color:White;background-color:#5D7B9D;font-weight:bold;"> <th>-</th> </tr> </table> </xsl:template>
Web siteniz için yurt dışından host hizmeti alıyorsanız, DateTime (Structure) yapısının string metotları istediğiniz sonuçları döndürmeyebilir. Bunun için örnek bir Extension Method hazırladım;
Şöyle bir düşündüğümüzde veritabınında bulunan herhangi bir tablonun verilerini Xml formatında dosyaya yazmanın kaç yolu vardır acaba? Sabahları genelde işe erken gelirim, 1.5 saat kadar :). Oturdum bir kaç örnek yaptım, paylaşıyorum tüm dünya ile. (Özgüvenin tavan yaptığı an) Aklıma gelen ilk yöntem DataTable nesnesini kullanmak. Bu nesneyi sadece yazmak için kullanmak kaynak tüketimi açısından çok iyi bir seçim olmaz fakat kullanım kolaylığı açısında tercih edilebilir.
Diğer bir yöntem ise henüz Veri KatmanındaDataLayer iken oracıkta Xml formatına dönüştürüp XmlTextWriter ile cayır cayır yazmak.
Son yöntem ise daha önce şu yazıda kullandığım teknik ile (attributenitelik yerine bu sefer nodedüğüm kullandım) XDocument ile manuel olarak Xml dosyasını oluşturmak. Sanırım en zoru bu. Yanlış anlaşılmasın benim için kolay da hani ilk yapan için diyorum :)
Web uygulamaları geliştirirken MasterPage kontrolü kullanıldığında içerik sayfalarında kullanılan sunucu kontrolleri istemci tarafında farklı isimlendirilir. Örneğin, Name özelliği txtAd olan TextBox kontrolünün istemci tarafında aldığı id değeri ctl00_ContentPlaceHolder1_txtAD olacaktır. Bu durumda istemci tarafındaki javascript fonksiyonundan kontrollere erişim çok pratik olmayacaktır. Şimdi bu durum karşısında nasıl bir tavır takınacağımıza bakalım :) Örneğimizde, içerik sayfasında bulunan 4 adet TextBox kontrolünün Text özelliğini temizleyen bir javascript fonksiyonumuz olacak.
Nasıl ki MasterPage kontrolü, karışıklığı engellemek için kontrollerin id özelliklerine öneki contentplaceholder ekliyorsa, bizde temizlemek istediğimiz kontrolleri, id özelliği region1 olan bir div içinde kullandık. Daha sonra div içindeki tüm input kontrollerini aldık ve özelliği text olanları temizledik.
Biz çok küçükken Cacheönbellek nesnesini kaşeye benzetirdik. Nasılsa ki kaşeyi mürekkebe bir kez bastırırsınız ve mürekkep bitene kadar kaşe aynı değerleri belgeye basmaya devam eder biz de böyle birşey sanırdık. Ne kadar doğru düşünmüşüz tartışmaya açık. Böyle bir giriş yaptığımıza göre konu olsa olsa Cache ile ilgili olacaktır. Yetim olarak tanımladığım (yıllardır toolbarda durur kimse kullanmaz) Substution nesnesini bir örnek ile hatırlatacağım. Varsayalım ki sayfanın tamamını (OutputCache) 60 saniye boyunca ön belleğe aldınız fakat sayfa içinde güncel olması gereken önemli bir bilgide yer almaktadır. İşte bu gibi durumlarda o önemli dediğiniz bilginin önbelleğe alınmasını engellemek için Substution nesnesi işinizi görecektir. Örnekte; şirket ürünleri önebellekten gelecek fakat son satılan ürün bilgisi sayfa her talep edildiğinde sunucu tarafından istemciye en güncel hali ile gönderilecektir.
Öğrencilerimin en sık sorduğu sorulardan biri de, veritabanında depolanmış resimleri web sayfasında nasıl gösterildiğidir. Internette bu konu hakkında zilyon tane yazı olmasına karşın bir tane yazma gereği hissettim.
Öncelikle anlaşılması gereken konu, html sayfalarında resim göstermenin ilk koşulu resmin fiziksel yolunun kontrole yada etikettage aktarılmasıdır. Örneğin;
Diğer taraftan baktığımızda ki bu taraf veritabanı tarafıdır, resim gibi içeriklerin hangi tip veri alanında saklanacağıdır. C# ile yazılım geliştiryorsanız resim yada bir dosya serileştiğinde (yani veritabına yazıldığında) byte dizisinden (byte[]) ibaret olacaktır. Bu durumda en uygun alan tipi varbinarybyte[] olsa iyi olur. :)
Kaçınılması gereken davranışlar.
yada
hiç olmadı :)
Peki yapılması gereken nedir? Veritabınından okunan byte dizisini resim formatında dışarı aktaracak (response) bir dosya (aspx,ashx) oluşturmak ve oluşan dosyanın yolunu resmi gösterecek kontrol yada etikete atamaktır.
Örnek tabloda gösterildiği gibi resim UrunResim alanında varbinarybyte[] olarak saklanıyor.
Resmi oluşturacak resim.aspx sayfasına gönderilen parametre değeri ile veritabanında basit bir sorgu yapılarak ve sonucu byte dizisi olarak elde edilir.
Son olarak ise sayfa çıktısının resim olacağını işaret eder ve çıktıyı BinaryWriter metotu ile oluştururuz.
Zengin içerikli elektronik postalare-mail hazırlarken en büyük sıkıntı kaynağın tekrar okunup gövdebody bilgisi olarak MailMessage nesnesine verilmesi diyebiliriz. Bu sıkıntıyı kolay bir şekilde atlatmanın yolu sanırım WebUserControl kullanmak olacaktır. Kullanalım o zaman :)
Verileri almak için kullanacağımız Stored Procedure;
E-Mail içeriğini sağlayacak olan WebUserControl;
Kontrolün toString metodunu ezerekoverride kullanım kolaylığı sağlıyoruz;
son olarak e-maili gönderecek olan kodlar;
Uygulamanın tamamı.
VS2005 SP1 ile New Project -> Web altında gelen Web Application üzerinden uygulaması geliştiriyorsak Profile kullanımı ne yazık ki Web Site ile kullanımından çok farklı bir hal alıyor. Peki bu hal nasıl ona bakalım; Önce web.config dosyasında birkaç küçük ayar yapıyoruz;
Daha sonra ise kod kısmında. Örneğin kullanıcı kayıt sırasında değerleri eşitlemek istersek;
WebForum'u içindeki varsayılandefault Button'u değiştirmek için JavaScript kodu aramaya gerek yok. Sunucu tarafında dinamik olarak üretilen WebResource içindeki WebForm_FireDefaultButton fonksiyonunu çağırmak yeterli olacaktır .
Not: Sayfaya ScriptManger ekleyin.
İkinci basit Web Part'ımız.
Bu aralar dersler de örnek olsun diye WebPart uygulaması yapıyorum. Bazı çıkarımlar olmadı değil. Sürü ile kontrol hazırladım. İyi kötü yazıyorum birkaç tanesini :)
Yazılımcı site yapar, çoklu dil desteği yapar. Birde yanına SiteMapPath olsun ister. Bu durum da SiteMapPath kontrolü için en önemli problem 2 adet .sitemap dosyasının olması ve hangisini kullanacağını bilememesidir. Bu durumu aşmanın yolu web.config dosyasına her bir sitemap için provider tanımlamaktır.
Tanımlanan providerları tarayıcının kullandığı dile göre kontrole eşitlemek işin son kısmı olacaktır.
Site içinde kullandığım E-mail uygulamasının kodları.
LinqToXml ile Xml dosyası oluşturup Treeview kontrolü ile gösterelim;
MemberShip ile kullanıcının giriş iznini belirleme
Küçük bir Globalization sorunu. Gridview içinde silme işlemi için client-sidekullanıcı taraflı uyarı ama hem Türkçe hem İngilizce;
Bir projede Login kontrollerinden PasswordRecovery kullanıyorum. E-mail içeriğindeki Türkçe karakterler problem oluşturuyor. Önce bu şekilde denedim.
olmadı, bende işi biraz uzattım.
mailBody.txt dosyasının içeriği;
Uygulamanızı sunucuya yükledikten sonra Türkçe karakter problemi yaşıyor iseniz (özellikle yurtdışı sunucularında) Head içerisindeki dil ile ilgili meta tagları kaldırıp web.config dosyasına globalization elemanını eklemek yeterli olacaktır.
WebForm'larında bulunan kontrollere odaklanmak için bir sürü yöntem varmış inceledik;
Asp.Net 2.0 ile gelen 2 yeni form özelliği;
Programatik yapmak istersek;
TreeView kontrolünü Menu gibi kullanmak istersek Css ile kolayca yapılabiliriz. Şahsen ben her zaman Menu kontrolüne tercih etmişimdir.
//head
//body
sonuç;
Gridview ile verileri gösterirken satır numarası da olsun;
Windows uygulamalarında klasör ve dosyaları listelemek için sıkça kullanılan TreeView kontrolünü aynı iş için Asp.Net ortamında nasıl kullanabiliriz? Web formuna ToolBox -> Navigation -> TreeView kontrolü ekleyelim ve kod tarafına geçelim. Öncelikle bir adet recursivetekrarlanan metot yazalım (System.IO eklemeye unutmayalım).
Bu metod başlangıç yolundan itibaren ne kadar klasör ve altında da ne kadar dosya varsa bitine kadar çalışacaktır. Fakat ortamın web olmasından dolayı bulunduğu Index'i bilemeyecektir. O yüzden ViewState tabanlı bir Propertyözellik yazalım.
Başlangıç noktasındaki dosyalar listeleniyor.
Kodu başlatıyoruz.
İşte sonuç.
Projei indir.
Site içinde kullanacağınız SiteMap' e tıklandığında yeni sayfada açılması için, ItemCreated doğru Eventolay gibi gözüküyor.
GridView kontrolü içinde Tooltip kullanımı için bir alternatif. Tooltip olarak gösterilecek alanı DataKeyNames içinde saklayıp uygun kolona Attributenitelik ile eşleştirmek.
Bir uygulama düşünün ki veriler Xml dosyasında sunum ise WebForm' unda olsun.
İşte tam aradığımız kontrol;
Verileri Xml dosyasında saklamının avantajlarından birisi de Xslt ile web uygulamalarına kolayca adapte edilebilmesidir. Örnek Xml verisi için Xslt kodu;
Proje kodları.
Windows uygulamalarında sıkça kullandığımız MessageBox.Show() birkaç adım ile WebForm'larında kullanılabiliyormuş.
Şöyle ki; Öncelikle projemize System.Windows.Forms Namespace'ini ekliyoruz. Daha sonra da aşağıdaki kodları yazıyoruz.
pek mantıklı değil:)
Bazen Asp.Net sayfalarımızın clientistemci tarafında durum gereği farklı davranmasını isteyebiliriz. Tabiki JavaScript kodlarını devreye sokarak. .NET Framework 2.0 versiyonu ile bunu yapmanın yolu ClientScriptManager Classnesne ının RegisterStartupScript metodunu kullanmak olacaktır. Bilindiği gibi RegisterStartupScript metodu 1.1 versiyonuda da bulunmaktaydı. Birçok metod gibi 2.0 ile bunun da kullanımı biraz değişmiş :) Uygulamamızda; clientistemci tarafında window.open( [sURL] [, sName] [, sFeatures] [, bReplace]) metodunu kod tarafında ise public void RegisterClientScriptBlock ( Type type, string key, string script ) metodunu kullanacağız.