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.


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.
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"?>ve sonuç;

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.



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>
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 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="aranyor" 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;
}
}
Lets 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, well 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.

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.

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.

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;

Xslt ile çalışıyorsanız bir kaç küçük ayrıntı.
- Xml verilerini sıralamak için for-each kalıbına
![]()
yazmak yeterli.
- Satırları ardışık olarak renklendirmek için de mod operatörü ve position() fonksiyonu bu işin üstesinden gelecektir.
![]()
Kodun tamamı;

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


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;
Proje dosyası, fckApplication.
Resimler
Toolbar optimizasyonu 
Dosya gösterimi için alternatif satır rengi 
Resimler için ön izleme 
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.

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 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. 
Bu tip uygulamaları yaparken kaynağın kopyası üzerinde çalışmayı tercih ederim. Hız açısından.


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

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

Dosyaları biraz süslü gösterelim.
![]()
Sonuç;
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;

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

- creator.js dosyasında ki 2. satırı şu şekilde değiştiriyoruz.
![]()
- creator.js dosyasını editörü kullanacağımız sayfaya link verdikten sonra sayfaya 1 adet texteara ekliyoruz.

artık sayfamızı test edebiliriz.

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;
Uygulamada kullanılan nesne diyagramı;
Uygulamada kullanılan örnek kod;

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

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

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.

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.

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.
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ında ki (Runtime) 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.
Internet Explorer -> Settings -> Advanced

| Seçili | Seçili Değil |
![]() |
![]() |
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.

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.

İş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(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.

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

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

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.

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

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

Kendi bilgisayarınızda kurulu olan 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.

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

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

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

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

Uygulamayı daha iyi anlamak için aşağıdaki projeyi indirip bakmanızda fayda var.
Ö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:

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

Azıcık kod yazalım.
.png)
Sonuç;

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

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.

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

Uygulama sonunda elde edeceğimiz veri listesi.

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.
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.
Tüm appSettings değerleri Applications.config dosyasında.
Tüm connectionStrings ifadeleri Connections.config dosyasında.
Örnek proje.