Asp.net

MemberShip ile kullanıcının giriş iznini belirleme.

...
<
Columns>
   <asp:BoundField DataField="UserName" HeaderText="UserName"
/>
   <asp:BoundField DataField="Email" HeaderText="Email"
/>
   <asp:TemplateField HeaderText="IsApproved" ShowHeader
="False">
   <ItemTemplate
>
   <asp:LinkButton ID="LinkButton1" runat="server" CausesValidation="false"

CommandName="setAppr" CommandArgument='<%# Eval("UserName") %>' Text='<%# Eval("IsApproved") %>'></asp:LinkButton
>
   </ItemTemplate
>
   <ItemStyle HorizontalAlign="Center"
/>
</asp:TemplateField
>

protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
   if (e.CommandName == "setAppr"
)
   {
      MembershipUser us = Membership
.GetUser(e.CommandArgument.ToString());
      us.IsApproved = !us.IsApproved;
      Membership
.UpdateUser(us);
      ...
   }
}

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.

JavaScript

Html

Nasıl ki MasterPage kontrolü, karışıklığı engellemek için kontrollerin id lerine 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.

Xml ve Xls

14.Ocak.2007 Asp.net C# Xml

Bir uygulama düşünün ki veriler xml dosyasında sunum ise web formunda olsun.

İşte tam aradığımız kontrol;

<asp:Xml ID="Xml1" runat="server" DocumentSource="~/App_Data/anket.xml" TransformSource="~/App_Data/Anket.xslt"></asp:Xml>

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;

<?xml version="1.0" encoding="utf-8"?>
   <
xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
      <
xsl:template match="/">
         <
div id="header">
            ANKET SONULARI

         </
div>
         <
hr />
         <
xsl:call-template name="anket_oy" />
      </
xsl:template>
   <
xsl:template name="anket_oy">
   <
xsl:variable name="toplamOy" select="sum(Anket/cevap)" />
   <
table border="0" cellspacing="1" cellpadding="1" width="100%" id="votes">
      <
tr>
         <
th colspan="2">
            <
xsl:value-of select="Anlet/@ad"/>
            <
br/>
            <
br/>
         </
th>
      </
tr>
      <
xsl:for-each select="Anket/cevap">
      <
tr>
         <
td>
         </
td>
         <
td>
            <
xsl:value-of select ="@text"/>
         </
td>
      </
tr>
      <
tr>
         <
td width="25%">
            <
xsl:variable name="Toplam" select=". * 100 div $toplamOy" />
            % <xsl:value-of select="format-number(. * 100 div $toplamOy,'0')" />
         </
td>
         <
td>
            <
xsl:variable name="Toplam" select=". * 100 div $toplamOy" />
            <
img src="images/anket.png" height="10" width="{$Toplam}%" />
         </
td>
      </
tr>
      </
xsl:for-each>
   </
table>
   </
xsl:template>
</
xsl:stylesheet>

ve sonuç;

Anket

Site içinde kullanacağınız SiteMap' e tıklandığında Url'in yeni sayfada açılması için, ItemCreated doğru Olay gibi gözüküyor.

protected void SiteMapPath1_ItemCreated(object sender, SiteMapNodeItemEventArgs e)
{
   if (e.Item.Controls[0] is HyperLink)
      (e.Item.Controls[0] as HyperLink).Attributes.Add("target", "blank");
}

Gridview ile verileri gösterirken satır numarası da olsun;

protected
void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
   if (e.Row.RowType == DataControlRowType.DataRow)
   {
      (e.Row.FindControl("lblRow") as Label).Text = (e.Row.RowIndex + 1 + (GridView1.PageIndex * 10)).ToString();
   }
}

Bazen Asp.Net sayfalarımızın client 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 Class ı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;

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

Şimdi ise Logon Button' nun Click Olayına ilgili kodu yazalım,

if (logon())
{
   ClientScriptManager csm = Page.ClientScript;
   
StringBuilder sb = new StringBuilder();
   
sb.Append(
"<script language=\"javascript\">");
   
sb.Append(
"window.onload = function()");
   
sb.Append(
"{");
   
sb.Append(
"window.open(\"loading.aspx\",\"load\",\"");
   
sb.Append(
"height=\" + (window.screen.availHeight - 30) + \",");
   
sb.Append(
"width=\" + (window.screen.availwidth - 10) + \",");
   
sb.Append(
"top=0, left=0, menubar=0, location=0, resizable=1, status=0\");");
   
sb.Append(
"if (window.name != \"load\")");
   
sb.Append(
"{");
   
sb.Append(
"this.focus();");
   
sb.Append(
"top.window.opener = top;");
   
sb.Append(
"top.window.open('','_parent','');");
   
sb.Append(
"top.window.close();");
   
sb.Append(
"}");
   
sb.Append(
"}");
   
sb.Append(
"</script>");
   
csm.RegisterClientScriptBlock(
this.GetType(), string.Empty, sb.ToString());
}
else
{
   
//Giriş Başarısız
}

StringBuilder sb = new StringBuilder();
sb.Append("window.onload = function picture()\n{\n"
);
sb.Append("var pictures = new Array();\n"
);
FileInfo[] files = new DirectoryInfo(Server.MapPath("./images/"
)).GetFiles();
for (int i = 0
; i < files.Length; i++)
   sb.Append(string.Format("pictures[{0}] = 'images/{1}';\n"
, i, files[i].Name));
sb.Append("var number = Math.floor(Math.random() * " + files.Length + ");\n"
);
sb.Append("document.getElementById('" + Image1.ClientID + "').src = pictures[number];\n"
);
sb.Append("setTimeout('picture()',1000);\n}"
);

ClientScriptManager
cn = Page.ClientScript;
if (!cn.IsStartupScriptRegistered("picture"
))
   cn.RegisterClientScriptBlock(typeof(Page), string.Empty, sb.ToString(), true
);

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. (Hakan' ın kulakları çınlasın)

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) Subtution 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 Subtution 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.

 substitution
substitution

subtution



 

Bir projede Login kontrollerinden PasswordRecovery kullanıyorum. E-mail içeriğindeki Türkçe karakterler problemli gözüküyor. Önce bu şekilde denedim.

using System.Text;
....

protected void PasswordRecovery1_SendingMail(object sender, MailMessageEventArgs
e)
{
   e.Message.SubjectEncoding = Encoding.GetEncoding("iso-8859-9"
);
   e.Message.BodyEncoding = Encoding.GetEncoding("iso-8859-9"
);
}

olmadı, bende işi biraz uzattım ama oldu :) - daha pratik birşey bulursam alta eklerim -

using
System.Text;
using
System.IO;
....

protected
void PasswordRecovery1_SendingMail(object sender, MailMessageEventArgs e)
{
   e.Message.SubjectEncoding = Encoding.GetEncoding("iso-8859-9"
);
   e.Message.BodyEncoding = Encoding.GetEncoding("iso-8859-9"
);
   e.Message.Subject = "CodeInBox - New Password."
;
   e.Message.IsBodyHtml = true
;
   FileStream fs = new FileStream(Server.MapPath("./App_Data/mailBody.txt"), FileMode
.Open);
   StreamReader rd = new StreamReader(fs, Encoding.GetEncoding("iso-8859-9"
));
   string
body = rd.ReadToEnd();
   rd.Close();
   fs.Close();
   MembershipUser user = Membership
.GetUser(PasswordRecovery1.UserName);
   body = body.Replace("<% UserName %>"
, user.UserName);
   body = body.Replace("<% Password %>"
, user.ResetPassword(PasswordRecovery1.Answer));
   e.Message.Body = body;
}

//mailBody.txt
.......
<br />
Üyelik Bilgileri:<br />
--------------------------------------------------------------<br />
<strong>Kullanıcı Adı :</strong>
<% UserName %>
<br />
<strong>Parola :</strong>
<% Password %>
<br />
--------------------------------------------------------------<br />
<br />
........

İkinci basit Web Part'ımız.

string getWeatherFromChache(string Sehir)
{
   if (HttpContext.Current.Cache[Sehir] == N'
)
   {
      try
      {
         string servis = "http://www.webservicex.net/globalweather.asmx/GetWeather?CityName=" + Sehir + "&CountryName=turkey"
;
         WebClient client = new WebClient
();
         string
data = client.DownloadString(servis);
         XmlDocument doc = new XmlDocument
();
         doc.LoadXml(data);
         string nodes = doc.GetElementsByTagName("string")[0
].InnerText;
         doc.LoadXml(nodes);
         string Temperature = doc.SelectSingleNode("/CurrentWeather/Temperature"
).InnerText;
         string RelativeHumidity = doc.SelectSingleNode("/CurrentWeather/RelativeHumidity"
).InnerText;
         StringBuilder sb = new StringBuilder
();
         sb.Append("<table style=font-family:verdana;font-size:12px; border=0 width=100%><tr>"
);
         sb.Append("<td width=20%><b>Sıcaklık : </b></td>"
);
         sb.Append("<td width=80%>"
);
         sb.Append(Temperature);
         sb.Append("</td></tr>"
);
         sb.Append("<td><b>Nem : </b></td>"
);
         sb.Append("<td>"
);
         sb.Append(RelativeHumidity);
         sb.Append("</td></tr>"
);
         sb.Append("</table>"
);
         HttpContext.Current.Cache.Insert(Sehir, sb.ToString(), N', DateTime.Now.AddHours(5), TimeSpan
.Zero);
      }
      catch
      {
         HttpContext.Current.Cache.Insert(Sehir, "Bilgi alınamıyor.", N', DateTime.Now.AddSeconds(5), TimeSpan
.Zero);
      }
   }
   return HttpContext
.Current.Cache[Sehir].ToString();
}

Şehir Listesi:

<?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>Afyon</Sehir
>
   <
Sehir>Antalya</Sehir
>
   <
Sehir>Gaziantep</Sehir
>
   <
Sehir>Iskenderun</Sehir
>
   <
Sehir>Konya</Sehir
>
   <
Sehir>Merzifon</Sehir
>
   <
Sehir>Samsun</Sehir
>
   <
Sehir>Sivas</Sehir
>
   <
Sehir>Zonguldak</Sehir
>
   <
Sehir>Malatya / Erhac</Sehir
>
   <
Sehir>Kayseri / Erkilet</Sehir
>
   <
Sehir>Sivrihisar</Sehir
>
   <
Sehir>Tokat</Sehir
>
   <
Sehir>Aydin</Sehir
>
   <
Sehir>Bursa</Sehir
>
   <
Sehir>Balikesir</Sehir
>
   <
Sehir>Bandirma</Sehir
>
   <
Sehir>Canakkale</Sehir
>
   <
Sehir>Eskisehir</Sehir
>
   <
Sehir>Izmir / Adnan Menderes</Sehir
>
   <
Sehir>Isparta</Sehir
>
   <
Sehir>Usak</Sehir
>
   <
Sehir>Dalaman</Sehir
>
   <
Sehir>Akhisar</Sehir
>
   <
Sehir>Corlu</Sehir
>
   <
Sehir>Bodrum</Sehir
>
   <
Sehir>Elazig</Sehir
>
   <
Sehir>Diyarbakir</Sehir
>
   <
Sehir>Erzincan</Sehir
>
   <
Sehir>Erzurum</Sehir
>
   <
Sehir>Kars</Sehir
>
   <
Sehir>Trabzon</Sehir
>
   <
Sehir>Urfa</Sehir
>
   <
Sehir>Van</Sehir
>
   <
Sehir>Batman</Sehir
>
</
Sehirler
>

Windows uygulamalarında sıkça kullandığımız MessageBox.Show() birkaç adım la webform larında kullanılabiliyormuş.Şöyleki.
öncelikle projemize System.Windows.Forms namespace ini ekliyoruz.

protected void Button1_Click(object sender, EventArgs e)
{
   if (MessageBox.Show("Google", "Google.com' a gider", MessageBoxButtons.YesNo) == DialogResult.Yes)
   Response.Redirect("http://www.google.com.tr");
}

pek mantıklı değil:)

Küçük bir globalization sorunu. Gridview içinde silme işlemi için client taraflı uyarı ama hem Türkçe hem İngilizce;

protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
   CultureInfo turkish = new CultureInfo("tr-TR"
);
   CultureInfo thisCulture = Thread
.CurrentThread.CurrentCulture;
   if (e.Row.RowType == DataControlRowType
.DataRow)
   {
      if
(turkish.Name == thisCulture.Name)
         (e.Row.FindControl("LinkButton1") as LinkButton).Attributes.Add("onclick", "return confirm('Eleman silinecek ?');"
);
      else
         (e.Row.FindControl("LinkButton1") as LinkButton).Attributes.Add("onclick", "return confirm('Item will be deleted ?');"
);
   }
}

TreeView kontrolünü Menu gibi kullanmak istersek css ile kolayca yapılabiliriz. Şahsen ben herzaman Menu kontrolüne tercih etmişimdir :)

head:
<
style type="text/css">
.menu_nodeStyle
{
   color:Black;
   font-family:Verdana;
   font-size:10pt;
   padding:2px 2px 2px 2px;
   width:100%;
   border:solid 1px #dad6d5;
   height:25px;
}

.menu_hoverNodeStyle
{
   background-color:#CCCCCC;
   border:solid 1px #888888;
   cursor:pointer;
}

.menu_selectedNodeStyle
{
   padding:2px 2px 2px 2px;
   font-weight:bold;
   color:#0a6082;
}

.menu
{
   padding-top: 10px;
   background-color: #dad6d5;
   width:200px;
}
</style>


body:
<div class="menu">
   <asp:TreeView ID="TreeView1" runat="server" DataSourceID
="SiteMapDataSource1">
      <NodeStyle CssClass="menu_nodeStyle"
/>
      <HoverNodeStyle CssClass="menu_hoverNodeStyle"
/>
      <SelectedNodeStyle CssClass="menu_selectedNodeStyle"
/>
   </asp:TreeView
>
   <asp:SiteMapDataSource ID="SiteMapDataSource1" runat="server"
/>
</div
>

result

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.

<system.web>
   ...

   <
globalization fileEncoding="iso-8859-9" requestEncoding="iso-8859-9" responseEncoding="iso-8859-9"/>
   ...
</system.web>

Asp.Net ve Focus

11.Temmuz.2007 Javascript Asp.net

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

//odaklanacak bir TextBox ise
<form id="form1" runat="server" defaultfocus
="txtSname">
//Button ise
<form id="form1" runat="server" defaultbutton
="btnSend">

//Asp.Net 1.1 olsaydı
<body onload
="document.form1.txtSname.focus()">
//yada
<body onload
="document.form1.txtSname.select()">

Programatik yapmak istersek

protected void Page_Load(object sender, EventArgs e)
{
   if
(!IsPostBack)
   {
      xtSname.Focus();
      //yada
      
SetFocus(txtSname);
      //yada
      RegisterStartupScript("sFocus", "<scrip>document.getElementById('" + txtSname.ClientID + "').focus();</script>");

   }
}

Web Forum'u içinde ki varsayılan Button'u değiştirmek için JavaScript kodu aramaya gerek yok. Sunucu tarafında dinamik olarak üretilen WebResource içinde ki WebForm_FireDefaultButton fonksiyonunu çağırmak yeterli olacaktır .

txtSearch.Attributes.Add("onkeypress", "javascript:return WebForm_FireDefaultButton(event, '" + LinkButton1.ClientID + "')");

GridView ToolTip

18.Haziran.2007 Asp.net C#

GridView de Tooltip kullanımı için bir alternatif.
Tooltip olarak gösterilecek alanı DataKeyNames de saklayıp uygun kolona attribute ile eşleştirmek.

protected
void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
   if (e.Row.RowType == DataControlRowType.DataRow)
   {
      e.Row.Cells[2].Attributes.Add("title", GridView1.DataKeys[e.Row.RowIndex][0].ToString());
   }
}

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 :)

//google.ascx
<%@ Control Language="C#" AutoEventWireup="true" CodeFile
="googleSearch.ascx.cs"
Inherits="googleSearch"
%>
<script type
="text/javascript">
   var
req= N'
;
   function
GetXmlHttpObject()
   {
      try
      
{
         req = new
XMLHttpRequest();
      }
      catch
(e)
      {
         try
         {
            req = new ActiveXObject("Msxml2.XMLHTTP"
);
         }
         catch
(e)
         {
            req = new ActiveXObject("Microsoft.XMLHTTP"
);
         }
      }
   }

   function
stateChange()
   {
      document.getElementById('calImg').style.display = 'inline'
;
      if(req.readyState == 4
)
      {
         document.getElementById('calImg').style.display = 'none'
;
         document.getElementById('calDiv'
).innerHTML = req.responseText;
      }
   }

   function
search()
   {
      var url = './resources/search.aspx?text=' + document.getElementById("txtSearch"
).value;
      GetXmlHttpObject();
      req.onreadystatechange = stateChange;
      req.open("post",url,true
);
      req.send(N'
);
   }
</script
>
<
table
>
   <tr
>
      <td align
="center">
         <img src="images/google.gif" style="width: 200px; height: 68px" alt="google"
/>
      </td
>
   </tr
>
   <tr
>
      <td align
="center">
         <input id="txtSearch" style="font-family: arial, Helvetica, sans-serif; font-size: 12px
;
border: 1px solid #808080" type="text" />
         <
input onclick="search()" id="Button1" style="font-family: arial, Helvetica, sans-serif
;
font-size: 12px; border: 1px solid gray; height: 19px; width: 66px;" type
="button"
value="Ara"
/>
      </td
>
   </tr
>
   <tr
>
      <td
>
         <img src="images/circle.gif" id="calImg" alt="aranyor" style="display: none;"
/>
         <br
/>
         <div id
="calDiv">
         </div
>
      </td
>
   </tr
>
</
table
>

//search.aspx.cs

protected void Page_Load(object sender, EventArgs
e)
{
   string kelime = Request["text"
];
   string adres = @"http://www.google.com.tr/search?hl=tr&q=" + kelime + "&meta="
;
   WebClient client = new WebClient
();
   DateTime dt1 = DateTime
.Now;
   string
data = client.DownloadString(adres);
   DateTime dt2 = DateTime
.Now;
   TimeSpan
ts = dt2 - dt1;
   string pattern = "<h2 class=r>(?<Link>.*?)</h2>"
;
   Regex myRegex = new Regex
(pattern);
   MatchCollection
myCol = myRegex.Matches(data);
   int counter = 0
;
   StringBuilder sb = new StringBuilder
();
   sb.Append("<b>Sonuçlar</b> (<i>"
);
   sb.Append(ts.TotalMilliseconds);
   sb.Append(" toplam Milisaniye</i>)<br />"
);
   sb.Append("<table border=0 width=100% style=font-family:arial;font-size:10px;>"
);
   foreach (Match m in
myCol)
   {
      if ((m.Groups[0].ToString().IndexOf("aramalar:")) == -1
)
      {
         counter++;
         sb.Append("<tr><td width=10%>"
);
         sb.Append(counter.ToString());
         sb.Append("</td>"
);
         sb.Append("<td>"
);
         sb.Append(m.Groups["Link"
].Value);
         sb.Append("</td></tr>"
);
      }
   }
   sb.Append("</table>"
);
   Response.Write(sb.ToString());
}

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. Oncelikle bir adet recursive metod yazalım (System.IO eklemeye unutmayalım).

void feelIT(DirectoryInfo[] folders, TreeNode node)
{
   for (int i = index; i < folders.Length; i++)
   {
      TreeNode folderNode = new TreeNode(folders[i].Name, folders[i].FullName);
      node.ChildNodes.Add(folderNode);
      FileInfo[] files = folders[i].GetFiles();
      foreach (FileInfo file in files)
      {
            TreeNode fileNode = new TreeNode(file.Name, file.FullName);
            folderNode.ChildNodes.Add(fileNode);
      }
      try
      {
            feelIT(folders[i].GetDirectories(), node.ChildNodes[i]);
      }
      catch
      {
            ;
      }
   }
}


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 propertie yazalım.

public int index
{
   get
   {
      if (ViewState["index"] == N')
         ViewState["index"] = 0;
      return (int)ViewState["index"];
   }
   set
   {
      ViewState["index"] = value;
   }
}

Let’s list the files that are on the start way.

public void restIT(DirectoryInfo folders, TreeNode node)
{
   FileInfo[] files = folders.GetFiles();
   foreach (FileInfo file in files)
   {
      TreeNode rootFileNode = new TreeNode(file.Name, file.FullName);
      node.ChildNodes.Add(rootFileNode);
   }
}

And lastly, we’ll start the process.

protected void Page_Load(object sender, EventArgs e)
{
   if (!IsPostBack)
   {
      DirectoryInfo folders = new DirectoryInfo(Server.MapPath("./"));
      TreeNode node = new TreeNode("Site", Server.MapPath("./"));
      trwExplorer.Nodes.Add(node);
      feelIT(folders.GetDirectories(), trwExplorer.Nodes[0]);
      restIT(folders, trwExplorer.Nodes[0]);
   }
}

İşte sonuç.

Site içinde kullandığım E-mail uygulamasının kodları...

//css
#dvFrame
{
   width: 600px
;
   margin: 0 auto
;
   padding: 5px
;
   text-align: left
;
   border: solid 1px gray
;
   background-color: White
;
}
#lblHead
{
   clear: left
;
   color: #495a92
;
   float: left
;
   font-size: 15px
;
   font-weight: bold
;
   text-decoration: none
;
}
#imgSPRT
{
   height: 1px
;
   width: 99%
;
   padding-top: 5px
;
   padding-bottom: 10px
;
}
#btnSend
{
   margin-left: 120px
;
   margin-top: 5px
;
   width: 90px
;
   border: solid 1px #c0c0c0
;
   font-size: 12px
;
}
#valSum
{
   font-size: 12px
;
   color: Maroon
;
}
#lblWarning
{
   text-align: center
;
   width: 100%
;
   font-size: 12px
;
   color: Maroon
;
}
.mailLabel
{
   float: left
;
   width: 120px
;
   font-weight: bold
;
   font-size: 12px
;
}
.mailText
{
   width: 180px
;
   margin-bottom: 5px
;
   border: solid 1px #c0c0c0
;
   font-size: 12px
;
}
.mailDesc
{
   width: 350px
;
   height: 150px
;
   border: solid 1px #c0c0c0
;
   font-size: 12px
;
}


//aspx

<
div id="dvFrame">
<asp:Label ID="lblHead" runat="server" Text="E-mail" /><br
/>
<img id="imgSPRT" src="images/bar.gif" alt="sprt"
/>
<asp:Label ID="lblName" runat="server" CssClass="mailLabel" Text="Ad" />

<asp:TextBox ID="txtName" runat="server" CssClass="mailText" />

<asp:RequiredFieldValidator ID="rqrName" runat="server" ControlToValidate
="txtName"
Display="None" ErrorMessage="Ad Gerekli." ValidationGroup="mail" /><br
/>
<asp:Label ID="lblMail" runat="server" CssClass="mailLabel" Text="E-mail" />

<asp:TextBox ID="txtMail" runat="server" CssClass="mailText" />

<asp:RequiredFieldValidator ID="rqrMail" runat="server" ControlToValidate
="txtMail"
Display="None" ErrorMessage="E-mail Gerekli." ValidationGroup="mail" />

<asp:RegularExpressionValidator ID="rqeMail" runat="server" ControlToValidate
="txtMail"
Display="None" ErrorMessage="Geçersiz E-mail." ValidationExpression
="\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*" ValidationGroup="mail" /><br />
<asp:Label ID="lblMessage" runat="server" CssClass="mailLabel" Text="Mesaj" />

<asp:TextBox ID="txtMessage" runat="server" CssClass="mailDesc" TextMode="MultiLine" />

<asp:RequiredFieldValidator ID="rqrMessage" runat="server" ControlToValidate
="txtMessage"
Display="None" ErrorMessage="Mesaj Gerekli." ValidationGroup="mail" /><br
/>
<asp:Button ID="btnSend" runat="server" Text="Gönder" OnClick="btnSend_Click" ValidationGroup="mail" /><br
/>
<asp:ValidationSummary ID="valSum" runat="server" ValidationGroup="mail"
/><br />
<asp:Label ID="lblWarning" runat="server"></asp:Label
>
</div
>

//cs

StringBuilder
messageBody = new StringBuilder();
messageBody.Append("Name : "
);
messageBody.Append(txtName.Text.Trim());
messageBody.Append("\n"
);
messageBody.Append("Email : "
);
messageBody.Append(txtMail.Text.Trim());
messageBody.Append("\n"
);
messageBody.Append("Message : "
);
messageBody.Append(txtMessage.Text.Trim());
messageBody.Append("\n"
);
//from ile To aynı adres olabilir.
MailMessage newMessage = new MailMessage("from@mailserver.com", "to@mailserver.com", "Contact"
, messageBody.ToString());
SmtpClient newSmtp = new SmtpClient("mail.mailserver.com");
newSmtp.Credentials = new System.Net.NetworkCredential("from@mailserver.com", "password"
);
try
{
   newSmtp.Send(newMessage);
   lblWarning.Text = "Tamam, Mesajınız bana iletildi..."
;
}
catch
{
   lblWarning.Text = "Hata, tekrar deneyin."
;
}

Zengin içerikli elektronik postalar hazırlarken en büyük sıkıntı kaynağın tekrar okunup gövde (body) 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;

ALTER procedure
enUcuz10Urun
AS
   SET ROWCOUNT
10
   SELECT Products.ProductName + ' - ' + cast(Products.UnitPrice as varchar(10)) + ' YTL' as Urun
   FROM Products
   ORDER BY Products.UnitPrice


Mail içeriğini sağlayacak olan WebUserControl;

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="mailContent.ascx.cs"
Inherits="feb.mailContent" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<h1 style="color: Red;
">
   Sizin için seçtiklerimiz !</h1
>
<
h3 style="color: Green;
">
   En Ucuz 10 ürün :)</h3
>
<% 
   using (SqlConnection cn = new SqlConnection("Data Source=.;Initial Catalog=Northwind;Integrated Security=True"))
   {
      using (SqlCommand cm = cn.CreateCommand())
      {
         cm.CommandText = "enUcuz10Urun";
         cm.CommandType = CommandType.StoredProcedure;
         cm.Connection.Open();
         using (SqlDataReader rd = cm.ExecuteReader())
         {
            while (rd.Read())
            {
%>
<ul type="circle" style="font-family:Verdana;font-size:12px;
">
<li
>
   <%=rd[0].ToString()%></li
>
</
ul
>
<%
            }
         }
      }
   }
%>
<br
/>
<
a href="http://www.northwind.com">Northwind</a
>

Kontrolün toString metodunu tekrar yazarak (override) kullanım kolaylığı sağlıyoruz;
 
public override string ToString()
{
   TextWriter tw = new StringWriter
();
   HtmlTextWriter htw = new HtmlTextWriter
(tw);
   this
.RenderControl(htw);
   return
tw.ToString();
}

son olarak e-maili gönderecek olan kodlar;

protected void btnSend_Click(object sender, EventArgs e)
{
   string to = "ilgili@karsifirma.com";
   string subject = "En Ucuz 10 ürün";
   mailContent mc = (mailContent)LoadControl("mailContent.ascx");
   string body = mc.ToString();
   MailMessage mail = new MailMessage("info@bizimFirma.com", to, subject, body);
   mail.IsBodyHtml = true;
   mail.SubjectEncoding = Encoding.GetEncoding(1254);
   mail.BodyEncoding = Encoding.GetEncoding(1254);
   SmtpClient smtp = new SmtpClient("mailServer");
   smtp.Credentials = new NetworkCredential("userName", "passWord");
   try
   {
      smtp.Send(mail);
   }
   catch
   {
      ;
   }
}

Linq to xml ile bir xml dosyası oluşturup çalışma zamanı da Treeview kontrolünde gösterelim.

//aspx
<
body>
   <form id="form1" runat
="server">
   <div
>
      <asp:TreeView ID="TreeView1" runat
="server">
         <DataBindings
>
            <asp:TreeNodeBinding DataMember="Categories" Text="Categories"
/>
            <asp:TreeNodeBinding DataMember="Category" TextField="CategoryName" ValueField="CategoryID"
/>
         </DataBindings
>
      </asp:TreeView
>
   </div
>
   </form
>
</
body>

//cs

private
void bindTree()
{
   northwindDataContext db = new northwindDataContext
();
   string path = Server.MapPath(".\\App_Data\\data.xml"
);
   if (!File
.Exists(path))
   {
      XDocument xdoc = new XDocument
(
         new XDeclaration("1.0", "utf-8","yes"
),
         new XElement("Categories"
,
            from p in
db.Categories
            orderby
p.CategoryName
            select
               new XElement("Category"
,
               new XAttribute("CategoryID"
, p.CategoryID),
               new XAttribute("CategoryName"
, p.CategoryName))));
      xdoc.Save(path);
   }
   XmlDataSource xd = new XmlDataSource
();
   xd.ID = "xid1"
;
   xd.DataFile = path;
   this
.form1.Controls.Add(xd);
   TreeView1.DataSourceID = "xid1"
;
}

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.

//web.config
<siteMap defaultProvider="sitemapTR">
   <
providers>
      <
add name="sitemapTR" type="System.Web.XmlSiteMapProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" siteMapFile="Web_tr.sitemap" description="türkçe"/>
      <
add name="sitemapEN" type="System.Web.XmlSiteMapProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" siteMapFile="Web_en.sitemap" description="english"/>
   </
providers>
</
siteMap>

Tanımlanan providerları tarayıcının kullandığı dile göre kontrole eşitlemek işin son kısmı olacaktır.

string provider = string.Format("sitemap{0}", Thread.CurrentThread.CurrentUICulture.Name.Substring(0, 2).ToUpper());
SiteMapPath1.SiteMapProvider = provider;

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:

<
anonymousIdentification enabled="true"/>
<
profile defaultProvider="mySqlProfileProvider" enabled="true"
>
   <
providers
>
   <
clear
/>
   <
add name="mySqlProfileProvider" connectionStringName="codeConnectionString" applicationName="/" type="System.Web.Profile.SqlProfileProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
/>
   </
providers
>
   <
properties
>
      <
add name="ad" allowAnonymous="true"
/>
      <
add name="soyad" allowAnonymous="true"
/>
      <
add name="dogumTarihi" type="DateTime" allowAnonymous="true"
/>
      <
add name="blog" allowAnonymous="true"
/>
<
add name="ulke" allowAnonymous="true"
/>
   </
properties
>
</
profile
>

Daha sonra ise kod kısmında, örneğin kullanıcı kayıt sırasında değerleri eşitlemek istersek;

MembershipCreateStatus
stat;
Membership.CreateUser(txtUN.Text.Trim(), txtPWD.Text.Trim(), txtMail.Text.Trim(), txtSQ.Text.Trim(), txtANS.Text.Trim(), true, out
stat);
lblMesaj.Text = userCreateStat(stat);
if (stat == MembershipCreateStatus
.Success)
{
   Roles.AddUserToRole(txtUN.Text.Trim(), "coder"
);
   FormsAuthentication.SetAuthCookie(txtUN.Text.Trim(), false
);
   Context.Profile.SetPropertyValue("ad"
, txtName.Text.Trim());
   Context.Profile.SetPropertyValue("soyad"
, txtLast.Text.Trim());
   Context.Profile.SetPropertyValue("blog"
, txtBlog.Text.Trim());
   Context.Profile.SetPropertyValue("dogumTarihi", Convert
.ToDateTime(txtDT.Text.Trim()));
   Context.Profile.SetPropertyValue("ulke"
, DropDownList1.SelectedValue);
   Context.Profile.Save();
   ...

Şöyle bir düşündüğümüzde veritabınında bulunan herhangi bir tablonun verilerini Xml biçiminde 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.

DataBase 2 Xml
 

Diğer bir yöntem ise henüz Veri Katmanında (DataLayer) iken oracıkta xml formatına dönüştürüp XmlTextWriter ile cayır cayır yazmak.

DataBase 2 Xml

Son yöntem ise daha önce şu yazıda kullandığım teknik ile (attribute yerine bu sefer node 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.

DataBase 2 Xml

Tarih Formatı

13.Ocak.2009 Asp.net C#

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;

Extension Method

Xslt ile çalışıyorsanız bir kaç küçük ayrıntı.
- Xml verilerini sıralamak için for-each kalıbına

Xslt Sort

yazmak yeterli.
- Satırları ardışık olarak renklendirmek için de mod operatörü ve position() fonksiyonu bu işin üstesinden gelecektir.

Xslt If

Kodun tamamı;

Cities

Xml verisinin devamı için tıklayın...

Xslt Doviz

Ara ara web tabanlı WYSIWYG editorleri incelerim. Geçenlerde Fck 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;

  • Editörün config dosyasını Asp.Net için ayarladım.
  • Sadece Asp.Net içinde kullanılacağı için gerekli olmayan dosya ve klasörleri sildim.
  • ToolBar' ı basitleştirdim.
  • Tek tema kullandım, diğerlerini sildim.
  • FileBrowser' ın dört faklı upload tipi için ayrı klasörler ayarladım.
  • Rar uzantı için resim dosyası ekledim.
  • FileBrowser ile dosya listelerken alternatif satır rengi ekledim.
  • FileBrowser' a resimler için önizleme ekledim.

Proje dosyası, fckApplication.

Resimler

Toolbar optimizasyonu Fck Editor Toolbar

Dosya gösterimi için alternatif satır rengi Fck Editor Filebrowser Alternatif

Resimler için ön izleme Fck Editor Filebrowser Image

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 ederim unutmuşuz :)

Adım adım ilerleyelim;

1. Gerekli dosyaları buradan indirelim.

2. Resimde işaretli klasörleri projeye ekleyelim.

Fck Folders

3. Eklediğimiz dosyalar içerisinde işaretli olan ascx dosyasını düzenleyerek upload edeceğimiz kaynakların yollarını belirleyebiliriz.

Fck Config

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.

Fck Toolbar

Artık Fck Editor kontrolünü Textbox kullanır gibi web formlarımızda kullanabiliriz.

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

Bu tip uygulamaları yaparken kaynağın kopyası üzerinde çalışmayı tercih ederim. Hız açısından.

Döviz Bilgisi

Döviz Kontrol

Ç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 lazım.

ListView

Veri kaynağı için basit ve hızlı bir çözüm, dosyalar.

DataSource - Linq

Dosyaları biraz süslü gösterelim.

Icon Output

Sonuç;

ListView

 

Bir WebFormu içerisinde birden fazla Default Button kullanmak için birden çok form etiketi 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;

default button

Öğ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 etikete aktarılmasıdır.
Örneğin;

<img src="/images/bullet.png" alt="Bullet" />

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 ibaret olacaktır. Bu durumda en uygun  alan tipi varbinary olsa iyi olur. :)

Kaçınılması gereken davranışlar.

<img src='<%# Eval("resim") %>' alt="Bullet" />

yada

img1.ImageUrl = reader[1].ToString();

hiç olmadı :)

img1.ImageUrl = command.ExecuteScalar().ToString();

Yapılması gereken gayet açık. 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 varbinary (byte dizisi) 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.

protected void Page_Load(object sender, EventArgs e)

   SqlConnection con = new SqlConnection
("Data Source=.;Initial Catalog=calismalar;Integrated Security=True;");
   SqlCommand com = new SqlCommand
("select UrunResim from Urunler where UrunId = @UrunId", con);
   com.Parameters.AddWithValue("@UrunId", Request["id"
]); 
   con.Open(); 
   byte[] resim = (byte
[])com.ExecuteScalar(); 
   con.Close(); 
   Response.ContentType = "image/png"

   Response.BinaryWrite(resim);
}

Son olarak ise sayfa çıktısının resim olacağını işaret eder ve çıktıyı BinaryWriter metotu ile oluştururuz.

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ştirmek 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.

htmlArea

- creator.js dosyasında ki 2. satırı şu şekilde değiştiriyoruz.

editor url

- creator.js dosyasını editörü kullanacağımız sayfaya link verdikten sonra sayfaya 1 adet texteara ekliyoruz.

editor generate

artık sayfamızı test edebiliriz.

htmlArea

Ben Xml'i 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;

Database Diagram

Uygulamada kullanılan nesne diyagramı;

Class Diagram

Uygulamada kullanılan örnek kod;

OyVer

Uygulama kaynak kodları da burada.

Asp.net sunucu kontrollerinden Panel'in GroupingText özelliğini kullanarak html çıktısı olarak Fieldset etiketi (etkisi) elde edilebilir.

Panel to Fieldset

Geçenlerde bir web proje için resim kırpma ve yeniden boyutlandırma 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.

image crop

Uygulama.

Asp.Net sunucu kontrollerinden TextBox kontrolünü TextMode="Multiline" özelliği ile kullanıldığında MaxLength özelliği çalışmamaktadır. Buraya çözüm için alternatif yöntemler yazacağım zaman zaman.

İlk çözüm yine sunucu kontrollerinden CustomValidator ile olacak.

CustomValidator;
textarea

devam edecek...

Data kaynağınız xml olduğunda okuma veritabanından okumak kadar kolay olmayabilir. XmlDataSorce ile bu işlem çok kolay hale getirebilir.

Repeater

Kodu biraz inceleyelim;
XmlDataSource nesnesinin DataFile özelliği (xml) data kaynağının yolunu ister. Bu disk üzerinde bir dosya olabileceği gibi bir rss dökümanı da olabilir.
Önemli olan DataFile ile belirttilen (xml) data içinden ne istenildiğidir. Bunu yapmanın en pratik yolu xpath kullanmak olacaktır.
XmlDataSource nesnesinin XPath özelliği ile de bunu belirtmek gerekir.

xml

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

Örnek proje.

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.

Birinci Bölüm

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

Yayın Öncesi Ayarlar

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.
compilation
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ında ki (Runtime) olası hataları daha ayrıntılı görmek için customError -> mode özelliğinin değerini false olarak ayarlıyoruz.
customerrors
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.


Internet Explorer -> Settings -> Advanced
explorer settings

Seçili Seçili Değil
checked unchecked

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, hata (Error) alınırsa işlem iptal olur. Kimi zaman ikazlar (Warning) 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.
publish folder
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şturu. 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.
publish settings
İş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.
publish output


Bin klasöründeki dll dosyaları ve config uzantılı dosyalar sunucuya yüklendiğinde(upload) uygulamanız sonladırılır(Application End) ve ilk çağrıda yeniden başlar(Application Start). Bu durumda uygulama içindeki tüm oturum vs yok olacaktır. Size tavsiyem bakım zamanlarını geç saatlerde yapın ve app_ofline.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ı uygulamyı kullanmanız.
ftp site settings
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.
ftp publish
 


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 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 heryere 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 sayfa da yada ona bağlı bir uygulamada hata oluştuğunda, hata ile ilgili detayların geliştiriciye mail olarak gönderilmesi daha sonra da kullanıcıya hata mesajı yerine basit bir html sayfası gösterilmesinden ibaret.

Öncelikle ihtiyaçları belirleyelim. Yani hangi bilgilerin gönderilmesi gerekiyor bir bakalım.

Error Class

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.

Mail Text

Daha iyi anlamak için Error nesnesi için yazdığımız yardımcı ErrorProvider nesnesine deki CreateMessage asdlı sabit metota göz atalım.

Error Provider

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.

Global.asax

Son bir adım kaldı. Kullanıcı hata mesajları yerine bizim belirlediğimiz sayfaları görsün istiyorsak;

Web.Config

web.config dosyası içindeki customError -> mode özelliğini On olarak değiştiririz. error alt düğümleri ile olası hatalar için  uygun sayfaların yollarını redirect özellikleri ile belirttikten sonra uygulamada bitmiş oluyor. Çeşitlendirmek mümkün.

Örnek proje.

Geçen hafta 1. bölümü biten site yayınlama konusunun devamı.

İkinci Bölüm

Bu bölümde, uygulama için tasarlanmış veritabanını 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.

Sql Publish Wizard

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 DDL(Create) scriptini oluştumanız daha sonra bunu çalıştırmalısınız. İskeleti oluşturduktan sonra DML(Insert) 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.

Sql Publish Wizard
Kendi bilgisayarınızda kurulu olan sql server' a bağlantı kuruyoruz.

Sql Publish Wizard
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.

Sql Publish Wizard
İhtiyaç duyduğumuz nesneleri (Table,View,Procedure vs) seçiyoruz.

Sql Publish WizardSql Publish Wizard
Alt nesneleri seçiyoruz.

Sql Publish Wizard
Oluşacak script için dosya adı ve yolu belirliyoruz.

Sql Publish Wizard
Uygun Ms Sql Server versiyonu seçillir.

Sql Publish WizardSql Publish Wizard
Ö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...

Geçenlerde Asp.Net sunucu kontrollerinden Takvim (Calendar) ü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. Veriyi kodda kullanmayı sağlayan basitte bir class 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ığında (Render) html tarafında bir table etiketine karşılık gelir. Varsayılan olarakta herbir hücredeki (td) gün ifadesi anchor etiketi 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.

Calendar Render

O yüzden kontrolün SelectionMode özelliğini None olarak ayarlıyoruz. Böylece hücre içlerine sadece gün değerleri eklenir.

Calendar

Detayları göstereceğimiz popup penceresini açmak için basit bir JavaScript fonksiyonu hazırlıyoruz.

Day Render

Önemli günleri vurgulayacak kodlarımızı Takvim kontrolünün DayRender adlı olayına 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.

Calendar Result
Uygulamayı daha iyi anlamak için aşağıdaki projeyi indirip bakmanızda fayda var.

Proje

Öyle bir tablom 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:
Data Diagram

Örneğimizdeki yapı şöyle olacak; Kategori hiyerarşinin en üstünde ise alt kategori değeri 0 (sıfır) olacak. Değilse üst kategorinin id değeri yer alacak.
Data

Azıcık kod yazalım.

Code

Sonuç;
Result

Örnek proje.

Repeater, veri kontrolleri içinde en sevdiğimdir. Onu esnek hale getiren basit yapısı 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 koyacağımız LinkButton kontrolleri ve sıralama bilgilerini ViewState içinde tutarak yapabilir.

Burada tablo başlıklarına birer LinkButton ve Image kontrolü koyuyoruz. LinkButton sıralama komutunu işlerken, Image kontrolleride sıralama yapılan satırları işaret edecek.

Repeater Sort

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 Özellik (Property) olarak tanımlıyoruz.

Repeater Sort

Sıralama komutu için ado.net kodlarımız. Kolon adı parametre olmadığı için String nesnedinin Format metotunu kullandım.

Repeater Sort

Uygulama sonunda elde edeceğimiz veri listesi.

Repeater Sort

Kalan detaylara projeyi indirip bakabilirsiniz.

Projeyi indir.

Web.config dosya tanımlamalarında bulunan configSource özelliği ile verileri birden fazla dosyaya dağıtarak yönetimi daha rahat bir hale getirebiliriz.
ConfigSource
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.
ConfigSource

Tüm appSettings değerleri Applications.config dosyasında.
ConfigSource

Tüm connectionStrings ifadeleri Connections.config dosyasında.
ConfigSource

Örnek proje.