Fırat Esmer

Microsoft Yazılımları

Internet Explorer ile FileUpload'da JPEG Sorunu

Internet Explorer 6, 7 veya 8 sürümlerinde FileUpload kontrolü ile yüklenmek istenen dosya jpeg uzantılı dosya ise dikkat etmeniz gereken noktalara değineceğim (Internet Explorer 6, 7 veya 8 diyorum çünkü 6'dan önceki sürümleri hesaba katmıyorum).

Senaryo : Bir FileUpload, bir Label ve bir Button'dan oluşan sayfamızda, FileUpload ile jpeg uzantılı dosya yüklemeye çalışacağız ve bu yüklenen dosyanın Internet Explorer 6, 7 veya 8 ile Internet Explorer 9 arasında çıkaracağı farklılığı gidereceğiz. Ayrıca yüklenmek istenen dosya türünün tarayıcı tarafından nasıl okunduğunu göreceksiniz (Label'da gösterilecek).

Bilinmesi Gerekenler :

  • Makaledeki örnek uygulama .NET Framework 4.0 (Web Application) ve Visual Studio 2010 ile hazırlanmıştır.

Neler Öğreneceksiniz :

  • Eğer FileUpload kontrolü ile jpeg uzantılı dosyaları yüklemeden önce dosyanın jpeg türü olup olmadığını kontrol edecekseniz, Internet Explorer sürüm farklılıklarında ne yapmanız gerekeceğini öğreneceksiniz.

FileUpload kontrolü ile yükleme yapılmak istenen dosyanın türünü öğrenmek için FileUpload.PostedFile.ContentType yazmamız yeterli. Ancak yüklenmek istenen dosyanın jpeg uzantılı olup olmadığını bir koşul ile kontrol ederken şunu sakın aklınızdan çıkarmayın. Internet Explorer bilmediğiniz bir şey yapıyor. O da jpeg uzantısını pjpeg olarak görmesidir. Nasıl mı? Şöyle :

if (fileUpload_jpeg.HasFile)
{
  lbl_fileContent.Text = String.Format("Upload ettiğiniz dosyanın türü : {0}", fileUpload_jpeg.PostedFile.ContentType);
  lbl_fileContent.ForeColor = Color.Green;
}

Yukarıdaki kod parçacığını Internet Explorer 9 aracılığıyla çalıştırdığımda çıkacak sonuç şöyledir.

Internet Explorer 9 ile Çıkan Sonuç

Yüklemek istediğimiz dosyanın türü image/jpeg olarak algılandı. Yani çalıştığınız yerde yetkili kişi size "sadece resim yüklenebilsin" der ve siz de önlem almak amacıyla fileUpload_jpeg.PostedFile.ContentType == "image/jpeg" koşulunu koyarsanız, Internet Explorer 6, 7 veya 8 ile hazırlamış olduğunuz siteye giren kişiler jpeg uzantılı dosya yükleyemeyecektir. Neden mi?

Internet Explorer 6, 7 veya 8 ile Çıkan Sonuç

Görmüş olduğunuz gibi Internet Explorer 6,7 veya 8 ile hazırlamış olduğunuz siteye giren kullanıcılar, türü jpeg olan dosyalardan yüklemek isterlerse başarısız olacaklardır. Çünkü yaptıkları işlem sizin belirlemiş olduğunuz "image/jpeg" koşuluna uymayacaktır. O yüzden "image/jpeg" koşuluna ek olarak "image/pjpeg" koşulunu da ekleyin. Şunu da unutmayın bu sıkıntı sadece Internet Explorer (6, 7, 8) için geçerlidir. Internet Explorer 9 için geçerli değildir.

Eğer hazırlamış olduğum örnek uygulamayı indirmek isterseniz buraya tıklayın.

CSS Sprite Kullanımı (HTTP İstek Sayısını Azaltarak Performans Artışı Sağlama)

Yeni bir ASP.NET performans makalesi ile karşınızdayım. Bu makalede, web uygulamamızdaki bir image üzerinden css koordinat (sprite) yöntemiyle nasıl birden fazla image'e yol verilir ve bu yöntemin avantajları nedir, kısaca açıklamalar yapacağım.

Facebook'ta bulunan küçük resimlerin  (durum, bağlantı, fotoğraf gibi) kaynağını incelediğinizde karşınıza şöyle bir resim çıkacak :

Facebook Resimleri

Gördüğünüz gibi tek büyük bir resim var. Bu tek büyük resim üzerinden parçalar alınarak, Facebook'ta bulunan diğer kesitlere image yolları veriliyor. Yapılan işlem aslında çok basit ve bir o kadar da kazançlı. Yöntem, tek resim üzerinden x ve y koordinatları verilerek diğer resimlere yol verilmesi işleminden ibaret aslında. Bu işlemi uygulayan tek şirket Facebook değil. Google Reader, Ask, µTorrent,Telerik bunlara örnek. Gelelim önemli iki noktaya. Neden böyle bir yola başvuruyoruz ve nasıl yapıyoruz?

Neden?

Sunucuya gönderilen istek sayısı azalıyor.

Eğer her resim için tek tek yol verseydiniz, bu her yol için sunucuya istek gönderilecekti. Ancak bir resim üzerinden koordinat yöntemiyle birden fazla resme yol verirseniz, sadece tek istek (büyük resim için) gidecekti. Sunucuya giden her istek tepki süresinin uzaması ve kullanıcının beklemesi demektir. Belki de koordinat yöntemiyle sunucuya giden istek sayısını azaltarak en kolay performans artışını sağlayacağız.


HTML Diğer
Yahoo! %10 %90
Google %25 %75
MySpace %9 %91
MSN %5 %95
eBay %5 %95
Amazon %38 %62
Youtube %9 %91
CNN %15 %85

Yahoo! User Interface Blog sitesinin, "Performance Research, Part 1: What the 80/20 Rule Tells Us about Reducing HTTP Requests" adlı makalesinden alıntıdır. Not : Yukarıdaki değerler, cache varsayılmadan ve ortalama 2.5 Mbps internet bağlantı hızının test sonuçlarıdır.

Yukarıdaki tablo popüler bir kaç web sitesinin sayfaları oluşturulurken harcadıkları zamanı gösteriyor. HTML belgesinin indirilmesi %5 ile %38 arasında zaman alırken, diğer parçaları (resimler, script ve style dosyaları) yüklemek %62 ile %95 arasında değişiyor. Yani HTTP istek sayısının azaltılmasıyla, gözle görünür seviyede performans artışı yaşayabiliriz. (İstatistiki bilgiler kullanıcının tarayıcı modeline ve gönderilen isteğe göre değişebilir.)

Tek resim daha az yer kaplıyor.

Birden fazla resmin kullanımı, tek bir resmin kullanımından daha dezavantajlıdır. Bunun en somut örneği; tek resmin boyutunun, diğer parçalar halinde kullanılan resimlerin boyutundan küçük olmasıdır. Böylece sayfayı yüklemek isteyen kullanıcılar daha az indirme işlemi yapıcak ve daha az bekleyeceklerdir.

Nasıl?

İşlemi 2'ye böleceğim. İlkinde resimlerin yolunu tek tek resimlerden çağırıp, sonucu inceleyeceğiz. İkincisinde ise resimlerin yollarını tek bir resimden çekip inceleyeceğiz. İncelemenin sonunda ne kazanıp, ne kaybettiğimizi analiz edip, konuyu kapatacağız (:

İLK HALİ

Bir adet table içerisine yaklaşık 9 tane kolon yerleştireceğim ve bu her kolonun içerisine CSS dosyasından resim ekleyeceğim. CSS dosyamız kısaca şöyle görünecek :

#koordinat a.item1

{

/*Direkt olarak resmin yolunu veriyoruz.*/

background-image: url(../image/image_1.png);

background-repeat: no-repeat;

margin-bottom: 30px;

}

#koordinat a.item2

{

background-image: url(../image/image_2.png);

background-repeat: no-repeat;

margin-bottom: 30px;

}

HTML tarafındaki a.item denilen kısım ise aşağıdaki gibi görünecektir.

<a class="item1" href="#" title="Gruplar">Gruplar</a>

İlk olarak buraya tıklayıp demo'yu inceleyin. Kaynak koduna bakın, öğeleri teftiş edin. Hatta HttpWatch adlı programa sahip değilseniz, buradan indirin. HttpWatch adlı program, kullanmak istediğiniz sayfanın sunucu ile ilişkisini bize detaylı bir şekilde gösterir. Bizim burada programı kullanma amacımız sunucuya kaç adet HTTP isteğinin gideceği ve tepki süresinin ne kadar süreceğini göreceğiz.

Demo'nun ekran görüntüsünü, analiziyle beraber görmek için buraya tıklayın!

Resimlerin yolunu tek tek verdiğimizde ortaya çıkan sonuç : 11 HTTP istek, 0.520 saniyelik sayfa yüklenme süresi ve 2,44KB resim dosyası boyutu.

SON HALİ

Şimdi yapacağımız işlemin, diğer örnektekinden farkı ufak dilimlere bölünmüş resim yerine hepsinin yer aldığı tek bir resim kullanmak ve CSS dosyamıda değişiklik yapmak. CSS dosyamızdaki değişiklik şöyle olacak :

#koordinat a

{

/*Bu sefer küçük resimlerin toplandığı büyük resmin yolunu veriyoruz.*/

background-image: url(../image/facebook.png);

background-repeat: no-repeat;

padding: 0 0 0 90px;

display: block;

height: 16px;

font-family:Tahoma;

}

#koordinat a.item1

{

background-position: 30px 0px;

margin-bottom: 30px;

}

#koordinat a.item2

{

/*Aşağıda yazılan css şunu açıklıyor : kesiti alınacak resmin x ve y koordinatlarını veriyoruz. Büyük resmimiz yukarıdan aşağıya olduğu için x koordinatı sabit, y ise belli aralıklarla eksi yönünde gidiyor. */

background-position: 30px -18px;

margin-bottom: 30px;

}

Web uygulamamızın son halinin demosunu görmek için buraya tıklayıp, diğer örnekte olduğu gibi inceleyin. Resimlerin tek bir resimden geldiğini göreceksiniz.

Demo'nun ekran görüntüsünü, analiziyle beraber görmek için buraya tıklayın!

Resimlerin yolunu tek bir resimden çektiğimizde çıkan sonuç : 3 HTTP istek, 0.132 saniyelik sayfa yüklenme süresi ve 1,19KB resim dosyası boyutu.

Gözle görülür şekilde performans artışı bu olsa gerek. Makalede geçen iki demo'nun da tek bir yerde toplanmış halini indirmek istiyorsanız buraya tıklayın (.NET Framework 3.5 ve Visual Studio 2010 ile hazırlandı). Yardımlarını esirgemeyen George'a teşekkürler (:

Ajax Minifier Hakkında

Geçenlerde DevExpress'in Webinar'larında neler olup bittiğini kontrol etmek amacıyla gezinirken Robert Boedighemier tarafından sunulan "Improving Web Site Performance and Scalability While Saving Money" adlı webinar'ı gördüm ve izlemeye başladım. Videoda Ajax Minifier adlı programdan bahsediyordu. Daha önce hiç duymadığım bu şeyi araştırmaya başladım. (Webinar'ı izlemek veya indirmek isterseniz buraya tıklayın.)

Ajax Minifier, Microsoft tarafından sunulmuş, css ve js uzantılı dosyalarımızın boyutu küçültmeye yarayan bir programdır. Sadece boyut küçültmekle kalmıyor, yazmış olduğunuz kodu analiz etmeye de yarıyor. Peki boyutu zaten küçük olan dosyayı, neden daha fazla küçültelim ki? Ne işimize yarayabilir? Ben de ilk olarak böyle düşünmüştüm ancak daha sonra yapmış olduğum basit matematik bu sorunun cevabını güzelce veriyordu. 25 KB'lık bir dosyayı, 10 KB'a düşürdüğünüzü düşünürseniz. sitesine girecek her bir kişinin 15 KB download etmesini (sizin yazmış/kullanmış olduğunuz css ve js uzantılı dosyaların indirmesini) engellemiş olursunuz. Sitenize yüz kişinin girdiğini düşünün, ortaya çıkacak olan boyut 1,5 MB olacaktır. Yani son kullanıcı daha çabuk sitenizi görebilecek, beklemeyecektir. Ajax Minifier'ın yaptığı işlem aslında çok basit ancak bizler için büyük bir zaman kaybı ve hata yapma payı yüksek bir işlem. Yapılan işlemin kısa açıklaması : gereksiz boşlukları, yorumları, ulaşılamaz kodları, fazla noktalı virgülleri, fazla parantezleri silmek ve değişkenlere kısa isim vermek.

O halde örnek olması amacıyla bir tane javascript dosyasının boyutunu küçültelim. Öncelikle yapmanız gereken ilk ve tek şey Ajax Minifier 4.21 (en güncel versiyonu) programını buradan indirmek. Programı indirip kurduktan sonra eğer bilgisayarınızın işletim sistemi 64 bit ise "C:\Program Files (x86)\Microsoft\Microsoft Ajax Minifier" bu dosya yoluna, eğer 32 bit ise "C:\Program Files\Microsoft\Microsoft Ajax Minifier" bu dosya yoluna gidin. Gidin diyorum çünkü program bir komut girişinden (Command Prompt) ibaret. Küçültmek istediğiniz dosyaları yukarıda belirttiğim dosya yoluna atıp, işlemi orada gerçekleştirirseniz komut girişine sadece dosya ismini yazarsınız. Ancak masaüstündeki bir dosyayı küçültmek isterseniz dosyanın yolunu da belirtmeniz gerekiyor (C:\Users\[kullanıcı ismi]\Desktop gibi). Elimde Nivo Slider adlı jquery ile hazırlanmış bir slider var ve küçültülmemiş hali 24,6 KB. Küçültme işlemi için komut girişine yazmanız gereken cümle "ajaxmin [küçültülecek dosyanın adını girin] -o [küçültülmüş dosyanın adını girin]". NOT : Sakın uzantıyı girmeyi unutmayın! (.js veya .css). Elimdeki javascript dosyasının küçültme işleminde kullanacağım cümle aşağıdaki gibidir.

Ajax Minifier Komutu

İşlemin gerçekleşmesi için Enter'a bastığımızda işlem gerçekleşecek ve bize şöyle bir rapor sunacak : 

Ajax Minifier İşlem Sonucu

Yukarıdaki görüntü bize şunu açıklıyor : jquery.nivo.slider isimli javascript dosyası %53.7 oranla küçültüldü ve 25.283 KB'tan 11.695 KB'a düştü. Yenibirdosya isimli küçültülmüş dosya ise aynı dizine çıkartılıyor. Çıkartmak istediğiniz yer farklı ise dosya yolunu başına eklerseniz istediğiniz yere dosyayı çıkaracaktır. Gelin bir de dosyalarımızın içeriğini görelim. Soldaki küçültülmemiş hali, sağdaki ise yeni, küçültülmüş hali. Sağ taraftakilerin boşluk olduğunu düşünmeyin, onlar alt satıra kayan cümlenin devamıdır.

Orjinal ve Küçültülmüş Dosyaların İçeriği

CSS dosyası küçültmenin, javascript dosyası küçültmekten farkı olmadığı için css dosyası için küçültme örneği yapmayacağım. Ajax Minifier'ın tüm komutlarına ulaşmak için "ajaxmin" yazmanız yeterli. Küçültmekten başka işlemlerin de olduğunu göreceksiniz. Dosyaların orjinal ve küçültülmüş halini görmek isterseniz, indirmek için buraya tıklayın.

ASP.NET İle reCAPTCHA Kullanımı

reCAPTCHAEğer bu makaleyi okumaya niyetliyseniz, birazdan güzel bir güvenlik önlemi olan CAPTCHA'yi (Completely Automated Public Turing Test To Tell Computers and Humans Apart, yani sizin insan mı yoksa bilgisayar mı olduğunuza karar veren mekanizmayı) ASP.NET ile kullanmayı öğreneceksiniz. Peki nedir bu CAPTCHA? CAPTCHA, bir resim üzerine işlenmiş metinin insan tarafından okunabilmesi için kolay ancak bilgisayar (bot diyelim) tarafından okunulabilmesi için zor sözcük üreten programdır. En az bir kere görmüşsünüzdür bu uygulamayı. Siteye üye olurken ya da yorum gönderirken sizden insan olup olmadığınızı anlayabilmeleri için soru sorarlar. Siz de cevap verirsiniz. Cevap doğruysa insansınızdır, yanlış ise bot muamelesi görürsünüz. İşte o yapı CAPTCHA'dir. Bu CAPTCHA'nin doğru resmi tıklatma, üzerinde rakamlar bulunan kutuları sıraya dizdirme gibi farklı varyasyonları da mevcut. Peki niye böyle bir şey yapıyorlar? Sebebi ise yorum eklenen bir sayfa düşünün, buraya botların girip 100'lerce gereksiz yorum yazdığını göz önüne alırsak hem görüntü hem de gereksiz veri açısından çok can sıkıcı bir durum olacaktır. Evet öyleyse başlayalım.
Senaryo : Bir adet textbox, bir adet button ve reCAPTCHA uygulaması ile post işlemi gerçekleştirmeye çalışacağız.
Bilinmesi Gerekenler :
  • Makaledeki örnek .NET Framework 3.5 ve Visual Studio 2010 ile hazırlandı,
  • reCAPTCHA uygulaması Google tarafından sunulan ücretsiz bir servis ancak Google hesabınız olması lazım.
İlk olarak reCAPTCHA uygulamasını indirmemiz için bir kaç basit adım gerekiyor.
İlk adımımız reCAPTCHA'nin sitesine girip "USE reCAPTCHA ON YOUR SITE" yazısı bulunan butona tıklıyoruz.
Use reCAPTCHA On Your Site
Daha sonra ise "Sign Up Now!" yazısı bulunan butona basıp Google hesabımız ile giriş yapıyoruz.
Sign Up Now
Google hesabımız ile giriş yaptıktan sonra karşımıza şöyle bir ekran çıkacak.
Create reCAPTCHA key
Burada domain yazan kısma internet sitenizin ismini yazarak "Create Key" butonuna bastığınızda sitenize özel iki adet key üretecektir. Bunlar private key ve public key'dir. Ekran görüntüsünde bulunan "Enable this key on all domains (global key)" opsiyonunu en sonunda anlatacağım.
Daha sonraki adımda domain ismine göre üretilecek şifreler aşağıdaki ekran görüntüsündeki gibi görünecektir.
reCAPTCHA Keys
Tüm işlemleri geçtik. Artık gerekli olan dökümanları indirip projemize dahil edeceğiz. Yukarıdaki ekran görüntüsünde bulunan "reCAPTCHA plugins and libraries" yazısına tıklayıp gerekli olan yerden de indirebilirsiniz ancak adım sayımızı biraz artıracağı için size direkt indirmeniz için indirme linkini veriyorum. (TIKLAYIN)
İndirdiğiniz sıkıştırılmış dosyayı açtığınızda karşınızda bir DLL dosyası göreceksiniz. Bu DLL dosyasını projenizde kullanabilmek için projenize sağ tıklayarak "Add Reference" demeniz gerekiyor.
reCAPTCHA DLL
Şimdi kod yazma işlemimiz başlıyor. Sayfanızın source kısmında üst tarafa aşağıdaki satırı ekleyin.
<%@ Register TagPrefix="recaptcha" Namespace="Recaptcha" Assembly="Recaptcha" %>
Burada reCAPTCHA kontrolünün sayfamızda kullanılacağını söylemiş oluyoruz. Daha sonra ise ;
<recaptcha:RecaptchaControl ID="recaptcha" runat="server" PublicKey="SİZE VERİLEN PUBLIC KEY’İ GİRİN" PrivateKey="SİZE VERİLEN PRIVATE KEY’İ GİRİN" />
satırını form tag'leri arasına eklediğinizde sayfamızın source tarafı ile işimiz bitiyor.
Şimdi kod yazma kısmına gelirsek yapacağımız işlem sayfamızdaki butona tıklandığında reCAPTCHA tarafından üretilen iki kelimenin doğru bir şekilde yazılıp yazılmadığını kontrol etmek ve çıkacak sonuca göre işlem yaptıracağız. Hepsi bu. Bu kodu da ekleyelim. 
protected void btn_Gonder_Click(object sender, EventArgs e)
    {
        // Sayfanın geçerli olup olmadığını kontrol ediyoruz.      
        if (Page.IsValid)
        {
            lbl_Sonuc.Text = "Doğru girdiniz!";
            lbl_Sonuc.ForeColor = Color.Green;
            return;
        }

        lbl_Sonuc.Text = "Yanlış girdiniz!";
        lbl_Sonuc.ForeColor = Color.Red;
    }
Gelelim  "Enable this key on all domains (global key)" olayına. Bu checkbox seçili ise size üretilecek olan private ve public key'ler tüm çapraz domainlerinizde geçerli olacak. Ancak seçili olmazsa, tek bir domain ve onun alt domain'lerinde geçerli olacak. Birden fazla site için key almak istiyorsanız reCAPTCHA'nin sitesinde sol taraftaki menüde bulunan "My Account" kısmına girerek birden fazla site için key alabilirsiniz. Bu arada reCAPTCHA ile ilgili söylemek istediğim son 2 şey var. Birincisi kontrolünüze uygulayabileceğiniz toplam 4 farklı tema bulunuyor. Bunları görmek için form tag'leri arasına yazdığınız recaptcha satırında Theme özelliğini kontrol edin. İkincisi, reCAPTCHA kontrolünüzde bulunan butonların üzerine gelindiğinde Türkçe açıklamalar bulunmasını istiyorsanız Language="tr" özelliğini ekleyin. Projemizde bulunan reCAPTCHA örneğinin en son ekran görüntüsü böyle olacaktır :
reCAPTCHA Demo Görüntüsü
Uygulamalı halini görmek için buraya tıklayın.
reCAPTCHA hakkında daha fazla bilgi almak için buraya tıklayın.

Runtime'da Web.Config Dosyasını Modifiye Etmek

Bu makaleyi yazmamın amacı hazırlanan projelerde web.config dosyasına istediğimiz zaman, istediğimiz şekilde müdahele edebilmenin yollarını paylaşmaktır. Peki neden böyle bir şeye başvuralım? Sebebi ise projenizin web.config dosyasını açmadan ister httpModule ekleyin, isterseniz de customErrors kesitinde değişiklikler yapın. Ama benim senaryom daha farklı ve güncel olacak.

Senaryo : Yapmakta olduğunuz web projesinde bir iletişim sayfası hazırladığınızı düşünün. Bu iletişim sayfasında da ziyaretçilerin size istek, öneri veya şikayet gibi mesajları e-posta ile iletebildiğini düşünün.  E-posta atılmasını sağlayacak olan bilgilerin de web.config'de tutulduğunu düşünün (hesap ismi, parola, port ve smtp gibi). Güvenli şifre kullanımı gereği yönetici parolasını her 10 günde bir değiştirmek istiyor. Paneliniz hazır kodlar sizi bekliyor.

İzlenecek Yol : Öncelikle şunu belirteyim, konuyu toplam 4 işlemde ve bu işlemleri 2 yoldan göstereceğim. Bu işlemler gösterme, güncelleme, ekleme ve silme. Yollar, XML ve Configuration başlığı altında olacak.

Bilinmesi Gerekenler :

  • Makaledeki örnek .NET Framework 3.5 ve Visual Studio 2010 ile hazırlandı,
  • Yazma izniniz olması lazım aksi takdirde web.config dosyasında yapılan değişiklikler sonrasında kaydetme işleminde hata alırsınız,
  • Gösterme ve güncelleme işlemlerinde değerler manuel, diğerlerinde ise dışarıdan verilecek değerlere göre yapılacaktır. Bu tamamen size kalmıştır. Makalenin en sonunda vereceğim örneği istediğiniz gibi şekillendirebilirsiniz,
  • Hiçbir validation, try-catch ve işlem sonrası bilgilendirme mesajı uygulanmamıştır. Amacım sadece gerekli olan kodu paylaşmak.

Web.config dosyamızdaki appSettings section'ı aşağıdaki gibidir.

 <appSettings>
    <add key="MailAddress" value="firatesmer@hotmail.com.tr" />
    <add key="MailPassword" value="merhaba" />
    <add key="MailPort" value="587" />
    <add key="MailSMTPAddress" value="smtp.live.com" />
    <add key="MailEnableSsl" value="true" />
</appSettings>

XML Yolu

Gösterme İşlemi

XmlDocument xmlDoc = new XmlDocument();

// Web.config dosyamızı yüklüyoruz.
xmlDoc.Load(HttpContext.Current.Server.MapPath("web.config"));

// Web.config dosyamızda, appSettings'in altındaki attribute'lere ulaşıp, hepsini bir list'e atıyoruz.
XmlNodeList nodeList = xmlDoc.SelectNodes("configuration/appSettings/add");

// List'imizin içerisinde dönüyoruz.
for (int i = 0; i < nodeList.Count; i++)
{
// key attribute'ünü alıyoruz.
XmlAttribute nodeKey = nodeList[i].Attributes["key"];
// value attribute'ünü alıyoruz.
XmlAttribute nodeValue = nodeList[i].Attributes["value"];

// Burası manuel olduğu için dışarıdan bir değer verdirmedim. Eğer döngümüzdeki mevcut key'in attribute'ü MailPassword ise girmesi için koşul koyuyoruz.
if (nodeKey.Value == "MailPassword")
{
// Ve formumuzda bulunan label'da key'i MailPassword olan ayarın value'sunu gösteriyoruz.
lbl_GuncelDeger.Text = nodeValue.Value;
}
}

Güncelleme İşlemi

XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(Server.MapPath("web.config"));

XmlNodeList nodeList = xmlDoc.SelectNodes("configuration/appSettings/add");

for (int i = 0; i < nodeList.Count; i++)
{
XmlAttribute nodeKey = nodeList[i].Attributes["key"];
XmlAttribute nodeValue = nodeList[i].Attributes["value"];

if (nodeKey.Value == "MailPassword")
{
//key'i MailPassword olan ayarın value'suna dışarıdaki textbox'tan gelen değeri atıyoruz.
nodeValue.Value = txt_YeniDeger.Text.Trim();
}
}

// Son olarak üzerinde değişiklik yaptığımız web.config dosyasını kaydediyoruz. Bunu, üzerinde oynanan notepad'in kapatılmak istedindiğinde yapılan değişikliklerin kaydedilmesini sorması gibi düşünün. Zaten bu işlemi bitirdiğinizde Visual Studio size web.config dosyasında yapılan değişikliklerin kaydedilip kaydedilmemesi sorusunu size soracaktır.
xmlDoc.Save(Server.MapPath("web.config"));

Ekleme İşlemi

XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(HttpContext.Current.Server.MapPath("web.config"));

// Burada yaptığımız işlem web.config dosyamızın appSettings kesitini (section) bir düğümde tutmak.
XmlNode xmlNode = xmlDoc.SelectSingleNode("/configuration/appSettings");

// Yukarıdaki düğümü aşağıda kullanmamızın sebebi, appSettings kesitine yeni bir ayar eklerken, diğer tüm ayarların silinmesinden dolayı, diğerlerini yukarıdaki node'da tuttuk ve yeni ayarımızı bu node ile birleştirip tekrar yazdırıyoruz.

// Yeni ayarımızın key ve value attribute'lerinin değerini dışarıdaki textbox'lardan alarak ekleme işlemini yapıyoruz. Fark ettiyseniz elementimizi bile yazıyoruz. Bu işlem ile elimizle yazmamız arasında hiçbir fark yoktur.
xmlNode.InnerXml = xmlNode.InnerXml + "<add key=\"" + txt_Key.Text.Trim() + "\" value=\"" + txt_Value.Text.Trim() + "\"/>";

// Son olarak web.config dosyamızı kaydediyoruz.
xmlDoc.Save(HttpContext.Current.Server.MapPath("web.config"));

Silme İşlemi

string sonuc = string.Empty;

XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(Server.MapPath("web.config"));

// appSettings altındaki sadece silinecek olan ayarı alıyoruz. Yani key'i, textbox'tan gelecek olan değere eşit olanı.
XmlNodeList silinecekAyar = xmlDoc.SelectNodes("/configuration/appSettings/add[@key=\"" + txt_SilinecekAyar.Text.Trim() + "\"]");

// appSettings altındaki tüm ayarları alıyoruz.
XmlNodeList tumAyarlar = xmlDoc.SelectNodes("/configuration/appSettings/add");

foreach (XmlNode node in tumAyarlar)
{
if (node.Attributes["key"].Value != silinecekAyar.Item(0).Attributes["key"].Value)
{
// ayar list'i üzerinde tuttuğumuz value ile ayarlar içerisinde uyuşan bir ayar yoksa sonuc adlı string'imize ekliyoruz. 
sonuc += "<add key=\"" + node.Attributes["key"].Value + "\" value=\"" + node.Attributes["value"].Value + "\" />";
}
}

XmlNode yeniAyarlar = xmlDoc.SelectSingleNode("/configuration/appSettings");

// yeniAyarlar adlı node'un yoluna bakarsanız direkt olarak appSettings'i göreceksiniz. Bunun sebebi ise hatırlarsanız ekleme işleminde tüm ayarlarımız siliniyordu ve bunun önüne geçmek için ayarlarımızı bir yerde toplayıp tekrar yazdırıyorduk.
yeniAyarlar.InnerXml = sonuc;
xmlDoc.Save(HttpContext.Current.Server.MapPath("web.config"));

Configuration Yolu

Gösterme İşlemi

// Projemizde bulunan web.config dosyamıza erişim sağlamak için aşağıdaki tek satırlık kod yetiyor.
Configuration config = WebConfigurationManager.OpenWebConfiguration("~");

//config nesnemiz üzerinden appSettings kesitine direkt olarak ulaşıp istediğimiz ayarın değerini alabiliyoruz. Bize de label'da göstermek kalıyor.
lbl_GuncelDeger.Text = config.AppSettings.Settings["MailPassword"].Value;

Güncelleme İşlemi  

Configuration config = WebConfigurationManager.OpenWebConfiguration("~");

// Gösterme işlemindeki gibi key'i MailPassword olan ayarımızın value'sunu direkt olarak dışarıdan gelen değer ile değiştiriyoruz.
config.AppSettings.Settings["MailPassword"].Value = txt_YeniDeger.Text.Trim();

// web.config dosyamızı kaydediyoruz.
config.Save();

Ekleme İşlemi  

Configuration config = WebConfigurationManager.OpenWebConfiguration("~");

// Add metodu ile yapmamız gereken tek şey key ve value'yu atamak.
config.AppSettings.Settings.Add(txt_Key.Text.Trim(), txt_Value.Text.Trim());
config.Save();

Silme İşlemi

Configuration config = WebConfigurationManager.OpenWebConfiguration("~");

// Silmek istediğimiz ayarın key'ini vermemiz yetiyor.
config.AppSettings.Settings.Remove(txt_SilinecekAyar.Text.Trim());
config.Save();

Uygulamalı bir halini görmek için buraya tıklayın.