. Aplicatie Online Pentru Recrutarea Si Facilitarea Comunicatiei Intre Membrii Programului
I. Tema lucrării
Se cere implementarea unei aplicații online pentru recrutarea și facilitarea comunicației între membrii unei companii multinationale.
Aplicația oferă următoarele facilități:
permite căutarea (după nume, prenume, țara și orașul în care aceștia își desfășoară activitatea, precum și cateva din datele lor personale);
permite vizualizarea si actualizarea datelor personale: nume, prenume, locul si data nașterii, adresa, poza;
permite vizualizarea si actualizarea datelor referitoare la liceu precum si vizualizarea, actualizarea, inserarea si ștergerea datelor despre universitățile sau studiile superioare pe care membrul respectiv l-a urmat sau le urmează;
permite vizualizarea, actualizarea, adăugarea si ștergerea datelor referitoare la experiență acumulata anterior de către membru precum si principalele aplicații ale acestora;
permite vizualizarea si modificarea datelor despre limbile pe care membru le cunoaște, precum si despre principale aptitudini;
permite vizualizare evenimentelor la care membru poate sa participe sau este înscris deja, precum si înscrierea sau vizualizarea statusului curent pentru un anumit eveniment.
Aceasta aplicație este foarte utila atât studenților cat si persoanelor de contact si se utilizează împreuna cu toolul e administrare la care au insa acces doar persoanele de contact.
Pentru implementare în urma solicitărilor beneficiarilor s-a optat pentru o aplicație ASP.NET 2.0 dezvoltată cu ajutorul Visual Studio .NET beta 2.0, cu logica scrisa in limbajul C#, iar baza de date implementata in SQL SERVER 2000.
II. Prezentare generală
Aplicația consta intr-o pagina de internet care permite vizualizarea, adăugarea, ștergerea si modificarea datelor unui membru al unei companii multinationale. Aplicația conține sase mari părți:
pagina de search;
pagina de informații personale;
pagina cu informații referitoare la studii;
pagina cu informații referitoare la experiențele anterioare;
pagina cu principalele abilitați;
pagina de evenimente.
Fiecare membru al programului dispune de un username si o parola cu ajutorul cărora poate accesa contul sau. Pe lângă membri mai exista si alte persoane care au acces la site. Acestea sunt persoanele de contact.
La încărcarea site-ului va fi pornita pagina de logare:
In cazul in care username-ul si parola vor fi corecte iar contul corespunzător este activat se va putea continua. In caz negativ utilizatorul va primi un mesaj de eroare.
In cazul in care contul este pentru un membru al programului acesta va fi redirectat spre pagina de search, iar in partea stânga va avea posibilitatea de a naviga intre paginile aplicației:
Pagina de seach permite căutarea membrilor din program după nume, prenume, sex, țară, oraș, limba vorbită și departamentul în care își desfășoară activitatea. In cadrul textboxului pentru nume si prenume se poate introduce un nume sau prenume întreg sau se poate caută după o anumita parte a acestuia. De exemplu, daca dorim sa căutam toți membrii al căror nume se termina in escu, in textboxul aferent numelui vom introduce: %escu. Aceasta înseamnă ca vor fi listați toți studenții al căror nume se termina in escu inclusiv si pe cei al căror nume este escu.
Daca in oricare din cele doua textboxuri nu se va introduce nimic se vor caută toți membrii care îndeplinesc celelalte condiții.
In listele pentru status, program principal si subprogram se pot selecta zero sau mai multe elemente. In cazul in care nu a fost selectat niciunul din elementele listei atunci se va considera implicit căutarea studenților care îndeplinesc celelalte condiții. Daca au fost selectate doua sau mai multe elemente vor fi listați studenții care participa la cel puțin unul din programe sau subprograme (sau respective au unul din statusurile selectate). Pentru a selecta mai multe elemente din lista va fi necesar sa se tina apăsat tasta ctrl si sa se selecteze elementele dorite. Pentru deselectare se va proceda in mod asemănător.
Rezultatul căutării va fi afișat sub forma unui table ale cărui rânduri pot fi precizare de utilizator. Implicit vor fi afișate cate zece rânduri pe pagina. In table vor fi afișate numele, prenumele, data de naștere, sexul, țara si adresa de e-mail:
Se observa ca datele sunt disponibile in patru pagini, Studenții sunt afișați in ordine alfabetica după nume si prenume. De asemenea pentru fiecare persoana in parte este disponibil un link spre CV-ul persoanei respective.
Un exemplu de CV este cel prezentat in figura următoare (pentru Rolf Alberecht). Date care sunt prezente in CV sunt: nume, prenume, adresa de e-mail, număr de telefon mobil, adresa de acasă si de la studiu sau serviciu, locurile de munca, studiile precum si principalele abilitați.
Pagina de informații personale este următoarea pagina:
Se observa ca aici sunt disponibile date ca nume, prenume, sex, nume de naștere, data si locul nașterii, naționalitate, precum si date de contact ca mail, număr de telefon fix si mobil, adresa de acasă si cea de serviciu.
De asemenea, după cum se observa in figura de mai sus, in aceasta pagina mai sunt disponibile informații despre programele si subprogramele la care membrul a fost sau este participant, precum si despre sponsorul si grupul regional din care face parte.
Datele din prima parte pot fi in cea mai mare parte modificare, excepție fac doar numele si data de naștere. In schimb datele din cea de-a doua parte nu pot fi modificare.
O alta facilitate a acestei pagini este de a da posibilitatea membrului sa-si încarce o poza. Aceasta poza va apărea si in CV-ul persoanei respective. Poza va fi salvata in baza de date.
A treia pagina a acestei aplicații este cea pentru studii. Sunt prezente atât date despre liceu cat si despre principalele studii superioare pe care membru le-a urmat sau le urmează.
Datele despre liceu sunt: nume, nota de terminare si tipul diplomei, data de început si de sfârșit, orașul si tara. Datele despre universitate sunt: data de început si de sfârșit, tipul, numele data e universitate principala, daca e terminata si cu ce fel de diploma, tipul si specialitatea, orașul si tara precum si programele pentru care aceasta universitate este relevanta. Acest lucru se stabilește de către persoanele de contact.
O a patra pagina este cea dedicata experienței persoanei. Sunt reținute date ca data de început si cea de sfârșit, tipul, firma (daca acesta firma este chiar siemens atunci acesta va fi semnalata prin checkboxul aferent, caz in care vor fi disponibile si alte informații precum departamentul, grupul si supervizorul), orașul si tara precum si o scurta descriere al acestei experiențe:
Exista un tip special de astfel de experiențe si anume experiențele de tip program aplicativ. Acestea nu pot fi adăugate si nici șterse, singurul lucru posibil fiind de a modifica datele prezente. In toate celelalte cazuri se pot adăuga noi experiențe precum si șterge. Programele aplicative pot fi adăugate numai de către persoanele de contact cu ajutorul toolului de administrare.
Nu exista o foarte mare diferența intre datele disponibile pentru o experiența normala si un program aplicativ singurele diferente constând din tipul aplicatei care diferă in general de tipurile disponibile pentru un job normal.
Cea de-a patra pagina este cea de abilitați:
In prima parte sunt disponibile date despre limbile pe care membrul le cunoaște precum si nivelul de cunoaștere al acestora. In parte a doua sunt disponibile date despre abilitați: abilitățile sunt împărțite in categorii, pentru fiecare categorie in parte fiind disponibile anumite abilitați. De asemene pentru fiecare membru in parte sunt specificate abilitățile de care acesta dispune. Acestea pot fi alese din lista de abilitați disponibile. De asemenea se poate renunța la o abilitate daca este cazul. Abilitățile alese deja nu mai apar in lista de abilitați disponibile ale acelei categorii.
Inserarea unei noi categorii si a unei noi abilitați la categoriile disponibile se poate face numai de persoanele de contact. Modificările apărute in cazul abilitaților sunt disponibile din momentul in care sunt făcute. In schimb modificările pentru limbi sunt disponibile numai daca este apăsat butonul Apply, ca si in cazul modificărilor efectuate in celelalte pagini de pana acum.
Ultima pagina disponibila este cea de evenimente:
Un eveniment reprezintă un miting la care participa o parte din membrii programului. Un anumit eveniment se distinge prin nume, locația in care are loc, datele intre care se desfășoară, dar mai ales prin membrii care pot participa.
Un eveniment are un anumit tip. Tipul unui eveniment specifica programul principal al persoanelor care pot participa. Un anumit membru poate sa aplice pentru participarea la acest eveniment doar daca este membru al programului respectiv. De asemenea se admit excepții dar acestea trebuie obligatoriu specificare manual. Odată înscris in pentru acest program un membru trece prin mai multe statusuri pana a deveni efectiv participant la acesta:
former participant – in acest stadiu se afla membri care sunt înscriși manual pentru acest program;
participant – in acest stadiu se afla membri care au fost acceptați pentru a participa la eveniment;
participant (not confirmed) – membri care nu au confirmat încă participarea lor la eveniment dar sunt acceptați;
participant cancelled – membri care au refuzat participare la eveniment;
possible participant – membri care pot participa la eveniment;
pre-registered – membri care s-au înregistrat pentru acest program;
rejected – membri care au fost respinși;
waiting queue – membri care așteaptă intr-o coada de așteptare.
Un membru poate participa la mai multe evenimente singura restricție fiind cea de tip, adică un membru nu poate participa in același timp la mai multe evenimente.
III. Fundamentare teoretica
III.1. Mașini virtuale
III.1.1. Introducere
Ideea unei mașini virtuale a prins viață în jurul anilor ‘70. Deși timidă la început, tendința de a realiza un program portabil, compilându-l mai întâi într-un limbaj intermediar generic (și având la dispoziție o mașină abstractă), a cunoscut în timp un curent de opinie favorabil.
III.1.1.1. Funcționalitate
Modul de operare este unul direct. Presupunem că pentru un program scris într-un limbaj de programare X, compilatorul este capabil să emită o formă intermediară de cod, privită ca un mijloc de transfer de informație între forma inițială programului (cod sursă, numit frontend) și forma sa finală (care produce rezultatul programului, numit și backend).
Etapele parcurse ar fi deci: compilarea și verificarea semantică a codului sursă, rezultatul fiind un limbaj intermediar, și generarea rezultatului final de către o mașină care înțelege și poate valida acest limbaj. O situație ideală pentru acest caz ar fi aceea în care frontend-ul este independent de ținta hardware, iar backend-ul ar fi sensibil independent de limbajul X. În acest caz, sarcina de a scrie compilatoare pentru N limbaje având la intrare M arhitecturi hardware ar fi redusă la a scrie N + M compilatoare “parțiale” (în ideea în care la un moment dat un compilator poate importa funcționalități ale altui compilator), în locul scrierii N x M compilatoare complete.
III.1.1.2. Exemple
Multe dintre reprezentările acestor limbaje intermediare se bazează pe stive abstracte (abstract stack machines). În timp au existat mai multe încercări de a susține o astfel de abordare și unele dintre acestea au evidențiat rezultate importante. Vom prezenta pe scurt, în ordine cronologică, câteva dintre acestea.
Primul exemplu ar fi reprezentarea P-Code ca formă intermediară pentru compilatoarele ETH Pascal, devenind instrumentul (machine code) pentru UCSD Pascal System. Unul din rezultatele la care s-a ajuns în urma acestui proiect a fost acela că limbajul destinat stivei abstracte poate fi utilizat în două moduri:
fie este compilat în limbajul mașinii țintă (de către un compilator situat ca aplicație pe ac compilat în limbajul mașinii țintă (de către un compilator situat ca aplicație pe această mașină);
fie există un interpretor care să emuleze mașina abstractă pe arhitectura țintă.
În acest caz, formula interpretării suferă din punctul de vedere al vitezei, dar are avantajul că informația trimisă mașinii abstracte are o densitate calitativ superioară. Se reamintește că sarcina unui compilator este să producă un cod mașină cât mai mic, pentru a facilita o execuție cât mai rapidă.
Un al doilea exemplu a fost inițiativa celor de la Open Software Foundation’s Architecture Neutral Distribution Form (ANDF). Premisa de la care s-a pornit în acest caz a fost de a distribui programele într-o formă intermediară și de a completa sarcina compilării în timpul instalării. Și în acest caz, această formă intermediară se adresează unei mașini abstracte și au fost evidențiate două puncte de vedere (critice):
fie se cunosc la momentul compilării destule informații despre mașina spre care codul intermediar va fi trimis;
fie acest lucru nu se cunoaște și în felul acesta, această informație (validă în cazul anterior) rămâne simbolică.
Ideea de a încorpora informația simbolică în forma distribuită a fost considerată ca o amenințare la adresa proprietății intelectuale și inițiativa, neavând suport, a eșuat.
Următorul pas semnificativ a fost realizarea limbajului Java și coincide cu succesul ideii de mașină abstractă (numită aici Java Virtual Machine – JVM). În această situație, codul scris în Java este transformat mai întâi într-o secvență de octeți (bytecode, deci un limbaj intermediar) care ulterior este tratată de JVM producând rezultatul final. Inițial, tratarea a însemnat interpretare, dar în prezent această tehnică este înlocuită de compilare (evident, pentru performanțe sporite). Sistemul gândit se bazează pe o stivă abstractă și mai mult, la fel ca și în cazul ANDF, prezența informației simbolice (pentru a permite spre exemplu, rezolvarea adresării și a offset-urilor câmpurilor de date să se realizeze în momentul folosirii și execuției). Prezența informației simbolice este de această dată un punct forte, pentru că este acea entitate care permite ca în timpul utilizării și al execuției să se realizeze o întărire a sistemului de tipuri (type system), printr-un motor numit bytecode verifier. În momentul de față, există mașini virtuale Java pentru aproape orice arhitectură.
Exemplul care ne interesează cel mai mult este platforma .NET care în primul rând mizează pe o lărgire a orizonturilor aplicațiilor pe suportul World Wide Web (WWW). Și aceasta, la rândul ei, se bazează pe un sistem orientat-obiect și cu suport de colectare (garbage collection) numit inițial NGWS runtime și ulterior CLR. Acest sistem produce o formă intermediară care, la fel ca și JVM, se bazează pe o stivă abstractă. Însă dincolo de această structură comună, design-ul și scopurile celor două sisteme sunt cu mult diferite.
III.1.2. Nucleul platformei Microsoft .NET. Common Language Runtime
III.1.2.1. Istoric
Undeva în Redmont, WA, 1997, în clădirea 42 a campusului Microsoft un programator începe să lucreze la ultimul DLL COM ("ever to be produced"). Componenta va fi numită mscoree.dll (Microsoft ~ Magnificent Software + Component Object Runtime + Execution Engine).
Mai târziu același programator începe să scrie prima componentă pentru .NET, mscorlib.dll (Microsoft ~ Magnificent Software + Component Object Runtime + Library). Este biblioteca standard unde toate tipurile de bază (System.Object, System.String) sunt definite.
Cele două componente fac tranziția de la platforma veche ("the real world") la noua platforma .NET ("the Matrix"). Diferența între acestea este metadata: creată, stocată și manipulată.
Când producătorii de software aduc pe piață noi tehnologii și produse informatice, acestea trebuie să fie concepute astfel încât să ofere servicii cât mai flexibile utilizatorilor (în sensul de end-users). Dintr-un punct de vedere cât se poate de real, o tehnologie (reprezentată prin modelul abstractizat și implementarea acestuia) se dovedește a fi de succes dacă atrage un procent semnificativ din "lumea" dezvoltatorilor, astfel încât noi produse (având ca suport această tehnologie) să fie lansate pe piața IT mondială. "Schema" unei astfel de tehnologii trebuie, în mod obligatoriu, să valideze tag-urile ce conțin: ușurința în a dezvolta și folosi (developing and deploying), disponibilitatea pe termen lung (high availability), stabilitatea (reliability), suportul pentru o gamă largă de aplicații (multi-target application support), rezultatul rapid (strength), eleganța și modernitatea. Prin noua sa platformă .NET, Microsoft completează această listă cu un tag esențial prin forța sa: interoperabilitatea. Această platformă, anunțată undeva la mijlocul anului 2000, își cunoaște începuturile undeva la sfârșitul anilor ’90, însumând punctele forte ale etapelor de dezvoltare existente până în acel moment în concepția Microsoft (cele mai esențiale fiind Win32 și COM).
III.1.2.2. Runtime environment
NET a fost gândită să funcționeze pe suportul oferit de o mașină virtuală. Acest nou cadru face pentru prima data diferența între ceea ce a fost și există în prezent (Win32, COM) și ceea ce va urma în mentalitatea dezvoltatorului atașat de platforme Microsoft. Runtime-ul .NET, numit Common Language Runtime (CLR), a fost gândit astfel încât să ofere o puternică interoperabilitate multi-limbaj.
Integrare
Dacă se dorește să se programeze în .NET folosind limbajul de programare X, compilatorul lui X trebuie să știe să emită cod intermediar pentru mașina virtuală .NET. Specificațiile acestui cod intermediar sunt publice și în acest moment, exisă în jur de 20 de limbaje compatibile cu .NET, dintre care: C#, C++, Visual Basic (.NET), Jscript (.NET), COBOL, Perl, etc.
Interoperabilitate
Modulele scrise în X pot fi utilizate în orice alt limbaj compatibil .NET. Spre exemplu, o clasă scrisă în X poate fi moștenită în C#, etc. În plus, în .NET, nu se mai pune problema vulnerabilității legate de versiunea modulului scris în X (în care se regăsește signatura și implementarea clasei de mai sus). Se poate spune că în .NET asistăm la End of DLL Hell (una din deficiențele majore ale programării cu componente – COM), datorită metadatei.
III.1.2.3. CLR
Mediul de execuție al .NET constă dintr-un sistem orientat-obiect înzestrat cu un mecanism de colectare integrală (fully garbage colected). În momentul lansării unui compilator compatibil .NET, se produce o formă intermediară de limbaj (cod) ce urmează a fi tratată de o stiva abstractă. La prima vedere, acest sistem seamănă extrem de mult cu sistemul existent în Java, dar lucrurile nu stau deloc așa. Cea mai riguroasă motivație este că Java a fost gândită pentru portabilitate, iar .NET pentru interoperabilitate. Mai mult decât atât, în .NET nu există nici o opțiune de intrepretare a codului intermediar, așa cum există în Java. Pentru a înțelege mai bine, se prezintă exemplul compilatorului de C#. Acest compilator este, evident, compatibil cu .NET și deci este suportat de CLR. La lansare (prima fază), compilatorul transformă codul sursă în cod ce va fi administrat și controlat de CLR (managed code). Acest cod conține un limbaj intermediar (Microsoft Intermediate Language – ce urmează a fi utilizat de stiva abstractă) și metadata. Ambele entități sunt însă împachetate într-un singur fișier (cu extensia .exe sau .dll), numit executabil portabil (PE). În a doua fază (execuție), PE-ul este încărcat de motorul de execuție care extrage separat MSIL și metadata. MSIL este JIT-compilat în cod mașină (binar) și executat. Prezența metadatei (data describing data) face ca acest cod administrat să poată să se auto-descrie (definiți de tipuri, versiune, restricții legate de securitate, etc). Această extra-informație asigură practic o interoperabilitate fără compromisuri.
Deci, în .NET, fișierele cu extensiile .exe și .dll nu mai au aceeași structură cu cele obișnuite.
III.1.2.4. MSIL
Codul produs de compilatorul limbajului C# este scris într-un limbaj denumit Microsoft Intermediate Language (MSIL sau IL). Așa cum numele sugerează MSIL nu este nici un limbaj de nivel înalt nici de nivel jos (cod mașină sau asm).
MSIL este de fapt compus dintr-o serie de instrucțiuni pe 8 biți pentru execuția unor instrucțiuni elementare și a instrucțiunilor de mutare. Câteva dintre instrucțiunile MSIL ar putea fi încadrate în setul de instrucțiuni al unui microprocesor RISC iar celelalte sunt instrucțiuni special proiectate pentru lucrul cu obiecte.
Codul IL este mai rapid decât un script și nu este legat de nici un sistem de operare, acest cod putând rula pe orice calculator care are un interpretor IL și .NET runtime. Un interpretor IL se numește JIT (Just-In-Time) compiler.
Acest compilator știe exact ce fel de procesor are utilizatorul și va produce instrucțiuni specifice mașinii utilizatorului. De asemenea va știi dacă utilizatorul are unul sau mai multe procesoare (dacă va detecta un singur procesor atunci nu va mai implica mecanisme de sincronizare a thread-urilor în procesul de compilare).
Deasemenea .Net Framework ne pune la dispoziție un utilitar denumit NGen.exe pentru o compilare mai rapidă, obținerea unui cod mașină optimizat și utilizarea eficientă a memoriei.
În momentul când se apelează acest utilitar din linia de comandă urmat de numele unui fișier .exe sau .dll (un asamblaj), fără alți parametrii, acesta va solicita CLR-ul pentru ca acesta să încarce asamblajul.
NGen.exe va forța JIT-ul să compileze fiecare metodă din respectivul asamblaj. Codul mașină rezultat va fi emis într-un fișier generat de NGen.exe. Acest utilitar poate fi folosit în procesul de instalare a unui asamblaj.
Pentru .NET Framework v1.1 acest utilitar are câteva dezavantaje în folosirea lui:
Fișierele generate de NGen.exe nu sunt șterse în momentul în care un asamblaj este dezinstalat.
Când Windows-ul încarcă un fișier generat de către acest utilitar verifică dacă acesta poate fi încărcat la o adresă preferată de acest fișier dacă nu poate fi încărcat la o astfel de adresa atunci sistemul de operare realoca acest fișier fixând toate adresele de memorie referite, operație costisitoare ca timp.
Pentru versiunea .NET Framework v2.0 viteza de execuție a codului obținut folosind NGen.exe este îmbunătățită față de viteza de execuția a codului mașină obținută fără a apela utilitarul NGen.exe (ci doar JIT compilarea).
În 2.0 JIT-ul (JIT64) și NGen-ul au fost scrise de către membrii din echipa VC++ și intern folosesc materiale de la compilatorul Microsoft VC++.
III.1.2.5. Metadata
Metadata este generată de compilatorul compatibil cu CLR. În Win32, un exemplu de producere a metadatei este decorarea funcțiilor exportate printr-un Dynamic Link Library (DLL) de către compilatorul de C++. Oricum, nu se pune problema comparării celor două tipuri de dată și motivul ar fi unul extrem de simplu: pentru rigurozitatea interoperabilității multi-limbaj, CLR-ul trebuie să forțeze compilatoarele compatibile să respecte aceleași reguli în ceea ce privește generarea codului intermediar. Acest lucru este o îmbunătățire a comportamentului compilatorului, pentru că emiterea informației binare (metadata) se face respectându-se o specificație (viitor standard). Această tendință, ca și multe altele, se încadrează în ceea ce Microsoft numește Common Language Specification (CLS). Metadata a fost gândită ca o informație ce poate servi simultan mai multor scopuri (multi-purpose). Mai jos sunt prezentate câteva dintre situațiile critice în care prezența metadatei este necesară:
declararea tipurilor utilizate de sistemul de tipuri (type system) cu care este înzestrat CLR;
reprezentarea informației pe care CLR o folosește pentru a localiza și încărca clasele (class loader);
încadrarea instanțelor acestor clase în memorie (class layout);
rezolvarea invocării metodelor;
sporirea securității.
III.1.2.6. JITters
Pentru ca MSIL să poată fi executat, trebuie convertit mai întâi în cod nativ. Limbajul intermediar nu este gândit ca un cod care să fie interpretat, ci este 100% compilat. Instrumentul căruia îi revine această sarcină se numește JIT-compiler. Codul nativ generat va putea fi executat doar pe platforma (arhitectura) pe care se află acest compilator (am putea spune deci că acest cod este specific procesorului cu care este înzestrată această arhitectură).
După cum spune și numele, un JIT-compilator este mai "deștept" și mai "rapid" decât un compilator obișnuit. De fiecare dată când este apelat, un JITter presupune că anumite parți din cod nu vor fi niciodată utilizate în timpul execuției. Prin urmare, el nu va consuma inutil cicluri CPU și memorie pentru a transforma tot MSIL-ul asociat unei aplicații în cod nativ, ci va converti exact codul MSIL necesar în timpul execuției, păstrând codul mașină generat pentru eventualele apeluri ulterioare.
Este de remarcat că tot la momentul JIT al compilării pot să se realizeze și alte operații, cum ar fi de exemplu verificarea codului intermediar (type safety verifier sau bytecode verifier). Deci a implementa un JIT compilator nu este deloc o sarcină ușoară. Poate de aceea algoritmii utilizați nu sunt făcuți publici. Același lucru se poate spune și despre motorul de control automatic al memoriei numit Garbage Collector. Acestea sunt domenii relativ noi (relativ deoarece spre exemplu, ideea de Garbage Collector a apărut în 1958) și nimeni nu va putea spune cu certitudine, cel puțin pentru moment, că a implementat cel mai bun motor de JIT compilare sau de control automatic al memoriei.
III.1.2.7. Virtual Execution Engine
Sistemul virtual de obiecte (VOS) este implementat de o entitate numită Virtual Execution Engine (VES), care reprezintă infrastructura responsabilă pentru runtime (implementată în mscoree.dll). Prin urmare, VES execută ceea ce se numește o aplicație compatibilă .NET. Componentele de bază ale VES sunt prezentate în următoarea figură.
Toate aceste servicii funcționează cross-language, cross aplication-types.
III.1.2.8. Assemblies
Formula atomică prin care o aplicație este reprezentată la runtime se numește assembly. Un executabil portabil conține codul ce va fi controlat, administrat, dar fără un manifest atașat, acest cod nu va însemna nimic la runtime. În cel mai fericit caz, va fi ignorat.
Comparabil cu un fișier .class din Java, un assembly combină codul administrat cu acest manifest. Există mai multe criterii de clasificare a tipurilor de assembly, din care se vor evidenția doar două.
Din punctul de vedere al felului în care este generat, un assembly poate fi:
static, în sensul că a fost generat de compilatorul unui limbaj la momentul în care s-a construit codul intermediar;
dinamic, în sensul că un assembly poate fi generat la runtime-ul unei alte aplicații.
Din punctul de vedere al numărului de fișiere "conținut", un assembly poate fi reprezentat:
printr-un singur fișier, în ideea că manifestul și codul administrat sunt împachetate într-un singur fișier;
prin mai multe fișiere (colecție logică), în contextul în care manifestul poate fi găzduit într-un executabil portabil "dedicat", de unde există referințe spre modulele aplicației (.netmodule) sau resursele acesteia (.bmp, etc).
III.1.2.9. Manifest
Fiecare assembly (static sau dinamic) trebuie să poată să descrie felul în care unele elemente depind de altele. Deci trebuie să conțină metadata. Un manifest conține metadata asociată unui assembly. La runtime, un assembly (build-ul intermediar al unei aplicații) trebuie să fie unic determinabil.
Manifestul va descrie felul în care un assembly poate fi identificat, cu ajutorul următoarelor câmpuri:
numele assembly-ului (Assembly Name), reprezentat ca text;
versiune, un "certificat" format din patru numere: major version number, minor version number, build number și revision number;
cultura (limbaj suportat, etc);
nume puternic (Strong Name), în sensul de unicitate.
III.2. ASP.NET
III.2.1. ASP
ASP este o tehnologie avansată de la Microsoft care permite elaborarea aplicațiilor pentru WWW. ASP lucrează sub Windows NT (2000 Server) și IIS (Internet Information Server); nu este un limbaj de programare, ci o tehnologie ce permite utilizarea programelor pentru generarea paginilor WEB.
Un plus al ASP-ului este posibilitatea păstrării într-un singur fișier a codului HTML și a codului de program.
Baza succesului ASP este posibilitatea utilizării unui limbaj simplu de tip "script" (Visual Basic Script sau Java Script) și posibilitatea utilizării componentelor COM externe.
III.2.2 Aplicatiile Web și ASP.NET
Aplicațiile web sunt acelea care asigură funcționalitate de pe un server către mașini client prin intermediul Internetului. Aplicațiile web compun răspunsuri la niște cereri către resurse aflate pe server. Aceste resurse pot fi: codul executabil care rulează pe server, Form-urile web, paginile HTML, imagini, fișiere multi-media.
ASP.NET este o componentă a .NET Framework care este folosită pentru a crea aplicații web. ASP.NET nu este singura tehnologie care permite acest lucru, însă ea se integrează foarte bine cu celelalte tehnologii Microsoft.
ASP.NET folosește:
Microsoft Internet Information Services (IIS) este serverul de aplicații web al Microsoft. El este o componentă a Windows XP: Add/Remove Programs -> Add/Remove Windows Components.
Visual Studio .NET 2005 este un mediu integrat de dezvoltare, care cuprinde inclusiv unelte de design al Form-urilor web, unelte de debug și deployment.
Colecția de namespaces System.Web. Acestea sunt parte integrantă a .NET Framework și include clase predefinite care se ocupă de chestiuni specifice aplicațiilor web.
Controalele HTML și server sunt componente ale interfeței cu utilizatorul care sunt folosite pentru a afișa respectiv colecta informații către/dinspre utilizatori.
Limbajul de programare C#.
ADO.NET – sunt clase predefinite care se ocupă de managementul datelor – accesul la date în baze de date ODBC și Microsoft SQL Server.
III.2.2.1. Controale
ASP.NET vine cu câteva controale predefinite, în plus față de cele HTML, numite și controale server, numite așa deoarece tratarea evenimentelor la care acestea răspund se execută pe server. Visual Studio .NET 2005 are o interfața care permite manipularea facilă a acestora din Toolbox. Atunci când se introduc controale într-un Form web, în codul “din spatele acestuia”, adică în fișierul .cs asociat, se produc niște modificări: se creează un nou obiect, în funcție de ce anume se adaugă, ca instanță al uneia dintre clasele din spațiul de nume System.Web.UI.WebControls.
Există controale folosite la afișare de date: Labels, TextBoxes – informații unicate; dar în mod curent se folosesc și unele pentru afișarea unor colecții de informații, cum ar fi: ListBoxes, DropDownLists și DataGrids. Acestea din urmă se folosesc foarte mult în aplicații de management al informațiilor, cum ar fi de exemplu una de bibliotecă, unde se poate dori afișarea tuturor cărților dintr-un anumit domeniu, etc.
Controalele au și evenimente predefinite la care știu să răspundă. De exemplu, butoanele au Click, textbox-urile au TextChanged, etc. În momentul în care se dorește să se trateze un astfel de eveniment, de exemplu apăsarea unui buton de către utilizator, trebuie să se asocieze un handler evenimentului predefinit Click al butonului respectiv. Un handler nu este altceva decât o funcție, iar asocierea respectivă se poate face foarte ușor din Visual Studio. Pentru cazul anterior, este suficient dublu-click pe buton, pentru ca să se creeze automat o metoda de tipul
private void ButtonX_Click(object sender,System.EventArgs e){}
și în plus aceasta este automat dată ca handler evenimentului Click.
De asemenea se poate afișa o colecție de informații în controale precum ListBox-ul. Cam așa se face adăugarea la runtime într-un ListBox și într-un DropDownList:
private void butAdd_Click(object sender,
System.EventArgs e)
{
ListBox1.Items.Add(txtSource.Text);
DropDownList1.Items.Add(txtSource.Text);
}
Pentru a putea referi informațiile după aceea, folosim o serie de proprietăți ale obiectului ListBox, cum ar fi:
ListBox1.SelectedItem // (de tip object) sau
ListBox1.SelectedValue // (de tip string)
Un caz special îl reprezintă GridWiew-ul care poate fi configurat ca, pe lângă datele pe care i le putem da automat setând proprietatea DataSource a lui, mai poate fi configurat să aibă coloane Template, în care putem să adăugăm orice controale dorim noi (click dreapta pe DataGrid-ul din modul Design al Form-ului, apoi Show Smart Tag și în fine în cadrul GridWiewTasks Edit Columns). Se poate adăuga o nouă coloană din lista Available fields în cadrul cărei ultima opțiune este chiar o coloană tempalate.
De asemenea, putem remarca Web User Controls. Acestea pot fi create de către programator și în general sunt folosite pentru a grupa un set de controale care vor fi folosite în mai multe pagini. Astfel, dacă se dorește să se vizualizeze cărțile unei biblioteci în două Form-uri, atât în Student.aspx cât și în Admin.aspx, se poate crea un control ViewBooks.ascx. În acest control se poate pune, de exemplu, un Label, un GridWiew și poate și alte controale. Apoi se va lua din Solution Explorer se va pune pe fiecare din cele două Form-uri.
Pentru a obține o așezare în pagină cât mai ordonată, se recomandă cu tărie folosirea de tabele, acestea putând fi găsite în Toolbox -> HTML, sau se pot scrie direct în codul HTML al paginii web.
De asemenea, dacă pe un Form dorim să efectuăm mai multe acțiuni, ca de exemplu Adăugare/Ștergere Cărți + Împrumut Cărți + Returnare Cărți, se poate să se grupeze controalele folosind Panel-uri. Acestea sunt utile și în momentul în care dorim ca o singură funcționalitate să fie vizibilă la un moment dat. De exemplu, vrem să fie vizibile doar controalele pentru Adăugare/Ștergere Cărți, iar controalele celorlaltor acțiuni nu. După ce le-am grupat pe toate în câte un Panel, facem proprietatea Visible a acestora true respectiv false.
III.2.2.2. Validarea datelor
Deoarece nu se poate știi ce informații vor introduce utilizatorii site- ului, acestea trebuie neapărat validate. Pentru asta, ASP.NET ne pune la dispoziție câteva controale, care după asocierea de un TextBox să spunem pot să avertizeze asupra introducerii unor informații greșite: CompareValidator, RequiredFieldValidator, RangeValidator, RegularExpressionValidator, CustomValidator, ValidationSummary. Acestea se pot folosi în modul următor:
se ia un astfel de control din Toolbox și se pune pe Form ;
se specifica controlul pe care se dorește să se valideze. La CompareValidator este necesar să se specifice și controlul de comparat ;
se setează proprietatea ErrorMessage;
trebuie să mai existe un control care să facă Post-Back, adică un control server, care să facă o cerere la server (de exemplu un buton). Chiar dacă validarea se realizează la nivel de client, ea nu începe înainte ca un Post-Back să aibă loc.
III.2.2.3. Păstrarea informațiilor
Având în vedere că ne referim la aplicații ASP.NET, trebuie să ținem cont de faptul că fiecare Form se execută pe server și la fiecare încărcare a sa, obiectele pe care le conține acesta, și care se doresc să fie folosite, nu își păstrează valoarea, adică sunt setate pe null. Deci la navigarea într-un Form nou și încărcarea acestuia, în mod normal nu se rețin obiectele folosite în cel anterior.
Mai trebuie observat faptul că fiecare Form se reîncarcă (adică pe scurt se execută Page_Load) la fiecare răspuns al serverului pentru un eveniment (cum ar fi apăsarea unui buton).
Se impune deci să păstrăm cumva starea obiectelor pe care dorim să le folosim, chiar dacă nu părăsim Form-ul curent.
Există următoarele modalități de a păstra informații utile: Query Strings, Cookies, View State, Session State, Application State.
O să ne referim doar la Session. Variabilele din Session pot fi create în timpul execuției, iar acesta poate fi imaginat ca un cos în care noi depunem obiecte pe care dorim să le păstram pe durata întregii execuții a aplicației de către utilizatorul curent. Astfel ar arata crearea unui nou obiect în Session.
Session["Feedback"] = objFeedback;
Iar “luarea” lui din Session:
objFeedback = (Feedback)Session["Feedback"];
Se observă că s-a făcut o conversie de tip. Asta pentru că în Session, toate variabilele sunt de tip object, iar de acolo se dorește citirea unui obiect de tip Feedback (asta fiind o clasa definită de noi).
III.2.2.4. Navigarea între Forms cu păstrarea informațiilor
Există mai multe posibilități de a naviga între Form-urile unei aplicații ASP.NET.
Controlul Hyperlink și metoda Response.Redirect() fac același lucru, doar că primul este un control care rezidă în .aspx, iar metoda se apelează din cod (.aspx.cs).
Metoda Server.Transfer(), face același lucru doar că așa se pot reține informații din Form-ul sursă și folosite în cel destinație. Dacă setăm parametrul preserveForm al metodei la valoarea true, atunci QueryString și ViewState din sursă vor fi vizibile în destinație. Totuși, pentru a le folosi, va trebui să setăm atributul EnableViewStateMac din directiva Page (fișierul .aspx) pe valoarea false. Asta pentru că în mod normal informația din ViewState este hash-uită, iar așa nu va mai fi, deci se va putea citi la nevoie.
Transferul de la un form la altul, păstrând informația utilă:
// Webform1.aspx
private void Button1_Click(object sender, System.EventArgs e)
{
Server.Transfer("Webform2.aspx", true);
}
// Webform2.aspx
private void Page_Load(object sender, System.EventArgs e)
{
System.Collections.Specialized.NameValueCollection colForm;
// Se citesc datele din form
colForm = Request.Form;
Response.Write("TextBox1.Text: " + colForm["TextBox1"] + " ");
}
O altă modalitate de a naviga între Form-uri și a păstra informație utilă, este folosirea Session. Iată cum ar arăta:
//”trainer_courses.aspx”
private void btnManage_Click(object sender, System.EventArgs e)
{
objTrainer = (Trainer)Session["Trainer"];
Response.Redirect("trainer_course.aspx");
}
//”trainer_course.aspx”
private void Page_Load(object sender, System.EventArgs e)
{
if (!IsPostBack)
{
objTrainer = (Trainer)Session["Trainer"];
Session["Trainer"] = objTrainer;
}
}
III.2.2.5. Baza de date
Pentru exemplele de mai jos se va folosi o bază de date numită Lib care conține două tabele : Books și Users.
ADO.NET
ADO.NET este componenta din .NET Framework care se ocupă cu accesul la baze de date ; este standardizată în sensul că se pot folosi aceleași obiecte pentru accesarea diferitelor tipuri de baze de date : Access, MS SQL Server, Oracle, etc. Sunt necesare la referințe două namespaces : System.Data și System.Data.SqlClient pentru MS SQL sau System.Data.OleDb pentru Access.
Primul lucru care trebuie realizat în lucrul cu baze de date este conectarea la o bază de date. Asta se poate realiza în două moduri.
1. folosind Visual Studio. Acesta pune la dispoziție View -> Server Explorer, unde se poate realiza Connect to Database. Apoi trebuie să se aleagă un Provider (de exemplu OLE DB Provider For SQL Server); Connection, unde trebuie să se specifice server name (o instanța de MS SQL aflată pe computerul personal sau în rețeaua din care acesta face parte), trebuie să se selecteze o baza de date de pe acest server și modul de autentificare, care poate să fie integrată cu Windows (se poate folosi un cont din mașina personală sau din Active Directory dacă e vorba de rețea) sau poate să fie specifică SQL Server, caz în care trebuie să se specifice un cont aflat în MS SQL cu o parolă validă.
2. direct în cod. Iată un exemplu
/* realizarea unei conexiuni la baza de date elearning aflată pe serverul MYSQLSEVER */
string strParameters = “Data Source=MYSQLSERVER;Initial Catalog=elearning;User Id=elearning;Password=elearmy”;
// sau, când MS SQL nu are nume de instanță.
string strParameters = “Data Source=(local);Initial Catalog=elearning;User Id=elearning;Password=elearmy”;
/* mai sus s-a folosit un cont specific MS SQL. Se poate folosi un cont existent în domeniu. Aici contul sub care rulează aplicația va accesa MS SQL; acesta este \ASPNET pentru aplicații web. */
string strParameters = “Data Source=(local);Initial Catalog=elearning;Integrated Security= true”;
/* evident că în toate cazurile de mai sus, userul folosit trebuie să aibă drepturi pe baza de date în MS SQL. */
//crearea conexiunii.
SqlConnection sqlConn = new SqlConnection(strParameters);
Citirea datelor
După realizarea conexiunii, putem să accesăm datele. În ADO.NET există două abordări pentru citirea datelor din baza de date.
folosind obiectul SqlDataReader respectiv OleDbDataReader pentru Access. Acesta are următoarele caracteristici:
poate fi returnat de execuția unei comenzi ADO.NET. Obiectul folosit pentru asta este SqlCommand sau OleDbCommand, asociat unei conexiuni deschise la baza de date;
ia rezultatele sub forma unei tabele, pe care o parcurge secvențial de sus în jos, neștiind de la început câte înregistrări are;
se recomandă pentru citirea unui număr mic de înregistrări.
// este deja creată o conexiune la baza de date.
SqlCommand comGet = new SqlCommand("SELECT * FROM Questions WHERE CourseID='" + CourseID + "'",sqlConn);
sqlConn.Open();
SqlDataReader dr = comGet.ExecuteReader();
/* acum vom parcurge DataReader-ul înregistrare cu înregistrare */
while(dr.Read())
{
AddCurrentQuestion();
}
sqlConn.Close();
folosind SqlDataAdapter sau OleDbDataAdapter pentru Access.
este echivalent cu execuția unei comenzi ADO.NET;
rezultatul este o tabelă care poate fi folosită pentru a umple un DataSet. DataSet este un obiect care poate sa retina mai multe tabele, inclusiv cu relații între ele, la nivelul aplicației. Este folosit ca sursă de date pentru GridWiew, DropDownList, etc;
se recomandă la citirea unui număr mare de înregistrări.
/* se citesc datele și se depun într-un DataSet. */
SqlDataAdapter daGet = new SqlDataAdapter("SELECT * FROM Courses",sqlConn);
daGet.Fill(dsCourses);
/* acum se va da unui GridWiew sursa de date. */
myGridWiew.DataSource = dsCourses;
myGridWiew.DataBind();
Update și Insert
Pentru a scrie sau a modifica date în bazele de date, avem nevoie de obiectele SqlCommand (MS SQL) sau OleDbCommand (Access). Atât pentru INSERT cât și pentru UPDATE, avem nevoie de o comandă asociată unei conexiuni la baza de date. Trebuie să deschidem conexiunea, apoi să executăm comanda și apoi să reînchidem conexiunea.
/* metoda returnează string … */
// se definește comanda SQL
SqlCommand com = new SqlCommand("INSERT INTO Marks(SignInID,LessonID,"
+ "PostedHomework) Values('" + SignInID + "','" + ID + "','1')",sqlConn);
try
{
// se deschide conexiunea la baza de date.
sqlConn.Open();
com.ExecuteNonQuery();
}
catch(SqlException sqlex)
{
// în caz de eroare, se semnalează utilizatorului…
return "Could not mark the homework!!!";
}
finally
{
/* se închide conexiunea la baza de date. Ramura finally se execută indiferent dacă a fost o eroare sau nu (s-a intrat pe catch sau nu) */
sqlConn.Close();
}
return "Homework marked.";
III.2.2.6. Securitate
Există mai multe moduri de a securiza o aplicație ASP.NET. În general, se poate face acest lucru atât din IIS Management Console (click dreapta pe un director virtual din IIS, Properties, Directory Security, Edit) – unde se pot alege mai multe tipuri de autentificare {Anonymous, Windows Integrated, Digest for Windows domain servers, Basic}.
Pe de alta parte, securizarea aplicației se poate face din ASP.NET. Pentru asta se folosește fișierul de configurare web.config, după cum se vede mai jos. Forms poate fi înlocuit cu Windows sau Passport.
<authentication mode="Forms">
Pentru o aplicație securizată, avem mai multe posibilități de autentificare, cele mai des întâlnite fiind sintetizate în tabelul care urmează. Implementarea politicii de securitate se poate face atât din IIS cât și din aplicația ASP.NET.
III.2.2.7. Tratarea erorilor
Atunci când apare o excepție în codul unei aplicații ASP.NET, pentru utilizator este vizibil imediat și într-un mod nu tocmai plăcut – apare o pagină urâtă în care este afișată excepția și utilizatorul nu mai poate să facă nimic decât să apese Back în browser.
Se recomandă ca porțiunile de cod în care se pot întâmplă lucruri necontrolate să fie incluse în blocuri de tratare a erorilor. Iată un exemplu:
try
{
m_trFile = File.OpenText(strPath);
line = m_trFile.ReadLine();
NoQuestions = System.Convert.ToInt32(line,10);
Questions = new Tester.TestQuestion[NoQuestions];
m_trFile.Close();
return "All questions read ok.";;
}
catch(System.IO.IOException ioex)
{
return "Could not open the file!!!";
}
catch(System.InvalidCastException icex)
{
return "Could not read the number of questions from file!!!";
}
catch(Exception ex)
{
return "Could not read the questions.";
}
În exemplul de mai sus, s-a izolat în try {…} zona de cod considerată critică. În aceasta se pot produce mai multe excepții, cum ar fi IOException (de exemplu nu s-a găsit fișierul specificat), InvalidCastException (conversia de la string la int a eșuat) și altele.
Se observă că sunt mai multe blocuri catch, primele două tratând cazurile în care se produc excepții concrete, știute, iar ultimul tratând cazul în care se produce o altă excepție (orice excepție). Contează și ordinea în care sunt scrise.
III.2.2.8. Performanta
Aplicațiile ASP.NET sunt aplicații web, deci accesibile probabil de un număr mare de utilizatori. De multe ori, este foarte important ca aplicația să facă față cu succes unei încărcări mari: mulți utilizatori simultani, multe tranzacții cu baza de date, etc.
În general se urmărește ameliorarea următorilor parametri:
Încărcarea procesorului și a memoriei sistemului.
Numărul de cereri pe care aplicația le poate servi pe unitate de timp.
Timpul de răspuns, latența.
Utilizarea cache-ului. Se pot urmări cache hits și cache misses.
Erori. Numărul de erori și excepțiile generate.
Etc.
Deoarece aplicațiile ASP.NET pot fi foarte diferite și mai ales pot să funcționeze în scenarii diferite, nu există niște limite cantitative clare, adică niște cifre asociate fiecărui indicator, care odată atinse să putem spune că aplicația nu mai este performantă. Acestea se stabilesc mai mult calitativ, iar cifre concrete se pot asocia doar atunci când se vorbește de aplicații și scenarii concrete.
III.2.3. Tehnologii concurente
III.2.3.1. Java
Java este la ora actuală una dintre cele mai puternice platforme de dezvoltare software – limbaj de programare independent, aducând în spectrul web posibilități excepționale de interacțiune client-server, cu mult dincolo de binecunoscutele formulare, animații, jocuri sau efecte vizuale interactive. Practic tehnologiile Java (de multe ori combinate cu alte standarde sau tehnologii cum ar fi XML spre exemplu), reprezintă o modalitate foarte apropiată de natural pentru implementarea de aplicații manipulând cu succes mai toate tipurile de generatori și consumatori de informație, de la telefoane mobile până la sisteme de gestionare a tranzacțiilor online. Portabilitatea și extensibilitatea celor doua tehnologii (Java și XML) face din acestea alegerea ideală pentru satisfacerea unei impresionante game de cerințe ale Internetului, de la cele mai simple programe până la aplicații rulând pe diferite platforme interconectate și solicitând nivele dintre cele mai performante de securitate, stabilitate și portabilitate.
III.2.3.2. JSP
Este o tehnologie alternativă la PHP și ASP, utilizată în același scop și anume implementarea site-urilor web dinamice și interactive. Când a devenit clar că folosirea Java pe parte de server era o idee foarte bună, s-a propus dezvoltarea unei interfețe API Java Servlet care a fost adoptată de mulți programatori de Java care lucrau la extinderea funcționalității serverelor web. Interfața API Java Servlet tratează în mod elegant multe dintre problemele cărora trebuiau să le facă față programatorii Java pe partea de server și oferea un standard pe baza căruia furnizorii de aplicații puteau construi motoare de servlet-uri. Toate dispuneau de facilitați de rulare și zone de izolare pentru securitate, ceea ce a simplificat mult programarea servlet-urilor pentru dezvoltatorii de aplicații Java. Servlet-urile aveau însă și câteva dezavantaje: trebuia să scrii instrucțiuni de ieșire speciale pentru fiecare bucată de cod HTML care voiai să fie afișată clientului; trebuia să ai cunoștințe de Java; în plus, existau și alte tehnologii concurente pe piață, ca de exemplu ASP (de la Active Server Pages, produs marca MicroSoft), care le permiteau programatorilor să creeze mai ușor conținut dinamic pentru web. Era de dorit ca puterea servlet-urilor Java să fie pusă la dispoziția celor care se ocupau de dezvoltare web, fără a-i obliga să învețe Java. Așa s-a născut specificația Java Server Pages (JSP) lansată de firma Sun la începutul anului 1998. Combinând puterea și extensibilitatea limbajului Java cu simplitatea și ușurință de folosire a scriptării pe baza de etichete, Java Server Pages a devenit rapid limbajul preferat de mulți programatori profesioniști pentru dezvoltarea aplicațiilor bazate pe web.
III.2.3.3. PHP
Pentru un site de prezentare de produse, în cazul căruia un calcul preliminar ne poate indica lesne ca se impune construirea a circa 500 de pagini de conținut și 2000 de poze, există o alternativă facilă la munca sisifică de actualizare și întreținere a lui. Ca să adaugi sau să modifici o pagina HTML a unui site trebuie să o descarci de pe server, să aplici modificările, să găsești și celelalte pagini care ar urma să aibă de suferit de pe urma schimbării link-urilor și să aplici și la acestea modificările de rigoare, iar apoi să transferi totul înapoi pe server. Dacă site-ul de 500 de pagini actualizabil în acest mod în fiecare zi a săptămânii mai trebuie să și poată vinde produsele online, să ofere facilitați avansate de căutare în paginile de produse și în plus să poată înregistra și o evidentă exactă vânzărilor, stocurilor și clienților, atunci perspectiva unei astfel de munci nu poate decât să sperie până și pe cel mai tenace creator de site-uri web. Utilizând însă o baza de date legată la o pagină web prin intermediul unui limbaj "server-side" (pe parte de server), web designer-ul nu mai are nevoie de ajustări în codul paginilor pentru a schimba periodic conținutul acestora sau pentru a oferi facilitățile amintite mai devreme. Crearea de site-uri web dinamice și interactive folosind tehnologia PHP combinată cu bazele de date operate în MySQL, totul utilizând un server Apache, este unul dintre cele mai bune lucruri.
III.3. C#
Viziunea inițială a Microsoft-ului asupra conceptului "Internet" este departe de conținutul rețelelor web din zilele noastre. Microsoft consideră Internetul viitor ca o lume a serviciilor interdependente dezvoltate de indivizi diferiți, scrise în limbaje diferite, desfășurate pe tipuri diferite de suportul fizic, și găzduite de diferite sisteme de operare Internet.
Oferta companiei pentru această nouă lume este platforma .Net. De fapt, .Net nu este o platformă în sensul tradițional; nu este un sistem software sau hardware comun. În schimb, .Net este o colecție de protocoale care permit diverselor aplicații internet să se folosească de servicii disparate care rulează pe mașini diferite.
Un rezultat direct al strategiei firmei Microsoft este că versiunea de Microsoft Visual Studio include limbaje remodelate, modificate explicit să suporte platforma .Net.
III.3.1. Avantajele C#
Dezvoltare rapidă de aplicații: Unul din cele mai importante obiective ale Microsoft pentru C# este suport pentru RAD (Rapid Application Development). Aplicațiile internet trebuie să fie dezvoltate în timp internet; un nou limbaj trebuie să fie ușor de învățat și depanat, și trebuie să producă cod care să se poate modifica ușor. În timp ce VB și Delphi excelează în aceste domenii, C++ nu a fost tocmai un succes. Limbajul în sine este complex și greu de mânuit, și puține biblioteci C++ oferă interfețe simple. În plus, managementul manual al memoriei și modelul de type-casting complex fac depanarea la C++ foarte dificilă. În plus C++ nu protejează inerent împotriva potențialelor probleme cauzate de incompatibilități ale versiunilor. Cu tot efortul depus de Microsoft ți Borland, C++ nu este potrivit pentru dezvoltare rapidă a aplicațiilor.
Funcționare inter-platforme: Limbajele internet ar trebui să suporte, prin definiție, o funcționare inter-platforme. Deoarece internetul este o rețea de sisteme disparate, serviciile trebuie să funcționeze pe o gamă largă de hardware și software. În plus, software-ul orientat pe client ar trebui să ruleze pe mai multe tipuri de dispozitive, inclusiv PDA și telefoane mobile. O astfel de flexibilitate este o provocare pentru toate limbajele, cu excepția Java. În special VB produce doar aplicații Windows pentru mașini bazate pe Intel. Delphi, de asemenea , are aceleași restricții. Delphi pentru Linux este disponibil deja, dar nu oferă încă suport pentru aplicații internet. Nici VB și nici Delphi nu îndeplinesc condițiile pentru funcționarea independentă de platformă.
Acces la resursele caracteristice platformei: Adesea este nevoie de astfel de acces pentru a scrie aplicații țintă puternice. Visual J++ 6.0 oferea programatorilor acces la Windows API, ceea ce Java de obicei nu permite. În schimb, Java oferă funcționare independentă de platformă prin definirea unui cel mai mic numitor comun standard implementat de orice mașină virtuală. Programatorii Java trebuie să codeze folosind acest standard mai puțin puternic, în loc să profite de serviciile mai puternice oferite doar de anumite platforme. Astfel, Java nu reușește să îndeplinească obiectivul de a da acces la resurse specifice platformei.
Suport pentru platformele COM și .Net: Microsoft a hotărât că suportul pentru COM și .Net este principalul obiectiv ce trebuie să-l îndeplinească C#. Nici un alt limbaj nu suportă platforma .Net, deoarece era încă în construcție. Spre deosebire de .Net, COM există de ceva vreme, dar totuși duce lipsa suportului unui limbaj puternic. Majoritatea limbajelor, incluzând C++ și Delphi, necesită ca programatorii să mai facă în plus o declarare IDL, o fabrică de clase și împachetări speciale pentru fiecare obiect COM creat.
III.3.1.1. C# este un mediu RAD.
Una dintre cele mai semnificative caracteristici RAD ale limbajului C# este colectarea spațiului disponibil în stilul limbajului Java. La intervalele arbitrare din timpul momentul execuției, toate obiectele care nu mai sunt referite sunt în mod automat șterse. Ușurând treaba programatorului de a elibera manual memoria – colectarea spațiului disponibil face generarea programelor mai ușoară și fără eroare. Colectarea spațiului disponibil automată este totuși consumatoare de timp și imprevizibilă. În consecință, C# permite programatorilor să dezactiveze local colectarea spațiului disponibil, marcând codul cu "nesigur", în situațiile în care este necesară realizarea performanței în timp real.
C# pune în aplicare un tip un sistem valoare/referință în stilul limbajelor Java/Delphi. În acest sistem, tipurile predefinite (întreg, real, string, și așa mai departe), enumerările, și structurile, sunt toate tipuri de valori. Operatori de comparație copiază și verifică valorile acestor tipuri de variabile. Interfețele, clasele, și "delegate"-urile sunt toate tipuri de referințe. Operatorii de comparare copiază și verifică identitatea obiectelor la care se referă aceste tipuri de variabile.
Acest tip de sistem este mai mult simplu decât pointerii din C++. Face mai ușoară folosirea obiectelor și elimină multe din erorile ce apar în programele de C și C++.
Declarațiile și definițiile metodelor de clasa sunt combinate: C# simplifică dezvoltarea aplicațiilor prin combinarea declarațiilor și definițiilor de metodele clasei, așa cum face Java. Programatorii de C++ trebuie să mențină separate fișierele pentru declarații (fișierul antet) și definiții (fișierul de implementare), complicând dezvoltarea procesului software. Ușurând programatorul de încă un task, C# descoperă automat relații printre modulele sursei. Acolo unde C++ necesita #include (și Delphi "uses") C# nu are nevoie de nimic adițional pentru a localiza fișierele înrudite de sursa.
În C# interfețele sunt declarate separat față de clase: C# de asemenea sprijină un model de interfață Delphi și Java, unde interfețele sunt declarate în mod independent de clase. Este opusul modelului C++, unde interfețele sunt clase de baza abstracte. Ambele, interfețe și clase, pot să moștenească interfețele multiple. În timp ce clasele pot să moștenească o singură clasa de bază, interfețele nu pot să moștenească clase deloc. Acest model evită problema multiplei moșteniri, în care pot apărea conflicte. Nevoia pentru mecanismele complexe ca de exemplu moștenirea virtuală este de asemenea eliminată. Interfața simplificată a C#-ului ajuta la mărirea vitezei aplicației.
C# folosește referirile metodelor, numite "delegate", în loc de pointerii la metodă: C# folosește referințele la metode pentru a conecta repede obiectele și metodele. Numite și "delegate", aceste metode sunt asemănătoare cu tipurilor procedurale ale limbajului Delphi. Un delegat este un tip de o referință care ține semnătura metodei. Când "delegate" este invocat, este chemată și metoda asociată.
Spre deosebire de tipurile de proceduri Delphi, "delegates" suportă și multicasting-ul. O aplicație poate să desemneze multe metode la o variabilă "delegat"; Când variabila este invocată, sunt apelate toate metodele.
C# folosește mecanismul Java pentru sincronizarea unui singur fir. Pentru a pune în aplicare sincronizarea firelor de execuție în C#, un programator pur și simplu marchează blocurile critice de cod. Unde un programator Java folosește cuvântul cheie "synchronised", un programator de C# folosește "lock"=lacat. Un mutex protejează blocul, permițând numai un fir să execute codul odată.
Un programator al unei o clase C# derivate, trebuie în mod clar să marcheze o suprascriere de metodă cu cuvântul cheie "override", așa cum face și în Delphi. Dacă o clasă derivată include o metodă care are același nume ca metoda virtuală din clasa de bază, compilatorul nu poate precis să deslușească intenția autorului.
III.3.1.2. Alte facilități C#
Luând în considerare toate caracteristicile discutate deja, suport puternic pentru RAD pare a fi unul din principalele obiective ale Microsoft pentru C#. Sunt și alte nevoi de dezvoltare importante la care C# trebuie să răspundă. Acestea includ dezvoltare independentă de platformă, acces la resurse tipice platformei, și suport pentru platformele COM și .NET. Să examinăm facilitățile C# prin care se intenționează a satisface aceste nevoi.
Funcționare independentă de platformă: C# rezolvă problema funcționării independente de platformă în același mod ca și Java. Compilatorul de C# generează un flux de cod binar care este interpretat de .Net runtime. Componenta runtime lucrează ca și o mașină virtuală Java; o aplicație poate fi rulată pe orice mașină pe care a fost portat .Net runtime.
Accesul aplicației la resurse specifice platformei: Spre deosebire de mașina virtuală Java, .Net runtime oferă acces programatic la resursele specifice platformei. Un program C# poate folosi, de exemplu, Windows API pentru a rula ca o aplicație completă sub Windows XP. Același program poate rula pe un PDA folosind subsetul Windows CE API. Bineînțeles, nu toate serviciile pe care aplicația le așteaptă vor fi disponibile pe toate mașinile. De aceea, este responsabilitatea developerului să testeze software-ul pe toate platformele țintă, și să scrie cod special, dacă este nevoie, care să permită funcționarea în absența unor servicii așteptate.
Suport pentru COM și .Net: Pentru a sprijini atât platforma COM, cât și .Net, C# include o importantă facilitate a limbajului, numită atribute. Un atribut este de fapt o clasa C# care separă codul sursă pentru a oferi metainformație. Atributele facilitează suportul oferit de C# unor tehnologii specifice precum COM sau .Net fără a îngreuna specificațiile limbajului în sine.
De exemplu, C# pune la dispoziție clase de atribute care convertesc interfețe C# în interfețe COM. Altele convertesc clase C# în clase COM. Nu este nevoie de IDL sau de vreo fabrică de clase pentru a face aceste conversii. Altă bibliotecă de atribute oferită împreună cu compilatorul de C# împachetează clasele și funcțiile ca servicii Web. Un serviciu Web este un modul software găzduit care poate fi chemat prin internet folosind un protocol precum SOAP. SOAP împachetează apelări de metode, împreună cu parametrii și valorile returnate de acestea, în pachete de date XML. Serviciile Web pot fi scrise în multe limbaje și livrate pentru multe platforme software și hardware. Mai mult, mai multe servicii Web pot coopera și forma o întreagă aplicație Web. Folosind atributele corespunzătoare, un programator poate modifica cu ușurință orice clasă sau funcție C# într-un serviciu Web.
III.3.2. Facilități care nu se găsesc la C#
Multe din facilitățile pe care C# le folosește în aplicațiile Internet sunt alese din Delphi și Java. Totuși Microsoft pretinde ca C# descende din C și C++. Mai jos se prezintă câteva facilitați ale C++ care lipsesc din C#.
Scopul și dereferirea operatorilor: C# nu folosește operatorul de scop C++ (::), în schimb se bazează pe echivalentul din Delphi și Java, punctul (.). Mai mult, deoarece se bazează pe sistemul valoare/referință de tipul Delphi/Java, C# adesea nu folosește operatorul de dereferire din C++ (->). În schimb, implementează din nou punctul. În timp ce operatorul punct supraîncărcat poate aduce confuzie în rândul programatorilor de C++ care tocmai învață C#, le va fi familiar celor care au fost developeri Delphi sau Java.
Sintaxa declarării referinței: Deoarece clasele, interfețele și tipurile delegate sunt implicit referințe, la C# lipsește declarația de referințe de la C++. În schimb, noul limbaj folosește o sintaxă similară cu declararea din delphi a parametrilor transmiși prin referință:
un parametru nemarcat este parametru de intrare;
cuvântul cheie ref indică un parametru de intrare-ieșire (asemănător cu var-ul din Delphi);
cuvântul cheie out indica un parametru de ieșire;
cuvântul cheie params indică o listă de parametri de lungime variabilă.
Template-uri: La fel ca Java și Delphi, C# nu are template-uri. Prin urmare, nu are un mecanism pentru a sprijini declarația puternic tipizată de colecții. În schimb, fiecare clasă este în final derivată din clasa de bază comună object. O clasă generică de colecție trebuie să fie o colecție de objects, necesitând un downcast nesigur al membrilor ei spre tipul dorit.
Totuși, chiar fără aceste facilități ale limbajului C++, C# este un limbaj puternic, proiectat cu facilități asemănătoare Java și Delphi pentru a permite dezvoltarea de aplicații internet. Datorită orientării spre mașină, și a lipsei de suport RAD, C++ nu ar fi fost o bază potrivită pentru un limbaj menit să fie folosit la a dezvolta aplicații internet.
III.3.3 Exemplu de cod
În exemplul de mai jos vom arăta cum C# face uz de resursele sistemului de operare (folosind o funcție API, InternetGetConnectedState). Aplicația este folosită pentru a determina conectivitatea la internet a calculatorului gazdă.
using System ;
using System.Runtime ;
using System.Runtime.InteropServices ;
public class InternetCS
{
//Creating the extern function…
[DllImport("wininet.dll")]
private extern static bool InternetGetConnectedState( out
int Description, int ReservedValue ) ;
//Creating a function that uses the API function…
public static bool IsConnectedToInternet( )
{
int Desc ;
return InternetGetConnectedState( out Desc, 0 ) ;
}
}
III.4. HTML
III.4.1.1. Origini
Unul din primele elemente, fundamentale de altfel, ale WWW (World Wide Web) este HTML (HyperText Markup Language), standard ce descrie formatul primar în care documentele sunt distribuite și văzute pe Web. Multe din trăsăturile lui, cum ar fi independentă față de platformă, structurarea formatării și legăturile hipertext, fac din el un foarte bun format pentru documentele Internet și Web. Primele specificații de bază ale Web-ului au fost HTML, HTTP și URL.
III.4.1.2. Menire și semnificații
HTML a fost dezvoltat inițial de Tim Berners-Lee la CERN în 1989. HTML este un limbaj bazat pe SGML (Standard Generalized Markup Language), o așa-numită aplicație a acestuia. SGML este un standard internațional (ISO-8879) aprobat în 1986. HTML a fost inițial văzut ca o posibilitate pentru fizicienii care utilizează computere diferite să schimbe între ei informație prin mijlocirea Internetului. Erau prin urmare necesare câteva condiții esențiale: independență de platformă, posibilități hipertext și structurarea documentelor. Independența de platformă semnifică faptul ca un document poate fi afișat în mod asemănător (sau aproape identic) de computere diferite (deci cu font, grafică și culori aidoma), lucru vital pentru o audiență numeroasă și extrem de variată. Hipertext se traduce prin faptul că orice cuvânt, frază, imagine sau element al documentului văzut de un utilizator (client) poate face referință la un alt document sau chiar la paragrafe din interiorul aceluiași document, ceea ce ușurează mult navigarea între părțile componente ale unui document sau între multiple documente. Structurarea riguroasă a documentelor permite convertirea acestora dintr-un format în altul precum și interogarea unor baze de date înglobând aceste documente.
III.4.1.3. Începuturile
Născut în urma cu aproximativ 30 de ani, într-o tentativă de a rezolva unele probleme ivite la transportul documentelor între diferite computere, limbajul hipertext a evoluat încet. În primii ani de evoluție HTML a demarat lent în principal pentru ca îi lipseau posibilitățile de a reda publicații electronice profesionale; limbajul permitea oarece control asupra fonturilor dar nu permitea inserarea graficii. În 1993, NCSA a îmbogățit limbajul pentru a permite inserarea graficii și a construit primul navigator grafic: Mosaic. Au urmat apoi contribuții ad-hoc ale diverselor firme care au adus tot felul de adăugiri limbajului HTML astfel încât, în 1994, limbajul părea scăpat de sub control. Urmarea a fost ca la prima conferință WWW de la Geneva (Elveția) s-a constituit un grup de specialiști (HTML Working Group) a cărui prima misiune a fost formalizarea HTML, lucru care s-a concretizat în HTML 2.0. Importanța acțiunii acestui grup constă în faptul că, odată standardizat, limbajul a putut fi apoi extins într-un mod mai controlat la alte nivele.
III.4.1.4. Standardizarea
Standardul oficial HTML este dat de World Wide Web Consortium (W3C), care este afiliat la Internet Engineering Task Force (IETF). W3C a enunțat câteva versiuni ale specificației HTML, printre care și HTML 2.0, HTML 3.0, HTML 3.2, HTML 4.0 și, cel mai recent, HTML 4.01. În același timp, autorii de browsere cum ar fi Netscape și Microsoft, au dezvoltat adesea propriile "extensii" HTML în afară procesului standard și le-au încorporat în browserele lor. În unele cazuri (cum ar fi tagul Netscape), aceste extensii au devenit standarde de facto adoptate de autorii de browsere. Când navigatorul încarcă un document HTML, el "citește" documentul în căutarea tag-urilor HTML, formatează textul și imaginea și le afișează pe ecran. Este motivul pentru care același document HTML apare ușor diferit când este privit utilizând navigatoare diferite.
Motivul principal pentru care a fost preferat HTML pentru publicații pe Web, când pentru realizarea publicațiilor electronice există multe alte tehnologii, este simplitatea. Al doilea este că permite formatarea textului ASCII cu tag-uri în format ASCII. Rezultă de aici o compresie bună, suport pentru legături hipertext și ușurință în a scrie navigatoare pentru vizualizarea documentelor.
III.4.1.5. HTML 4.0, HTML 4.01
În acest moment, HTML 4.0 este larg utilizat și au fost deja publicate specificațiile HTML 4.01. Elementul esențial diferit adus de versiunea 4.0 și mai ales 4.01 față de versiunea 3.2 este posibilitatea separării structurii unui document de prezentarea lui prin introducerea „stilurilor de documente“ (style sheet). Utilizând limbajul HTML pentru structurarea unui document și style sheet-urile pentru a stiliza prezentarea acestuia, proiectanții pot obține mult mai ușor independență de periferic/computer/platformă hard-soft, lucru care a făcut HTML-ul atât de popular. Un document cu o structură complexă poate fi prezentat în diferite moduri pe medii diferite, permițând documentului însuși să se adapteze mai ușor noilor tehnologii (cum ar fi, de exemplu, browserele capabile să vorbească, cititoarele , etc.).
În plus, separarea conținutului de partea de prezentare permite modificarea înfățișării chiar a unui întreg site doar prin modificarea unui style-sheet (a unui document care descrie stilul). Experiența a demonstrat că o astfel de abordare poate reduce dramatic costurile de deservire a unui spectru larg de platforme și probleme, facilitând și o întreținere ulterioară și modificări mult mai ușoare.
III.4.2. JavaScript
JavaScript este un limbaj de scripting dezvoltat la origine de Netscape, permițând scrierea de secvențe de program care se execută la apariția unui eveniment utilizator. JavaScript este utilizat la ora actuală de majoritatea paginilor web din Internet pentru a îmbunătăți design-ul general, valida datele utilizator din formulare, adaugă interacțiune cu utilizatorul prin efecte speciale aplicabile elementelor de pagina în funcție de evenimentele generate de utilizator. La ora actuală este cel mai important limbaj de script de pe Internet. Trebuie să facem distincție între limbajul de programare Java și limbajul de scripting JavaScript. Spre deosebire de JavaScript, Java este un limbaj de programare considerat "de nivel înalt" (foarte apropiat de gândirea utilizatorului și nu de arhitectura calculatorului) care permite scrierea de aplicații de aproape orice tip și grad de complexitate.
III.4.3. Stiluri
Stilurile pun la dispoziția creatorilor de site-uri web noi posibilități de personalizare a paginilor HTML. Un stil reprezintă un mod de formatare exactă a unui bloc de text (spre exemplu anumite caracteristici pentru font, mărime, culoare, aranjare în pagină, distanțare față de margini etc).
Există două modalități de a defini un stil
sintaxa CSS (Cascading Style Sheets);
sintaxa Javascript.
Terminologia CSS – Cascading Style Sheets – desemnează "foi în stilul cascadă". În primul rând această denumire are la origine posibilitățile oferite de tehnică CSS. Practic, tehnologia CSS facilitează oricărui proiectant de pagini web posibilitatea de a cerea un stil pentru fiecare tag HTML întrebuințat la un moment dat, putând ulterior să aplice implicit acest stil în toate paginile site-ului pentru elementul de pagina respectiv (adică pentru tagul HTML stilizat).
Standardul CSS permite informațiilor cu privire la stil să fie specificate și referite în mai multe feluri. Stilurile pot fi specificate în interiorul fiecărui tag HTML în parte, în cadrul secțiunii HEAD a documentelor HTML sau într-un fișier extern cu extensia ".CSS". În interiorul aceluiași document HTML pot fi referite mai multe fișiere CSS externe.
La modul general putem afirma că toate stilurile utilizate pentru elementele HTML ale unei pagini web vor "cascada" într-un fișier de stil virtual atot cuprinzător, în care precedența diferitelor tipuri de stiluri aplicate tagurilor din pagină va fi următoarea (de la precedența cea mai mică la precedența cea mai mare):
Prima precedență: stilul specificat în setările browserului (exemplu în IE: View -> Text Size -> Largest);
A doua precedență: stilul specificat în cadrul setărilor din fișierul de stil extern;
A treia precedență: stilul intern specificat în secțiunea HEAD a documentului HTML;
A patra precedență: stilul intern specificat în cadrul tagului curent.
III.4.4. XHTML
XHTML (EXtensible HyperText Markup Language) practic este un înlocuitor modern al mai vechiului limbaj HTML, fiind aproape identic cu standardul HTML 4.01, o versiune îmbunătățită, mult mai strictă și mai curată a standardului HTML 4.0. Abstractizând puțin, se poate afirma că XHTML reprezintă o definire de tip XML a unui document HTML, pe scurt o combinație între HTML și XML. Avantajele unei aplicații XHTML sunt multiple: pot fi citite de toate dispozitivele XML, în timp ce păstrează compatibilitatea cu toate browserele de Internet mai vechi sau mai noi fără a necesita specificații suplimentare.
III.4.5. DHTML
DHTML nu este un standard (nu există fișiere cu extensia DHTML). DHTML este o denumire generică adoptată în unanimitate de proiectanții de pagini web, desemnând arta de a combina tehnologiile HTML, CSS și JavaScript pentru a realiza site-uri web cu adevărat interactive, adăugând o puternică notă de impact cu utilizatorul și efecte vizuale dintre cele mai spectaculoase.
III.5. XML
III.5.1. Fundamente
XML (EXtensible Markup Language) a fost proiectat pentru a manipula date în mod riguros. Ineditul pe care îl aduce limbajul XML este faptul că nu conține taguri standard (predefinite). Practic, tagurile XML sunt definite (construite) exclusiv de utilizator (proiectant). Este așadar un limbaj extensibil. Trebuie menționat faptul că standardul XML nu este decât într-un mod foarte general asemănător cu HTML. În timp ce standardul HTML urmărește afișarea datelor având ca obiectiv central modul în care acestea arată în browser, scopul XML este acela de a structura, stoca și transmite date sub formă de informații utilizator, având ca obiectiv central semnificația profunda a acestora. Intr-un cuvânt, HTML afișată informații, în timp ce XML descrie și manipulează informațiile în mod riguros. Atenție: XML nu este un înlocuitor pentru HTML. O evoluție previzibilă a web-ului sugerează o completare reciprocă a celor două standarde prin utilizarea împreună în cadrul acelorași documente: XML va fi utilizat pentru a descrie date, în timp ce HTML va formata și afișa corespunzător aceste date.
Prin date structurate înțelegem lucruri ca spreadsheets, liste de contacte, parametri de configurație, tranzacții financiare sau desene tehnice. XML este un set de reguli (sau convenții) pentru a crea formate text care îți permit să structurezi datele. XML nu este un limbaj de programare și nu trebuie să fii programator pentru a-l învăța și folosi. Cu XML, unui calculator îi este ușor să genereze și să citească datele, cât și să se asigure că structura datelor este corectă. XML evită problemele obișnuite ale limbajelor de programare: este extensibil, independent de platformă și suportă internaționalizarea și localizarea. XML este complet compatibil cu Unicode.
Dezvoltarea XML a început în 1996 și XML a devenit o recomandare W3C din Februarie 1998, ceea ce ne poate face să credem că este o tehnologie tânără. De fapt, această tehnologie nu e chiar atât de nouă. Înaintea XML-ului a fost SGML, creat la începutul anilor '80, standard ISO din 1986, și folosit pe scara largă pentru proiecte de documentație mari. Dezvoltarea HTML a început în 1990. Designerii XML-ului au preluat cele mai bune parți din SGML, folosind și experiența oferită de HTML, și au produs ceva nu mai puțin puternic decât SGML, dar cu mult mai regulat și mai ușor de folosit.
Ca și HTML, XML folosește tags-uri (cuvinte cuprinse în '<' și '>') și atribute (de forma nume="valoare"). Pe când HTML specifică ce înseamnă fiecare tag și atribut, și deseori cum va apărea textul marcat cu acestea în browser, XML folosește taguri doar pentru a delimita bucăți de date, lăsând interpretarea acestor date cu totul în seama aplicației care le citește. Cu alte cuvinte, dacă întâlnim "<p>" într-un fișier XML, nu trebuie să presupunem că este un paragraf. În funcție de context, poate fi un preț, un parametru, o persoană (sau un cuvânt care nici măcar nu începe cu p).
Programe care produc spreadsheets, liste de contacte și alte tipuri de date structurate deseori păstrează datele pe hard, folosind un format binar sau text. Un avantaj al formatului text este că permite utilizatorului, dacă este necesar, să vizualizeze fișierul fără a folosi programul care l-a produs. Adică putem citi datele (textul) cu editorul de text preferat. De asemenea, formatul text face debugging-ul mai ușor pentru developeri. Ca și HTML, fișierele XML sunt fișiere pe care utilizatorii nu sunt obligați să le citească, dar pot face acest lucru dacă au nevoie. Comparat cu HTML, regulile XML permit mai puține variații. Un tag uitat sau un atribut fără ghilimele face un fișier XML inutilizabil, pe când în HTML acest lucru este permis. Specificația XML interzice unei aplicații să încerce să ghicească ce a vrut să facă creatorul unui fișier XML greșit. Dacă apare o greșeală, aplicația trebuie să oprească citirea și să raporteze o eroare.
Deoarece XML este un format text și folosește taguri pentru a delimita datele, fișierele XML sunt aproape întotdeauna mai mari decât formatele binare. Designerii XML au luat această decizie pentru motive bune. Avantajele formatului text sunt evidente, iar dezavantajele pot fi de obicei compensate la un alt nivel. Spațiul pe disk este mai ieftin decât era în trecut. Programe de compresie ca zip și gzip pot comprima fișierele foarte bine și foarte rapid. În plus, protocoluri de comunicare ca protocolul modem și HTTP/1.1, protocolul de bază al web-ului, pot comprima datele din mers, economisind bandwidth-ul la fel de bine ca formatul binar.
Există o importantă aplicație XML care are format de document: XHTML, succesorul HTML-ului. XHTML are multe din elementele HTML-ului. Sintaxa a fost schimbată un pic pentru a corespunde regulilor XML. Un format bazat pe XML moștenește sintaxa XML și o constrânge în mai multe feluri (spre exemplu, XHTML permite folosirea "<p>", dar nu a "<r>"); totodată, se adaugă înțeles sintaxei (XHTML spune că "<p>" înseamnă "paragraph", și nu "preț", "persoană" sau altceva).
XML permite să se definească un nou format de document combinând și refolosind alte formate. Deoarece cele două formate pot folosi elemente sau atribute cu același nume, trebuie să se aibă la combinarea lor (înseamnă "<p>" "paragraf" dintr-un format, sau "persoana" din celalalt format?). Pentru a elimina confuzia, XML are un mecanism numit namespace (domenii pentru nume). XSL si RDF sunt exemple de formate bazate pe XML care folosesc namespace-uri. XML Schema este conceput cu acest suport pentru modularizare. Această modularizare la nivelul definirii unui document XML face posibilă combinarea a doua scheme pentru a forma o a treia, care definește un document combinat (combinație de documente definite de cele două scheme inițiale).
A folosi XML este asemănător cu a alege SQL pentru baza de date: tot trebuie să ne construim baza de date și programele (și procedurile) care ne permit să o folosim, dar există și multe unelte gata făcute și o multitudine de oameni care ne pot ajuta. Și pentru că nu trebuie licență pentru a folosi XML, nu trebuie să plătim nimic nimănui. Comunitatea mare de persoane care folosesc XML înseamnă că nu depindem de un sigur producător. Deși XML nu este întotdeauna cea mai bună soluție, se merita cel puțin să îl considerăm printre opțiuni.
III.5.2. XSL
Practic, XSL (EXtensible Style Language) reprezintă pentru documentul XML ceea ce reprezintă CSS pentru HTML, adică o foaie de stiluri. Diferența dintre CSS (HTML Style Sheets) și XSL (XML Style Sheets) este foarte mare. HTML utilizează taguri (marcaje) predefinite și semnificația acestora este de la bun început cunoscută și înțeleasă de browser. Spre exemplu, tagul <TABLE> definește un tabel, iar browserul știe ce este acesta și cum trebuie afișat. Adăugând stiluri fișierului HTML vom indica browserului să afișeze un element de pagina (precum tabelul exemplificat mai sus) într-un anumit mod, uzând de data aceasta de atribute CSS predefinite – indicând, spre exemplu, margine de dimensiune 1 și culoare albastră. În schimb XML nu lucrează cu taguri predefinite (se știe că se poate defini câte taguri personalizate dorim). Așadar, semnificația tagurilor XML utilizate de proiectant nu este cunoscută browser-ului. Tagul <TABLE> în XML poate desemna, într-adevăr, un tabel, la fel de bine ca și un formular sau un obiect abstract iar browserul nu va ști cum să-l afișeze. De aceea trebuia să existe o componentă adițională documentelor XML care să traducă browserului modul în care un document XML va fi afișat. Și aceasta este XSL. Totuși, XSL este mai mult decât un standard de stiluri pentru documentele XML. Practic, XSL se constituie din 3 parți componente: XSLT, care este un limbaj menit să transforme documentele XML în documente XHTML; XPath care este un limbaj menit să definească și să izoleze porțiuni din documentele XML; XSL-FO, practic un limbaj de formatare (structurare) superioară a documentelor XML.
III.6. Microsoft SQL Server 2000
SQL Server 2000 este un sistem de gestiune al bazelor de date performant, prezentând un nivel ridicat de scalabilitate și posibilități de adaptare la cerințele diverselor categorii de utilizatori. Având în vedere tehnologiile și instrumentele integrate, SQL Server 2000 determină reducerea timpului necesar pentru dezvoltarea aplicațiilor care necesită integrarea suportului pentru bazele de date. În acest sens, realizarea unor arhitecturi bazate pe SQL Server simplifică dezvoltarea soluțiilor Web complexe, a aplicațiilor tradiționale, oferind totodată posibilități avansate de organizare a informațiilor în depozitele de date. Implementarea acestei soluții simplifică substanțial procesele de administrare și oferă un nivel ridicat de securitate.
Limbajul SQL a fost dezvoltat într-un prototip de sistem de management a bazelor de date relaționale – System R – de IBM la mijlocul anilor 1970. În 1979, Corporația Oracle introduce prima implementare a SQL în varianta comercială.
La început sistemele de management a bazei de date a utilizat un limbaj separat pentru fiecare categorie în parte. SQL le-a unificat pe toate acestea într-un singur limbaj. SQL a devenit un limbaj standard industrial pentru bazele de date relaționale.
Institutul National American de Standarde (ANSI) a adoptat SQL ca limbaj standard pentru RDBMS în anul 1986. Organizația Internațională de Standarde (ISO) a adoptat deasemenea SQL ca limbaj standard pentru RDBMS. Toate RDBMS-urile suportă unele forme de SQL și toți vânzătorii de RDBMS intenționează să se alinieze la standardele ANSI.
III.6.1. Scalabilitate și performanță
SQL Server 2000 oferă un nivel deosebit de scalabilitate, răspunzând în acest mod la cerințele diverselor categorii de utilizatori. Cele șapte ediții ale SQL Server oferă suportul bazelor de date pentru o gamă variată de aplicații, începând cu soluțiile dedicate dispozitivelor mobile și încheind cu sistemele informatice mission critical. În acest sens, se distinge ediția SQL Server Enterprise (64 bit) Edition care poate fi integrată în arhitecturi de până la 64 de procesoare și poate adresa un maxim de 512 GB RAM.
III.6.2. Suport extins pentru XML
XML constituie modalitatea cea mai simplă și, totodată, cea mai eficientă prin intermediul căreia datele pot fi transferate folosind rețelele locale și Internet-ul.
SQL Server 2000 integrează suport complet pentru XML. Astfel, este asigurată o modalitate eficientă de transfer a datelor și posibilități de integrare în mediile care presupun existența unor sisteme informatice eterogene.
Versiunea 2000 integrează tehnologiile XPath și URL Query, simplificând procesele de transfer a datelor în format XML. De asemenea, limbajul procedural Transact SQL (T-SQL) a fost întregit cu noi funcții care facilitează aceste operațiuni. Prin noua clauză OpenXML, specifică instrucțiunii SELECT, este automatizat transferul datelor din modelul relațional (caracteristic bazei de date) în cel ierarhic (specific limbajului XML), fiind asigurate mijloace pentru sincronizarea permanentă a celor două modalități de organizare a informației.
III.6.3. Simplificarea administrării.
SQL Server 2000 reduce eforturile solicitate pentru administrarea și configurarea bazei de date. În acest sens, sunt disponibile instrumente grafice de configurare și experți tip wizard pentru realizarea diverselor operațiuni de administrare.
Pentru dezvoltatori, noile funcționalități integrate în limbajul Transact-SQL contribuie la reducerea substanțială a eforturilor necesare pentru realizarea aplicațiilor tradiționale sau a celor orientate spre Web.
De asemenea, integrarea cu mediul de dezvoltare Visual Studio .NET contribuie la reducerea dramatică a timpului alocat pentru dezvoltarea și testarea aplicațiilor care solicită suport pentru bazele de date.
III.6.4. Securitate ridicată a datelor
Având în vedere posibilitățile de accesare a aplicațiilor cu suport pentru bazele de date prin intermediul Web-ului, SQL Server 2000 introduce importante îmbunătățiri la capitolul securitate.
În acest sens, au fost integrate instrumente pentru monitorizarea și auditul de securitate al serverelor, o gestiune eficientă a rolurilor și profilelor, precum și posibilități de tratare a principalelor evenimente de securitate care pot apărea în exploatarea acestei soluții.
De asemenea, versiunea 2000 extinde conceptul “out of the box” în ceea ce privește securitatea. SQL Server 2000 este preconfigurat pentru a oferi nivelul maxim de securitate după instalare, permițând astfel implementarea simplă și rapidă a serverului.
III.6.5. Integrarea cu alte soluții și servere
SQL Server 2000 prezintă un nivel deosebit de integrare cu alte soluții și servere. Sunt de menționat posibilitățile de integrare cu BizTalk Server și Commerce Server.
De asemenea, este de remarcat nivelul ridicat de integrabilitate cu soluțiile disponibile în noul Microsoft Office System. Astfel, Access 2003 poate fi utilizat pentru dezvoltarea aplicațiilor care să exploateze bazele de date SQL Server, precum și pentru realizarea de rapoarte și grafice pe baza informațiilor furnizate Analysis Services.
IV.1. Limbaje de programare
Platforma Microsoft ASP.NET 2.0 oferă suport pentru mai multe limbaje: C#, Visual Basic, J#, etc. Mai mult decât atât, în același proiect se pot folosi scripturi din două sau mai multe limbaje.
Un exemplu de astfel de îmbinare de cod este moștenire unei clase scrisă în Visual Basic, de exemplu, de către o clasă scrisă în C#. Trebuie însă remarcat că nu se poate folosi cod din două sau mai multe limbaje în același fișier. Astfel, pentru exemplu considerat trebuie să creem separat în partea de cod a aplicației două directoare, unul în care vor fi incluse fișierele .cs, fișiere care conțin cod C#, și celalalt în care vor fi incluse fișierele .vb, fișiere care conțin cod Visual Basic. Acest lucru trebuie semnalat în fișierul de configurare al proiectului, astfel:
După ce am adăugat în directorul de C# un fișier în care am scris o clasă, CukooBase de exemplu, putem să o moștenim în fișierul Visual Basic:
În cadrul proiectului am folosit scripturi scrise în C#, în cadrul implementării pe partea de server, și scripturi scrise în JavaScript, în cadrul implementării pe partea de server. Spre deosebire de ASP, care folosea cod scris în VBScript, în ASP.NET se folosește codul Visul Basic full. În plus, suportă scripturi C#. Ca și în ASP, în ASP.NET sunt suportate scripturile JScript.
Codul C#, sau orice alt script, în cadrul unei pagini ASP.NET poate să fie prezent în același fișier cu codul ASP.NET sau în fișier separat. În cadrul fiecărei pagini ASP.NET trebuie precizat limbajul de scriptare folosit prin atributul Language al elementului Page. Dacă se dorește o inserare a codului în cadrul aceluiași fișier atunci se va folosi tagul <script> și se va preciza, prin atributul runat, ca acest script va fi rulat pe server. Acest lucru este necesar deoarece în caz contrar nu se va putea face diferența între scripturile scrise pentru partea de server, ca acestea, și cele scrise pe partea de client, de exemplu cele scrise în javascript.
Iată un exemplu de cod C# inclus în același fișier cu codul ASP:
<%@ page language="C#" %>
<script runat="server">
void Button1_Click(object sender, EventArgs e)
{
Label1.Text = "Hello " + TextBox1.Text;
}
</script>
<html>
<head>
<title>ASP.NET Inline Pages</title>
</head>
<body>
<form id="Form1" runat="server">
<h1>Welcome to ASP.NET 2.0!</h1>
<b>Enter Your Name:</b>
<asp:TextBox ID="TextBox1" Runat="server"/>
<asp:Button ID="Button1" Text="Click Me" OnClick="Button1_Click" Runat="server"/>
<br />
<br />
<asp:Label ID="Label1" Text="Hello" Runat="server" />
</form>
</body>
</html>
În cadrul proiectul s-a uzat de cealaltă modalitate, și anume s-a preferat păstrarea codului într-un fișier separat. Această modalitate este nouă în ASP.NET 2.0 și are marele avantaj al păstrării codului C# la un loc făcând mentenanță mult mai ușoară. Astfel pentru fiecare pagina se creează o clasă nouă al cărei nume trebuie specificat prin atributul Inherits al elementului Page. Trebuie menționat ca membrii acestei clase trebuie să fie public sau cel puțin protected (nu se acceptă membri private).
Se prezintă exemplul codului scris pentru butonul de search în pagina de search a aplicației.
<asp:Button ID="SearchButton" runat="server"
OnClick="SearchButton_Click" Text="Search" />
Se observă că atributul OnClick are setat să apeleze funcția SearchButton_Click, funcție a cărei implementare se găseste în fișierul de cod:
protected void SearchButton_Click(object sender, EventArgs e)
{
string s;
int[] a;
s = SearchFirstNameTextBox.Text;
if(s.Length == 0)
s = "%";
dsSearchResult.SelectParameters["firstName"].DefaultValue = s;
s = SearchLastNameTextBox.Text;
if (s.Length == 0)
s = "%";
dsSearchResult.SelectParameters["lastName"].DefaultValue = s;
a = SearchMainProgramListBox.GetSelectedIndices();
if(a.Length == 0)
s = "%";
else
{
s = "(";
for (int i = 0; i < a.Length; i++)
{
s += SearchMainProgramListBox.Items[Convert.ToInt32(a.GetValue(i))].Value;
if(i < a.Length-1)
s += ",";
}
s += ")";
}
dsSearchResult.SelectParameters["mainProgramIDs"].DefaultValue = s;
a = SearchStatusListBox.GetSelectedIndices();
if (a.Length == 0)
s = "%";
else
{
s = "(";
for (int i = 0; i < a.Length; i++)
{
s += SearchStatusListBox.Items[Convert.ToInt32(a.GetValue(i))].Value;
if (i < a.Length – 1)
s += ",";
}
s += ")";
}
dsSearchResult.SelectParameters["statusIDs"].DefaultValue = s;
a = SearchSubprogramListBox.GetSelectedIndices();
if (a.Length == 0)
s = "%";
else
{
s = "(";
for (int i = 0; i < a.Length; i++)
{
s += SearchSubprogramListBox.Items[Convert.ToInt32(a.GetValue(i))].Value;
if (i < a.Length – 1)
s += ",";
}
s += ")";
}
dsSearchResult.SelectParameters["subProgramIDs"].DefaultValue = s;
try
{
if (Convert.ToInt32(SearchRecordsPerPageTextBox.Text) > 0)
{
SearchGridView.AllowPaging = true;
SearchGridView.PageSize =
Convert.ToInt32(SearchRecordsPerPageTextBox.Text);
}
else
{
SearchGridView.AllowPaging = false;
}
}
catch (Exception)
{
SearchGridView.AllowPaging = false;
}
}
Acest cod se va rula pe server deoarece controlul Button are setat atributul runat=server. De asemenea în cadrul funției sunt disponibile informații despre elementul care a apelat funcție, cât și de evenimentele care au loc prin paramentrii transmiși.
În ceea ce priveste scripturile pe partea de client s-a folosit javscript. Javascript este la ora actuală cel mai bun limbaj de scriptare pe partea de client.
Pentru a include cod javascript în cadrul unui fișier ASP există două modalitați (ca și în cazul includerii codului de javascript în cadrul unui fițier HTML). Prima variantî este includerea inline a codului. Aceasta se realizează cu ajutorul tagului <script> al cărui atribui laguage va primii valoare javascript. Iată un exemplu:
<script language=javascript>
function OpenPopupPage (pageUrl, MemberID)
{
window.open(pageUrl + '?member=' + MemberID, 'popupcal', 'scrollbars=yes, width=570, height=700, left=100, top=0');
}
</script>
………………
<a href="javascript:OpenPopupPage ('CV.aspx', '<%# Eval("pk_ID") %>')">
<asp:Label ID="SearchFirstNameLabel" ToolTip="Last Name" runat="server"
Text='<%# Eval("Lastname") %>'>
</asp:Label>
</br>
<asp:Label ID="SearchLastNameLabel" runat="server" ToolTip="First Name"
Text='<%# Eval("FirstName") %>'>
</asp:Label>
</a>
Se observa ca elementul a nu are un atrubut runat. Acest lucru este valabil de fapt pentru toate elementele HLML. Astfel se poate folosi jvascript ca si in cadrul unor fisiere HTML obisnuite. O problema speciala apare atunci can se doreste setarii unui atribut al unui element ASP deoarece acestea nu au atributele de evenimnte ale elementelor HTML. Totusi acestea pot fi fortate sa apeleze cod javascript, desi compilatorul ne avertizeaza asupra acestui fapt.
In cadrul proiectului s-a preferat pastrarea codului javascript intr-un fisier separat. Aceasta este o alta modalitate de a include codul javascript. Pentru aceasta trebuie inclus in headerul paginii tagul script cu atributul laguage=javascript si atributul src va fi setat drept fisierul in care este prezent codul javascript.
<script language=javascript src="script.js"></script>
Exemplu de cod:
//fisierul script.js
……………
function Disabled(ID1)
{
document.getElementById(ID1).disabled = false;
}
…………
//fisierul peronal.aspx.cs
…………
protected void OtherSkillsGridView_RowDataBound(object sender,
GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
Button bAdd =
(Button)(e.Row.FindControl("SetNotAvailableButton"));
ListBox lAvailable =
(ListBox)(e.Row.FindControl("SkillsAvailableListBox"));
lAvailable.Attributes.Add("onclick", "javascript:Disabled('" +
bAdd.ClientID + "')");
bAdd.Attributes.Add("disabled", "true");
Button bRemove =
(Button)(e.Row.FindControl("SetAvailableButton"));
ListBox lNotAvailable =
(ListBox)(e.Row.FindControl("SkillsMemberListBox"));
lNotAvailable.Attributes.Add("onclick", "javascript:Disabled('" +
bRemove.ClientID + "')");
bRemove.Attributes.Add("disabled", "true");
}
}
………
Se observă că de această dată a fost adăugat (la inițializare) atributul onclick care va apela o funcție javascript. Trebuie precizat faptul că javascript trebuie să apară obligatoriu în fața funției deoarece, în caz contrat nu se va știi dacă e vorba de o funcție C# (sau orice alt limbaj de scriptare pe partea de server) sau de o funcție javascript deoarece acest atribut este un atribut al unui control ASP. De fapt la rulare se va incerca (daca javascript lipsește) să se execute funția cu același nume dar scrisă în limbajul de scriptare de pe server, iar în cazul în care nu va fi gasită se va semnala eroare.
IV.2. Master Pages
"Master pages" reprezintă un concept cerut de comunitatea de programatori .NET încă de la prima versiune de ASP.NET. Până acum, un dezvoltator de pagini web, de fiecare data când dorea să replice anumite părți ale unei pagini într-o pagina noua (de ex. avea un heder, un footer si un meniu care trebuia replicat pe toate paginile site-ului), avea la dispoziție 2 cai principale:
calea muncitoreasca: făcea un binecunoscut copy-paste între cele 2 pagini (dezavantaj major în momentul în care trebuia modificat header-ul site-ului din anumite motive => toate paginile trebuiau refăcute);
calea ceva mai eficienta: își crea unul sau mai multe "UserControl" pe care le "arunca" apoi pe pagina web nou creata (aceasta calea avea avantajul ca, în momentul modificării controlului de heder de exemplu, modificările erau reflectate în toate paginile care foloseau acel control).
În cazul ASP.NET 2.0, dezvoltatorul trebuie mai întâi sa creeze o pagina Master (Master Page), care sa conțină toată funcționalitatea de bază care trebuie replicată mai apoi în paginile următoare. În cadrul acestei pagini Master, va introduce apoi controale de tipul ContentPlaceHolder, pentru a defini zonele în care paginile derivate își vor defini conținutul. Din aceste pagini derivate, pagina Master poate fi referita prin directiva:
<%@ Page MasterPageFile="~/Trial.master" %>
În aceste pagini derivate, trebuiesc folosite controale de tip Content pentru a umple controalele de tip ContentPlaceHolder, despre care am vorbit mai sus. În același timp, o aplicație web își poate defini o pagina Master implicita pentru toate paginile sale în fișierul web.config astfel:
<configuration>
<system.web>
<pages masterPageFile="~/Default.master" />
</system.web>
</configuration>
Master Pages au extensia .master si pot conține orice conține o pagina ASP.NET uzuala . Ceea ce e diferit e ca pot sa conțină unul sau mai multe controale . Acestea indica regiune de conținut înlocuibil in implementarea specifica a fiecărei pagini diferite.
In implementarea in parte a fiecărei pagini care se dorește a fi un content page, trebuie specificata pagina master.Bineinteles se poate face nesting . Adică multiple nivele de master – details. Si peste toate , existe suport in design mode.
Pagina construita pentru proiect conține doua controale de tip ContentPlacerHoder:
Aceasta pagina va fi folosita in aproape toate paginile aplicației. Iată si cum arata si o pagina care folosește acest Master Page:
Se observa ca in Content-ul din stânga a fost introdus un meniu, iar in cel din dreapta informația specifica. De asemenea Pentru fiecare pagina in parte se pot folosi alte stiluri: colori, fonturi, mărimi, etc. Un mare avantaj al acestui concept este ca se poate ignora informația dintr-un Content. Iată un exemplu in care nu am avut nevoie de meniul din stânga, deoarece membrii de tip contact nu au drepturi de vizualizare decât asupra tagului de search. In consecința la încărcarea paginii i se va afișa pagina de search iar restul paginilor nu vor mai putea fi accesate deoarece meniul din stânga nu va mai apărea. Astfel informația din acesta nu mai este vizibila.
De asemenea in cazul paginii de logare nu mai este nevoie de meniul din partea stanga:
Master Page-ul este construit aproape ca o pagina HTML (conține un heder si un body). In heder se poate specifica un titlu generic al paginii, acesta putând sa fie modificat daca este necesar. De asemenea se por specifica eventualele scripturi si link-uri:
<head runat="server">
<title>Siemens Student Program</title>
<link href="images/icon.ico" rel="SHORTCUT ICON" />
<script language=javascript src="script.js"></script>
</head>
In cadrul tagului <body> este necesara prezenta unui tag <form> care va fi executat pe serverul de ASP (va avea atributul runat = ”server”). De asemenea tagul body poate avea atributele obișnuite HTML, iar in interior pot fi prezente controale de tip HTML sau ASP rulate pe server sau nu. Tot in cadrul corpului paginii vor fi inserate unul sau mai multe controale de tip ContentPlaceHolder In care va fi pusă informația diferita in cadrul paginilor care vor moștenii aceasta pagina.
O alta facilitate este aceea ca in cadrul paginilor care moștenesc un Master Page se pot accesa elementele paginii master. De asemenea se pot construi pagini master care pot moștenii alte paginii master. Astfel putem structura paginile astfel in cat sa construim o pagina master principala, care sa conțină structura de baza a site-ului, adică doar elementele care sunt comune tuturor paginilor din cadrul aplicației, după care se por construi alte paginii master care se derivează din aceasta si in plus introduc alte părți comune unui departament, de exemplu.
Master Pages este o noua facilitate in ASP.NET care permite crearea unei pagini template si folosirea acesteia mai departe ca punct de pornire in design-ul celorlalte pagini din cadrul aplicației . Un lucru foarte eficient, daca luam chiar si un exemplu simplu , adică scenariul când fiecare pagina trebuie să conțină același heder , sau footer, sau ambele.
IV.3. Teme si skin-uri
ASP.NET 2.0 introduce conceptele de "skin" si "theme", prin care felul în care arata o pagina poate fi modificat atât static (în timpul creării paginii), cât si dinamic (în timpul rulării aplicației web). Un "skin" reprezintă un set de atribute vizuale ale unui control. Un "theme" reprezintă o colecție de skin-uri. Exista predefinite o serie de teme (cu skin-urile aferente), care pot fi găsite în directorul (si subdirectoarele din): Microsoft.NET\Framework\…\ASP.NETClientFiles\Themes. Pentru a folosi o astfel de tema, în pagina respectiva se introduce atributul "Theme" în directiva page astfel:
<%@ Page Theme="SmokeAndGlass" %>
Temele mai pot fi modificate si programatic, la rularea aplicației, prin manipularea din cod a proprietății "Theme" a obiectului "Page". Se pot defini si teme personalizate, care pot fi stocate într-un subdirector al directorului Theme din rădăcina structurii de directoare a aplicației web. Regula ce trebuie respectata este ca numele subdirectorului sa fie identic cu numele temei.
Se observa in figura ca sunt definite doua teme: “Default” si “MyThemes”. In interiorul temei se pot include oricâte fișiere .css sau .skin. Intr-o pagina nu se poate folosi decât o singura tema dar aceasta tema poate fii schimba prin cod. La momente de timp diferite se pot folosi teme diferite. Acesta e un mare avantaj pentru design-ul paginilor deoarece se pot concepe diferite interfețe care apoi pot fi ușor configurate pentru fiecare client in parte.
Exista doua posibilități de a include teme intr-o pagina asp. Prima varianta este de a seta parametrul “Theme” al paginii cu numele temei dorite. Setând in acest fel nu mai exista posibilitate redefinirii proprietăților controalelor in interiorul paginii. Cealaltă varianta este de a seta parametrul “StylesheetThemes” cu numele temei respective. In acest caz se pot supradefinii proprietățile controalelor.
Daca se vor folosi cele doua proprietăți împreuna trebuie sa se tina cont de următoarea observație: tema care apare in “Theme” suprascrie tema din “StylesheetThemes”. In schimb daca o proprietate a controlului este suprascrisa in interiorul paginii si aceasta proprietate este definita si in tema din “StylesheetThemes” aceasta proprietate va primi atributul din “StylesheetThemes” chiar daca a fost definita si in “Theme”.
IV.3.1. Foi de stil in cascada (CSS)
Ca si o pagina web, o foaie de stil in cascada consta din instrucțiuni de tip text ASCII care ii spun browser-ului cum sa formateze documentul care se încarcă. Instrucțiunile CSS pot fi plasate chiar in cadrul respectivei pagini web, sau se pot afla intr-un document separat care este legat de pagina HTML.
Iată un exemplu inserat in cadrul secțiunii HEAD a unei pagini web:
<style type="text/css">
<!–
.body
{
margin-bottom: 0pt;
margin-left: 0pt;
margin-right: 0pt;
margin-top: 0pt;
font-family: Arial;
font-size: 12px;
}
–>
</style>
Aceasta este una din modalitățile de includere a CSS-urilor. O alta modalitate, mult mai uzitata, este de a include intr-un fișier separat, de tip .css, toate aceste proprietății. După aceasta se specifica in hederul paginii despre care din fișierele css este vorba. Pot fi incluse unul sau mai multe fișiere de acest tip. De asemenea aceste fișiere se pot include intr-o tema care v-a fi apoi inclusa in pagina (incluse in tema care este inclusa in pagina).
Intr-un browser care înțelege foile de stiluri in cascada, codul de deasupra va face ca pagina sa aibă culoarea de fundal alba si textul negru. Textul va fi afișat folosind ori fontul Arial, ori Helvetica, iar in cazul in care niciunul nu este disponibil va fi folosit un font din familia "sans serif". Codul are exact același efect cu o eticheta BODY care are atributele "background" si "text", urmata de o eticheta FONT.
Se pune întrebarea fireasca de ce am păstra date in CSS daca exista posibilitatea de a specifica aceste proprietăți in cadrul codului ASP. Principalul motiv invocat de apărătorii CSS este ca acesta permite sa ți elementele de formatare separate de elementele funcționale.
De exemplu, etichetele <H1></H1> (si restul familiei) sunt destinate a fi folosite in cadrul titlurilor. Când scrii un text intre aceste doua etichete, acesta devine imediat un titlu. Totuși, unora dintre designerii web nu le plac tipul si mărimea fonturilor implicite si vor recurge la construirea titlurilor folosind etichetele <FONT></FONT>. Rezultatul va fi ca paginile vor arata dezordonate, iar orice schimbare vor face la unul dintre titluri va trebui aplicata tuturor celorlalte titluri.
Cu foile de stil in cascada, daca se dorește ca toate titlurile H1 sa folosească un font "sans serif" cu dimensiunea de 24 de puncte, doar vei pune fragmentul următor de cod
H1 {
font-face: sans-serif ;
font-size: 24pt ;
}
intre etichetele CSS. De fiecare data când vei folosi eticheta H1, browser-ul va alege un font "sans-serif" cu dimensiunea 24. Răzgândește-te in legătura cu aceste amănunte si va trebui sa faci o singura modificare, in foaia de stil in cascada si nu in întregul document.
Problema nu sta in CSS in sine, ci in faptul ca nu oricine are un browser compatibil cu foile de stil in cascada. Numai ultimele versiuni ale Netscape si Internet Explorer (versiunile 4 sau mai noi) si Opera suporta CSS. Deoarece inca mai exista oameni care folosesc browsere vechi, frumoasa ta formatare a unei pagini poate sa nu fie vazuta de acestia cand vor incarca pagina ta creata cu ajutorul CSS.
ASP.NET pune la dispoziție pentru controale proprii proprietatea CSSClass pentru folosirea stilurilor definite. De asemenea, având in vedere ca ASP.NET interpretează codul si îl trimite la client ca fiind un cod HTML, multe din controalele ASP au un corespondent HTML. De exemplu, un control TextBox din ASP.NET se va transpune intr-un control de tip input cate are type=”text”. Cu toate acestea ASP.NET nu pune exact la dispoziția dezvoltatorului aceleași proprietăți pe care HTML le oferă. Totuși aceste proprietăți pot fi adăugate prin cod.
Iată un exemplu in care se dorește ca butonul de adăugare a skill-urilor sa fie dezactivat atât timp cat utilizatorul nu a selectat unul in elementele listei cu skill-uri disponibile:
protected void OtherSkillsGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
Button bAdd = (Button)(e.Row.FindControl("SetNotAvailableButton"));
ListBox lAvailable = (ListBox)(e.Row.FindControl("SkillsAvailableListBox"));
lAvailable.Attributes.Add("onclick", "javascript:Disabled('" + bAdd.ClientID + "')");
bAdd.Attributes.Add("disabled", "true");
Button bRemove = (Button)(e.Row.FindControl("SetAvailableButton"));
ListBox lNotAvailable = (ListBox)(e.Row.FindControl("SkillsMemberListBox"));
lNotAvailable.Attributes.Add("onclick", "javascript:Disabled('" +
bRemove.ClientID + "')");
bRemove.Attributes.Add("disabled", "true");
}
}
Se observa ca s-a setat atributul disabled. ASP.NET nu oferea acest atribut. De aceea a fost necesara setare prin cod.
IV.3.2. Skin-uri
Skin-urile sunt definiții ale controalelor care păstrează anumite proprietari ale acestora care vor fi comune mai multor controale de același tip.
Exemplu:
<asp:TextBox
runat="server"
Font-Size=".9em"
Font-Names="Arial"
ForeColor="#585880"
BorderWidth="1pt"
BorderColor="transparent"
BackColor="#FFFFFF"
/>
Se pot defini o mai multe proprietăți ale controlului. Toate controalele de acest tip vor avea aceste proprietăți. De asemenea se pot împărții in categorii definindu-se un SkinID care va fi specificat apoi de fiecare din controalele care vor fi din aceasta categorie.
Exemplu:
In fisierul Default.skin:
……………….
<asp:Label
runat="server"
Font-Names="Arial"
Font-Size="8pt"
/>
<asp:Label
SkinID="AnotherLabel"
runat="server"
Font-Names="Arial"
Font-Size="14pt"
ForeColor="#000066"
/>
<asp:Label
SkinID="LargeLabel"
runat="server"
Font-Names="Arial"
Font-Size="10pt"
/>
…………………………
in fisierul Personal.aspx:
…………………..
<asp:Label ID="Label2" runat="server" Text='<%# Bind("MemberID") %>'>
……………………
<asp:Label ID="SkillsCategoryLabel" runat="server" Text='<%# Bind("SkillsCategory") %>' Font-Bold="True" Font-Overline="False" SkinID="AnotherLabel"></asp:Label>
…………………..
Primul dintre cele doua Label-uri nu are setat atributul SkinID. In consecința acesta va avea proprietățile specificate in skin-ul care nu are specificat SkinID. Cel de-al doilea are acest atribut setat si ca atare va avea proprietățile specificate in acest SkinId.
Se pot definii numai anumite proprietăți altele putând fi lăsat nespecificate pentru a putea fi personalizate mai târziu in codul ASP.
In funcție de tipul de includere a temei se pot suprascrie aceste proprietăți sau nu.
IV.4. Utilizatori
Accesul la aplicație este restricționat. Deoarece este vorba de informații personale singurii care au acces sunt studenții din cadrul programului (deoarece se ține evidența acestora și aceste date nu vor fi șterse imediat după ce stagiul va lua sfârșit pot avea acces toți cei care au participat de-alunul anilor la acest program). De asemenea mai există o categorie specială de utilizatori și anume cei care intră în contact cu acești studenți. Acești utilizatori au în schimb un acces restricționat, și anume nu pot vedea decât câteva date despre fiecare din cei care sunt înregistrați ca membrii.
Utilizatorii de tip membru au acces la informațiile în baza de date, pe care le pot și modifica. Există însa câteva date pe care nu pot să le modifice (ca de exemplu nume de familie și data de naștere), date care pot fi modificate numai de administratorului bazei de date, și care sunt introduse atunci când acest candidat capătă acest cont.
IV.4.1. Autentificare
În ASP.NET 2.0 există controale care încapsulează toată funcționalitatea necesară pentru a controla accesul utilizatorilor în aplicația web. Astfel, programatorul este degrevat de "povara" implementării unui sistem de autentificare, putându-se concentra mai mult pe implementarea funcționalitățiilor cu adevărat utile pentru un potențial vizitator. Unul din aceste controale este "CreateUserWizard", care afișează un formular (complet customizabil prin template-uri), în care un utilizator se poate înregistra pe site. Alt control este "Login", care afișează un formular în care un utilizator se poate autentifica pe site, din nou un control complet customizabil.
Evident că nu este nimic magic în această ușurință în crearea unui sistem de autentificare, în spate existând evident o baza de date, în care se păstrează (transparent pentru programator), toate informațiile despre utilizatorii înregistrați (username/parola, grup din care face parte). Implicit, imediat după instalare, ASP.NET 2.0 își păstrează aceste date într-o bază de date de tip Access, dar acest lucru este configurabil. Există de asemenea, un tool, numit Web Site Administration Tool, care, într-o interfața web foarte simplă și eficientă, dă posibilitatea administratorului aplicației web, să creeze noi conturi, să le șteargă, să asigneze utilizatori la anumite grupuri etc.
Există posibilitatea atașării de informații mai complexe la fiecare utilizator al aplicației web, prin intermediul serviciului "Personalization". Modul de utilizare al acestei facilitați este următorul: se setează în fișierul web.config, în secțiunea "profile", acele categorii de informații care dorim să le salvăm pentru fiecare, iar apoi, în aplicația web, folosim obiectul predefinit Profile pentru a accesa aceste informații pentru utilizatorul înregistrat în acel moment.
Exemplu:
în web.config:
<profile>
<property name="FirstName" />
<property name="ShoppingCart"
type="MyStore.ShoppingCart, MyStore"
serializeAs="Binary" />
</profile>
iar în aplicația web putem folosi construcții de forma:
Profile.FirstName = "Ruth";
Profile.ShoppingCart = objShoppingCart;
…
string FirstName = Profile.FirstName;
ShoppingCart objShoppingCart = Profile.ShoppingCart;
In cadrul proiectului s-a folosit un control de tip Login:
Ca și celelalte controale HTML sau ASP.NET, și acest control are o gamă largă de proprietăți care pot fi configurate.
<asp:Login ID="Login1" runat="server"DestinationPageUrl="~/Personal.aspx"
OnAuthenticate="Login1_Authenticate">
</asp:Login>
Se observă că pentru autentificare se va apela funcția Login1_Authenticate:
protected void Login1_Authenticate(object sender, AuthenticateEventArgs e)
{
Login l = (Login)sender;
bool memberAuth = DataAccess.memberAuthenticate(l.UserName.ToString(), l.Password.ToString());
bool contactAuth = DataAccess.contactAuthenticate(l.UserName.ToString(), l.Password.ToString());
if (memberAuth)
{
e.Authenticated = true;
Session["type"] = "member";
}
else
if (contactAuth)
{
e.Authenticated = true;
Session["type"] = "contact";
}
else
e.Authenticated = false;
}
Pentru ca autentificare să reusească este necesară setarea parametrului Authenticated al obiectului de tip AuthenticateEventArgs pe care această funcție il primeste. Se observă că există două cazuri în care se acceptă logarea:
cazul în care autentificarea reușește pentru un membru, adică există în tabelă tbl_Member din baza de date un membru care are user-ul și parola pe care acesta le-a introdus;
cazul în care autentificare reuseste pentru un utilizator de tip contact, adică există în tabela tbl_Contat un membru de tip contact care are parola și userul pe care acesta le-a introdus.
Cele doua funcții de autentificare sunt două funcții statice din cadrul clasei DataAcess în namespace-ul siemens:
private const string SP_MEMBER_AUTHENTICATE = "web_AuthenticateMember";
private const string SP_CONTACT_AUTHENTICATE = "web_AuthenticateContact";
public static bool memberAuthenticate(string username, string password)
{
// Execute SQL Command
SqlCommand sqlCmd = new SqlCommand();
AddParamToSQLCmd(sqlCmd, "@ReturnValue", SqlDbType.Int, 0,
emensspace-ulrul clasei DataAcess unt prei userul pe care acesta le-a introdus.
ember din baza de date un membru care are o paParameterDirection.ReturnValue, null);
AddParamToSQLCmd(sqlCmd, "@Username", SqlDbType.NText, 255,
ParameterDirection.Input, username);
AddParamToSQLCmd(sqlCmd, "@Password", SqlDbType.NText, 255,
ParameterDirection.Input, password);
SetCommandType(sqlCmd, CommandType.StoredProcedure,
SP_MEMBER_AUTHENTICATE);
ExecuteScalarCmd(sqlCmd);
int returnValue = (int)sqlCmd.Parameters["@ReturnValue"].Value;
return (returnValue == 0 ? true : false);
}
public static bool contactAuthenticate(string username, string password)
{
// Execute SQL Command
SqlCommand sqlCmd = new SqlCommand();
AddParamToSQLCmd(sqlCmd, "@ReturnValue", SqlDbType.Int, 0,
ParameterDirection.ReturnValue, null);
AddParamToSQLCmd(sqlCmd, "@Username", SqlDbType.NText, 255,
ParameterDirection.Input, username);
AddParamToSQLCmd(sqlCmd, "@Password", SqlDbType.NText, 255,
ParameterDirection.Input, password);
SetCommandType(sqlCmd, CommandType.StoredProcedure,
SP_CONTACT_AUTHENTICATE);
ExecuteScalarCmd(sqlCmd);
int returnValue = (int)sqlCmd.Parameters["@ReturnValue"].Value;
return (returnValue == 0 ? true : false);
}
Se observă că pentru autentificare se apelează două proceduri stocate, câte una pentru cele două tipuri de autentificări și anume web_AuthenticateMember și web_AuthenticateContact, prima pentru autentificarea membrilor și cea de-a doua pentru utilizatorii de tip contact:
CREATE PROCEDURE web_AuthenticateMember
@Username NVarChar(255),
@Password NVarChar(255)
AS
set nocount on
IF EXISTS( SELECT pk_id FROM tbl_Member WHERE LoginAccount = @Username
AND LoginPwd = @Password)
RETURN 0
ELSE
RETURN -1
CREATE PROCEDURE web_AuthenticateContact
@Username NVarChar(255),
@Password NVarChar(255)
AS
set nocount on
IF EXISTS( SELECT pk_id FROM tbl_Contact WHERE Account = @Username AND
LoginPwd = @Password)
RETURN 0
ELSE
RETURN -1
De asemenea se va pastra, cu ajutorul unei variabile de tip Session, tipul utilizatorului deoarece în funcție de tip se vor atribui drepturile (utilizatorii de tip contact, de exemplu, nu au acces decât la pagina de search).
IV.4.2. Delogare
Pentru delogare ASP.NET pune la dispoziția dezvoltatorilor de pagini web un control special: LoginStatus. Acesta are două stări: login și logout. În starea de login utilizatorului îi este permis accesul în cadrul paginii. În momentul în care s-a făcut click asupra acestui control, acesta trece în starea de logout. În acest moment se distrug toate variabilele aplicației. Programul detectează prin cod faptul că aceste variabile nu mai exită și în consecință va produce distrugerea paginii:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
try
{
if (Session["type"].ToString().CompareTo("member") == 0)
{
if (User.Identity.Name != "")
{
int MemberID = DataAccess.getMemberIDByUsername(User.Identity.Name);
dsPersonalData.SelectParameters["pk_ID"].DefaultValue =
MemberID.ToString();
dsPersonalMembership.SelectParameters["MemberID"].DefaultValue =
MemberID.ToString();
dsPersonalSponsor.SelectParameters["MemberID"].DefaultValue =
MemberID.ToString();
dsPersonalMentor.SelectParameters["MemberID"].DefaultValue =
MemberID.ToString();
dsPersonalSpeaker.SelectParameters["MemberID"].DefaultValue =
MemberID.ToString();
dsEducationHSDegree.SelectParameters["pk_ID"].DefaultValue =
MemberID.ToString();
dsEducationUniversity.SelectParameters["MemberID"].DefaultValue =
MemberID.ToString();
dsOccupations.SelectParameters["MemberID"].DefaultValue =
MemberID.ToString();
dsSkillsLaguages.SelectParameters["MemberID"].DefaultValue =
MemberID.ToString();
dsSkillsCategories.SelectParameters["MemberID"].DefaultValue =
MemberID.ToString();
dsEvents.SelectParameters["MemberID"].DefaultValue = MemberID.ToString();
dsEvents.SelectParameters["EventStatusID"].DefaultValue = "1";
dsEvents.SelectParameters["ParticipationStatusID"].DefaultValue = "8";
EventsGridView.Columns[3].Visible = true;
EventsGridView.Columns[4].Visible = false;
EventsGridView.Columns[5].Visible = false;
OccupationGridView.Sort("BeginDate", SortDirection.Ascending);
}
else
{
this.Dispose();
Response.Redirect("index.aspx");
}
}
else
{
PersonalMenu.Visible = false;
if (User.Identity.Name == "")
{
this.Dispose();
Response.Redirect("index.aspx");
}
}
}
catch (NullReferenceException)
{
Response.Redirect("index.aspx");
}
}
}
După ce pagina a fost distrusă browserul este redirectat către pagina de login.
IV.5. Meniul
IV.5.1. Site Navigation Service (SiteMap)
In ASP.NET Whidbey este posibil sa ținem structura logica a site-ului, separat si diferit fata de cea fizica (de pe disk). Acest lucru îmbunătățește mult managementul unor site-uri mari, actualizate sau schimbate des. Structura logica se poate reprezenta prin așa numitul SiteMap care este de fapt un fișier XML in care se reprezintă toate relațiile intre paginile si resursele aplicației web. Avem si posibilitatea de a obține un SiteMap de la un custom provider sau o baza de date sau orice alt content management system.
După crearea unui SiteMap, ASP.NET Whidbey expune un SiteMap API puternic, prin care pune la dispoziție suport programatic pentru a identifica unde anume se afla un browser care navighează site-ul respective.
IV.5.2. Navigation Controls
Acestea se folosesc in paralel cu SiteMap. De exemplu, odată având un SiteMap este foarte ușor de a realiza un meniu pentru aplicația web. Pur si simplu putem folosi ceva clasic, gen menu sau unul din noile controale: SiteMapPath sau TreeView. Daca vrem un meniu derulant si pe mai multe nivele, cel mai usor e sa punem la treaba controlul.
Pe de alta parte știm cu toții formularele mari, care trebuie completate si asupra cărora nu avem cum sa acționam ca sa realizam un user experience cat mai prietenos. De cele mai multe ori ajungem sa facem o pagina care se întinde peste rezoluția ecranului. Daca ar fi spargem (in ASP.NET 1.x) formularul in mai multe pagini, ar presupune ceva munca la a transmite data intre web form-uri, si de-abia pe ultima sa realizam prelucrarea. Din fericire in ASP.NET Whidbey exista un control pentru spargerea formularelor in categorii, numit wizard. Teoretic e mai general si se poate folosi la a pune la dispoziție wizard-uri pe care utilizatorul sa le urmeze.
In linii mari interfața este formata din doua panouri. Primul panou, cel din partea stânga, este la rândul sau alcătuit din doua elemente: un meniu si un link.
La rândul sau meniul este alcătuit din sase elemente: cate un link pentru fiecare pagina in parte. Linkul care nu face parte din meniu este cel prin care se iese din cont.
Lucrul cu un astfel de meniu este foarte simplist, adăugarea si ștergerea unui element din lista fiind foarte ușoara:
<asp:Menu ID="PersonalMenu" runat="server"
OnMenuItemClick="PersonalMenu_MenuItemClick" Font-Names="Arial" Font-
Size="8pt">
<Items>
<asp:MenuItem Text="Search" Value="search" Selected="True">
</asp:MenuItem>
<asp:MenuItem Text="Personal Information" Value="personal">
</asp:MenuItem>
<asp:MenuItem Text="Educations" Value="education">
</asp:MenuItem>
<asp:MenuItem Text="Occupations" Value="occupation">
</asp:MenuItem>
<asp:MenuItem Text="Skills & Activities" Value="skills">
</asp:MenuItem>
<asp:MenuItem Text="Events" Value="events">
</asp:MenuItem>
</Items>
<StaticMenuItemStyle Font-Names="Arial" Font-Size="8pt" />
<StaticSelectedStyle CssClass="menuSelectedColor" />
<StaticHoverStyle CssClass="menuHoverColor" />
</asp:Menu>
Fiecare element al meniului este introdus prin tagul asp MeniuItem specificandu-se valoarea si textul care va aparea pe link. De asemenea se poate specifica tipul si stilul meniului. In cazul de fata, de exemplu, s-a folosit un meniu cu orientare verticala.
De asemenea acest control permite tratarea unor evenimente. De exemplu pentru cazul nostru a fost necesar ca in cazul in care se apasa un link sa se schimbe pagina din cadrul wizard-ului:
protected void PersonalMenu_MenuItemClick(object sender, MenuEventArgs e)
{
if (PersonalMenu.SelectedItem.Value.CompareTo("search") == 0)
{
Page.Title = "Search Page";
PersonalWizard.ActiveStepIndex = 0;
}
if (PersonalMenu.SelectedItem.Value.CompareTo("personal") == 0)
{
Page.Title = "Personal Page";
PersonalWizard.ActiveStepIndex = 1;
}
if (PersonalMenu.SelectedItem.Value.CompareTo("education") == 0)
{
Page.Title = "Education Page";
PersonalWizard.ActiveStepIndex = 2;
}
if (PersonalMenu.SelectedItem.Value.CompareTo("occupation") == 0)
{
Page.Title = "Occupations Page";
PersonalWizard.ActiveStepIndex = 3;
}
if (PersonalMenu.SelectedItem.Value.CompareTo("skills") == 0)
{
Page.Title = "Skills Page";
PersonalWizard.ActiveStepIndex = 4;
}
if (PersonalMenu.SelectedItem.Value.CompareTo("events") == 0)
{
Page.Title = "Events Page";
PersonalWizard.ActiveStepIndex = 5;
}
}
Aceasta functie trateaza evenimentul de apasare cu mouse-ul pe un element al meniului: OnMenuItemClick. Fiecare din elementele meniului a primit ca valoare primul cuvant din componenta numelui elementului. Daca un element a fost selectat atunci obiectul meniu, in cazul de fata PersonalMenu, intoarce prin atributul SelecteItem valoarea acestui element.
In functia de mai sus s-a comparat valoarea intoarsa de meniu cu fiecare valoare in parte si pentru fiecare caz in parte s-a redefinit titlul aplicatiei, iar in controlul wizard s-a incarcat pagina corespunzatoare.
Cele doua panouri sunt definite in MasterPage. Întrucât si pagina de login este derivata tot din același MasterPage si in cadrul acesteia apare acest prin panou. Deoarece in acest panou nu a fost introdus nimic acesta nu se observă in cadrul paginii.
O alta problemă a fost ascunderea acestui control, controlul meniu, in cazul in care la aplicație se logheaza un utilizator care deține un cont de persoana de contact deoarece acesta nu are dreptul si nici date disponibile pentru celelalte pagini ale aplicației. Astfel s-a apelat la o variabila de sesiune care va retine tipul utilizatorului logat. In cazul in care acest utilizator este o persoana de contact atunci controlul meniu va fi ascuns.
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
try
{
if (Session["type"].ToString().CompareTo("member") == 0)
{
if (User.Identity.Name != "")
{
Session["username"] = User.Identity.Name;
}
else
{
this.Dispose();
Response.Redirect("index.aspx");
}
}
else
{
PersonalMenu.Visible = false;
if (User.Identity.Name == "")
{
this.Dispose();
Response.Redirect("index.aspx");
}
}
}
catch (NullReferenceException)
{
Response.Redirect("index.aspx");
}
}
}
Dupa cum am precizat mai sus in cadrul interfetei utilizator exista doua panouri principale: primul contine meniu si este asezat in partea din stanga, iar cel de-al doilea contine controlul wizard si este asezat in partea din mijlocul paginilor.
Întreaga aplicație se învârte in jurul controlului wizard. Un control wizard este foarte asemănător cu un control tab din aplicațiile clasice. Acesta conține mai multe pagini care pot fi schimbate in urma acțiunii executate de un utilizator. In cazul de fata pentru schimbarea paginilor s-a apelat la ajutorul unui control meniu.
La încărcarea contului unui utilizator s-a dorit postarea paginii de search. In consecința s-a apelat la forțarea setării paginii ca fiind cea corespunzătoare paginii search, adică prima pagina (implicit acest control păstrează ca pagina de start ultima pagina in care s-a lucrat, si care de obicei diferea de pagina de search):
protected void PersonalWizard_Init(object sender, EventArgs e)
{
Wizard w1 = (Wizard)sender;
Page.Title = "Search Page";
w1.ActiveStepIndex = 0;
}
IV.6. Calendar
Selectarea datei poate fi făcută în ASP.NET mult mai elegant, soluție oferită de controlul Calendar. Acesta permite afișarea unei singure luni, selectarea datei, trecerea de la o lună la alta. Pune la dispoziția programatorului diferite proprietăți pentru specificarea stilului de afișare și a modului de selectare a datei. Folosind proprietatea SelectionMode se poate specifica selectarea unei singure zile, a unei saptămâni sau a întregii luni. Controlul suportă toate tipurile de calendar definite în spațiul de nume System.Globalization (Gregorian, Japonez, Korean, Hijri, Hebrew, Julian).
<asp:Calendar ID="HighestSchoolBeginCalendar" runat="server"
OnSelectionChanged="HighestSchoolBeginCalendar_SelectionChanged" Width="150px"
DayNameFormat="FirstTwoLetters">
La ora actuala, majoritatea aplicațiilor Web folosesc un sistem de gestiune al bazelor de date în spatele aplicației. În sprijinul unei bune prezentări a acestor surse de date, platforma .NET include un set de trei controale ce fac posibilă afișarea unor mari cantități de date foarte ușor. Sursa de date reprezintă o mulțime specifica de date care poate fi reprezentata de un server de baze de date (SQL Server 2000), un fișier XML sau o colecție de date care implementează interfața System.Collections.IEnumerable. In cazul aplicației data a fost stocata in baza de date sspdb.
Totuși o afișare de forma unui calendar, prezentata mai sus, nu este tocmai eleganta, pe de o parte, iar pe de alta parte duce la încărcarea paginii cu foarte mult conținut. Se prefera, mai ales in aplicațiile tip desktop, utilizarea unui control mai complex care conține un textbox in care este afișata data si un buton care, atunci când este apăsat, afiseaza calendarul în care utilatorul poate alege data dorita. Astfel calendarul este afișat doar atunci când se dorește afișarea lui, si anume după apăsarea butonului.
Acest control a fost implementat si in cadrul aplicatei, un astfel de contol fiind compus din trei controale ASP: un textbox, un buton si un calendar:
<asp:TextBox ID="HighestSchoolBeginTextBox" runat="server" Text='<%#
Bind("HighestSchoolBegin", "{0:d}") %>'
Width="130px">
</asp:TextBox>
<asp:Button ID="HighestSchoolBeginButton" runat="server"
OnClick="HighestSchoolBeginButton_Click" Text="…" Width="20px" />
<br />
<asp:Calendar ID="HighestSchoolBeginCalendar" runat="server"
OnSelectionChanged="HighestSchoolBeginCalendar_SelectionChanged"
Width="150px" DayNameFormat="FirstTwoLetters" Visible="False">
</asp:Calendar>
Se observa ca pentru inceput controlul calendar este invizibil. In textbox va fi afisata data prezenta in baza de date. De asemenea controlul calendar nu este legat direct la baza de date. La apasarea butonului acesta apeleaza functia HighestSchoolBeginButton_Click:
protected void HighestSchoolBeginButton_Click(object sender, EventArgs e)
{
TextBox textbox = (TextBox)
(EducationHSDegreeFormView.FindControl("HighestSchoolBeginTextBox"));
Calendar calendar =(Calendar)
(EducationHSDegreeFormView.FindControl("HighestSchoolBeginCalendar"));
if (textbox.Text != "")
{
try
{
calendar.SelectedDate = Convert.ToDateTime(textbox.Text);
calendar.VisibleDate = Convert.ToDateTime(textbox.Text);
}
catch(Exception)
{
calendar.SelectedDate = DateTime.Today;
calendar.VisibleDate = DateTime.Today;
}
}
else
{
calendar.SelectedDate = DateTime.Today;
calendar.VisibleDate = DateTime.Today;
}
calendar.Visible = !calendar.Visible;
}
Data prezenta in textbox va zi afisata si in calendar. Totusi, deoarece controlul textbox poate accepta orice text, data introdusa poate sa nu fie corecta sau poate chiar sa lipseasca. Aceste oua cazuri sunt tratate prin if si prin try. In cazul in care data nu este corecta in controlul calendar va fi introdusa data curenta. In final calendarul va fi afisat in pagina prin schimbarea vizibilitatii. Trebuie mentionat ca in cazul in care calendarul este afisat si se apasa acest buton, calendarul va fi ascuns din nou.
In figura urmatoare este prezenta atat un control neactivat (adica sunt afisate in pagina doar textbox-ul si buton-ul) si anume cel pentru data de sfarsit a liceului, cat si un control activat (adica pe langa buton si textbox in pagina mai este prezent si calendarul) si anume cel pentru inceputul liceului:
Atunci cand se selecteaza o alta data din calendar (adica se modifica selectia) se va apela functia HighestSchoolBeginCalendar_SelectionChanged:
protected void HighestSchoolBeginCalendar_SelectionChanged(object sender, EventArgs e)
{
Calendar calendar = (Calendar)
(EducationHSDegreeFormView.FindControl("HighestSchoolBeginCalendar"));
calendar.Visible = false;
TextBox textbox = (TextBox)
(calendar.Parent.FindControl("HighestSchoolBeginTextBox"));
textbox.Text = calendar.SelectedDate.ToShortDateString();
EducationHiddenTextBox.Text = "a1";
EducationMessageRedLabel.CssClass = "inline";
}
Calendarul va disparea de pe pagina, iar in textbox-ul aferent va fi pusa noua valoare a date (cea pe care utilizatorul a selectat-o din calendar). In sfarsit, utilizatorul va fi informat ca in pagina au avut loc modificari, prin afisarea mesajului rosu ca avertizeaza asupra acestui lucru.
Un astfel de control este folosit de fiecare data cand este necesara introducerea sau modificarea unei date.
O problema speciala este aceea de salvare a datei in baza de date avand in vedere ca intr-un textbox date este interpretata ca orice alt text, iar interpretarea datei difera de la un calculator la altul in functie de setarile pe care acesta le are pentru timp. ASP.NET rezolvă in mod elegant aceasta problema prin setarea parametrilor care se transmit catre baza de date ca fiind de tip data. Astfel acestia sunt codificati intr-un mod special astfel incat pe calculatorul destinatie (pe care se afla baza de date) vor fi interpretati corect:
<asp:Parameter Name="HighestSchoolBegin" Type="DateTime" />
Tipul parametrului poate fi setat si prin cod:
dsEvents.UpdateParameters["LastChangeDate"].Type = TypeCode.DateTime;
dsEvents.UpdateParameters["LastChangeDate"].DefaultValue =
DateTime.Today.ToString();
Dupa cum se poate observa, data poate fi modificata si direct in textbox. Exista de asemenea si un dezavantaj al acestul control, si anume atunci cand se doreste afisarea controlului calendar pagina va trebui sa faca un postback care va implica reincarcarea tuturor controalelor in pagina.
IV.7. Baza de date
SQL Server este un sistem de baze de date relaționale client-server, având ca suport de baza in exploatarea bazelor de date limbajul SQL. In esența aceasta arhitectura presupune o baza de date centrala aflata pe un server, care este accesata de mai mulți clienți simultan. Acești clienți se conectează ca utilizatori in cadrul rețelei locale sau respectiv ca utilizatori ai Internetului. Consultarea si actualizarea bazelor de date prin intermediul Internetului presupune realizarea de aplicații care vor fi rulate in browser-ul Web si vor fi interconectate cu baza de date prin intermediul unor scripturi ASP sau prin intermediul tehnologiei XML. De asemenea accesul utilizatorilor din Internet presupune colaborarea intre severul de baze de date si serverul de Web (exemplu Microsoft Internet Information Server), cele doua componente lucrând in tandem pentru a satisface cererile utilizatorilor din Internet.
Pentru administrarea bazei de date, SQL Server va pune la dispoziție un instrument vizual de administrare SQL Server Enterprise Manager. Enterprise Manager are o interfața asemănătoare Explorer-ului din Windows. In partea stânga sunt prezentate, sub forma ierarhica, principalele clase de obiecte gestionate de interfața. La nivelul superior al ierarhiei se afla serverul SQL (respectiv serverele) care sunt administrate prin intermediul consolei. Făcând clic pe unul din Servere se pot realiza prin intermediul ferestrei deschise in dreapta o serie de operațiuni importante cum ar fi: înregistrarea unui nou server care va fi gestionat prin intermediul acestui program, backup-ul bazelor de date, configurarea clienților, crearea login-urilor, crearea unei baze de date etc. Interesant de subliniat este ca pentru realizarea acestor operațiuni se oferă posibilitatea utilizării "vrăjitorilor”.
IV.7.1. Structura bazei de date
Baza de date pe care se sprijină întreaga aplicație (atât partea de web cat si toolul de administrare) conține: peste 100 de tabele, peste 100 de proceduri stocate precum si 6 funcții si alte câteva trigere. Întreaga baza de date se învârte insa in jurul tabele tbl_Member, care conține datele principale despre membri:
In continuare se prezintă principalele tabele in tabele, iar in fiecare caz in parte câteva din câmpuri (cele mai importante).
Tabela tbl_Member are 79 de câmpuri dintre care cele mai importante sunt:
pk_ID, care este cheia primara a tabelei si care este cu autoindexare;
LFD_NR_BEW – cheia primara in tabela din care sunt importate o parte din date (trebuie precizat ca cea mai mare parte de date sunt importate din alte baze de date – mai exact din alte patru baze de date dbase si din alte doua documente exel), care a fost păstrata pentru a asigura omogenitatea si integritatea, si unicitatea datelor;
Lastname – nume membrului, de tip nvarchar;
Firstname – prenumele, de tip nvarchar ca si numele;
DateOfBirth – data de naștere e tip datetime (menționez ca acest câmp nu este modificat de către aplicație – se modifică doar de către toolul de administrare si se presupune ca nu mai este nevoie sa se modifice);
fk_Nationality1ID – este o cheie externa spre tabela tbl_Country si are semnificația primei naționalități; de asemenea mai exista si o a doua cheie externă de acest tip fk_Nationality2ID care cel mai probabil va fi foarte rar folosita;
NameOfBirth – numele de naștere al membrului (acest câmp va fi completat doar I cazul in care membrul respectiv si-a schimbat numele in urma unei căsătoriri);
PlaceOfBirth si fk_PlaceOfBirthCountry – localitatea si tara de naștere (in cazul tarii câmpul reprezintă o cheie externă către tabela tbl_Country);
EmailAddress1 si EmailAddress2 – câmpuri in care se rețin adresele de email ale membrilor; cea de-a doua adresa este păstrata pentru o mai mare siguranța (in cazul in care unul din serverele de mail are probleme de exemplu);
Mobile – numar de telefon mobil;
HomeStreetNo, HomeZipCode, HomeTown, fk_CountryHomeID si HomeTelephoneNo rețin date despre adresa studentului (adresa de reședința);
UniStreetNo, UniZipCode, UniTown, fk_CountryUniversityID, UniTelephoneNo (adresa de studiu);
uniAddressIsPostalAddress este un câmp de tip bit care precizează care din cele doua adrese sunt cele pe care vor fi trimise eventualele expediții; acest lucru se întâmpla deoarece sunt foarte dese cazurile in care un student nu are aceiași adresa de studiu cu cea de acasă, iar el este de obicei la studiu si in consecința expedițiile vor fi trimise pe aceste adrese;
De asemenea tabela mai conține a gama larga d câmpuri cu date despre sponsor, adresa de munca, o cheie externa spre persoana de contact care răspunde de aceasta persoana, date despre grupul regional, date despre contul membrului (username si parola), cat si date despre contul si banca la care este acest cont.
De asemenea aceasta tabela conține o constrângere si anume s-a dorit impunerea restricției ca un student sa fie introdus o singura data in baza de date si pentru a evita orice greșeala s-a apelat la următoarea constrângere:
Tabela tbl_Contact este o alta tabela importanta din baza de date. Aceasta conține 29 de câmpuri. In aceasta tabela se rețin date despre persoanele de contact. O persoană de contact este foarte importanta deoarece are acces la pofilele tuturor membrilor din cadrul programului, dar in schimb nimeni nu are acces la profilul sau.
Ca si in cazul tabelei tbl_Member, tabela tbl_Contact are o cheie primara pk_ID. De asemenea conține câmpuri pentru reținerea datelor personale: LastName reține numele persoanei de contact, FirstName reține prenumele persoanei, Sex sexul, Mail reține adresa de mail, Phone telefonul, Fax reține faxul. Tot in aceasta tabela se rețin si userul si parola cu ajutorul cărora aceștia au acces la program.
După cum s-a observat cele doua tabele conțin., pe lângă informații personale despre persoanele respective si informații despre cont, si anume userul si parola. Doua din procedurile stocate se ocupa de confirmarea logarii la aplicație si anume: web_AuthenticateContact si web_AuthenticateMember.
Prima procedura se ocupa de logarea persoanelor de contact:
CREATE PROCEDURE web_AuthenticateContact
@Username NVarChar(255),
@Password NVarChar(255)
AS
set nocount on
IF EXISTS( SELECT pk_id FROM tbl_Contact WHERE Account = @Username
AND LoginPwd = @Password)
RETURN 0
ELSE
RETURN -1
GO
Procedura primește doi parametrii: usermane-ul si parola persoanei de contact si in cazul in care aceasta combinație exista in baza de date atunci aceasta procedura va returna 0, adică o confirmare, in caz contrar nu va avea loc confirmarea.
Cea de a doua procedura se ocupa de membrii din cadrul programului:
CREATE PROCEDURE web_AuthenticateMember
@Username NVarChar(255),
@Password NVarChar(255)
AS
set nocount on
IF EXISTS( SELECT pk_id FROM tbl_Member WHERE LoginAccount = @Username
AND LoginPwd = @Password)
RETURN 0
ELSE
RETURN -1
GO
Ca si in cazul persoanelor de contact si in acest caz procedura primește doi parametrii: usermane-ul si parola membrului de aceasta data si in cazul in care aceasta combinație exista in baza de date atunci aceasta procedura va returna 0, adică o confirmare, in caz contrar nu va avea loc confirmarea.
Alte trei tabele importante in baza de date sunt:
tbl_MemberHasMainProgram;
tbl_MemberHasMainProgramStatus;
tbl_MemberHasUniversity.
Primele doua rețin date despre programul principal la care membrul respectiv este înscris sau despre programele la care a fost participant.
Din diagrama se observa ca un membru este sau a fost participant la unul sau mai multe programe, iar in cadrul acestora la suprograme. Fiecare program principal are un anumit status. De asemenea un membru are una sau mai multe universității. O persoană de contact are posibilitate de a comenta fiecare din aceste participări ale studenților la programe.
Principalele programe din acest proiect sunt:
TOPAZ,
Youth and Knowledge,
Yolante,
Ernst von Siemens-Stip.;
Werkstudenten-Stip.;
VIP;
CEMS;
IEP;
UNITECH;
SSP RC;
SBS Upgrade.
In momentul in care se caută un membru sau mai mulți membri in baza de date se dorește sa se afișeze despre acesta si câteva date despre programele la care a fost participant. O abordare simplista a acestei probleme ar fi ca in cazul in care se comanda căutarea, procedura de căutare sa interogheze si tabele de membership si sa returneze informația dorita. Aceasta abordare are avantajul simplității dar are un mare dezavantaj si anume timpul de căutare care este un factor crucial in aplicațiile de acest tip. In consecința s-a renunțat la aceasta varianta in favoarea unei variante mai complexe dar care reduce tipul de căutare vizibil.
Aceasta varianta presupune existenta unui câmp in plus in tabela tbl_Member, MainProgram, in care va fi introdusa informația despre programele principale. Aceasta va fi introdusa in momentul in care este adăugata o noua linie in tabela de membership cu ajutorul unui trigger.
Exista doua triggere: unul in tabela tbl_MemberHasMainProgram si celalalt in tabela tbl_MemberHasMainProgramStatus.
Pentru tabela tbl_MemberHasMainProgram triggerul RefreshProgramInfoFromProgram se executa la inserare si la modificare:
CREATE TRIGGER RefreshProgramInfoFromProgram ON
dbo.tbl_MemberHasMainProgram
FOR INSERT, UPDATE
AS
declare @ID int
declare @Now datetime
set @Now = getdate()
declare cMainProgram cursor for
select distinct
fk_MemberID
from
inserted
open cMainProgram
fetch next from cMainProgram into @ID
while @@fetch_status = 0
begin
update
tbl_Member
set
MainProgram = dbo.webfn_memberProgramInfoGET(@ID, @Now)
where
pk_id = @ID
fetch next from cMainProgram into @ID
end
close cMainProgram
deallocate cMainProgram
Pentru tabela tbl_MemberHasMainProgramStatus triggerul RefreshProgramInfoFromStatus se executa la inserare si la modificare:
CREATE TRIGGER RefreshProgramInfoFromStatus ON
[dbo].[tbl_MemberHasMainProgramStatus]
FOR INSERT, UPDATE
AS
declare @ID int
declare @Now datetime
set @Now = getdate()
declare cMainProgram cursor for
select distinct
MhMP.fk_MemberID
from
inserted MhMPS
inner join tbl_MemberHasMainProgram MhMP
on MhMPS.fk_MemberHasMainProgramID = MhMP.pk_id
open cMainProgram
fetch next from cMainProgram into @ID
while @@fetch_status = 0
begin
update
tbl_Member
set
MainProgram = dbo.webfn_memberProgramInfoGET(@ID, @Now)
where
pk_id = @ID
fetch next from cMainProgram into @ID
end
close cMainProgram
deallocate cMainProgram
Se observa ca in ambele cazuri se creează un cursor pe tabela care actualizează datele din câmpul MainProgram din tabela tbl_Member. Pentru aceasta actualizare se apelează funcția webfn_memberProgramInfoGET care returnează o prescurtare a informației despre program.
CREATE FUNCTION dbo.webfn_memberProgramInfoGET
(
@memberID int,
@now datetime
)
RETURNS nvarchar(200)
BEGIN
declare @resultString as nvarchar(200)
declare @mainProgram as nvarchar(20)
declare @subProgram as nvarchar(20)
declare @programStatus as nvarchar(10)
declare @relevantStudy as nvarchar(40)
declare @newline nvarchar(2)
declare @separator nvarchar(1)
set @newline = '/'–char(10) + char (13)
set @separator = '#'
declare cMemberProgramInfo cursor fast_forward for
select
(select ShortStr from tbl_MainProgram where pk_id =
mhmp.fk_MainProgramID)
as MainProgram,
(select Subprogram from tbl_SubProgram where pk_id =
mhmp.fk_SubProgramID) as SubProgram,
(select ShortStr from tbl_ProgramStatus where
pk_id=max(mhmps.fk_ProgramStatusID)) as ProgramStatus,
(
select
u.UniversityName + @separator + f.ShortStr + @separator +
rtrim(convert(char(2),month(u.StudyBegin))) + '.' +
convert(char(4),year(u.StudyBegin)) + '-' +
rtrim(convert(char(2),month(u.StudyEnd))) + '.' +
convert(char(4),year(u.StudyEnd))
from
tbl_MemberHasUniversity u
left join tbl_FieldOfStudy f
on u.fk_FieldOfStudyID = f.pk_id
where
u.pk_id = mhmp.fk_RelevantStudyID
) as RelevantStudy
from
tbl_MemberHasMainProgramStatus mhmps
inner join tbl_MemberHasMainProgram mhmp
on mhmps.fk_MemberHasMainProgramID = mhmp.pk_id
inner join tbl_ProgramStatus ps
on ps.pk_id = mhmps.fk_ProgramStatusID
where
BeginStatus <= @now
and mhmp.fk_MemberID=@memberID
group by
mhmps.fk_MemberHasMainProgramID,
mhmp.fk_MemberID,
mhmp.fk_MainProgramID,
mhmp.fk_SubProgramID,
mhmp.fk_RelevantStudyID
set @resultString = ''
open cMemberProgramInfo
fetch next from cMemberProgramInfo into @mainProgram, @subProgram, @programStatus, @relevantStudy
while @@fetch_status = 0
begin
if (@subProgram = '-')
set @subProgram = ''
else
set @subProgram = ' ' + @subProgram
set @resultString = @resultString
+ IsNull(@mainProgram,'')
+ IsNull(@subProgram,'')
+ '(' + ISNull(@programStatus,'') + ')'
+ @separator + IsNull(@relevantStudy,'')
set @resultString = @resultString + @newline
fetch next from cMemberProgramInfo into @mainProgram, @subProgram,
@programStatus, @relevantStudy
end
close cMemberProgramInfo
deallocate cMemberProgramInfo
return @resultString
END
Funcția preia pentru fiecare id din tabela tbl_Member informația prezenta in tabelele tbl_MemberHasMainProgram, tbl_MemberHasSubprogram, tbl_MemberHasProgramStatus, tbl_HasUniversity, realizează o prescurtare a acestora cu ajutorul câmpului shortName din tabelele respective si introduce informația respectiva in câmpul MainProgram corespunzător id-ului respectiv.
O alta parte importanta a bazei de date este partea de Events. Un eveniment reprezintă un miting la care participa o parte din membrii programului. Un anumit eveniment se distinge prin nume, locația in care are loc, datele intre care se desfășoară, dar mai ales prin membrii care pot participa.
Un eveniment are un anumit tip. Tipul unui eveniment specifica programul principal al persoanelor care pot participa. Un anumit membru poate sa aplice pentru participarea la acest eveniment doar daca este membru al programului respectiv. De asemenea se admit excepții dar acestea trebuie obligatoriu specificare manual. Odată înscris in pentru acest program un membru trece prin mai multe statusuri pana a deveni efectiv participant la acesta:
former participant – in acest stadiu se afla membri care sunt înscriși manual pentru acest program;
participant – in acest stadiu se afla membri care au fost acceptați pentru a participa la eveniment;
participant (not confirmed) – membri care nu au confirmat încă participarea lor la eveniment dar sunt acceptați;
participant cancelled – membri care au refuzat participare la eveniment;
possible participant – membri care pot participa la eveniment;
pre-registered – membri care s-au înregistrat pentru acest program;
rejected – membri care au fost respinși;
waiting queue – membri care așteaptă intr-o coada de așteptare.
Un membru poate participa la mai multe evenimente singura restricție fiind cea de tip, adică un membru nu poate participa in același timp la mai multe evenimente.
V. Concluzii
Microsoft .NET reprezintă, înainte de toate, o infrastructură prefabricată menită să lărgească orizontul aplicațiilor pe WEB, dar nu numai. Este o continuare firească a ceea ce au gândit în 1992 Tony Williams și Bob Atkinson (arhitecții originali ai tehnologiei COM) și a ceea ce înseamnă astăzi COM+ (infrastructură prefabricată pentru soluții enterprise).
Cu cât procesul de dezvoltare a aplicațiilor devine mai simplu și mai flexibil (cel puțin la prima vedere), cu atât mai sofisticată și mai abstractă devine tehnologia care suportă acest proces. Este cazul Java și, în mod normal, cazul .NET.
Platforma Java a fost gândită pentru portabilitate și multe din scopurile sale inițiale au fost remodelate în timp. Exemplul cel mai bun ar fi că Java este în cele mai multe cazuri JIT-compilată în prezent și nu interpretată, așa cum a fost inițial. În acest context, scopul .NET a fost ca limbajul intermediar să fie direct pentru JIT-compilare. Opțiunea de interpretare a fost eliminată din start.
Microsoft .NET înseamnă înainte de toate interoperabilitate la un nivel fără precedent. Vom vedea dacă în timp .NET se va extinde și la portabilitate.
Java a fost (și este) un succes. Rămâne de văzut dacă provocarea .NET (care a însumat mulți ani de muncă și mulți bani cheltuiți în același timp) va fi acceptată de programatori și dezvoltatori. Judecând după numărul de site-uri care au ca subiect .NET, se poate spune că tranziția de la Windows DNA la Microsoft .NET a început deja, chiar dacă în acest moment platforma se află în versiunea Beta 2 (sau chiar a fost lansat primul candidat pentru versiunea finală).
Contribuții personale
Partea dezvoltata in acest proiect face parte dintr-un proiect mult mai mare si mai complex pe care inginerii din laboratorul de informatică din cadrul Fachhochschule Regensburg s-au angajat sa-l dezvolte pentru filiala din Nurenberg a firmei Siemens.
Proiectul consta din proiectarea si implimentarea unui tool pentru mentinerea evidentei studentilor practicanti ai acestei firme. Initial, in urma cu multi ani, a fost proiectat un astfel de tool cu ajutorul sistemului de gestiune al bazelor de date Dbase. Acesta oferea pe langa stocarea datelor si posibilitatea afisarii acestora intr-o interfata comoda si eleganta.
O mare parte din structura bazei de date din acele timpuri a necesitat modificari datorita necesitatii de adaptare la cerintele actuale. Pe de alta parte modul de lucru sub sistemul de operare MS-DOS sub care a fost implementata aplicatie ingreuna foarte greu adaptarea la noile sisteme de operare. De asemenea se dorea o interactiune cu studentii, care sa pota modifica datele existente in baza de date, pentru o mai usoara corectare a acestora.
In urma cu ingineri din laborator au dezvoltat un alt proiect pentru firma Siemens dar pentru alt departament din cadrul acesteia. Datorita bunelor recomandari pe care acesta dezvoltare le-a primit s-a pus incredere in aceasta echipa de dezvoltare.
Dezvoltarea a constat din trei mari parti:
un tool de administrare al caror beneficiari sunt persoanele de contact din cadrul firmei, care au posibilitatea de a adauga persoane, de a modifica date personale si de a sterge membrii din baza de date;
o aplicatie online care sa faciliteze modificarea datelor persoale ale persoanelor din cadrul proiectului (la aceasta aplicatie au acces pe langa membrii programului si persoanele de contact care pot sa vada o scurta descriere a persoanelor din cadrul programului);
un tool care sa usureze migrarea datelor din vechea aplicație din dbase (datele aveau o alta structura).
Ultimele doua parti ale acestui proiect au fost sarcina mea. Aceasta aplicație a fost dezvoltata pe timpul in care am beneficiat de bursa Socrates in Germania la Fachhochschule Regensburg.
VI. Bibliografie
http://www.microsoft.com
Cursuri “Baze de date” Augustin Ionescu
Cursuri “Proiectarea bazelor de date” Augustin Ionescu
http://www.asp.net/vwd/starterkits.aspx
http://beta.asp.net/guidedtour
http://msdn.microsoft.com/asp.net/beta2/ui/default.aspx
http://beta.asp.net/QuickStartv20/aspnet/default.aspx
“Proiectarea aplicațiilor WEB cu ajutorul ASP.NET” Editura Teora
http://www.w3schools.com/js/js_conditionals.asp
http://msdn.microsoft.com/msdnmag
Cursuri “Proiectarea aplicațiilor web” Dan Mancaș
http://www.w3schools.com
http://www.w3schools.com/xml/default.asp
http://www.w3schools.com/html/default.asp
http://www.w3schools.com/js/default.asp
http://www.w3schools.com/asp/default.asp
http://www.w3schools.com/css/default.asp
=== Anexa ===
VI. ANEXE
Fișierul Personal.aspx.cs
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Data.SqlClient;
using System.IO;
using siemens;
public partial class Personal : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
try
{
if (Session["type"].ToString().CompareTo("member") == 0)
{
if (User.Identity.Name != "")
{
Session["username"] = User.Identity.Name;
}
else
{
this.Dispose();
Response.Redirect("index.aspx");
}
}
else
{
PersonalMenu.Visible = false;
if (User.Identity.Name == "")
{
this.Dispose();
Response.Redirect("index.aspx");
}
}
}
catch (NullReferenceException)
{
Response.Redirect("index.aspx");
}
}
}
protected void PersonalMenu_MenuItemClick(object sender, MenuEventArgs e)
{
if (PersonalMenu.SelectedItem.Value.CompareTo("search") == 0)
{
Page.Title = "Search Page";
PersonalWizard.ActiveStepIndex = 0;
}
if (PersonalMenu.SelectedItem.Value.CompareTo("personal") == 0)
{
Page.Title = "Personal Page";
PersonalWizard.ActiveStepIndex = 1;
}
if (PersonalMenu.SelectedItem.Value.CompareTo("education") == 0)
{
Page.Title = "Education Page";
PersonalWizard.ActiveStepIndex = 2;
}
if (PersonalMenu.SelectedItem.Value.CompareTo("occupation") == 0)
{
Page.Title = "Occupations Page";
PersonalWizard.ActiveStepIndex = 3;
}
if (PersonalMenu.SelectedItem.Value.CompareTo("skills") == 0)
{
Page.Title = "Skills Page";
PersonalWizard.ActiveStepIndex = 4;
}
if (PersonalMenu.SelectedItem.Value.CompareTo("events") == 0)
{
Page.Title = "Events Page";
PersonalWizard.ActiveStepIndex = 5;
}
}
protected void PersonalWizard_Init(object sender, EventArgs e)
{
Wizard w1 = (Wizard)sender;
Page.Title = "Search Page";
w1.ActiveStepIndex = 0;
}
protected void Load_Steps(object sender, EventArgs e)
{
switch(PersonalWizard.ActiveStepIndex)
{
case 1:
{
if (((TextBox)PersonalInf1.FindControl("PersonalHiddenTextBox")).Text.CompareTo("a") == 0)
((Label)PersonalInf1.FindControl("PersonalMessageRedLabel")).CssClass = "none";
else
((Label)PersonalInf1.FindControl("PersonalMessageRedLabel")).CssClass = "inline";
} break;
case 2:
{
if (((TextBox)Education1.FindControl("EducationHiddenTextBox")).Text.CompareTo("a") == 0)
((Label)Education1.FindControl("EducationMessageRedLabel")).CssClass = "none";
else
((Label)Education1.FindControl("EducationMessageRedLabel")).CssClass = "inline";
} break;
case 3:
{
if (((TextBox)Occupation1.FindControl("OccupationHiddenTextBox")).Text.CompareTo("a") == 0)
((Label)Occupation1.FindControl("OccupationsMessageRedLabel")).CssClass = "none";
else
((Label)Occupation1.FindControl("OccupationsMessageRedLabel")).CssClass = "inline";
} break;
case 4:
{
if (((TextBox)Skills1.FindControl("SkillsHiddenTextBox")).Text.CompareTo("a") == 0)
((Label)Skills1.FindControl("SkillsMessageRedLabel")).CssClass = "none";
else
((Label)Skills1.FindControl("SkillsMessageRedLabel")).CssClass = "inline";
} break;
}
}
}
Fișierul PersonalInf.asp.cs
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Data.SqlClient;
using System.IO;
using siemens;
public partial class PersonalInf : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
int MemberID = DataAccess.getMemberIDByUsername(Session["username"].ToString());
dsPersonalData.SelectParameters["pk_ID"].DefaultValue = MemberID.ToString();
dsPersonalMembership.SelectParameters["MemberID"].DefaultValue = MemberID.ToString();
dsPersonalSponsor.SelectParameters["MemberID"].DefaultValue = MemberID.ToString();
dsPersonalMentor.SelectParameters["MemberID"].DefaultValue = MemberID.ToString();
dsPersonalSpeaker.SelectParameters["MemberID"].DefaultValue = MemberID.ToString();
}
}
protected void Upload_DataBinding(object sender, EventArgs e)
{
FileUpload FileUpload1 = (FileUpload)(PersonalDataFormView.FindControl("FileUpload1"));
if (FileUpload1.HasFile)
{
System.IO.Stream data = FileUpload1.FileContent;
int length = Convert.ToInt32(data.Length);
byte[] origImageData = new byte[length];
data.Read(origImageData, 0, length);
string cxnstr = System.Configuration.ConfigurationManager.ConnectionStrings["sspdbConnectionString"].ConnectionString;
SqlConnection connection = new SqlConnection(cxnstr);
string query = "Update tbl_Member Set Picture = @origImageData where pk_ID = @MemberID";
SqlCommand command = new SqlCommand(query, connection);
SqlParameter param1 = new SqlParameter("@origImageData", SqlDbType.Image);
param1.Value = MakeThumb(origImageData, 118);
command.Parameters.Add(param1);
SqlParameter param2 = new SqlParameter("@MemberID", SqlDbType.Int);
param2.Value = DataAccess.getMemberIDByUsername(Session["username"].ToString()).ToString(); ;
command.Parameters.Add(param2);
connection.Open();
command.ExecuteScalar();
connection.Close();
}
}
public static byte[] MakeThumb(byte[] fullsize, int maxwidth)
{
System.Drawing.Image iOriginal, iThumb;
double scale;
iOriginal = System.Drawing.Image.FromStream(new MemoryStream(fullsize));
if (iOriginal.Width > maxwidth)
{
scale = iOriginal.Width / maxwidth;
int newheight = Convert.ToInt32(iOriginal.Height / scale);
iThumb = new System.Drawing.Bitmap(iOriginal, maxwidth, newheight);
MemoryStream m = new MemoryStream();
iThumb.Save(m, System.Drawing.Imaging.ImageFormat.Jpeg);
return m.GetBuffer();
}
else
{
return fullsize;
}
}
protected void PersonalDataFormView_DataBound(object sender, EventArgs e)
{
Image pic = (Image)(PersonalDataFormView.FindControl("Picture"));
string cxnstr = System.Configuration.ConfigurationManager.ConnectionStrings["sspdbConnectionString"].ConnectionString;
SqlConnection connection = new SqlConnection(cxnstr);
string query = "select Picture from tbl_Member where pk_ID=@item_id"; ;
SqlCommand command = new SqlCommand(query, connection);
SqlParameter param0 = new SqlParameter("@item_id", SqlDbType.Int);
param0.Value = pic.ImageUrl;
command.Parameters.Add(param0);
connection.Open();
byte[] buffer = null;
int length = 0;
try
{
buffer = ((byte[])(command.ExecuteScalar()));
length = buffer.Length;
}
catch (Exception)
{
}
if (length != 0)
{
pic.ImageUrl = "~/ImageFetch.ashx?ImageID=" + pic.ImageUrl;
}
else
{
pic.ImageUrl = "~/images/nophoto.gif";
}
TextBox tbNameOfBirth = (TextBox)(PersonalDataFormView.FindControl("PersonalDataNameOfBirthTextBox"));
TextBox tbFirstName = (TextBox)(PersonalDataFormView.FindControl("PersonalDataFirstNameTextBox"));
TextBox tbPlaceOfBirth = (TextBox)(PersonalDataFormView.FindControl("PersonalDataPlaceOfBirthTextBox"));
TextBox tbAddress1 = (TextBox)(PersonalDataFormView.FindControl("PersonalDataEmailAddress1TextBox"));
TextBox tbAddress2 = (TextBox)(PersonalDataFormView.FindControl("PersonalDataEmailAddress2TextBox"));
TextBox tbMobile = (TextBox)(PersonalDataFormView.FindControl("PersonalDataMobileTextBox"));
TextBox tbHomeStreetNo = (TextBox)(PersonalDataFormView.FindControl("PersonalDataHomeStreetNoTextBox"));
TextBox tbHomeZipCode = (TextBox)(PersonalDataFormView.FindControl("PersonalDataHomeZipCodeTextBox"));
TextBox tbHomeTown = (TextBox)(PersonalDataFormView.FindControl("PersonalDataHomeTownTextBox"));
TextBox tbHomeTelephoneNo = (TextBox)(PersonalDataFormView.FindControl("PersonalDataHomeTelephoneNoTextBox"));
TextBox tbWorkAddress_Company = (TextBox)(PersonalDataFormView.FindControl("PersonalDataWorkAddress_CompanyTextBox"));
TextBox tbWorkAddress_Department = (TextBox)(PersonalDataFormView.FindControl("PersonalDataWorkAddress_DepartmentTextBox"));
TextBox tbUniStreetNo = (TextBox)(PersonalDataFormView.FindControl("PersonalDataUniStreetNoTextBox"));
TextBox tbUniZipCode = (TextBox)(PersonalDataFormView.FindControl("PersonalDataUniZipCodeTextBox"));
TextBox tbUniTown = (TextBox)(PersonalDataFormView.FindControl("PersonalDataUniTownTextBox"));
TextBox tbUniTelephoneNo = (TextBox)(PersonalDataFormView.FindControl("PersonalDataUniTelephoneNoTextBox"));
TextBox tbWorkAddress_URL = (TextBox)(PersonalDataFormView.FindControl("PersonalDataWorkAddress_URLTextBox"));
DropDownList ddlSex = (DropDownList)(PersonalDataFormView.FindControl("PersonalDataSexDropDownList"));
DropDownList ddlCountry = (DropDownList)(PersonalDataFormView.FindControl("PersonalDataCountryOfBirthDropDownList"));
DropDownList ddlNationality1 = (DropDownList)(PersonalDataFormView.FindControl("PersonalDataNationality1DropDownList"));
DropDownList ddlNationality2 = (DropDownList)(PersonalDataFormView.FindControl("PersonalDataNationality2DropDownList"));
DropDownList ddlHomeCountry = (DropDownList)(PersonalDataFormView.FindControl("PersonalDataHomeCountryDropDownList"));
DropDownList ddlUniGroup = (DropDownList)(PersonalDataFormView.FindControl("PersonalDataUniGroupDropDownList"));
DropDownList ddlUniCountry = (DropDownList)(PersonalDataFormView.FindControl("PersonalDataUniCountryDropDownList"));
tbNameOfBirth.Attributes.Add("onchange", "javascript:Changed('" + PersonalHiddenTextBox.ClientID + "', '" + PersonalMessageRedLabel.ClientID + "')");
tbFirstName.Attributes.Add("onchange", "javascript:Changed('" + PersonalHiddenTextBox.ClientID + "', '" + PersonalMessageRedLabel.ClientID + "')");
tbPlaceOfBirth.Attributes.Add("onchange", "javascript:Changed('" + PersonalHiddenTextBox.ClientID + "', '" + PersonalMessageRedLabel.ClientID + "')");
tbAddress1.Attributes.Add("onchange", "javascript:Changed('" + PersonalHiddenTextBox.ClientID + "', '" + PersonalMessageRedLabel.ClientID + "')");
tbAddress2.Attributes.Add("onchange", "javascript:Changed('" + PersonalHiddenTextBox.ClientID + "', '" + PersonalMessageRedLabel.ClientID + "')");
tbMobile.Attributes.Add("onchange", "javascript:Changed('" + PersonalHiddenTextBox.ClientID + "', '" + PersonalMessageRedLabel.ClientID + "')");
tbHomeStreetNo.Attributes.Add("onchange", "javascript:Changed('" + PersonalHiddenTextBox.ClientID + "', '" + PersonalMessageRedLabel.ClientID + "')");
tbHomeZipCode.Attributes.Add("onchange", "javascript:Changed('" + PersonalHiddenTextBox.ClientID + "', '" + PersonalMessageRedLabel.ClientID + "')");
tbHomeTown.Attributes.Add("onchange", "javascript:Changed('" + PersonalHiddenTextBox.ClientID + "', '" + PersonalMessageRedLabel.ClientID + "')");
tbHomeTelephoneNo.Attributes.Add("onchange", "javascript:Changed('" + PersonalHiddenTextBox.ClientID + "', '" + PersonalMessageRedLabel.ClientID + "')");
tbWorkAddress_Company.Attributes.Add("onchange", "javascript:Changed('" + PersonalHiddenTextBox.ClientID + "', '" + PersonalMessageRedLabel.ClientID + "')");
tbWorkAddress_Department.Attributes.Add("onchange", "javascript:Changed('" + PersonalHiddenTextBox.ClientID + "', '" + PersonalMessageRedLabel.ClientID + "')");
tbUniStreetNo.Attributes.Add("onchange", "javascript:Changed('" + PersonalHiddenTextBox.ClientID + "', '" + PersonalMessageRedLabel.ClientID + "')");
tbUniZipCode.Attributes.Add("onchange", "javascript:Changed('" + PersonalHiddenTextBox.ClientID + "', '" + PersonalMessageRedLabel.ClientID + "')");
tbUniTown.Attributes.Add("onchange", "javascript:Changed('" + PersonalHiddenTextBox.ClientID + "', '" + PersonalMessageRedLabel.ClientID + "')");
tbUniTelephoneNo.Attributes.Add("onchange", "javascript:Changed('" + PersonalHiddenTextBox.ClientID + "', '" + PersonalMessageRedLabel.ClientID + "')");
tbWorkAddress_URL.Attributes.Add("onchange", "javascript:Changed('" + PersonalHiddenTextBox.ClientID + "', '" + PersonalMessageRedLabel.ClientID + "')");
ddlSex.Attributes.Add("onchange", "javascript:Changed('" + PersonalHiddenTextBox.ClientID + "', '" + PersonalMessageRedLabel.ClientID + "')");
ddlCountry.Attributes.Add("onchange", "javascript:Changed('" + PersonalHiddenTextBox.ClientID + "', '" + PersonalMessageRedLabel.ClientID + "')");
ddlNationality1.Attributes.Add("onchange", "javascript:Changed('" + PersonalHiddenTextBox.ClientID + "', '" + PersonalMessageRedLabel.ClientID + "')");
ddlNationality2.Attributes.Add("onchange", "javascript:Changed('" + PersonalHiddenTextBox.ClientID + "', '" + PersonalMessageRedLabel.ClientID + "')");
ddlHomeCountry.Attributes.Add("onchange", "javascript:Changed('" + PersonalHiddenTextBox.ClientID + "', '" + PersonalMessageRedLabel.ClientID + "')");
ddlUniGroup.Attributes.Add("onchange", "javascript:Changed('" + PersonalHiddenTextBox.ClientID + "', '" + PersonalMessageRedLabel.ClientID + "')");
ddlUniCountry.Attributes.Add("onchange", "javascript:Changed('" + PersonalHiddenTextBox.ClientID + "', '" + PersonalMessageRedLabel.ClientID + "')");
}
protected void PersonalDataApplyButton_Click(object sender, EventArgs e)
{
PersonalHiddenTextBox.Text = "a";
PersonalMessageRedLabel.CssClass = "none";
PersonalDataFormView.UpdateItem(true);
}
}
Fișierul Education.ascx.cs
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Data.SqlClient;
using System.IO;
using siemens;
public partial class Education : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
int MemberID = DataAccess.getMemberIDByUsername(Session["username"].ToString());
dsEducationHSDegree.SelectParameters["pk_ID"].DefaultValue = MemberID.ToString();
dsEducationUniversity.SelectParameters["MemberID"].DefaultValue = MemberID.ToString();
}
}
protected void EducationApplyButton_Click(object sender, EventArgs e)
{
EducationHiddenTextBox.Text = "a";
EducationMessageRedLabel.CssClass = "none";
EducationHSDegreeFormView.UpdateItem(true);
for (int i = 0; i < EducationUniversityGridView.Rows.Count; i++)
EducationUniversityGridView.UpdateRow(i, true);
}
protected void HighestSchoolBeginButton_Click(object sender, EventArgs e)
{
TextBox textbox = (TextBox)(EducationHSDegreeFormView.FindControl("HighestSchoolBeginTextBox"));
Calendar calendar = (Calendar)(EducationHSDegreeFormView.FindControl("HighestSchoolBeginCalendar"));
if (textbox.Text != "")
{
try
{
calendar.SelectedDate = Convert.ToDateTime(textbox.Text);
calendar.VisibleDate = Convert.ToDateTime(textbox.Text);
}
catch (Exception)
{
calendar.SelectedDate = DateTime.Today;
calendar.VisibleDate = DateTime.Today;
}
}
else
{
calendar.SelectedDate = DateTime.Today;
calendar.VisibleDate = DateTime.Today;
}
calendar.Visible = !calendar.Visible;
}
protected void HighestSchoolBeginCalendar_SelectionChanged(object sender, EventArgs e)
{
Calendar calendar = (Calendar)(EducationHSDegreeFormView.FindControl("HighestSchoolBeginCalendar"));
calendar.Visible = false;
TextBox textbox = (TextBox)(calendar.Parent.FindControl("HighestSchoolBeginTextBox"));
textbox.Text = calendar.SelectedDate.ToShortDateString();
EducationHiddenTextBox.Text = "a1";
EducationMessageRedLabel.CssClass = "inline";
}
protected void HighestSchoolEndButton_Click(object sender, EventArgs e)
{
Calendar calendar = (Calendar)(EducationHSDegreeFormView.FindControl("HighestSchoolEndCalendar"));
TextBox textbox = (TextBox)(EducationHSDegreeFormView.FindControl("HighestSchoolEndTextBox"));
if (textbox.Text != "")
{
try
{
calendar.SelectedDate = Convert.ToDateTime(textbox.Text);
calendar.VisibleDate = Convert.ToDateTime(textbox.Text);
}
catch (Exception)
{
calendar.SelectedDate = DateTime.Today;
calendar.VisibleDate = DateTime.Today;
}
}
else
{
calendar.SelectedDate = DateTime.Today;
calendar.VisibleDate = DateTime.Today;
}
calendar.Visible = !calendar.Visible;
}
protected void HighestSchoolEndCalendar_SelectionChanged(object sender, EventArgs e)
{
Calendar calendar = (Calendar)(EducationHSDegreeFormView.FindControl("HighestSchoolEndCalendar"));
calendar.Visible = false;
TextBox textbox = (TextBox)(calendar.Parent.FindControl("HighestSchoolEndTextBox"));
textbox.Text = calendar.SelectedDate.ToShortDateString();
EducationHiddenTextBox.Text = "a1";
EducationMessageRedLabel.CssClass = "inline";
}
protected void EducationUniversityBeginButton_Click(object sender, EventArgs e)
{
Button button = (Button)sender;
Calendar calendar = (Calendar)(button.Parent.FindControl("EducationUniversityBeginCalendar"));
TextBox textbox = (TextBox)(button.Parent.FindControl("EducationUniversityBeginTextBox"));
if (textbox.Text != "")
{
try
{
calendar.SelectedDate = Convert.ToDateTime(textbox.Text);
calendar.VisibleDate = Convert.ToDateTime(textbox.Text);
}
catch (Exception)
{
calendar.SelectedDate = DateTime.Today;
calendar.VisibleDate = DateTime.Today;
}
}
else
{
calendar.SelectedDate = DateTime.Today;
calendar.VisibleDate = DateTime.Today;
}
calendar.Visible = !calendar.Visible;
}
protected void EducationUniversityBeginCalendar_SelectionChanged(object sender, EventArgs e)
{
Calendar calendar = (Calendar)sender;
calendar.Visible = false;
TextBox textbox = (TextBox)(calendar.Parent.FindControl("EducationUniversityBeginTextBox"));
textbox.Text = calendar.SelectedDate.ToShortDateString();
EducationHiddenTextBox.Text = "a1";
EducationMessageRedLabel.CssClass = "inline";
}
protected void EducationUniversityEndButton_Click(object sender, EventArgs e)
{
Button button = (Button)sender;
Calendar calendar = (Calendar)(button.Parent.FindControl("EducationUniversityEndCalendar"));
TextBox textbox = (TextBox)(button.Parent.FindControl("EducationUniversityEndTextBox"));
if (textbox.Text != "")
{
try
{
calendar.SelectedDate = Convert.ToDateTime(textbox.Text);
calendar.VisibleDate = Convert.ToDateTime(textbox.Text);
}
catch (Exception)
{
calendar.SelectedDate = DateTime.Today;
calendar.VisibleDate = DateTime.Today;
}
}
else
{
calendar.SelectedDate = DateTime.Today;
calendar.VisibleDate = DateTime.Today;
}
calendar.Visible = !calendar.Visible;
}
protected void EducationUniversityEndCalendar_SelectionChanged(object sender, EventArgs e)
{
Calendar calendar = (Calendar)sender;
calendar.Visible = false;
TextBox textbox = (TextBox)(calendar.Parent.FindControl("EducationUniversityEndTextBox"));
textbox.Text = calendar.SelectedDate.ToShortDateString();
EducationHiddenTextBox.Text = "a1";
EducationMessageRedLabel.CssClass = "inline";
}
protected void EducationUniversityInsertButton_Click(object sender, EventArgs e)
{
EducationApplyButton_Click(sender, e);
int MemberID = DataAccess.getMemberIDByUsername(Session["username"].ToString());
dsEducationUniversity.InsertParameters["MemberID"].DefaultValue = MemberID.ToString();
dsEducationUniversity.Insert();
}
protected void EducationUniversityDeleteButton_Click(object sender, EventArgs e)
{
Button button = (Button)sender;
Label label = (Label)(button.Parent.FindControl("Label1"));
dsEducationUniversity.DeleteParameters["UniversityID"].DefaultValue = label.Text;
dsEducationUniversity.Delete();
}
protected void EducationHSDegreeFormView_DataBound(object sender, EventArgs e)
{
TextBox tbName = (TextBox)(EducationHSDegreeFormView.FindControl("HighestSchoolNameTextBox"));
TextBox tbDegreeMark = (TextBox)(EducationHSDegreeFormView.FindControl("HighestSchoolDegreeMarkTextBox"));
TextBox tbDegree = (TextBox)(EducationHSDegreeFormView.FindControl("HighestSchoolDegreeTextBox"));
TextBox tbBegin = (TextBox)(EducationHSDegreeFormView.FindControl("HighestSchoolBeginTextBox"));
TextBox tbEnd = (TextBox)(EducationHSDegreeFormView.FindControl("HighestSchoolEndTextBox"));
DropDownList ddlCountry = (DropDownList)(EducationHSDegreeFormView.FindControl("EucationHSCountryDropDownList"));
DropDownList ddlCity = (DropDownList)(EducationHSDegreeFormView.FindControl("EucationHSCityDropDownList"));
tbName.Attributes.Add("onchange", "javascript:Changed('" + EducationHiddenTextBox.ClientID + "', '" + EducationMessageRedLabel.ClientID + "')");
tbDegreeMark.Attributes.Add("onchange", "javascript:Changed('" + EducationHiddenTextBox.ClientID + "', '" + EducationMessageRedLabel.ClientID + "')");
tbDegree.Attributes.Add("onchange", "javascript:Changed('" + EducationHiddenTextBox.ClientID + "', '" + EducationMessageRedLabel.ClientID + "')");
tbBegin.Attributes.Add("onchange", "javascript:Changed('" + EducationHiddenTextBox.ClientID + "', '" + EducationMessageRedLabel.ClientID + "')");
tbEnd.Attributes.Add("onchange", "javascript:Changed('" + EducationHiddenTextBox.ClientID + "', '" + EducationMessageRedLabel.ClientID + "')");
ddlCountry.Attributes.Add("onchange", "javascript:Changed('" + EducationHiddenTextBox.ClientID + "', '" + EducationMessageRedLabel.ClientID + "')");
ddlCity.Attributes.Add("onchange", "javascript:Changed('" + EducationHiddenTextBox.ClientID + "', '" + EducationMessageRedLabel.ClientID + "')");
}
protected void EducationUniversityGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
TextBox tbBegin = (TextBox)(e.Row.FindControl("EducationUniversityBeginTextBox"));
TextBox tbEnd = (TextBox)(e.Row.FindControl("EducationUniversityEndTextBox"));
TextBox tbName = (TextBox)(e.Row.FindControl("EducationUniversityNameTextBox"));
TextBox tbSpecFoS = (TextBox)(e.Row.FindControl("EducationUniversitySpecFoSTextBox"));
DropDownList ddlType = (DropDownList)(e.Row.FindControl("EducationUniversityTypeDropDownList"));
DropDownList ddlDegree = (DropDownList)(e.Row.FindControl("EducationUniversityDegreeDropDownList"));
DropDownList ddlFoS = (DropDownList)(e.Row.FindControl("EducationUniversityFoSDropDownList"));
DropDownList ddlCity = (DropDownList)(e.Row.FindControl("EducationUniversityCityDropDownList"));
DropDownList ddlCountry = (DropDownList)(e.Row.FindControl("EducationUniversityCountryDropDownList"));
CheckBox cbIsHome = (CheckBox)(e.Row.FindControl("EducationUniversityIsHomeCheckBox"));
CheckBox cbDegreeReached = (CheckBox)(e.Row.FindControl("EducationUniversityDegreeReachedCheckBox"));
tbBegin.Attributes.Add("onchange", "javascript:Changed('" + EducationHiddenTextBox.ClientID + "', '" + EducationMessageRedLabel.ClientID + "')");
tbEnd.Attributes.Add("onchange", "javascript:Changed('" + EducationHiddenTextBox.ClientID + "', '" + EducationMessageRedLabel.ClientID + "')");
tbName.Attributes.Add("onchange", "javascript:Changed('" + EducationHiddenTextBox.ClientID + "', '" + EducationMessageRedLabel.ClientID + "')");
tbSpecFoS.Attributes.Add("onchange", "javascript:Changed('" + EducationHiddenTextBox.ClientID + "', '" + EducationMessageRedLabel.ClientID + "')");
ddlType.Attributes.Add("onchange", "javascript:Changed('" + EducationHiddenTextBox.ClientID + "', '" + EducationMessageRedLabel.ClientID + "')");
ddlDegree.Attributes.Add("onchange", "javascript:Changed('" + EducationHiddenTextBox.ClientID + "', '" + EducationMessageRedLabel.ClientID + "')");
ddlFoS.Attributes.Add("onchange", "javascript:Changed('" + EducationHiddenTextBox.ClientID + "', '" + EducationMessageRedLabel.ClientID + "')");
ddlCity.Attributes.Add("onchange", "javascript:Changed('" + EducationHiddenTextBox.ClientID + "', '" + EducationMessageRedLabel.ClientID + "')");
ddlCountry.Attributes.Add("onchange", "javascript:Changed('" + EducationHiddenTextBox.ClientID + "', '" + EducationMessageRedLabel.ClientID + "')");
cbIsHome.Attributes.Add("onchange", "javascript:Changed('" + EducationHiddenTextBox.ClientID + "', '" + EducationMessageRedLabel.ClientID + "')");
cbDegreeReached.Attributes.Add("onchange", "javascript:Changed('" + EducationHiddenTextBox.ClientID + "', '" + EducationMessageRedLabel.ClientID + "')");
}
}
}
Fișierul Events.ascx.cs
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Data.SqlClient;
using System.IO;
using siemens;
public partial class Event : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
int MemberID = DataAccess.getMemberIDByUsername(Session["username"].ToString());
dsEvents.SelectParameters["MemberID"].DefaultValue = MemberID.ToString();
dsEvents.SelectParameters["EventStatusID"].DefaultValue = "1";
dsEvents.SelectParameters["ParticipationStatusID"].DefaultValue = "8";
EventsGridView.Columns[3].Visible = true;
EventsGridView.Columns[4].Visible = false;
EventsGridView.Columns[5].Visible = false;
}
}
protected void EventsSelectCategoriesDropDownList_SelectedIndexChanged(object sender, EventArgs e)
{
DropDownList dpSelectCategories = (DropDownList)sender;
switch (dpSelectCategories.SelectedIndex)
{
case 0:
{
dsEvents.SelectParameters["ParticipationStatusID"].DefaultValue = "8";
EventsGridView.Columns[3].Visible = true;
EventsGridView.Columns[4].Visible = false;
EventsGridView.Columns[5].Visible = false;
} break;
case 1:
{
dsEvents.SelectParameters["ParticipationStatusID"].DefaultValue = "1";
EventsGridView.Columns[3].Visible = false;
EventsGridView.Columns[4].Visible = false;
EventsGridView.Columns[5].Visible = false;
} break;
case 2:
{
dsEvents.SelectParameters["ParticipationStatusID"].DefaultValue = "2";
EventsGridView.Columns[3].Visible = false;
EventsGridView.Columns[4].Visible = false;
EventsGridView.Columns[5].Visible = false;
} break;
case 3:
{
dsEvents.SelectParameters["ParticipationStatusID"].DefaultValue = "3";
EventsGridView.Columns[3].Visible = false;
EventsGridView.Columns[4].Visible = true;
EventsGridView.Columns[5].Visible = false;
} break;
case 4:
{
dsEvents.SelectParameters["ParticipationStatusID"].DefaultValue = "4";
EventsGridView.Columns[3].Visible = false;
EventsGridView.Columns[4].Visible = false;
EventsGridView.Columns[5].Visible = true;
} break;
case 5:
{
dsEvents.SelectParameters["ParticipationStatusID"].DefaultValue = "7";
EventsGridView.Columns[3].Visible = false;
EventsGridView.Columns[4].Visible = false;
EventsGridView.Columns[5].Visible = false;
} break;
case 6:
{
dsEvents.SelectParameters["ParticipationStatusID"].DefaultValue = "5";
EventsGridView.Columns[3].Visible = false;
EventsGridView.Columns[4].Visible = false;
EventsGridView.Columns[5].Visible = false;
} break;
}
}
protected void EventsGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
Label lDeadline = (Label)e.Row.Cells[1].FindControl("EventsDeadlineLabel");
lDeadline.Text = "(" + lDeadline.Text + ")";
Label lLocation = (Label)e.Row.Cells[1].FindControl("EventsLocationLabel");
if (lLocation.Text.CompareTo("") != 0)
lLocation.Text = lLocation.Text + ", ";
}
}
protected void EventsCancelButton_Click(object sender, EventArgs e)
{
Button b1 = (Button)sender;
Label l1 = (Label)(b1.Parent.FindControl("EventParticipantsIDLabel"));
int MemberID = DataAccess.getMemberIDByUsername(Session["username"].ToString());
dsEvents.UpdateParameters["MemberID"].DefaultValue = MemberID.ToString();
dsEvents.UpdateParameters["EventParticipantsID"].DefaultValue = l1.Text;
dsEvents.UpdateParameters["StatusID"].DefaultValue = "5";
dsEvents.UpdateParameters["LastChangeDate"].Type = TypeCode.DateTime;
dsEvents.UpdateParameters["LastChangeDate"].DefaultValue = DateTime.Today.ToString();
dsEvents.Update();
}
protected void EventsConfirmButton_Click(object sender, EventArgs e)
{
Button b1 = (Button)sender;
Label l1 = (Label)(b1.Parent.FindControl("EventParticipantsIDLabel"));
int MemberID = DataAccess.getMemberIDByUsername(Session["username"].ToString());
dsEvents.UpdateParameters["MemberID"].DefaultValue = MemberID.ToString();
dsEvents.UpdateParameters["EventParticipantsID"].DefaultValue = l1.Text;
dsEvents.UpdateParameters["StatusID"].DefaultValue = "4";
dsEvents.UpdateParameters["LastChangeDate"].Type = TypeCode.DateTime;
dsEvents.UpdateParameters["LastChangeDate"].DefaultValue = DateTime.Today.ToString();
dsEvents.Update();
}
protected void EventsDeclineButton_Click(object sender, EventArgs e)
{
Button b1 = (Button)sender;
Label l1 = (Label)(b1.Parent.FindControl("EventParticipantsIDLabel"));
int MemberID = DataAccess.getMemberIDByUsername(Session["username"].ToString());
dsEvents.UpdateParameters["MemberID"].DefaultValue = MemberID.ToString();
dsEvents.UpdateParameters["EventParticipantsID"].DefaultValue = l1.Text;
dsEvents.UpdateParameters["StatusID"].DefaultValue = "5";
dsEvents.UpdateParameters["LastChangeDate"].Type = TypeCode.DateTime;
dsEvents.UpdateParameters["LastChangeDate"].DefaultValue = DateTime.Today.ToString();
dsEvents.Update();
}
protected void EventsRegisterButton_Click(object sender, EventArgs e)
{
Button b1 = (Button)sender;
Label l1 = (Label)(b1.Parent.FindControl("EventParticipantsIDLabel"));
int MemberID = DataAccess.getMemberIDByUsername(Session["username"].ToString());
dsEvents.UpdateParameters["MemberID"].DefaultValue = MemberID.ToString();
dsEvents.UpdateParameters["EventParticipantsID"].DefaultValue = l1.Text;
dsEvents.UpdateParameters["StatusID"].DefaultValue = "1";
dsEvents.UpdateParameters["LastChangeDate"].Type = TypeCode.DateTime;
dsEvents.UpdateParameters["LastChangeDate"].DefaultValue = DateTime.Today.ToString();
dsEvents.Update();
}
}
Fișierul Occupation.ascx.cs
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Data.SqlClient;
using System.IO;
using siemens;
public partial class Occupation : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
int MemberID = DataAccess.getMemberIDByUsername(Session["username"].ToString());
dsOccupations.SelectParameters["MemberID"].DefaultValue = MemberID.ToString();
OccupationGridView.Sort("BeginDate", SortDirection.Ascending);
}
}
protected void OccupationApplyButton_Click(object sender, EventArgs e)
{
OccupationHiddenTextBox.Text = "a";
OccupationsMessageRedLabel.CssClass = "none";
for (int i = 0; i < OccupationGridView.Rows.Count; i++)
{
Label lType = (Label)OccupationGridView.Rows[i].FindControl("TypeLabel");
dsOccupations.UpdateParameters["Type"].DefaultValue = lType.Text;
Label lpk_ID = (Label)OccupationGridView.Rows[i].FindControl("pk_IDLabel");
dsOccupations.UpdateParameters["pk_ID"].DefaultValue = lpk_ID.Text;
TextBox tbBeginDate = (TextBox)OccupationGridView.Rows[i].FindControl("OccupationBeginTextBox");
dsOccupations.UpdateParameters["BeginDate"].Type = TypeCode.DateTime;
dsOccupations.UpdateParameters["BeginDate"].DefaultValue = tbBeginDate.Text;
TextBox tbEndDate = (TextBox)OccupationGridView.Rows[i].FindControl("OccupationEndTextBox");
dsOccupations.UpdateParameters["endDate"].Type = TypeCode.DateTime;
dsOccupations.UpdateParameters["EndDate"].DefaultValue = tbEndDate.Text;
DropDownList ddlTypeID = (DropDownList)OccupationGridView.Rows[i].FindControl("OccupationTypeDropDownList");
dsOccupations.UpdateParameters["TypeID"].DefaultValue = ddlTypeID.SelectedValue;
TextBox tbCompany = (TextBox)OccupationGridView.Rows[i].FindControl("OccupationCompanyTextBox");
dsOccupations.UpdateParameters["Company"].DefaultValue = tbCompany.Text;
CheckBox cbIsS = (CheckBox)OccupationGridView.Rows[i].FindControl("OccupationSCheckBox");
dsOccupations.UpdateParameters["ISSiemens"].Type = TypeCode.Boolean;
dsOccupations.UpdateParameters["ISSiemens"].DefaultValue = cbIsS.Checked.ToString();
DropDownList ddlGroup = (DropDownList)OccupationGridView.Rows[i].FindControl("OccupationGroupDropDownList");
dsOccupations.UpdateParameters["fk_GroupID"].DefaultValue = ddlGroup.SelectedValue;
TextBox tbDepartment = (TextBox)OccupationGridView.Rows[i].FindControl("OccupationDepartamentTextBox");
dsOccupations.UpdateParameters["Department"].DefaultValue = tbDepartment.Text;
TextBox tbSupervisor = (TextBox)OccupationGridView.Rows[i].FindControl("OccupationSupervisorTextBox");
dsOccupations.UpdateParameters["Supervisor"].DefaultValue = tbSupervisor.Text;
DropDownList ddlCity = (DropDownList)OccupationGridView.Rows[i].FindControl("OccupationCityDropDownList");
dsOccupations.UpdateParameters["fk_CityID"].DefaultValue = ddlCity.SelectedValue;
DropDownList ddlCountry = (DropDownList)OccupationGridView.Rows[i].FindControl("OccupationCountryDropDownList");
dsOccupations.UpdateParameters["fk_CountryID"].DefaultValue = ddlCountry.SelectedValue;
TextBox tbDescription = (TextBox)OccupationGridView.Rows[i].FindControl("OccupationDescriptionTextBox");
dsOccupations.UpdateParameters["Description"].DefaultValue = tbDescription.Text;
dsOccupations.Update();
}
}
protected void OccupationBeginButton_Click(object sender, EventArgs e)
{
Button button = (Button)sender;
Calendar calendar = (Calendar)(button.Parent.FindControl("OccupationBeginCalendar"));
TextBox textbox = (TextBox)(button.Parent.FindControl("OccupationBeginTextBox"));
if (textbox.Text != "")
{
try
{
calendar.SelectedDate = Convert.ToDateTime(textbox.Text);
calendar.VisibleDate = Convert.ToDateTime(textbox.Text);
}
catch (Exception)
{
calendar.SelectedDate = DateTime.Today;
calendar.VisibleDate = DateTime.Today;
}
}
else
{
calendar.SelectedDate = DateTime.Today;
calendar.VisibleDate = DateTime.Today;
}
calendar.Visible = !calendar.Visible;
}
protected void OccupationBeginCalendar_SelectionChanged(object sender, EventArgs e)
{
Calendar calendar = (Calendar)sender;
calendar.Visible = false;
TextBox textbox = (TextBox)(calendar.Parent.FindControl("OccupationBeginTextBox"));
textbox.Text = calendar.SelectedDate.ToShortDateString();
OccupationHiddenTextBox.Text = "a1";
OccupationsMessageRedLabel.CssClass = "inline";
}
protected void OccupationEndButton_Click(object sender, EventArgs e)
{
Button button = (Button)sender;
Calendar calendar = (Calendar)(button.Parent.FindControl("OccupationEndCalendar"));
TextBox textbox = (TextBox)(button.Parent.FindControl("OccupationEndTextBox"));
if (textbox.Text != "")
{
try
{
calendar.SelectedDate = Convert.ToDateTime(textbox.Text);
calendar.VisibleDate = Convert.ToDateTime(textbox.Text);
}
catch (Exception)
{
calendar.SelectedDate = DateTime.Today;
calendar.VisibleDate = DateTime.Today;
}
}
else
{
calendar.SelectedDate = DateTime.Today;
calendar.VisibleDate = DateTime.Today;
}
calendar.Visible = !calendar.Visible;
}
protected void OccupationEndCalendar_SelectionChanged(object sender, EventArgs e)
{
Calendar calendar = (Calendar)sender;
calendar.Visible = false;
TextBox textbox = (TextBox)(calendar.Parent.FindControl("OccupationEndTextBox"));
textbox.Text = calendar.SelectedDate.ToShortDateString();
OccupationHiddenTextBox.Text = "a1";
OccupationsMessageRedLabel.CssClass = "inline";
}
protected void OccupationInsertButton_Click(object sender, EventArgs e)
{
OccupationApplyButton_Click(sender, e);
int MemberID = DataAccess.getMemberIDByUsername(Session["username"].ToString());
dsOccupations.InsertParameters["MemberID"].DefaultValue = MemberID.ToString();
dsOccupations.Insert();
}
protected void OccupationDeleteButton_Click(object sender, EventArgs e)
{
Button button = (Button)sender;
Label label = (Label)(button.Parent.FindControl("pk_IDLabel"));
dsOccupations.DeleteParameters["OccupationID"].DefaultValue = label.Text;
dsOccupations.Delete();
}
protected void OccupationGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
TextBox tbBegin = (TextBox)(e.Row.FindControl("OccupationBeginTextBox"));
TextBox tbEnd = (TextBox)(e.Row.FindControl("OccupationEndTextBox"));
DropDownList ddlType = (DropDownList)(e.Row.FindControl("OccupationTypeDropDownList"));
TextBox tbCompany = (TextBox)(e.Row.FindControl("OccupationCompanyTextBox"));
CheckBox cbIsS = (CheckBox)(e.Row.FindControl("OccupationSCheckBox"));
TextBox tbDepartament = (TextBox)(e.Row.FindControl("OccupationDepartamentTextBox"));
DropDownList ddlGroup = (DropDownList)(e.Row.FindControl("OccupationGroupDropDownList"));
TextBox tbSupervisor = (TextBox)(e.Row.FindControl("OccupationSupervisorTextBox"));
DropDownList ddlCity = (DropDownList)(e.Row.FindControl("OccupationCityDropDownList"));
DropDownList ddlCountry = (DropDownList)(e.Row.FindControl("OccupationCountryDropDownList"));
TextBox tbDescription = (TextBox)(e.Row.FindControl("OccupationDescriptionTextBox"));
Label lDepartament = (Label)(e.Row.FindControl("OccupationDepartamentLabel"));
Label lGroup = (Label)(e.Row.FindControl("OccupationGroupLabel"));
Label lSupervisor = (Label)(e.Row.FindControl("OccupationSupervisorLabel"));
if (!cbIsS.Checked)
{
tbDepartament.CssClass = "none";
ddlGroup.CssClass = "none";
tbSupervisor.CssClass = "none";
lDepartament.CssClass = "none";
lGroup.CssClass = "none";
lSupervisor.CssClass = "none";
}
tbBegin.Attributes.Add("onchange", "javascript:Changed('" + OccupationHiddenTextBox.ClientID + "', '" + OccupationsMessageRedLabel.ClientID + "')");
tbEnd.Attributes.Add("onchange", "javascript:Changed('" + OccupationHiddenTextBox.ClientID + "', '" + OccupationsMessageRedLabel.ClientID + "')");
ddlType.Attributes.Add("onchange", "javascript:Changed('" + OccupationHiddenTextBox.ClientID + "', '" + OccupationsMessageRedLabel.ClientID + "')");
tbCompany.Attributes.Add("onchange", "javascript:Changed('" + OccupationHiddenTextBox.ClientID + "', '" + OccupationsMessageRedLabel.ClientID + "')");
cbIsS.Attributes.Add("onclick", "javascript:ClickedDel('" + cbIsS.ClientID + "', '" + tbDepartament.ClientID + "', '" + ddlGroup.ClientID + "', '" + tbSupervisor.ClientID + "', '" + lDepartament.ClientID + "', '" + lGroup.ClientID + "', '" + lSupervisor.ClientID + "')");
cbIsS.Attributes.Add("onmouseup", "javascript:Changed('" + OccupationHiddenTextBox.ClientID + "', '" + OccupationsMessageRedLabel.ClientID + "')");
tbDepartament.Attributes.Add("onchange", "javascript:Changed('" + OccupationHiddenTextBox.ClientID + "', '" + OccupationsMessageRedLabel.ClientID + "')");
ddlGroup.Attributes.Add("onchange", "javascript:Changed('" + OccupationHiddenTextBox.ClientID + "', '" + OccupationsMessageRedLabel.ClientID + "')");
tbSupervisor.Attributes.Add("onchange", "javascript:Changed('" + OccupationHiddenTextBox.ClientID + "', '" + OccupationsMessageRedLabel.ClientID + "')");
ddlCity.Attributes.Add("onchange", "javascript:Changed('" + OccupationHiddenTextBox.ClientID + "', '" + OccupationsMessageRedLabel.ClientID + "')");
ddlCountry.Attributes.Add("onchange", "javascript:Changed('" + OccupationHiddenTextBox.ClientID + "', '" + OccupationsMessageRedLabel.ClientID + "')");
tbDescription.Attributes.Add("onchange", "javascript:Changed('" + OccupationHiddenTextBox.ClientID + "', '" + OccupationsMessageRedLabel.ClientID + "')");
}
}
}
Fișierul search.ascx.cs
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public partial class Search : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void SearchButton_Click(object sender, EventArgs e)
{
string s;
int[] a;
s = SearchFirstNameTextBox.Text;
if (s.Length == 0)
s = "%";
dsSearchResult.SelectParameters["firstName"].DefaultValue = s;
s = SearchLastNameTextBox.Text;
if (s.Length == 0)
s = "%";
dsSearchResult.SelectParameters["lastName"].DefaultValue = s;
a = SearchMainProgramListBox.GetSelectedIndices();
if (a.Length == 0)
s = "%";
else
{
s = "(";
for (int i = 0; i < a.Length; i++)
{
s += SearchMainProgramListBox.Items[Convert.ToInt32(a.GetValue(i))].Value;
if (i < a.Length – 1)
s += ",";
}
s += ")";
}
dsSearchResult.SelectParameters["mainProgramIDs"].DefaultValue = s;
a = SearchStatusListBox.GetSelectedIndices();
if (a.Length == 0)
s = "%";
else
{
s = "(";
for (int i = 0; i < a.Length; i++)
{
s += SearchStatusListBox.Items[Convert.ToInt32(a.GetValue(i))].Value;
if (i < a.Length – 1)
s += ",";
}
s += ")";
}
dsSearchResult.SelectParameters["statusIDs"].DefaultValue = s;
a = SearchSubprogramListBox.GetSelectedIndices();
if (a.Length == 0)
s = "%";
else
{
s = "(";
for (int i = 0; i < a.Length; i++)
{
s += SearchSubprogramListBox.Items[Convert.ToInt32(a.GetValue(i))].Value;
if (i < a.Length – 1)
s += ",";
}
s += ")";
}
dsSearchResult.SelectParameters["subProgramIDs"].DefaultValue = s;
try
{
if (Convert.ToInt32(SearchRecordsPerPageTextBox.Text) > 0)
{
SearchGridView.AllowPaging = true;
SearchGridView.PageSize = Convert.ToInt32(SearchRecordsPerPageTextBox.Text);
}
else
{
SearchGridView.AllowPaging = false;
}
}
catch (Exception)
{
SearchGridView.AllowPaging = false;
}
}
protected void SearchGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
string s = "";
Label ll = (Label)(e.Row.Cells[4].FindControl("SearchResultMainProgram"));
for (int i = 0; i < ll.Text.Length; i++)
{
if ((ll.Text[i] != '#') && (ll.Text[i] != '/'))
s += ll.Text[i];
else
if (ll.Text[i] == '#')
s += " ";
else
s += "<br>";
}
ll.Text = s;
}
}
}
Fișierul Skills.ascx.cs
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Data.SqlClient;
using System.IO;
using siemens;
public partial class Skills : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
int MemberID = DataAccess.getMemberIDByUsername(Session["username"].ToString());
dsSkillsLaguages.SelectParameters["MemberID"].DefaultValue = MemberID.ToString();
dsSkillsCategories.SelectParameters["MemberID"].DefaultValue = MemberID.ToString();
}
}
protected void SkillsApplyButton_Click(object sender, EventArgs e)
{
SkillsHiddenTextBox.Text = "a";
SkillsMessageRedLabel.CssClass = "none";
for (int i = 0; i < SkillsLaguagesGridView.Rows.Count; i++)
SkillsLaguagesGridView.UpdateRow(i, true);
}
protected void ButtonSetAvailable_Click(object sender, EventArgs e)
{
Button button = (Button)sender;
ListBox list2 = (ListBox)(button.Parent.FindControl("SkillsMemberListBox"));
if (list2.SelectedIndex != -1)
{
SqlDataSource dsSkillsMember = (SqlDataSource)(button.Parent.FindControl("dsSkillsMember"));
dsSkillsMember.Update();
ListBox list1 = (ListBox)(button.Parent.FindControl("SkillsAvailableListBox"));
list1.DataBind();
}
}
protected void ButtonSetNotAvailable_Click(object sender, EventArgs e)
{
Button button = (Button)sender;
ListBox list1 = (ListBox)(button.Parent.FindControl("SkillsAvailableListBox"));
if (list1.SelectedIndex != -1)
{
SqlDataSource dsSkillsAvailable = (SqlDataSource)(button.Parent.FindControl("dsSkillsAvailable"));
dsSkillsAvailable.Update();
ListBox list2 = (ListBox)(button.Parent.FindControl("SkillsMemberListBox"));
list2.DataBind();
}
}
protected void LaguagesInsertButton_Click(object sender, EventArgs e)
{
SkillsApplyButton_Click(sender, e);
int MemberID = DataAccess.getMemberIDByUsername(Session["username"].ToString());
dsSkillsLaguages.InsertParameters["MemberID"].DefaultValue = MemberID.ToString();
dsSkillsLaguages.Insert();
}
protected void LaguagesDeleteButton_Click(object sender, EventArgs e)
{
Button b1 = (Button)sender;
Label l1 = (Label)b1.Parent.FindControl("Label4");
dsSkillsLaguages.DeleteParameters["original_pk_ID"].DefaultValue = l1.Text;
dsSkillsLaguages.Delete();
}
protected void SkillsLaguagesGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
DropDownList ddlLanguage = (DropDownList)(e.Row.FindControl("SkillsLanguagesLanguageDropDownList"));
DropDownList ddlLevel = (DropDownList)(e.Row.FindControl("SkillsLanguagesLevelDropDownList"));
ddlLanguage.Attributes.Add("onchange", "javascript:Changed('" + SkillsHiddenTextBox.ClientID + "', '" + SkillsMessageRedLabel.ClientID + "')");
ddlLevel.Attributes.Add("onchange", "javascript:Changed('" + SkillsHiddenTextBox.ClientID + "', '" + SkillsMessageRedLabel.ClientID + "')");
}
}
protected void OtherSkillsGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
Button bAdd = (Button)(e.Row.FindControl("SetNotAvailableButton"));
ListBox lAvailable = (ListBox)(e.Row.FindControl("SkillsAvailableListBox"));
lAvailable.Attributes.Add("onclick", "javascript:Disabled('" + bAdd.ClientID + "')");
bAdd.Attributes.Add("disabled", "true");
Button bRemove = (Button)(e.Row.FindControl("SetAvailableButton"));
ListBox lNotAvailable = (ListBox)(e.Row.FindControl("SkillsMemberListBox"));
lNotAvailable.Attributes.Add("onclick", "javascript:Disabled('" + bRemove.ClientID + "')");
bRemove.Attributes.Add("disabled", "true");
}
}
}
Fișierul script.js
// JScript File
function OpenPopupPage (pageUrl, MemberID)
{
window.open(pageUrl + '?member=' + MemberID, 'popupcal', 'scrollbars=yes, width=570, height=700, left=100, top=0');
}
function ClickedDel(ID1, ID21, ID22, ID23, ID31, ID32, ID33)
{
if (document.getElementById(ID1).checked != true)
{
document.getElementById(ID21).style.display = "none";
document.getElementById(ID22).style.display = "none";
document.getElementById(ID23).style.display = "none";
document.getElementById(ID31).style.display = "none";
document.getElementById(ID32).style.display = "none";
document.getElementById(ID33).style.display = "none";
}
else
{
document.getElementById(ID21).style.display = "inline";
document.getElementById(ID22).style.display = "inline";
document.getElementById(ID23).style.display = "inline";
document.getElementById(ID31).style.display = "inline";
document.getElementById(ID32).style.display = "inline";
document.getElementById(ID33).style.display = "inline";
}
}
function Changed(ID1, ID2)
{
document.getElementById(ID2).style.display = "inline";
document.getElementById(ID1).value = "a1";
}
function Disabled(ID1)
{
document.getElementById(ID1).disabled = false;
}
Fișierul index.ascx.cs
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using siemens;
using System.Data.SqlClient;
public partial class LoginPage : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Login1_Authenticate(object sender, AuthenticateEventArgs e)
{
Login l = (Login)sender;
bool memberAuth = DataAccess.memberAuthenticate(l.UserName.ToString(), l.Password.ToString());
bool contactAuth = DataAccess.contactAuthenticate(l.UserName.ToString(), l.Password.ToString());
if (memberAuth)
{
e.Authenticated = true;
Session["type"] = "member";
}
else
if (contactAuth)
{
e.Authenticated = true;
Session["type"] = "contact";
}
else
e.Authenticated = false;
}
}
Fișierul CV.ascx.cs
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public partial class CV : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string member = Request.QueryString["member"].ToString();
dsCVLFname.SelectParameters["MemberID"].DefaultValue = member;
dsCVHomeAddress.SelectParameters["MemberID"].DefaultValue = member;
dsCVWorkAddress.SelectParameters["MemberID"].DefaultValue = member;
dsCVOccupations.SelectParameters["MemberID"].DefaultValue = member;
dsCVUniversity.SelectParameters["MemberID"].DefaultValue = member;
dsCVLanguage.SelectParameters["MemberID"].DefaultValue = member;
dsCVSkillsCategory.SelectParameters["MemberID"].DefaultValue = member;
}
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
Label l1 = (Label)(e.Row.Cells[0].FindControl("CVLanguageNameLabel"));
Label l2 = (Label)(e.Row.Cells[0].FindControl("CVLanguageLavelLabel"));
Label l = (Label)(e.Row.Cells[0].FindControl("CVLanguageLabel"));
l.Text = l1.Text + "(" + l2.Text + ")";
}
}
}
Copyright Notice
© Licențiada.org respectă drepturile de proprietate intelectuală și așteaptă ca toți utilizatorii să facă același lucru. Dacă consideri că un conținut de pe site încalcă drepturile tale de autor, te rugăm să trimiți o notificare DMCA.
Acest articol: . Aplicatie Online Pentru Recrutarea Si Facilitarea Comunicatiei Intre Membrii Programului (ID: 148950)
Dacă considerați că acest conținut vă încalcă drepturile de autor, vă rugăm să depuneți o cerere pe pagina noastră Copyright Takedown.
