4. [SimuPaie] uygulaması – sürüm 1 – ASP.NET
4.1. Introduction
Bir kullanıcının, bir belediyenin "Maison de la petite enfance" derneğine bağlı çocuk bakıcılarının maaş hesaplamalarını simüle etmesine olanak tanıyan bir .NET uygulaması yazmak istiyoruz.
'daki ASP.NET numaralı maaş hesaplama formu şu şekilde görünecektir:

ASP.NET uygulaması aşağıdaki mimariye sahip olacaktır:
![]() |
- Uygulamaya yapılan ilk istekte, [System.Web.HttpApplication] türünden türetilen [Global] türünde bir nesne oluşturulur. Web uygulamasının [web.config] yapılandırma dosyasını işleyen ve veritabanındaki belirli verileri önbelleğe alan nesne budur (yukarıdaki işlem 0).
- Uygulamanın tek sayfası olan [Default.aspx] sayfasına yapılan ilk istek (yukarıdaki işlem 1) sırasında, [Load] olayı işlenir. Burada, çalışanlar açılır menüsünün doldurulması işlemi gerçekleştirilir. Kombinasyon listesi için gerekli veriler, bu verileri önbelleğe almış olan [Global] nesnesinden istenir. Bu, yukarıdaki işlem 2’dir. İşlem 4, bu şekilde başlatılan sayfayı kullanıcıya gönderir.
- [Default.aspx] sayfasında maaş hesaplama talebi (işlem 1) yapıldığında, [Load] olayı yeniden işlenir. Bu bir POST türü istek olduğu için herhangi bir işlem yapılmaz; zira [Pam_Load] işleyicisi, bu durumda hiçbir işlem yapmayacak şekilde yazılmıştır (IsPostBack boole değeri kullanılır). [Load] olayı işlendiğinde, ardından [Salaire] düğmesindeki [Click] olayı işlenir. Bu olay, [Global]'te önbelleğe alınmamış verilere ihtiyaç duyar. Bu nedenle olay işleyicisi bu verileri veritabanından ister. Bu, yukarıdaki 3. işlemdir. Ardından maaş hesaplaması yapılır ve 4. işlem sonuçları kullanıcıya gönderir.
4.2. Visual Web Developer 2008 projesi
![]() |
- dosyasında, [1] dosyasında, [Web / Application Web ASP.NET] türünde yeni bir proje
- [2]'te, [Web / Application Web ASP.NET] türünde
- [3]'te projeye bir ad verilir
- [4]'te, projenin adını ve [5]'te konumunu belirtin. Proje için [c:\temp\pam-aspnet\pam-v1-adonet] adlı bir klasör oluşturulacaktır.
![]() |
- [5]'te, Visual Web Developer projesi
- [6]'te, projenin özellikleri (projeye sağ tıklama / Özellikler / Uygulama).
- [7]'e, projenin derlenmesi sonucu oluşturulacak derleme adı
- [8]'te, proje sınıfları için kullanmak istediğimiz varsayılan ad alanı. [Default.aspx.cs] ve [Default.aspx.designer.cs] dosyalarında tanımlanan [_Default] sınıfı ise proje adından türetilen [pam_v1_adonet] ad alanında oluşturulmuştur. Bu ad alanını, bu iki dosyanın kodunda doğrudan değiştirebiliriz:
[Default.aspx.cs]
using System;
....
namespace pam_v1
{
public partial class _Default : System.Web.UI.Page
{
[Default.aspx.designer.cs]
//------------------------------------------------------------------------------
// <otomatik olarak oluşturuldu>
// Bu kod bir araç tarafından oluşturulmuştur.
// Çalışma zamanı sürümü: 2.0.50727.3603
//
// Bu dosyada yapılan değişiklikler hatalı çalışmaya neden olabilir ve
// kod yeniden oluşturulursa kaybolacaktır.
// </auto-generated>
//------------------------------------------------------------------------------
namespace pam_v1 {
public partial class _Default {
.........
[Default.aspx] dosyasının etiketleri de değiştirilmelidir:
![]() |
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="pam_v1._Default" %>
...
Yukarıdaki Inherits özniteliği, [Default.aspx.cs] ve [Default.aspx.designer.cs] dosyalarında tanımlanan sınıfı belirtir. Burada pam_v1 ad alanı kullanılır.
4.2.1. [Default.aspx] formu
[Default.aspx] formunun görsel görünümü şöyledir:
![]() |
Bileşenler şunlardır:
No | Tür | Ad | İşlev |
DropDownList | ComboBoxEmployes | Çalışanların isim listesini içerir | |
TextBox | TextBoxHeures | Çalışılan saat sayısı – gerçek sayı | |
TextBox | TextBoxJours | Çalışılan gün sayısı – tam sayı | |
Düğme | ButtonSalaire | Maaş hesaplamasını talep eder | |
TextBox | TextBoxErreur | Kullanıcıya yönelik bilgilendirme mesajı ReadOnly=true, TextMode=MultiLine | |
Etiket | LabelNom | (1) numaralı seçilen çalışanın adı | |
Etiket | LabelPrénom | (1) numaralı seçilen çalışanın adı | |
Etiket | LabelAdresse | Adres | |
Etiket | LabelVille | Şehir | |
Etiket | LabelCP | Posta kodu | |
Etiket | LabelIndice | Endeks | |
Etiket | LabelCSGRDS | Prim oranı CSGRDS | |
Etiket | LabelCSGD | Prim oranı CSGD | |
Etiket | LabelRetraite | Emeklilik katkı payı oranı | |
Etiket | LabelSS | Sosyal Güvenlik prim oranı | |
Etiket | LabelSH | (11) numaralı satırda belirtilen endeks için temel saatlik ücret | |
Etiket | LabelEJ | (11) numaralı endeks için günlük geçim ödeneği | |
Etiket | LabelRJ | (11) numaralı satırda belirtilen endeks için günlük yemek ödeneği | |
Etiket | LabelCongés | Temel maaşa uygulanacak ücretli izin ödenek oranı | |
Etiket | LabelSB | Temel maaş tutarı | |
Etiket | LabelCS | Ödenecek sosyal güvenlik primleri tutarı | |
Etiket | LabelIE | Bakılan çocuğun bakım ödeneği tutarı | |
Etiket | LabelIR | Bakılan çocuğun yemek yardımı tutarı | |
Etiket | LabelSN | Çalışana ödenecek net maaş |
Form ayrıca iki adet [Panel] tipi alan içerir:
(5) numaralı bileşeni içerir: TextBoxErreur | |
(6) ila (24) numaralı bileşenleri içerir |
[Panel] türündeki bir bileşen, [Panel].Visible adlı boole özelliği sayesinde programlama yoluyla görünür veya görünmez hale getirilebilir.
4.2.2. Girişlerin doğrulanması
Maaşı hesaplamak için kullanıcı:
- [1]'te bir çalışanı seçer
- [2]'te çalışılan saat sayısını girer. Bu sayı, 2 saat 30 dakika için 2,5 gibi ondalık olabilir.
- [3]'te çalışılan gün sayısını girer. Bu sayı tam sayıdır.
- [4] düğmesiyle maaşı sorgulayın
![]() |
Kullanıcı, [2] ve [3] alanlarına hatalı veriler girdiğinde, kullanıcı başka bir giriş alanına geçtiği anda bu veriler doğrulanır. Bu nedenle, aşağıdaki ekran görüntüsü, kullanıcı [Salaire] düğmesine tıklamadan önce alınmıştır:
![]() |
Yukarıdaki davranışın gerçekleşmesi için iki koşul gereklidir:
- doğrulama bileşenlerinin EnableClientScript özelliğinin "true" olarak ayarlanmış olması gerekir:
![]() |
- sayfayı görüntüleyen tarayıcı, bir sayfaya gömülü JavaScript kodunu çalıştırabilmelidir HTML.
İstemci tarayıcısı verilerin geçerliliğini kendisi kontrol etmezse, bu veriler ancak tarayıcı formdaki girdileri sunucuya gönderdiğinde kontrol edilecektir. Bu durumda, sunucuda bulunan ve tarayıcının isteğini işleyen kod, verilerin geçerliliğini kontrol edecektir. Unutulmamalıdır ki, istemci tarayıcısında görüntülenen sayfada aynı doğrulamayı yapan bir JavaScript kodu bulunsa bile bu doğrulama her zaman yapılmalıdır. Zira sunucu, kendisine gönderilen POST isteğinin gerçekten bu sayfadan geldiğinden ve dolayısıyla verilerin doğrulanmış olduğundan emin olamaz.
Doğrulayıcıların listesi şöyledir:
No. | Tür | Ad | Rol |
RequiredFieldValidator | RequiredFieldValidatorHeures | [2] ve [TextBoxHeures] alanlarının boş olmadığını kontrol eder | |
RangeValidator | RangeValidatorHeures | [2] ve [TextBoxHeures] alanlarının [0, 200] aralığında bir gerçek sayı olup olmadığını kontrol eder | |
RequiredFieldValidator | RequiredFieldValidatorJours | [3] [TextBoxJours] alanının boş olmadığını kontrol eder | |
RangeValidator | RangeValidatorJours | [3] ve [TextBoxJours] alanlarının [0,31] aralığında bir tamsayı olup olmadığını kontrol eder |
Yapılması gereken iş: [Default.aspx] sayfasını oluşturmak. Öncelikle, içlerinde bulunması gereken bileşenleri yerleştirebilmek için [PanelErreurs] ve [PanelSalaire] adlı iki konteyneri yerleştireceğiz.
4.2.3. Uygulamadaki öğeler
![]() |
Okunduktan sonra, [cotisations], [employes] ve [indemnites] tablolarındaki satırlar, [Cotisations] türündeki nesnelere yerleştirilecektir; [Employe] ve [Indemnites] türündeki nesnelere aktarılacaktır; bu nesneler aşağıdaki gibi tanımlanmıştır:
namespace Pam.Entites
{
public class Cotisations
{
// otomatik özellikler
public double CsgRds { get; set; }
public double Csgd { get; set; }
public double Secu { get; set; }
public double Retraite { get; set; }
// yapıcılar
public Cotisations()
{
}
public Cotisations(double csgRds, double csgd, double secu, double retraite)
{
CsgRds = csgRds;
Csgd = csgd;
Secu = secu;
Retraite = retraite;
}
// ToString
public override string ToString()
{
return string.Format("[{0},{1},{2},{3}]", CsgRds, Csgd, Secu, Retraite);
}
}
}
namespace Pam.Entites
{
public class Employe
{
// otomatik özellikler
public string SS { get; set; }
public string Nom { get; set; }
public string Prenom { get; set; }
public string Adresse { get; set; }
private string Ville { get; set; }
private string CodePostal { get; set; }
private int Indice { get; set; }
// üreticiler
public Employe()
{
}
public Employe(string ss, string nom, string prenom, string adresse, string codePostal, string ville, int indice)
{
SS = ss;
Nom = nom;
Prenom = prenom;
Adresse = adresse;
CodePostal = codePostal;
Ville = ville;
Indice = indice;
}
// ToString
public override string ToString()
{
return string.Format("[{0},{1},{2},{3},{4},{5},{6}]", SS, Nom, Prenom, Adresse, Ville, CodePostal, Indice);
}
}
}
namespace Pam.Entites
{
public class Indemnites
{
// otomatik özellikler
public int Indice { get; set; }
public double BaseHeure { get; set; }
public double EntretienJour { get; set; }
public double RepasJour { get; set; }
public double IndemnitesCP { get; set; }
// üreticiler
public Indemnites()
{
}
public Indemnites(int indice, double baseHeure, double entretienJour, double repasJour, double indemnitesCP)
{
Indice = indice;
BaseHeure = baseHeure;
EntretienJour = entretienJour;
RepasJour = repasJour;
IndemnitesCP = indemnitesCP;
}
// kimlik
public override string ToString()
{
return string.Format("[{0}, {1}, {2}, {3}, {4}]", Indice, BaseHeure, EntretienJour, RepasJour, IndemnitesCP);
}
}
}
4.2.4. Uygulamanın yapılandırılması
Uygulamayı yapılandıran [Web.config] dosyası şu şekilde olacaktır:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
...
</configSections>
<connectionStrings>
<add name="dbpamSqlServer2005" connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=C:\data\...\dbpam.mdf;User Id=sa;Password=msde;Connect Timeout=30;" providerName="System.Data.SqlClient"/>
</connectionStrings>
<appSettings>
<add key="selectEmploye" value="select NOM,PRENOM,ADRESSE,VILLE,CODEPOSTAL,INDICE from EMPLOYES where SS=@SS"/>
<add key="selectEmployes" value="select PRENOM, NOM, SS from EMPLOYES"/>
<add key="selectCotisations" value="select CSGRDS,CSGD,SECU,RETRAITE from COTISATIONS"/>
<add key="SelectIndemnites" value="select INDICE,BASEHEURE,ENTRETIENJOUR,REPASJOUR,INDEMNITESCP from INDEMNITES"/>
</appSettings>
<system.web>
<!--
Définissez compilation debug="true" pour insérer des symboles
de débogage dans la page compilée. Comme ceci
affecte les performances, définissez cette valeur à true uniquement
lors du développement.
-->
<compilation debug="false">
...
</configuration>
- 9. satır: önceki SQL Sunucusuna bağlantı dizesini tanımlar
- 13-16. satırlar: kodda sabit olarak yazılmalarını önlemek amacıyla uygulama tarafından kullanılan SQL sorgularını tanımlar.
- 13. satır: SQL sorgusu yapılandırılmıştır. Parametre notasyonu SQL Sunucusuna özgüdür.
Yapılması gereken iş: Bu parametreleri [Web.config] dosyasına eklemek. 9. satır, [dbpam.mdf] veritabanının gerçek yoluna göre uyarlanacaktır.
4.2.5. Uygulamanın başlatılması
ASP.NET uygulamasının başlatılması, [Global.asax.cs] dosyası aracılığıyla gerçekleştirilir. Bu dosya şu şekilde oluşturulur:
![]() |
- [1] dosyasında, projeye yeni bir öğe eklenir
- [2] dosyasında, varsayılan olarak [Global.asax] olarak adlandırılan genel uygulama sınıfı eklenir [3]
![]() |
- [4]'te, [Global.asax] dosyası ve ilişkili sınıf [Global.asax.cs]
- [5]'te, [Global.asax]'in etiket yapısı görüntülenir
<%@ Application Codebehind="Global.asax.cs" Inherits="pam_v1.Global" Language="C#" %>
[pam_v1.Global] sınıfı, [Global.asax.cs] dosyasında tanımlanmıştır. Bizim sorunumuz için bu sınıf şu şekilde tanımlanacaktır:
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data.SqlClient;
using Pam.Entites;
namespace pam_v1
{
public class Global : System.Web.HttpApplication
{
// --- uygulamanın statik verileri ---
public static Employe[] Employes;
public static Cotisations Cotisations;
public static Dictionary<int, Indemnites> Indemnites = new Dictionary<int, Indemnites>();
public static string Msg = string.Empty;
public static bool Erreur = false;
public static string ConnectionString = null;
// uygulamanın başlatılması
public void Application_Start(object sender, EventArgs e)
{
...
try
{
// oturum açma
ConnectionString = ...
using (SqlConnection connexion = new SqlConnection(ConnectionString))
{
connexion.Open();
// çalışan listesi alınır ve statik tabloya aktarılır [Employes]
...
// katkı payı oranları alınır ve statik değişken [Cotisations]'e aktarılır
...
// tazminatları statik sözlük [Indemnites]'ten alınır
...
// işlem başarıyla tamamlandı
Msg = "Base chargée...";
}
}
catch (Exception ex)
{
// hatayı not ediyoruz
Msg = string.Format("L'erreur suivante s'est produite lors de l'accès à la base de données : {0}", ex);
Erreur = true;
}
}
}
}
- 20. satır: [Application_Start] yöntemi, web uygulamasının başlatılması sırasında yürütülür. Bu yöntem yalnızca bir kez yürütülür.
- 12-17. satırlar: Sınıfın genel ve statik alanları. Statik bir alan, sınıfın tüm örnekleri tarafından paylaşılır. Dolayısıyla, [Global] sınıfının birden fazla örneği oluşturulursa, hepsi [Employes] adlı aynı statik alanı paylaşır; bu alana [Global.Employes] ve c.a.d referansları aracılığıyla erişilebilir. [NomDeClasse].ChampStatique. [Global] bir sınıfın adıdır. Dolayısıyla bu bir veri türüdür. Bu ad keyfi olarak belirlenir. Sınıf her zaman [System.Web.HttpApplication]'ten türetilir.
[Global] sınıfımıza geri dönelim. Bu sınıfın alanlarını statik olarak tanımlamanın gerekli olup olmadığı sorusu akla gelebilir. Aslında, bazı durumlarda [Global] sınıfının birden fazla örneğine sahip olunabileceği görülmektedir; bu da, tüm bu örnekler tarafından paylaşılması gereken alanların statik hale getirilmesini haklı kılar.
Bir web uygulamasının farklı sayfaları arasında "uygulama" kapsamındaki verileri paylaşmanın başka bir yolu daha vardır. Böylece, çalışanlara ait Employes dizisi, Application_Start yordamında şu şekilde depolanabilir:
Application.Add("employes",Employes);
[Application], varsayılan olarak tüm ASP.NET uygulamalarında, [Global.asax.cs] ile tanımlanan sınıfın bir örneğine yapılan bir referanstır. Application, her türden nesneyi depolayabilen bir kapsayıcıdır. Employes dizisi, web uygulamasının herhangi bir sayfasındaki kodda şu şekilde çağrılabilir:
Employe[] employes=Application.Get["employes"] as Employe[];
Application konteyneri her türden nesneyi depoladığından, Object türünde bir nesne elde edilir ve bu nesnenin türü daha sonra dönüştürülmelidir. Bu yöntem her zaman kullanılabilir, ancak [Global] nesnesinin tiplendirilmiş statik alanları aracılığıyla veri paylaşmak, tip dönüştürme işlemlerini ortadan kaldırır ve derleyicinin geliştiriciye yardımcı olacak tip denetimleri yapmasını sağlar. Burada bu yöntem kullanılacaktır.
Tüm kullanıcılar tarafından paylaşılan veriler şunlardır:
- 12. satır: Tüm çalışanların basitleştirilmiş listesini (SS, NOM, PRENOM) depolayacak olan [Employe] türündeki nesnelerden oluşan dizi
- 13. satır: prim oranlarını depolayacak [Cotisations] türündeki nesne
- 14. satır: Çalışanların çeşitli endekslerine bağlı tazminatları depolayacak sözlük. Bu sözlük, çalışanın endeksine göre indekslenecek ve değerleri [Indemnites] türünde olacaktır
- satır 15: başlatma işleminin nasıl sonuçlandığını (başarılı mı yoksa hata mı) belirten bir mesaj
- satır 16: Başlatma işleminin hata ile mi yoksa hatasız mı sonuçlandığını belirten bir boole değeri.
- satır 17: veritabanına bağlantı dizesi.
Soru: [Application_Start] sınıfının kodunu tamamlayınız.
4.3. [Default.aspx] formundaki olaylar
4.3.1. [Page_Load] yordamı
[Default.aspx] formu yüklendiğinde, [Global.Employes] tablosundan (satır 12) çalışanların adlarını alır ve bunları [1] açılır listesine ekler:
![]() |
- [1] açılır listesi doldurulmuştur
- TextBox ve [5], veritabanının doğru şekilde okunduğunu gösterir
Uygulamanın başlatılması sırasında başlatma hataları meydana gelirse, TextBox ve [5] kodları bunu gösterir:

Soru: Uygulamanın başlatılması sırasında çalıştırıldığında yukarıdaki işleyişi sağlayan [Default.aspx] web sayfasındaki [Page_Load] prosedürünü yazınız.
4.3.2. Maaş hesaplaması
[4] düğmesine tıklandığında aşağıdaki yönetici çalıştırılır:
protected void ButtonSalaire_Click(object sender, System.EventArgs e)
Bu yönetici, öncelikle [2] ve [3]'te yapılan girişlerin geçerliliğini kontrol eder. İkisinden biri hatalıysa, daha önce gösterildiği gibi hata bildirilir. [2] ve [3] girişleri doğrulanıp geçerli bulunduktan sonra, uygulama [1]'te seçilen kullanıcı hakkında ek verileri ve maaşını görüntülemelidir (bkz. 4.1. paragrafındaki ekran görüntüsü).
Soru: [ButtonSalaire_Click] prosedürünün kodunu yazınız.











