. Comert Electronic. Arhitectura Unui Sistem de Comert Electronic Si Avantejele Sale

1. Introducere

1.1 Comert electronic (e-commerce)

In ultimul deceniu , Internetul a evoluat intr-o unealta formidabila avand un impact major in toate aspectele vietii . La fiecare jumatate de an apar schimbari asa de importante incat este imposibil de prevazut unde se va ajunge in urmatorii 10 ani .

Nici o alta dezvoltare tehnologica nu a avut un impact atat de profund asupra lumii afacerilor ca Internetul. Utilizarea inteligenta a tehnologiei Internet in procesele de afaceri se transforma intr-un factor esential de succes pentru multe companii.

Internet-ul si Web-ul ca si alte multe tehnologii anterioare, se prezinta acum, cu un set nou de opotunitati si avantaje, cu noi propuneri si deschideri indraznete, indreptandu-se incetul cu incetul spre domenii care, nu cu mult timp in urma erau irealizabile, sau de neimaginat, unul dintre acestea fiind si comertul electronic. Inceputul noului mileniu, este dominat de revolutia tehnico-informatica, de noua era a Internet-ului si de noile posibilitati de comunicatie, in care informatia circula cu viteze ametitoare, provocand din ce in ce mai mult, atat dezvoltatorii cat si intreprinzatorii si fortandu-i sa schimbe radical modul in care gandesc, concep si privesc afacerile.

Viteza cu care evolueaza tehnologia Internet-ului este impresionanta. Daca acum se apreciaza ca exista cateva milioane de oameni care folosesc serviciile Internet in fiecare moment, numarul lor va creste exponential in anii urmatorii.

Vrand, nevrand Internet-ul ne schimba modul in care vom realiza afacerile in viitorii ani. Pentru a veni in intampinarea acestei schimbari, inca de pe acum, se simte o sete pentru aplicatiile de comert electronic. Realizarea lor cu mijloace modeste ar insemna insa, nu numai o munca in plus, dar si una consumatoare de mult timp, timp in care cerintele poate s-ar dubla sau tripla, fara a le mai putea face fata. Iata de ce, noi tehnologii pentru programarea destinata Internet-ului, care sa simplifice extrem programarea, sunt indispensabile. Astfel se incearca realizarea urmatoarelor caracteristici:

Construirea de sisteme care sa suporte cat mai multi clienti

Cresterea calitatii aplicatiilor

Realizarea aplicatiilor cu cat mai putine resurse

Posibilitatea dezvoltarii rapide a aplicatiilor

Explorarea noilor tehnologii pentru un avantaj competitiv

Cresterea portabilitatii si a interconectivitatii aplicatiilor si construirea de sisteme capabile de a lucra cu procese si date mai vechi.

Utilizata pana in prezent mai mult ca sursa de informatii, reteaua Internet se indreapta incetul cu incetul si spre un alt domeniu, acela al comertului electronic. Deja puteti cumpara prin Internet ultima aplicatie lansata de o anumita firma sau puteti chiar sa va faceti cumparaturile. Comertul electonic reprezinta in zilele noastre unul din factorii cheie a infrastructurii informationale globale, venind in intampinarea consumatorului prin crearea de posibilitati de cumparare si alegere dintr-o gama larga de oferte.

1.1.1 Ce este comertul electronic?

Comert electronic inseamna, in acceptiune "traditionala", utilizarea in retele cu valoare adaugata a unor aplicatii de tipul transferului electronic de documente (EDI), a comunicatilor fax, codurilor de bare, transferului de fisiere si a postei electronice. Extraordinara dezvoltare a interconectivitatii calculatoarelor in Internet, in toate segmentele societatii, a condus la o tendinta tot mai evidenta a companiilor de a folosi aceste retele in aria unui nou tip de comert, comertul electronic in Internet, care sa apeleze – pe langa vechile servicii amintite – si altele noi.

Este vorba, de exemplu, de posibilitatea de a se efectua cumparaturi prin retea, consultand cataloage electronice "on" pe Web sau cataloage "off" pe CD-ROM si platind prin intermediul cartilor de credit sau a unor portmonee electronice.

Pentru altii, comertul Internet reprezinta relatiile de afaceri care se deruleaza prin retea intre furnizori si clienti, ca o alternativa la variantele de comunicatii "traditionale" prin fax, linii de comunicatii dedicate sau EDI pe retele cu valoare adaugata.

In fine, o alta forma a comertului Internet implica transferul de documente – de la contracte sau comenzi pro forma, pana la imagini sau inregistrari vocale.

Comertul electronic este una dintre solutiile complexe, "integrate", pe care le ofera tehnologia Internet. Asta inseamna ca o multitudine de aplicatii si de furnizori de servicii Internet trebuie sa conlucreze intr-o sincronizare perfecta pentru ca un site de comert electronic sa poata functiona.

O alta definitie succinta si larg acceptata a comertului electronic este urmatoarea: Comertul electronic (e-commerce) este acea maniera de a conduce activitatile de comert care foloseste echipamente electronice pentru a mari aria de acoperire (locul in care se pot afla potentialii clienti) si viteza cu care este livrata informatia. (Mircea Cioata, [8])

Comertul electronic ofera oportunitatea de a comercializa produse in intreaga lume, sporind numarul de potentiali clienti in primul rand prin eliminarea barierelor geografice dintre clienti si comercianti. Pentru intelege care este rolul si locul comunicatiilor si solutiilor informatice (IT) intr-un astfel de mecanism, sa studiem putin arhitectura unui sistem de comertul electronic.

1.1.2 Arhitectura unui sistem de comert electronic.

Pentru a construi un sistem de e-commerce, din punct de vedere arhitectural este nevoie de colaborarea a patru componente (subsisteme electonice/informatice) corespunzatoare urmatoarelor roluri:

Client. Un echipament, clasic un PC, conectat direct (via un ISP) sau indirect (o retea a unei corporatii) la Internet. Cumparatorul foloseste acest echipament pentru a naviga si a face cumparaturi.

Comerciant. Sistem informatic (hard & soft), situat de regula la sediul comerciantului, care gazduieste si actualizeaza catalogul electronic de produse disponibile a fi comandate on-line pe Internet.

Sistemul tranzactional. Sistemul informatic (hard & soft) responsabil cu procesarea comenzilor, initierea platilor, evidenta inregistrarilor si a altor aspecte de business implicate in procesul de tranzactionare.

Dispecer plati. (Payment Gateway). Sistem informatic responsabil cu rutarea instructiunilor de plata in interiorul retelelor financiar-bancare, cu verificarea cartilor de credit si autorizarea platilor; acest sistem joaca rolul unei porti care face legatura dintre reteaua globala Internet si subreteaua financiar-bancara (supusa unor cerinte de securitate sporite), poarta prin care accesul este controlat de un "portar" (gatekeeper). Pe baza informatiilor specifice cartii de credit (tip card, numar card) din instructiunile de plata "portarul" redirecteaza informatia catre un centru de carduri (CC – un server certificat in acest scop si agreat de banca emitenta). In acest loc este identificata banca care a emis cardul iar instructiunile de plata sunt trimise mai departe catre serverul acestei banci conectat in reteaua interbancara. Odata informatiile ajunse in reteaua bancii cu care lucreaza cumparatorul, sunt efectuate (automat) o serie de verificari privind autenticitatea si soldul disponibil in contul cardului implicat in tranzactie.
In functie de rezultatul acestor verificari, banca decide fie efectuarea platii (transfer bancar – catre contul comerciantului care poate fi deschis la orice alta banca), fie refuza sa faca aceasta plata. In ambele cazuri, rezultatul deciziei (confimare plata sau refuz) este trimis in timp real, parcurgand acest lant de servere in sens invers, catre client. Cu alte cuvinte, in cateva secunde cumparatorul afla daca banca sa a operat plata sau nu.

(Mircea Cioata, [8])

1.1.3 Ce este un magazin electronic?

Un magazin electronic este (simplificat vorbind) o pagina de internet care intruneste minim urmatoarele conditii:

Prezinta informatii despre produse sau servicii, inclusiv pretul acestora.

Include un sistem prin care vizitatorii paginii pot selecta produsele dorite si le pot adauga intr-un "cos electronic de cumparaturi" (la fel cum intr-un supermarket vizitatorii pot lua produsele dorite de pe raft si le pot pune in cos).

Include un sistem de transmitere preluare si transmitere a datelor personale ale cumparatorului, pentru a putea fi contactat de catre vanzator.

Nu in ultimul rand, include un sistem de plata prin care vanzatorul isi poata incasa banii de la clientul "virtual".

Dupa cum am precizat mai sus, acestea sunt doar caracteristicile de baza absolut necesare si pe care vizitatorii paginii de internet le pot vedea. Ele reprezinta insa doar "vitrina" unui magazin electronic.

Un magazin electronic uzual va include in plus un sistem de administrare invizibil pentru vizitatorii obisnuiti. Prin intermediul acestuia se introduc si actualizeaza informatiile despre produse, se tine evidenta comenzilor, a conturilor cumparatorilor inregistrati, se urmaresc statistici despre produsele cele mai cautate si, nu in ultimul rand, se trimit mesaje de promovare menite sa informeze clientii magazinului despre ofertele curente. Lista de optiuni de administrare nu este desigur limitata la cele descrise mai inainte, in practica existand o multitudine de optiuni disponibile.

1.1.4 Avantajele comertului electronic

Un magazin electronic este in multe privinte superior fata de unul obisnuit. Principalele avantaje ale comertului electronic fata de comertul clasic sunt:

Oferta dumeavostra este accesibila clientilor din intreaga lume, 24 de ore din 24.

Orice persoana cu acces la Internet poate comanda, indiferent de locul in care se afla. Preluati comenzi 24 de ore din 24.

Nu aveti nevoie de vanzatori suplimentari.

Nu trebuie sa tineti produse pe stoc.

Poate deveni un punct de referinta pentru clienti.

Imbunatateste comunicarea cu clientii.

Aveti la dipozitie un instrument puternic si ieftin de promovare a ofertelor si promotiilor dumneavoastra: mesajele electronice catre clienti.

Simplifica preluarea comenzilor de la clienti deja existenti.

Comertul Electronic este cheia competitivitatii intreprinderilor in era informationala, asigurand:

accesul la noi segmente de piata (noi clienti).

cresterea vitezei de derulare a afacerilor.

flexibilitate ridicata a politicilor comerciale.

reducerea costurilor de aprovizionare, de desfacere, de publicitate, etc.

simplificarea procedurilor.

cresterea competitivitatii.

Pentru a asigura succesul pe termen lung al unui proiect de e-commerce, arhitectura acestuia trebuie proiectata cu grija tinand cont de toate aspectele de business cu care se va confrunta sistemul, lasand totodata portite care sa permita adaptarea sa in timp, pe masura ce apar noi provocari iar tehnologiile evolueaza.

1.2. Enuntul temei si obiectivul propus

Prin lucrarea de fata s-a urmarit studiul, proiectarea si implementarea unei aplicatii de comert electronic pe Internet ca o alternativa la solutiile existente in prezent.

Obiectivul propus a fost acela de dezvoltare a unei aplicatii de comert electronic care sa permita realizarea operatiunii de vanzare prin intemediul unui magazin virtual pe Internet. Pe langa implementarea functiilor de baza pe care trebuie sa le ofere orice aplicatie de comert electronic (magazin virtual) cum ar fi: inregistrarea clientilor din intreaga lume, consultarea unui catalog de produse, cautarea avansata a produselor, adaugarea unui produs in cosul virtual, vizualizarea cosului in orice moment, actualizarea/stergerea de produse din cos, trimiterea ordinului de cumparare, s-a incercat dezvoltarea unor noi functionalitati care sa diferentieze aplicatia de produsele existente in prezent. Astfel s-a stabilit ca si obiectiv implementarea urmatoarelor functionalitati suplimentare:

Posibilitatea clientului de a-si alege valuta in care doreste sa-i fie afisate preturile produselor. Preturile vor fi afisate in permanenta in valuta stabilita de organizatie si in valuta dorita de client.

Preturi preferentiale stabilite de ont.

Preturi preferentiale stabilite de organizatie pentru anumiti clientii fideli.

Posibilitatea clientilor de a face cadouri. Un sistem care permite ca fiecare comanda sa poata fi trimisa la o adresa specificata de client.

Salvarea ”cosului virtual” in baza de date pentru o vizita ulterioara cu posibilitatea de incarcare a produselor salvate.

Un sistem de taxe aplicate comenzilor in functie de tara in care se va face livrarea si de taxele stabilite de organizatie.

Fiecare client are un cont in care poate vedea situatia comenzilor sale.

Implementarea unui sistem care sa-i permita clientului accesul la contul sau prin intermediul unui dispozitiv mobil (telefon celular, Pocket PC).

Clientul sa-si poata verifica situatia comenzilor sale, si sa poata fi la curent cu noile produse aparute, cu ofertele promotionale ale organizatiei, toate acestea prin intermediul unui dispozitiv mobil (telefon celular, Pocket PC).

Astfel obiectivul propus a fost acela de realizare a partii ”vizibile” a unui magazin virtual (partea de Internet) fara a implementa partea de administrare a magazinului.

2. Memoriu Tehnic

Pentru a realiza o aplicatie de comert electronic, pentru a o lansa pe piata Internetului si pentru a fi utila unui numar cat mai mare de utilizatori, aceasta trebuie realizata de programatori ce cunosc bine modul de functionare a Web-ului, tehnica proiectarii bazelor de date, modul de administrare al acestora, modul si tehnica de conectare la bazele de date, cunosc limbajul SQL, au experienta in lucrul cu limbajele orientate obiect, in dezvoltarea de aplicatii dinamice pentru Web, cunosc tehnologii de programare pentru dezvoltarea aplicatiilor de Web si nu in ultimul rand stiu sa realizeze o interfata utilizator grafica cat mai prietenoasa, mai simpla si mai utila, prin care utilizatorul sa realizeze procesul de cumparare al produselor.

Cunoscand bine toate aceste lucruri, s-a incercat realizarea unei aplicatii de comert electonic (magazin virtual pe Internet), folosind cele mai noi tehnologii de la Microsoft: platforma Microsoft.NET, tehnologiile .NET, ASP.NET, C#.NET, ADO.NET, mediul vizual de dezvoltare Visual Studio .NET (VS.NET), Microsoft Mobile Internet Toolkit, sistemul de gestionare a bazelor de date (RDBMS) Microsoft SQL Server.

2.1 De ce Microsoft.NET?

Evolutia ingineriei software in ultimii 5 ani a minimalizat utilizarea limbajelor 4GL, asa cum limbaje ca Smalltalk au fost inlocuite de Java, iar conceptul de „fat client” a fost inlocuit de o arhitectura multinivel. In compensatie s-au impus diferite tehnologii web si XML (Extended Markup Language). Initiative de tip middleware cum ar fi Distributed Computing Enviroment (DCE) sau Common Object Request Broker Arhitecture (CORBA) sunt inlocuite treptat cu infrastructuri tehnice de mare complexitate.

Astazi au ramas in esenta numai doua platforme tehnologice pentru aplicatii noi: Java 2 Entreprise Edition (J2EE) si Microsoft .NET. J2EE si .NET sunt platformele viitorului. Dar care platforma se potriveste cel mai bine pentru obiectivul propus?

Pentru a lua o decizie corecta s-a facut un studiu comparativ asupra tehnologiilor J2EE si .NET, singurele alternative profesionale pentru dezvoltarea de aplicatii in mediul de afaceri.

2.1.1 J2EE versus .NET

Dupa succesul inregistrat de Java in ultimii zece ani, Microsoft incearca sa introduca pe piata .Net, o creatie proprie si proprietara, care sa concureze tehnologia Java.

J2EE framework s-a impus in randul dezvoltatorilor de aplicatii ca un mediu puternic, portabil si larg suportat. Anuntul despre .NET a captat atentia cel putin la fel de mult, reprezentand de fapt directia Microsoft, de la aplicatiile desktop la tool-urile de dezvoltare ca VisualStudio si servere precum SQL Server. Este .Net cu adevarat o alternativa?

Limbajul Java a cunoscut o dezvoltare deosebita in ultimii cinci ani, de la un „capriciu” al impatimitilor pentru limbajele orientate obiect la o tehnologie larg raspandita. Aceasta evolutie se datoreaza mai putin farmecului limbajului si mai mult fortei platformei tehnice asociate.

Recent si Microsoft ofera o platforma tehnologica asemanatoare. Cei din Redmond au inceput cu Distributed InterNet Architecture (DNA), care avea insa multe defecte.

Pe langa problemele cu registrul si conflictele de la nivelul DLL-urilor, a aparut conceptul de model obiect componenta (COM), care a devenit prea complex din cauza suportului pentru diferite limbaje. De asemenea procesarea distribuita cu solutii DCOM pe baza conceptului Microsoft RPC si a registrului Windows nu s-a dovedit a fi compatibila cu Internetul.

Incepand cu .NET, Microsoft a realizat o importanta schimbare fata de DNA, compania lui Bill Gates deschizand problema tehnologiei predecesoare. La capitolul arhitectura si functionalitate .NET si J2EE sunt foarte asemanatoare, dar Microsoft ofera o solutie tehnica mai moderna, prin implementarea tehnologiilor web si a limbajului XML. De asemenea, noul limbaj C# si masina virtuala (CLR) sunt idei provenite din Java. Exista si alte diferente de importanta strategica:

J2EE nu este un produs, ci o specificatie, pentru care diferite companii ofera produse. Aplicatiile sunt independente de proprietarul suportului middleware. Astfel, companiile obtin nu numai o independenta fata de un anumit furnizor, dar pot sa-si dezvolte propriile platforme tehnologice.

.NET este o colectie de produse ale unui singur producator si ruleaza numai impreuna cu Windows. Se asigura integrarea diferitelor componente si utilizarea unor caracteristici speciale ale sistemului de operare Windows.

J2EE este independent de conceptul de sistem de operare. Portabilitatea este asigurata de Java Runtime Environment, iar serverul de aplicatii si alte produse middleware pot fi programate in functie de sistemul de operare.

Platforma Java a fost gandita pentru portabilitate si multe din scopurile sale initiale au fost remodelate in timp. Exemplul cel mai bun ar fi ca Java este in cele mai multe cazuri JIT-compilata in prezent si nu interpretata, asa cum a fost initial. In acest context, scopul .NET a fost ca limbajul intermediar sa fie direct pentru JIT-compilare. Optiunea de interpretare a fost eliminata din start.

Microsoft .NET inseamna inainte de toate interoperabilitate la un nivel fara precedent. Vom vedea daca in timp .NET se va extinde si la portabilitate.

Microsoft a invatat din greselile altora si a produs o incredibila platforma de dezvoltare.

Pe langa aceste aspecte, mai exista si alte criterii importante in luarea unei decizii in privinta acestor doua tehnologii, cum ar fi nivelul de comprehensibilitate si dezvoltare, ceea ce analistii de la Gartner numesc „completeness of vision”. (Despina Eftimescu, [13])

.NET poseda cateva avantaje, deoarece utilizeaza de la inceput tehnologii moderne cum ar fi XML si serviciile web. Prin dezvoltarea propriei masini virtuale Microsoft rezolva problemele datorate interpretorului din Java. Multe functionalitati ale sistemului de operare Windows pot fi utilizate direct, cum ar fi serverul web IIS, Active Directory, OLEDB. Cuplarea eficienta cu sistemul de operare este cauza performantelor imbunatatite ale aplicatiilor .NET, comparativ cu cele ale aplicatiilor J2EE.

Dincolo de criteriile de performanta, trebuie sa tinem cont de eficienta platformei si de productivitatea furnizata in dezvoltarea aplicatiilor. Daca se masoara productivitatea numai pe baza „numarului de linii de cod”, .NET prezinta avantaje clare in fata J2EE. Crucial este insa cat dintre aceste linii de cod trebuie sa fie scrise la mana. Aici intervine atat procesul automatizat de dezvoltare cat si inteligenta mediului de dezvoltare software.

2.1.2 Avantaje si dezavantaje ale platformelor J2EE si .NET

Ambele ofera un model de server-side si client-side pentru asamblarea aplicatiilor, API-uri care permit creare de interfete utilizator si API-uri pentru acces la servicii critice cum ar fi tranzactii sau obiecte la distanta. La un nivel mai jos, ambele se bazeaza pe o masina virtuala (portabilitatea poate ar fi diferanta majora dintre cele doua).

Cand J2EE a fost introdus de Sun, folosea mult componente JavaBean si Enterprise JavaBean. JavaBeans sunt componenete Java, iar Enterprise JavaBeans sunt echivalentul pentru componenete Java accesibile la distanta. .NET Framework nu se bazeaza pe modelele COM si COM+ si sunt inlocuite cu noua arhitectura din .NET. CLR-ul ofera servicii precum garbage collection similare cu JVM, care nu au fost disponibile in COM. Deci CLR defineste un model nou, unde componentele COM si COM+ sunt accesibile, dar sunt separate si distincte fata de COM. Suportul MS pentru componente are o lunga istorie, determinata in primul rand de Visual Studio, principalul mediu de dezvoltare Microsoft. Modelul Java are handicapul dependentei de limbaj si de natura open a evolutiei sale.

Pentru interfetele client, J2EE ofera JavaSwing, cu o serie de componenete JavaBean care pot fi asamblate programatic. Pentru clienti mici, exista JSP si servlets si sunt suportate de o serie de producatori de tool-uri de dezvoltare. In trecut, Microsoft oferea MFC, dar .NET ofera WindowsForms. WindowsForms au de fapt acelasi rol ca si MFC-ul, dar sunt incorporate in .NET Framework si in noul model de obiecte. Similar, pentru clientii "slabi", exista ASP.NET, predecesorul ASP-ului. Functional, ASP.NET indeplineste acelasi rol, dar participa in noul CLR. Paginile ASP.NET sunt compilate sub forma de cod IL (Intermediate Language), si nu interpretate cum sunt paginile ASP.

J2EE si .NET suporta cateva API-uri strategice si servicii cum ar fi accesul la surse de date si servicii director, si suport XML pentru aplicatii. Accesul la sursele de date din Java se realizeaza prin JDBC. Drivere JDBC exista pentru toate bazele de date comerciale si populare. Serviciile director sunt accesate in Java folosind JNDI. Accesul la diferite servicii director (LDAP, Novel NDS, NIS sau DSML XML) sunt realizate de diferiti JNDI provideri, analog driverelor JDBC. Serviciile orientate catre sursele de date de la Microsoft au condus la DAO, apoi ADO. .NET ofera ADO.NET, modelul COM pe care se baza ADO fiind inlocuit cu XML, iar in .NET Framework exista un pachet pentru accesul la servicii director.

Poate vom ajunge ziua in care sistemele enterprise care se bazeaza pe aceste framework-uri (J2EE framework si .NET Framework) vor putea fi integrate si vor comunica unele cu altele.

De asemenea pentru a lua o decizie cat mai buna, s-a studiat si comparatia facuta de cei de la Microsoft asupra tehnologiilor .NET si J2EE prin implementarea aplicatiei Microsoft.NET Pet Store ca o alternativa la aplicatiei Java Pet Store dezvoltata de cei de la Sun. Cei de la Microsoft au prezentat avantajele oferite de tehnologia .NET. (Microsoft .Net Pet Shop, [12])

Luand in considerare toate cele prezentate mai sus, precum si avantajelor pe care le ofera tehnologia .NET pentru dezvoltarea de aplicatii Web, s-a ales ca mediu de dezvoltare a obiectivului propus platforma .NET si tehnologiile pe care le ofera aceasta: C#, ASP.NET, ADO.NET.

In urmatoarele capitole voi prezenta detaliat aceste tehnologii .NET folosite pentru realizarea aplicatiei de comert electronic, a obiectivului propus.

2.2 Limbajul C#

In ultimii ani, programarea a suferit o schimbare de paradigma de la un peisaj dominat de sisteme izolate la un mediu on-line, in care sistemele sunt conectate in retea. Limbajul C# a fost inventat ca raspuns la necesitatea unui limbaj de programare modern, care sa corespunda cerintelor lumii interconectate.

C# reprezinta pasul urmator in evolutia limbajelor de programare. Limbajul a preluat rezultatele cele mai bune din trecut, incorporand totodata si ultimele descoperiri din proiectarea limbajelor de programare moderne. De exemplu, C# a imprumutat facilitati atat de la Java, cat si din C++ – doua din cele mai importante limbaje pe plan modial. In acelasi timp, C# a venit cu inovatii proprii, cum ar fi delegarile si indexarile. Datorita faptului ca C# utilizeaza arhitectura .NET, codul rezultat este extrem de portabil si permite programarea in limbaj mixt. De exemplu, componentele software create utilizand C# sunt compatibile cu codul creat in alte limbaje de programare, atat timp cat acesta este destinat tot arhitecturii .NET. In acest capitol voi prezenta notiunile fundamentale ale programarii in C#.

2.2.1. Fundamentele limbajului C#

Cautarea unui limbaj de programare perfect dateaza de la inceputurile afirmarii programarii ca disciplina. In aceasta cautare, C# devine purtatorul actual al stindardului. Creat de firma Microsoft ca instrument de dezvoltare pentru arhitectura .NET, C# combina facilitatile testate de-a lungul timpului cu inovatii de ultim moment. Limbajul ofera o modalitate facila si eficienta de a scrie programe pentru mediul profesional modern de dezvoltare, care cuprinde sistemul Windows, Internetul, componentele software. Pe parcursul dezvoltarii sale, C# a redefinit peisajul in programare.

C# este mostenitorul unei averi bogate in domeniul programarii. Limbajul deriva direct din doua dintre cele mai de succes limbaje de programare pe plan modial: C si C++. De asemenea, C# este o ruda apropiata a unui alt limbaj de succes: Java.

Chiar daca Java a rezolvat cu succes multe din problemele legate de portabilitate in mediul Internet, exista inca facilitati care ii lipsesc. Una dintre acestea este interoperabilitatea limbajelor diferite, cunoscuta si sub numele de programare in limbaj mixt. Aceasta reprezinta posibilitatea codului scris intr-un anumit limbaj de a lucra in mod natural impreuna cu codul scris in alt limbaj.

O alta facilitate care nu exista in Java este integrarea deplina cu platforma Windows. Desi programele Java pot fi executate intr-un mediu Windows, Java si Windows nu sunt rude apropiate. Cum Windows este sistemul de operare cel mai raspandit in lume, lipsa suportului direct pentru Windows este un neajuns important al limbajului Java. Pentru a raspunde acestor nevoi si altora, Microsoft a dezvoltat limbajul C#.

C# este direct inrudit cu C, C++ si Java. Cele trei limbaje sunt printre cele mai raspandite limbaje de programare din lume. Arborele genealogic pentru C# este prezentat in figura … . „Bunicul” limbajului C# este C-ul. De la C, C# mosteneste sintaxa, multe dintre cuvintele cheie si operatorii. C# construieste modelul de obiecte definit in C++, imbunatatindu-l totodata. Relatia dintre C# si Java este ceva mai complicata. Java deriva la randul sau din C si C++. Java mosteneste de asemenea sintaxa C/C++ si modelul obiectual. Ca si Java, C# a fost proiectat pentru a produce cod portabil. Limbajul C# nu deriva insa din Java. Intre C# si Java exista o relatie similara celei dintre „veri”, ele avand un stramos comun, dar deosebindu-se prin multe caracteristici importante.

Limbajul C# contine multe facilitati novatoare, dar unele dintre cele mai importante se refera la suportul incorporat pentru componente software. De fapt, C# a fost caracterizat ca fiind un limbaj orientat spre componente, deoarece contine un suport complet pentru dezvoltarea de componente software. De exemplu, C# dispune de dacilitati care implementeaza direct elementele care alcatuiesc componentele, cum ar fi proprietatile, metodele, evenimentele. Cea mai importanta facilitate „orientata spre componente” de care dispune C# este probabil posibilitatea de lucru intr-un mediu cu limbaj mixt.

2.2.2 Relatia dintre C# si arhitectura .NET

C# este un nou limbaj de programare special conceput de Microsoft pentru dezvoltarea serviciilor si aplicatiilor internet care vor rula pe noua platforma Microsoft .NET. Aplicatiile web bazate pe componente, dezvoltate in C#, sunt la fel de performante ca si cele bazate pe arhitectura client/server, deoarece Microsoft .NET Framework este constituit dintr-un mediu de executie numit Common Language Runtime (CLR) si un set de biblioteci de clase, care ofera o platforma de dezvoltare compatibila cu diverse limbaje si unelte specifice.

Chiar daca C# este un limbaj de programare ce poate fi studiat separat, are o legatura deosebita cu mediul sau de rulare, arhitectura .NET. Si aceasta din doua motive. Mai intai, C# a fost initial dezvoltat de Microsoft pentru crearea codului pentru arhitectura .NET. In al doilea rand, bibliotecile utilizate de C# sunt cele definite de arhitectura .NET. In concluzie, chiar daca este posibil sa separam limbajul C# de mediul .NET, acestea sunt deocamdata foarte apropiate.

Arhitectura .NET defineste un mediu care permite dezvoltarea si executia aplicatiilor independente de platforma. Aceasta permite amestecarea diferitelor limbaje de programare si ofera facilitati de securitate si portabilitate a programelor si un mediu de programare coomun pentru platformele Windows. Este foarte important sa mentionam ca arhitectura .NET nu se limiteaza la Windows, ceea ce inseamna ca programele scrise pentru ea pot deveni portabile in medii non-Windows in viitor.

Legat de C#, arhitectura .NET defineste doua entitati foarte importante. Prima dintre acestea este motorul comun de programare, Common Language Runtime (CLR). Acesta este sistemul care se ocupa de executia programelor. Pe langa alte avantaje, motorul comun de programare este parrtea arhitecturii .NET care permite programelor sa fie portabile, asigura programarea in limbaj mixt si securitatea.

Cea de-a doua entitate este biblioteca de clase a arhitecturii .NET (.NET Framework Class Library). Prin intermediul acestei biblioteci, programul dumneavoastra are acces la mediul de rulare. Atat timp cat programul dumneavoastra se limiteaza la facilitatile definite in biblioteca de clase .NET, poate rula oriunde motorul de rulare .NET este disponibil.

Cum C# utilizeaza automat bibliotecile de clase .NET, programele C# sunt automat portabile in orice mediu .NET. Astfel C# ofera o serie de avantaje si de facilitati novatoare care fac din acesta un limbaj de programare demn de luat in considerare la alegerea mediului potrivit pentru dezvoltarea de aplicatii. (Bogdan Pisai [3])

Dat fiind faptul ca limbajele de programare C++ si Java sunt foarte cunoscute la ora actuala, si limbajul C# este asemanator cu acestea, nu s-a insitat pe prezentarea detaliata a acestui limbaj. S-a prezentat doar o descriere a ceea ce este limbajul C#.

2.3 ASP.NET

2.3.1 Introducere

Odata cu aparitia Internetului si a infrastructurii World-Wide-Web nascuta in anii '90, ideea si solutia aplicatiilor distribuite a capatat o alta culoare. Aplicatiile distribuite au luat nastere in urma vizualizarii clare a lumii informatice, a imposibilitatii de a avea dispozitive informatice care sa ruleze aplicatii monopost complexe, lucru care evident nu a condus decat la o centralizare a informatiei si a aplicatiilor in general. Bazata pe modelul client/server, platforma WWW ofera o infrastructura viabila si testata ca serviciu al retelei Internet si promite la nivel de client o interfata standardizata, chiar independenta de platforma, comuna pentru vizualizarea informatiilor Web, interfata cunoscuta sub numele de browser sau navigator Web.

Modelul de realizare a aplicatiior Web a cunoscut o intreaga evolutie a tehnologiilor de programare la nivel de server. Putem enumera astfel:

Solutia CGI (Common Gateway Interface) reprezinta o serie de script-uri executate pe serverul WWW. Acestea pot fi scrise in orice limbaj de programare (interpretat sau compilat) cu respectarea urmatoarelor restrictii: programul scrie datele la iesirea standard si genereaza antete care permit serverului Web sa interpreteze corect iesirea scriptului, conform specificatiilor HTTP (de exemplu, se pot folosi limbaje precum bash, Perl, C/C++, Delphi). Neajunsul CGI-urilor il reprezinta faptul crearii unui nou proces pe serverul Web pentru fiecare cerere si restrictionarea task/fisier executabil.

Solutia ISAPI (Internet Server API) reprezinta o alternativa CGI pe platforme Windows. Dezvoltatorii Win32 pot scrie un program care sa comunice direct cu aceasta interfata pentru a face orice lucru posibil cu CGI, pot folosi ISAPI pentru a obtine date din formulare si pentru a trimite continut HTML la client. Codul la nivel de server poate fi scris in oricare limbaj cu suport pentru DLL-uri Windows, ca C/C++, Java, Visual Basic, rezultatul compilarii fiind un fisier .dll. Fata de CGI, ISAPI ruleaza in acelasi spatiu de adrese cu serverul HTTP, are acces la toate resursele serverului HTTP, pot fi incluse mai multe task-uri intr-un .dll si nu creeaza procese aditionale pentru rezolvarea cererilor clientilor Web. O alternativa la ISAPI este NSAPI – utilizabila in cadrul serverului Web Netscape.

Solutia PHP (1994) sau ASP (1996) marcheaza un salt in dezvoltarea aplicatiilor Web. Desi difera din punct de vedere al sintaxei, ambele limbaje sunt interpretate, codul lor fiind stocat in fisiere externe cu extensia .php/.asp. De fapt, ASP nu ofera un limbaj nou, ci se bazeaza pe limbajele VBScript si JScript. Un fisier PHP/ASP poate fi combinat cu date de tip text, marcatori HTML si comenzi script. In momentul executiei, in urma cererii unui client Web, fisierul este procesat, fiecare script din cadrul lui este interpretat si rezultatul executiei este introdus inapoi in fisierul static HTML inainte ca rezultatul sa fie trimis catre browser. Mai mult, in sprijinul programatorului, limbajele pun la dispozitia acestuia o serie de metode si obiecte care usureaza lucrul cu cookie-uri, cu bazele de date (Oracle, MS-SQL, MySQL, etc.), care preiau elegant intrarile unui formular HTML si le proceseaza pe server, care preiau informatii despre utilizator (clientul Web), care trimit informatii la utilizator, care stocheaza informatii despre sesiunea unui utilizator (Session), care partajeaza informatii intre utilizatorii unei aplicatii (Application) s.a.m.d.. Mai nou, din partea PHP-ului, incepand cu versiunea 4.0, acesta ofera suport pentru programarea obiectuala: incapsularea datelor, mostenirea si polimorfismul. Aceste modele completeaza destul de bine suportul dezvoltarii aplicatiilor Web, insa aduc unele limitari: sunt lente deoarece la fiecare accesare fisierele sunt procesate si interpretate (in loc sa fie compilate), nu sunt capabile sa construiasca controale reutilizabile care sa incapsuleze functionalitati complexe pentru interactiunea cu utilizatorul.

JSP (JavaServer Pages) face parte din familia Java si reprezinta o tehnologie care permite crearea de aplicatii Web independente de platforma. JSP separa interfata utilizator de continutul generat dinamic permitand schimbarea intregului sablon al site-ului WEB fara a altera informatiile afisate. Tehnologia utilizeaza marcatori XML si scripturi scrise in limbajul de programare Java pentru a incapsula logica aplicatiei care genereaza continutul paginilor WEB. JSP-urile sunt o extensie a tehnologiei Java Servlet. Servlet-urile sunt independente de platforma 100% si reprezinta module la nivel de server care se integreaza in cadrul unei aplicatii Web si care pot fi utilizate pentru a extinde capabilitatile unui server WEB. Tehnologia JSP si servlet-urile ofera o alternativa pentru crearea aplicatiilor WEB fata de alte limbaje de scripting/programare a aplicatiilor WEB, oferind independenta de platforma, performanta, separarea logicii aplicatiei de partea de interfata utilizator, administrare usoara si extensibilitate.

In perioada de inceput a proiectarii si dezvoltarii site-urilor de Web din Internet, tehnologiile erau limitative. Informatiile pe care o persoana dorea sa le prezinte celor interesati erau furnizate de pagini HTML statice. Deoarece pe atunci tehnologiile folosite erau mai limitative, era mai usor sa creezi un site care sa nu fie atat de interactiv pe cat ar fi trebuit sa fie. In prezent insa este important sa stii cum sa creezi site-uri de Web dinamice, interactive, mai ales in conditiile folosirii tot mai intense a elementelor multimedia si a dezvoltarii site-urilor de tip e-commerce si e-business, care necesita integrarea de baze de date.

Pentru a raspunde acestei cerinte, Microsoft a creat o platforma pentru realizarea aplicatiilor de Web, numita Active Server Pages sau ASP. ASP a fost acceptat si folosit la scara larga de majoritatea creatorilor din domeniu pentru ca le permitea utilizarea cunostintelor deja acumulate in Visual Basic si VBScript pentru crearea aplicatiilor de Web.

In ciuda acestei acceptari la scara larga, folosirea mediului Active Server Pages era limitativ in unele privinte. De exemplu, validarea datelor din formulare necesita uneori scrierea unor coduri extinse atat in browserul client, cat si in server. De asemenea, unele aspecte din ASP nu erau extensibile la scara unei retele extinse si nu oferea fiabilitatea necesara in site-urile cu trafic ridicat (desi existau solutii pentru acest gen de probleme). In plus, combinarea codului aplicatiei server cu HTML si JavaScript in aceeasi pagina avea adesea ca rezultat generarea unor pagini de Web care contineau un amestec complicat de cod de executie pentru interfata server si codurile HTML extravagante folosite pentru interfata cu utilizatorul, care impreuna cu alte probleme faceau intretinerea codului o sarcina dificila.

Pentru a elimina aceste probleme si multe altele, Microsoft a creat ASP.NET, un mediu modern pentru dezvoltarea aplicatiilor de Web. Daca aveti experienta in programarea de aplicatii, vetii sesiza ca lucrul cu ASP.NET seamana foarte mult cu crearea aplicatiilor client-server.

Astfel, odata cu aparitia noii platforme .NET, Microsoft a adus o noua tehnologie in programarea si dezvoltarea aplicatiilor dinamice pentru Web, si anume, ASP.NET. Desi nu putem spune clar ca ASP.NET este o versiune urmatoare a ASP-ului, acesta pastreaza compatibilitatea cu aplicatiile scrise in ASP.

2.3.2 Ce este ASP.NET?

Orice programator care intra in contact cu ASP.NET pentru prima data se va intreba: Ce este ASP.NET? In cele ce urmeaza voi incerca sa prezint unele raspunsuri la acesta intrebare.

ASP.NET este o noua tehnologie de programare pentru Internet creata de Microsoft, care foloseste o abordare mai directa, orientata pe obiecte, pentru dezvoltarea de aplicatii dinamice pentru Web. ASP.NET reprezinta o platforma de dezvoltare unificata care furnizeaza dezvoltatorilor serviciile necesare construirii de aplicatii Web complexe. Platforma ofera un model nou de programare si o infrastructura care, fata de clasicul model ASP, aduce mai multa securitate, scalabilitate si stabilitate aplicatiilor.

Bazat pe platforma .NET, ASP.NET beneficiaza de capabilitatile acesteia in crearea si dezvoltarea de aplicatii Web, cum ar fi: Common Language Runtime, siguranta tipurilor, mostenire, manipularea consistenta a erorilor, securitate, s.a.m.d. Exista cateva aspecte ale noului model de programare care fac din ASP.NET o tehnologie cu o arie larga de interes.

ASP.NET este un limbaj de programare independent de browser. ASP.NET poate fi executat de cele mai noi versiuni ale browserelor Internet Explorer si Netscape Navigator, precum si de alte browsere folosite curent, cum ar fi Opera. De asemenea, ASP.NET poate asigura fara probleme compatibilitatea cu versiunile mai vechi de IE si NN. Asta inseamna ca vasta majoritate a utilizatorilor de Internet vor putea folosi aplicatiile de Web pe care le creati fara a fi nevoie sa introduceti un cod specific pentru browser.

ASP.NET este independent de limbajul de programare, fiind posibila dezvoltarea aplicatiilor in oricare limbaj de programare acceptat de platforma .NET. Platforma .NET Framework specifica faptul ca aplicatiile pot fi scrise in orice limbaj de programare care este compatibil cu Common Language Runtime (CLR).

Pentru cea mai recenta versiune a platformei .NET Framework, Microsoft introduce patru limbaje diferite care pot fi folosite la scrierea codurilor specifice CLR. Aceste limbaje sunt Visual Basic .NET (VB.NET), C#.NET, Visual C++.NET si Jscript.NET.

ASP.NET aduce performanta aplicatiilor sale prin compilarea codului. Astfel la prima accesare a unei pagini, mediul de executie compileaza codul si pagina ceruta, memoreaza rezultatul compilat intr-o copie, iar pentru restul cererilor la aceeasi pagina este utilizata copia compilata (intr-o maniera intrucatva asemanatoare servlet-urilor Java). In acest mod, raspunsul cererilor este mult mai rapid, deoarece dupa prima cerere codul nu mai necesita o noua compilare, deci o noua procesare a codului.

Astfel, putem deja compara ASP.NET cu limbajele de scripting ASP si PHP in care codul HTML este imbricat cu cel executabil (care este interpretat la fiecare acces). Fata de ASP, noul venit este mult mai structurat si orientat pe obiecte ceea ce implica modificari in portarea unei aplicatii ASP sub platforma .NET.

Alte facilitati oferite de mediu ar fi accesul usor la bazele de date, lucru facilitat de ADO.NET – proiectat pentru a intampina nevoile noului model de programare: o arhitectura de date deconectate, integrare cu XML, reprezentarea comuna a datelor cu abilitatea de a combina multiple si variate surse de date.

ASP.NET pune la dispozitia programatorilor avansati doua interfete, IHttpHandler si IHttpModule, pentru programare la nivelul serverului IIS prin Internet Server API (ISAPI). Astfel, pentru a interactiona la cel mai jos nivel cu serviciile de cerere-raspuns ale serverului IIS se poate folosi interfata IHttpHandler, iar pentru a include evenimente proprii la fiecare cerere din cadrul aplicatiei se foloseste interfata IHttpModule.

Alte facilitati oferite implicit sunt schemele de autentificare si autorizare pentru aplicatiile Web, furnizate de platforma .NET si ASP.NET. In acest sens, ASP.NET in conjuncþie cu IIS poate autentifica un utilizator si limita accesul la resurse folosind una din metodele de autentificare disponibile: Windows, Microsoft Passport Authentification, Forms.

Mai trebuie evidentiat, de asemenea, suportul pentru caching-ul paginilor Web, pentru diverse tipuri de date, obiecte, suportul pentru utilizarea starilor la nivel de aplicatie si/sau sesiune, suportul pentru depanarea erorilor in aplicatiile Web, suportul utilizarii cookie-urilor pentru browsere fara suport (sau cu optiune dezactivata) si facilitati de configurare a aplicatiilor Web la nivel de masina si aplicatie folosind fisiere text in format XML (vezi detalii de configurare a fisierelor Machine.config si Web.config in documentatia .NET Framework SDK).

Pana acum am prezentat de ce merita sa folosim ASP.NET in locul altor tehnologii de creatie pentru Web. Acum trebuie sa aflati care este componenta acestei tehnologii si cum se manifesta ea, care este modul de functionare a tehnologiei ASP.NET.

2.3.3 WebForms, o tehnologie ASP.NET

In acest subcapitol voi prezenta formularele de Web (WebForms), o tehnologie ASP.NET care ii permite programatorului sa creeze cu usurinta pagini de Web dinamice, pe baza codului de executie.

Paginile ASP.NET, numite si WebForms – formulare Web, permit crearea de interfete utilizator pentru aplicatiile Web, prezentand informatia catre orice browser sau dispozitiv client. Ele reprezinta un model scalabil de programare la nivelul serverului pentru a genera dinamic pagini Web.

In ASP.NET, formularele de Web sunt folosite pentru crearea unor pagini de Web programabile. Ele ii permit programatorului sa separe procesul de creare in HTML a interfetei cu utilizatorul de codul interfetei server care contine portiunea dinamica a unei pagini de Web. Iata cateva aspecte suplimentare pe care trebuie sa le cunoasteti cu privire la formularele de Web (WebForms):

Asigura o independenta de browser, executand in mod automat codul corect indiferent de browserul folosit la accesul in pagina. De asemenea este posibila configurarea formularelor de Web pentru un anumit browser, astfel incat sa beneficieze de numeroasele facilitati care nu sunt prezentate in alte browsere.

Pot fi programate in oricare din limbajele recunoscute de platforma .NET.

Ofera toate avantajele specifice mediului .NET Framework cum ar fi codul gestionat, siguranta tipologiei si mostenirea.

Folosesc controale incluse in server care ajuta la separarea proceselor de creare a interfetei cu utilizatorul de cele de creare a codului de executie.

Permit inregistrarea facila a datelor introduse de utilizator in timp ce acesta viziteaza site-ul de Web.

Ofera un model orientat obiect si bazat pe evenimente.

Asemanator modelului de programare WinForms (oferit de aplicatiile clasice in Visual C++ sau Visual Basic) un formular de Web (WebForms) este format din doua parti: componenta vizuala (furnizand interfaþa cu utilizatorul) si logica aplicatiei, codul (oferind implementarea efectiva). Codul lucreaza in conjunctie cu instructiunile HTML generate pentru crearea paginii de Web, pentru a crea pagini de Web integral dinamice.

Componeta vizuala a unui formular de Web este formata din codul HTML si din controalele de server ale formularului de Web, care sunt de doua tipuri: controale HTML si controale Web. Componenta de cod a formularului de Web permite interactiunea programatica cu componenta vizuala, precum si interactiunea cu evenimentele interfetei client initiate de utilizator. Componenta de cod mai este cunoscuta si drept „code-behind” (cod ascuns). Codurile ascunse pot fi scrise in orice limbaj recunoscut de platforma .NET, dar cele mai folosite limbaje sunt VB.NET si C#.

Componenta vizuala este reprezentata de un fisier cu extensia .aspx – actionand ca un container pentru HTML, text static si controale server care pot fi afisate in browser, iar logica aplicatiei este reprezentata de un fisier cu extensia .aspx.cs (pentru C#) sau .aspx.vb (pentru VB.NET). Fisierele .aspx mai sunt referite ca pagini ASP.NET. Aceasta tehnica de separare a codului de partea de prezentare este numita "code-behind programming", metoda care elimina disfunctionalitati de programare aducand robustete si dezvoltare usoara a paginilor. Solutia oferita permite detectarea erorilor de programare in timpul compilarii si nu in timpul primei accesari ale paginii Web si elimina codul "spagetti" dintr-un fisier HTML imbricat cu script-uri care era greu de scris si de intretinut.

Codul aplicatiei logice reprezinta in fapt o clasa care extinde functionalitatea clasei System.Web.UI.Page. Aceasta clasa contine metode care trateaza diferite evenimente (de exemplu, Page_Load care este apelata la fiecare acces al unei pagini Web), proprietati (ca IsPostBack – ne spune daca pagina este accesata in urma unei postari de formular electronic pe server), atribute corespunzatoare unor controale din pagina WebForms si alte date membre necesare implementarii aplicatiei.

In ASP.NET, cu putine modificari, oricare pagina WebFroms poate fi reutilizata in alta pagina ca un control server, numit prin extensie “user controls”. Controalele utilizator ofera la randul lor acelasi model abstract de programare, orientat pe obiecte si bazat pe evenimente, insa nu este posibila accesarea lor independenta, fiind necesare a fi incluse intr-o pagina WebForms. Clasa pe care o extinde un control utilizator este System.Web.UI.UserControls, iar fisierul care implementeaza un astfel de control are extensia .ascx. Asemanator WebForm-urilor, controalele utilizator sunt compilate la primul acces si stocate in memoria serverului pentru a reduce timpul de raspuns cererilor succesive.

Toate fisierele aplicatiei logice – codul din spate – sunt compilate intr-o biblioteca dinamica .dll care contine o clasa derivata din System.Web.UI.Page. Pentru fisierele .aspx, la prima cerere a browser-ului, runtime-ul ASP.NET genereaza o a doua bilblioteca dinamica .dll, temporara, care contine o clasa .NET. Aceasta clasa mosteneste clasa din primul .dll, iar in momentul rularii (executiei), cand un utilizator face o cerere a unei pagini, se executa .dll-urile asociate si rezultatul executiei este trimis la client intr-unul din limbajele HTML, XML, WML si ECMAScript (Jscript, JavaScript). Acest rezultat este influentat de capabilitatile navigatorului client, care poate fi chiar un dispozitiv mobil, astfel paginile WebForms transmit cod HTML compatibil browser-ului. De altfel, in functie de browser, pentru Internet Explorer 5 sau ulterior paginile WebForms pot fi programate pentru a beneficia de toate facilitatile acestuia.

Arhitectura ASP.NET suporta si un model asemanator ASP-ului, in care elementele de interfata si codul se afla in acelasi fisier, functionalitatea fiind aceeasi cu cea oferita de modelul cu doua fisiere. Totusi, exista mici diferente, la compilare codul din pagina nu mai este compilat intr-un fisier separat, clasa din .dll-ul asociat paginii .aspx deriva direct din clasa System.Web.UI.Page. Acest model are avantajul ca poate fi usor de utilizat in dezvoltarea paginilor Web.

2.3.4 Procesarea paginilor cu formulare de Web

Cand un utilizator solicita o pagina de Web de la un server de Web, se intampla mai multe lucruri. In primul rand este creata pagina de catre server, care apoi este trimisa catre browserul client. Apoi utilizatorul intra in interactiune cu pagina, transmitand formularul inapoi la server pentru procesare. Serverul de Web poate returna in mod automat o pagina de Web la utilizator in aceeasi stare in care era inainte de a fi expediata. Serverul de Web poate de asemenea executa o opearatie de procesare , iar pagina este retrimisa catre utilizator cu eventuale modificari ca urmare a procesarii.

Acest proces se numeste circuit, in care formularul este expediat sau transmis inapoi la server pentru procesare si apoi este returnat la utilizator. In timpul acestui proces, toate datele din pagina sunt in mod automat salvate de serverul de Web, si apoi returnate catre utilizator la incheierea circuitului. Astfel, modelul de executie al paginilor .aspx este format din mai multe etape, pornind de la cererea clientului pana la procesul executat de server. Vom observa ca viteza de raspuns a unei cereri este optimizata dupa prima accesare.

La prima accesare a unei pagini .aspx, procesul de raspuns al serverului ASP.NET este alcatuit din mai multi pasi:

Procesarea, interpretarea codului sursa si trimiterea acestuia compilatorului.

ASP.NET invoca compilatorul in urma caruia rezulta unul sau mai multe assemblies (cod intermediar, Intermediate Language – MSIL), plasat apoi in assembly cache

mediul de executie incarca in memorie si executa codul intermediar, iar rezultatul este trimis la client

La o urmatoare cerere ale aceleiasi pagini .aspx, timpul de raspuns este redus, mediul de executie ASP.NET incarca si executa codul intermediar care a fost analizat si compilat in timpul primei accesari.

ASP.NET, pentru a aduce performanta si scalabilitate aplicatiilor Web, ofera posibilitatea stocarii obiectelor, paginilor ASP.NET, partilor din pagini in memorie dupa prima cerere. In acest fel, procesul de raspuns al unei pagini poate fi redus la minim prin plasarea unei pagini construite (dupa prima cerere) in "output cache" (buffer de iesire). Astfel, o alta cerere a aceleiasi pagini va fi servita folosind copia din “output cache”.

Este foarte important sa intelegem cum este procesat un formular de Web (WebForms) pe server pentru a putea programa eficient. Un formular de Web, la procesarea pe serverul Web, poate fi privit ca un program executabil pentru care iesirea standard o reprezinta browserul sau dispozitivul client. In acest model, pagina trece printr-o serie de stagii de procesare: initializare, procesare si eliberare. In ordinea aparitiei, acestea sunt:

OnInit, eveniment care initializeaza pagina si in care proprietatile controalelor sunt actualizate. Aici este corect sa initializam controale care se adauga dinamic la pagina sau variabile necesare inainte de initializarea paginii;

Page_Load poate fi numit locul in care utilizatorul isi initializeaza codul. Evenimentul este generat de fiecare data cand pagina este incarcata dupa ce controalele au fost initializate la pasul anterior;

Validate, reprezinta stagiul in care se pot invoca metodele Validate ale fiecarui control server de validare;

Tratarea evenimentelor utilizator, reprezinta stagiul in care sunt tratate evenimentele generate de client cum ar fi: schimbarea unui text intr-un control, apasarea unui buton etc. Trebuie retinut ca aceste evenimente nu sunt tratate in ordine pe server, iar tratarea lor are loc dupa aparitia unui eveniment Click care trimite formularul la server.

Page_Unload este ultimul eveniment care se executa inainte ca pagina sa fie eliberata. Evenimentul este util de folosit atunci cand dorim sa efectuam ultimele operatii de eliberare a resurselor: inchiderea fisierelor, a conexiunilor la baza de date si eliberarea obiectelor din memorie.

Intr-o aplicatie Web, datorita naturii protocolului HTTP, procesul in care un browser acceseaza o resursa Web se rezuma la urmatorii pasi:

se stabileste o legatura cu serverul Web care primeste cererea resursei;

resursa este procesata de server in functie de caracteristicile ei;

rezultatul executiei este trimis la client;

resursele ocupate de serverul Web la procesarea cererii sunt eliberate din memorie;

conexiunea de la primul pas poate fi eliberata.

Datorita acestui model, paginile Web pot fi considerate lipsite de stari (stateless). De obicei, un navigator prezinta informatii unui client intr-un formular electronic. Acesta (clientul) interactioneaza cu elementele din formular modificand anumite stari ale controalelor, lucru care cauzeaza in final o trimitere a paginii pe server pentru a fi procesate informatiile curente. Serverul proceseaza pagina conform modificarilor, apoi returneaza formularul browser-ului. Aceasta secventa este cunoscuta si sub numele de round trip.

Deoarece paginile unei aplicatii Web sunt recreate cu fiecare round trip, se pune problema cum poate fi memorata starea controalelor intre doua round trip-uri (consecutive) sau cum stim daca o pagina este accesata pentru prima data.

ASP.NET ofera o infrastructura care suplineste aceste limitari:

salveaza proprietatile controalelor si a paginii intre round-trip-uri;

furnizeaza un management al starilor care permite salvarea de obiecte la nivel de aplicatie si de sesiune (gestionarea starilor);

poate detecta daca un browser cere o pagina pentru prima data, astfel pagina poate avea functionalitati diferite in functie de primul acces.

2.3.5 Elementele constitutive ale unui WebForms

O pagina WebForms contine un numar de comenzi numite directive la nivel de pagina care pot fi stocate in fisierele .aspx. Aceste directive au sintaxa urmatoare:

@ <nume directiva> si sunt incadrate de simbolurile <% si %>, pozitia lor fiind la inceputul paginii .aspx. Rolul lor este de a specifica anumite configuratii cand este procesata o pagina WebForms. Paginile WebForms suporta urmatoarele directive:

@ Page – defineste atribute specifice paginii WebForms care sunt utilizate de analizor si compilator (doar pentru fisiere .aspx).

@ Control – defineste atribute specifice controalelor utilizator care sunt utilizate de analizor si compilator. Aceasta directiva poate fi inclusa numai in fisiere ASCX.

@ Import – importa un spatiu de nume explicit intr-o pagina sau control utilizator.

@ Implements – indica unei pagini sau control utilizator ca implementeaza o interfata specifica .NET Framework.

@ Register – inregistreaza controale utilizator si controale obisnuite pentru a fi utilizate intr-un WebForms.

@ Assembly – creeaza legaturi catre assemblies in timpul compilarii, facand disponibile clasele si interfeþele din assemblies pentru a fi folosite in pagina.

@ OutputCache – declara politici de caching pentru controale dintr-o pagina sau user control.

@ Reference – adauga referinte catre un fisier .aspx sau .ascx extern.

Directiva @ Page este cea mai des utilizata si poate fi folosita o singura data in cadrul unui fisier ASPX, in schimb poate avea mai multe atribute. Dintre acestea, cele mai importante sunt: Codebehind, Inherits, Src, Language, Trace, Debug. De exemplu, atributul Language defineste limbajul implicit pentru toate scripturile din pagina si este util atunci cand folosim constructii <% … %> , atributul Debug activeaza suportul pentru depanarea paginii. Atributele Inherits si Src specifica mediului de executie ASP.NET sa compileze automat codul din spatele formularului.

Directiva @ Import poate fi gandita ca fiind similara contructiei "using" din C# si scopul ei este de a importa spatii de nume in care se gasesc tipuri pe care dorim sa le folosim si care nu sunt cunoscute implicit de compilator. Fata de directiva @ Page, aceasta poate aparea de mai multe ori in cadrul paginii.

Directiva @ OutputCache este probabil una dintre cele mai interesante si care aduce un bonus de performanta aplicatiei. ASP.NET permite doua forme de caching: intreaga pagina sau fragmente din aceasta (obiecte din cadrul paginii).

De exemplu, codul <%@ OutputCache Duration="60" VaryByParam="none" %> are ca rezultat salvarea pe disc a continutului paginii timp de 60 de secunde. Orice modificare in fisier nu este vizibila cererilor urmatoare decat dupa expirarea celor 60 de secunde, dupa care se creeaza un nou caching cu aceeasi durata. Atributul VaryByParam poate contine mai multe variabile delimitate de caracterul “;”.

2.3.6 Tratarea evenimentelor in formularele de Web.

Evenimentele din paginile cu formulare de Web sunt capturate de browser si transmise catre serverul de Web pentru procesare. Toate operatiile de procesare pentru controale server din formularele de Web sunt executate in serverul de Web.

Capturarea evenimentelor in paginile WebForms reprezinta o operate facila, similara tratarii evenimentelor in WinForms. In acest sens, ASP.NET furnizeaza un mecanism virtual pentru capturarea, transmiterea si interpretarea evenimentelor fara sa fim nevoiti sa cunoastem modul in care evenimentele sunt capturate la client si trimise la server pentru a fi procesate in codul corespunzator.

Evenimentele tratate in controalele server pot fi in general de tipul Click, dar exista altele speciale, mult mai abstracte, ca OnChange si SelectionChanged. De regula, evenimentele de tip Click genereaza o postare a paginii la serverul Web, iar cele de tipul OnChange sunt capturate, dar nu sunt trimise imediat la server (sunt mentinute intr-o coada de mesaje si procesate intr-o ordine aleatoare). Pentru acele controale in care se genereaza evenimentul OnChange exista proprietatea AutoPostBack care daca are valoarea true trimite automat formularul la server.

Metoda care trateaza evenimentele in ASP.NET respecta acelasi tipar cu cele folosite pe platforma .NET Framework. Astfel, toate evenimentele paseaza metodei doua argumente: un obiect care identifica obiectul care a aruncat evenimentul si un alt obiect continand informatii specifice evenimentului. Acesta din urma, este de obicei de tipul System.EventArgs, dar exista si alte tipuri cum ar fi ImageClickEvensArgs pentru controlul Web ImageButton.

Adaugarea unei metode care sa trateze mesajul generat se poate specifica astfel:

daca evenimentul este generat de un control HTML, acesta poate fi capturat atat la client cat si la server. Aceasta se specifica prin adaugarea atributelor OnClick, respectiv OnServerClick care vor indica metoda care va fi apelata la generarea evenimentului.
Exemplu: <input type="submit" value="Enter" OnServerClick= "SubmitBtn_Click" runat="server">, unde metoda void SubmitBtn_Click (object sender, EventArgs e) este cea care trateaza evenimentul pe server.

daca evenimentul este generat de un control Web, nu se poate specifica tratarea unui eveniment la client in sintaxa HTML, dar se poate adauga dinamic un nou atribut astfel: Button1.Attributes.Add("onclick","clientfunction();"). Putem specifica si o metoda dinamica care sa trateze mesajul evenimentului pe server.

2.3.7 Controalele de server in formularele de Web

Inaintea introducerii tehnologiei ASP.NET, paginile erau considerate programabile. Cand o pagina de Web era procesata de server, se folosea VBScript pentru personalizarea aspectului ei in functie de identitatea utilizatorului sau de alte informatii furnizate de utilizator. ASP.NET a dus aceasta tehnica mai departe. Pagina de Web este acum un formular de Web care contine controale de server.

Unul din aspectele care vor duce la o dezvoltare rapida a interfetelor utilizator pentru paginile WebForms il reprezinta aceste controalele server. Controalele server sunt folosite pentru a crea interfata-utilizator in paginile WebForms.

Caracteristicile acestora pot fi rezumate astfel: sunt componente care pot fi programate in server si care ofera un model orientat obiect ce poate fi mentionat in codul dintr-un formular de Web, incapsuleaza un mecanism de persistenta a starilor intre round-trip-uri, genereaza evenimente client care sunt tratate la server, la executie genereza cod compatibil browser-ului sau dispozitivului destinat (detectat in mod automat).

Exista doua tipuri de baza in care pot fi impartite controalele:

HTML Controls, reprezinta elemente HTML care pot fi programate la nivelul serverului si expun un model obiectual restrictionat la capabilitatile elementelor HTML pe care le afiseaza;

Web Controls, aduc facilitati superioare controalelor HTML incluzand controale mult mai complexe, iar modelul obiect nu reflecta neaparat sintaxa HTML.

Prin extensie, se definesc alte doua tipuri de controale, si anume:

Controale de validare incapsuleaza functionalitati care permit validarea intrarilor utilizatorului. Ele genereaza in mod automat cod pe partea de client (Jscript) care sa valideze intrarile utilizatorului pentru navigatoare mai performante. Acestea se ataseaza controalelor de intrare ale utilizatorului si furnizeaza mai multe tipuri de verificari ale datelor. Functionalitatea controalelor de validare poate fi dedusa usor din numele claselor de care sunt reprezentate: CompareValidator, CustomValidator, RangeValidator, RegularExpressionValidator, RequiredFieldValidator.

Controale utilizator (User Controls) sunt similare paginilor WebForms diferind de acestea prin faptul ca fisierele au extensia .ascx si nu contin tagurile <HTML>, <BODY>, <FORM>, aceste elemente aflandu-se in pagina gazda. Ele permit crearea de componente refolosibile.

Controalele server HTML (HtmlControls)

Controalele de server HTML (Html Controls) nu sunt ceva nou; ele sunt elementele HTML obisnuite carora le-au fost adaugate atribute speciale pentru procesarea in server. Fiecare element HTML poate fi programat pe server prin adaugarea atributului runat=”server” si asignarea unui atribut id=”[valoare]” pentru a putea fi referit controlul ca membru de clasa in codul de pe server.

Acest ID trebuie sa fie unic in cadrul paginii Web pentru a nu aparea conflicte de nume in tratarea lor pe server. Controalele HTML sunt instante ale claselor definite in spatiul de nume System.Web.UI.HtmlControls si sunt derivate direct/indirect din clasa de baza HtmlControl. In figura 2.3 este prezentata o ierarhie de clase HtmlControls.

De exemplu, urmatorul cod creeaza un control de editare text care este reprezentat la runtime de clasa System.Web.UI.HtmlControls.HtmlInputText:

<input type="text" runat="server" id="txEmail" value="email" />

ASP.NET furnizeaza controale HTML predefinite, de la formulare pana la controale pentru introducerea de informatii text pe una sau mai multe linii, de la checkbox-uri pana la controale de selectie, butoane de tip submit, list box-uri, tabele, imagini si alte controale corespunzatoare elementelor HTML.

Figura 2.3 Ierarhia de clase HtmlControls

Cand un WebForms continand controale HTML este procesat pe server, se creeaza cate o instanta pentru fiecare control, iar atributele acestora devin proprietati ale claselor corespunzatoare. Atributele nerecunoscute sunt ignorate, dar sunt accesibile pe server folosind colectia Attributes a clasei controlului.

Controalele HTML ASP.NET sunt utile atunci cand dorim sa convertim o aplicatie clasica HTML sau ASP la ASP.NET pentru a putea programa controalele la nivel de server. Mai mult, ele sunt o alegere buna atunci cand dorim sa programam controlul atat la client cat si la server deoarece sintaxa lor, in ambele parti, este identica (sunt tratate ca text simplu). In schimb, acestea prezinta si dezavantaje, cum ar fi faptul ca toate valorile controalelor sunt siruri de caractere, deci nu se aplica siguranta tipurilor oferita de platforma .NET, iar suportul pentru detectarea tipului navigatorului client lipseste.

In final, putem rezuma facilitatile oferite de controalele HTML:

un model obiectual prin care fiecare control server expune proprietati corespunzatoare atributelor unui element HTML folosind tehnici orientate obiect pentru programare;

abilitatea de a captura evenimente in script-urile client;

intretinerea automata a starilor controalelor, astfel incat daca pagina WebForms face un round trip pe server, atunci valorile introduse de utilizator sunt automat salvate si retrimise inapoi la browser;

posibilitatea de a scrie cod corespunzator evenimentelor client in aceeasi maniera si pentru server;

interactiune cu controalele de validare care pot verifica usor daca utilizatorul a introdus informatii corecte;

suport pentru CSS, daca browser-ul suporta standardul HTML 4.0 sau ulterior.

Controalele server ASP.NET (WebControls)

Pentru a abstractiza mai mult modelul de programare al paginilor WebForms, ASP.NET defineste un al doilea tip de controale – Web Controls. Numite si „controale inteligente”, ele pot fi caracterizate prin:

ofera un bogat si consistent model obiectual de programare;

detecteaza automat tipul navigatorului, iar afisarea la client va fi optimizata in functie de capabilitatile acestuia;

pentru unele controale se pot defini sabloane (template-uri) de afisare;

posibilitatea de a controla generarea evenimentelor pe server;

posibilitatea de a trimite evenimente unui container din interiorul acestuia (de exemplu, un control de tip buton in interiorul unui tabel);

legarea la surse de date a tuturor proprietatilor controalelor pentru a influenta afisarea la executie.

Controalele server ASP.NET sunt declarate cu eticheta <asp:servercontrol>, care face trimitere la spatiul de nume asp, unde servercontrol este denumirea controlului propriu-zis, pe care il definiti. Toate controalele server ASP.NET trebuie sa fie inchise corect, cu o eticheta de inchidere </asp:servercontrol>.

Adaugarea controalelor Web Controls in paginile WebForms se face in acelasi mod in care se adauga un element HTML. Totusi, sintaxa de reprezentare a unui control intr-un fisier .aspx (.ascx) respecta urmatoarele criterii:

conform sintaxei XML sunt declarate elemente care refera spatiul de nume asp;

toate elementele trebuie sa aiba marcaj de sfarsit;

includ atributul runat= ”server”;

au definit atributul ID care permite programarea controlului la nivel de server;

proprietatile controalelor sunt declarate ca atribute.

Fata de controalele HTML, controalele Web nu corespund elementelor HTML si, intr-un numar de aproximativ 30, ele acopera o gama larga de controale pentru programarea unor interfete utilizator complexe in cadrul paginilor Web.

Ele sunt definite in spatiul de nume System.Web.UI.WebControls si mostenesc, direct sau indirect, clasa de baza WebControl. O ierarhie a acestor clase poate fi urmarita in Figura 2.6.

Web Controls include o serie de controale traditionale ca Label, TextBox, Button pana la altele cu un nivel de abstractizare mai mare cum ar fi controalele Calendar, Repeater, DataList si DataGrid. Toate controalele derivand din clasa de baza WebControls beneficiaza de proprietati, metode si evenimente care sunt comune tuturor controalelor Web. Proprietati pentru a specifica: tipul, dimensiunea, culoarea fontului; culoarea background-ului; stilul, grosimea, culoarea border-ului; inaltimea si latimea controlului etc.

In continuare voi prezenta pe scurt aceste controale Web folosite in aplicatia realizata:

Label – Folosit pentru a afisa text static sau text conectat la o sursa de date in pagina.

TextBox – Permite editarea textului folosind mai multe moduri de utilizare prin proprietatea TextMode: editare pe o singura linie, pe linii multiple si pentru introducerea unei parole.

CheckBox – Creeaza o caseta de marcare care permite selectarea unei stari true sau false. Pentru utilizarea mai multor controale CheckBox exista alternativa controlului CheckBoxList cu posibilitati de legare la o sursa de date. Se pot specifica formate de afisare folosind proprietatile RepeatLayout si RepeatDirection.

CheckBoxList – Creeaza o lista de casete de marcare grupate care pot fi dinamic generate prin legarea la o sursa de date. Pentru a specifica un element care vrem sa apara in lista folosim controlul ListItem intre tag-urile de deschidere si inchidere a controlului CheckBoxList.

Figura 2.4 Ierarhia de clase WebControls

RadioButton – Ca si controlul CheckBox, acesta permite selectarea unui singur buton dintr-un grup definit.

RadioButtonList – Furnizeaza dezvoltatorului o singura selectie a unui buton radio dintr-un grup care poate fi generat dinamic dintr-o sursa externa de date (de exemplu,. o baza de date).

DropDownList – Este utilizata pentru selectarea unei optiuni dintr-un numar de optiuni afisate ca o lista „drop-down”. Aceasta lista poate fi conectata la o sursa de date externa.

ListBox – Este folosit pentru a genera o lista cu bara de derulare din care se pot selecta una sau mai multe optiuni.

Urmatoarele 4 controale sunt utilizate pentru trimiterea informatiilor introduse in formular. Atunci cand sunt apasate, continutul intregii pagini WebForms este trimis la serverul Web. Acestea genereaza evenimentul Click la server care poate fi tratat in codul programatorului.

Button – Creeaza un buton de apasare (push button) in pagina WebForms. Sunt doua tipuri de butoane care pot fi create: submit button sau command button.

LinkButton – Are aceeasi functionalitate ca a unui control Button, doar ca este afisat ca un hiperlink in pagina formular.

HyperLink – Folosit pentru crearea unei legaturi catre un alt URL. Controlul poate fi afisat ca text folosind proprietatea Text sau ca imagine utilizand proprietatea ImageUrl.

ImageButton – Folosit pentru a afisa in pagina imagini care raspund la evenimente de tipul Click. Are aceeasi functionalitate ca a unui control Button.

Panel – Reprezinta un container pentru alte controale si este util de folosit in situatia in care trebuie adaugate dinamic controale in pagina Web sau trebuie ascunse/afisate un grup de controale. De retinut ca acest control nu este vizual, doar grupeaza logic un grup de controale din interiorul acestuia.

Table, TableRow, TableCell – Aceste controale permit construirea unui tabel HTML dinamic folosind acelasi model abstract orientat obiect pentru construirea altor controale.

Calendar – Selectarea datei poate fi facuta acum mult mai elegant, solutie oferita de controlul Calendar. Acesta permite afisarea unei singure luni, selectarea datei, trecerea de la o luna la alta. Pune la dispozitia programatorului diferite proprietati pentru specificarea stilului de afisare si a modului de selectare a datei. Folosind proprietatea SelectionMode se poate specifica selectarea unei singure zile, a unei saptamani sau a intregii luni. Controlul suporta toate tipurile de calendar definite in spatiul de nume System.Globalization.

La ora actuala, majoritatea aplicatiilor Web folosesc un sistem de gestiune al bazelor de date in spatele aplicatiei. In sprijinul unei bune prezentari a acestor surse de date, platforma .NET include un set de trei controale (Repeater, DataList, DataGrid) ce fac posibila afisarea unor mari cantitati de date foarte usor.

Sursa de date reprezinta o multime specifica de date care poate fi reprezentata de un server de baze de date (MS SQL Server), un fisier XML sau o colectie de date care implementeaza interfata System.Collections.IEnumerable. Operatie prin care se afiseaza surselor de date se numeste legarea datelor (data binding).

Controale care permit legarea datelor ofera o metoda DataBind() care realizeaza legarea datelor de la sursa de date specificata prin proprietatea DataSource. Pentru a forta actualizarea tuturor legaturilor se poate apela metoda Page.DataBind() care are ca rezultat actualizarea legaturilor din pagina.

Repeater

Reprezinta o simpla lista conectata la o sursa de date care foloseste sabloane pentru afisarea informatiilor. Fara un sablon predefinit, programatorul este nevoit sa-si defineasca propriul model de afisare folosind elemente HTML. In schimb, controlul este singurul care ofera libertate maxima in definirea modului de afisare, a stilului si formatarii.

Pentru a realiza legarea datelor trebuie introdusa intre caracterele <%# %> o referinta la o valoare care trebuie legata. In cadrul tagurilor ItemTemplate se definesc elementele care sunt interpretate o singura data pentru fiecare rand din sursa de date. Pentru afisarea datelor din sursa de date se foloseste o expresie de legare (data-binding expression) la un camp (field) din sursa de date a repeater-ului. De exemplu, putem avea:

<ItemTemplate>

<a href='mailto:<%# DataBinder.Eval(Container.DataItem, "Email")

%>'><%# DataBinder.Eval(Container.DataItem, "Nume") %></a>

</ItemTemplate>

DataList

In completarea unor functionalitati predefinite, controlul DataList afiseaza inregistrarile unei surse de date folosind sabloane existente, dand posibilitatea totodata sa ne definim propriile modele de afisare, sa selectam si sa editam articolele.

DataGrid

Controlul DataGrid este o grila multicoloana, care afiseaza inregistrari conectate la o sursa de date, oferind optiuni pentru selectarea, sortarea, paginarea si editarea datelor.

Fiecare camp din baza de date este afisat in coloane separate in ordinea aparitiei in baza de date. Implicit, proprietatea AutoGenerateColumn este setata pe true, ceea ce inseamna crearea unui obiect BoundColumn pentru fiecare inregistrare din sursa de date. Se pot controla ordinea, functionarea si afisarea fiecarei coloane. DataGrid-ul suporta mai multe tipuri de coloane oferind diferite functionalitati de baza in prelucrarea datelor:

BoundColumn, afiseaza fiecare articol dintr-o inregistrare ca text simplu;

ButtonColumn, afiseaza un buton de comanda pentru fiecare articol dintr-o coloana. Acesta permite crearea de controale Button cu functionalitati gen Adaugare si Stergere;

EditCommandColumn, afiseaza o coloana care contine comenzi de editare pentru fiecare articol dintr-o coloana;

HyperLinkColumn, afiseaza fiecare articol dintr-o coloana ca un hyperlink;

TemplateColumn, afiseaza fiecare articol dintr-o coloana folosind un sablon specificat.

Putem spune ca secretul functionarii controalelor server il reprezinta atributul runat="server" care activeaza lucrul cu evenimente pe partea de server si intretine starea controalelor intre round-trip-uri. Fara acest atribut, controlul este tratat ca un simplu element HTML care nu beneficiaza de posibilitatea tratarii evenimentelor pe partea de server si nici nu sunt mentinute starile intre round-trip-uri. Acelasi atribut, adaugat elementului <FORM> intretine starea tuturor controalelor formularului dintr-o pagina ASP.NET. Cand o pagina este trimisa la server, ASP.NET verifica in mod automat daca starea controalelor s-a modificat, stare pe care o memoreaza apoi intr-un control ascuns numit _VIEWSTATE. In acest mod, starea intregii pagini WebForms poate fi salvata de-a lungul unor accesari succesive ale aceluiasi formular.

ASP.NET suporta diferite solutii pentru gestionarea starilor in cadrul aplicatiilor Web:

la client: folosind proprietatea ViewState, controale Hidden, Cookies, Query Strings;

la server: la nivel de aplicatie, la nivel de sesiune, stari memorate intr-o baza de date.

2.3.8 Validarea in formularele de Web

Cand creati aplicatii pentru Web, este important sa asigurati conditiile ca datele de intrare introduse de utilizator sa fie introduse corect. Aceasta se face prin operatia de validare, prin care se verifica daca valoarea introdusa indeplineste o anumita conditie si se returneaza un mesaj de eroare daca acea conditie nu este indeplinita. In paginile ASP.NET, validarea se face cu ajutorul unor controale de validare din interfata server care verifica daca valoarea transmisa de un control de intrare indeplineste diferite tipuri de situatii de eroare si afiseaza o descriere a problemei daca este indeplinita una din situatii. Mediul ASP.NET mareste in mod semnificativ productivitatea programatorului in scrierea codului de validare.

In ASP.NET se pot folosi controale de validare pentru aproape toate controalele de intrare dintr-o pagina, care sunt fie controale server HTML, fie controale server dintr-un formular de Web. Aceluiasi control de intrare ii pot fi asociate mai multe tipuri de controale de validare, permitand astfel validarea in functie de criterii multiple.

La generarea unei pagini ASP.NET cu controale de validare, valorile controalelor de intrare legate de controalele de validare sunt procesate in functie de codul corespunzator indicat de controalele de validare. Dupa evaluarea tuturor conditiilor, proprietatile controalelor de validare sunt definite ca True sau False, in functie de rezultatul evaluarii. Dupa procesarea tututror controalelor de validare, pagina propriu-zisa defineste o proprietate in functie de valorile proprietatilor stabilite de validarea controalelor. Daca unul din controalele nu a fost validat, pagina defineste in mod automat proprietatea de validare cu valoarea False (proprietatea Page.IsValid).

Controale de validare

ASP.NET are sase tipuri de controale de validare: RequiredFieldValidator, RegularExpressionValidator, CompareValidator, RangeValidator, CustomValidator si ValidationSummary. Toate aceste controale folosesc un set de proprietati si metode comune, acestea fiind, in cea mai mare parte, mostenite de la clasa BaseValidator, de la clasa WebControl si de la clasa Control. O exceptie de la aceasta regula o reprezinta proprietatea Text, care este mostenita de la clasa Label.

Cele mai importante proprietati comune ale controalelor de validare sunt ControlToValidate, ErrorMessage, Display, Enabled, Text si IsValid. Acestea sunt principalele proprietati pe care le veti folosi in asociere cu controalele de validare.

Cea mai importanta metoda este metoda Validate – evalueaza valabilitatea si actualizeaza proprietatea IsValid pentru controlul de validare. Aceasta este apelata frecvent pentru a verifica daca datele introduse in controale sunt corecte.

RequiredFieldValidator – Verifica daca utilizatorul a introdus sau a selectat o valoare din controlul de intrare. Are o proprietate specifica numai lui: proprietatea InitialValue – valoarea initiala care trebuie comparata cu valoarea controlului care trebuie verificat. Daca valoarea controlului specificat este egala cu valoarea proprietatii InitialValue, validarea controlului respectiv esre refuzata.

RegularExpressionValidator – Verifica daca o intrare corespunde unui model definit de o expresie „regular expression”. Aceasta este un model de text format din caractere obisnuite si caractere deosebite, numite metacaractere. Acest gen de validare permite cautarea unor siruri de caractere previzibile, cum ar fi cele din adresele de e-mail, numerele de telefon, codurile postale. Controlul are asociata o proprietate specifica numai lui: ValidationExpression. Ea specifica expresia care defineste criteriile de validare.

CompareValidator – Compara valoarea unui control cu valoarea unui alt control. Acest gen de control este util mai ales pentru un camp de confirmare a parolei. Are asociate mai multe proprietati specifice numai lui, cum ar fi ControlToCompare, ValueToCompare, Type si Operator.

RangeValidator – Compara valoarea unui control de intrare cu un interval de valori. Intervalul de valori poate fi reprezentat de doua numere, doua caractere sau doua zile calendaristice. Controlul RangeValidator mai are si proprietatile: MinimumValue, MaximumValue si Type.

CustomValidator – Permite crearea unui sistem de validare personalizat pentru controalele ASP.NET. Acest gen de control este folosit de regula pentru validarea valorilor prin comparatie cu o baza de date sau pentru validarea unui control printr-o rutina de validare care nu a fost inca definita. Functia de validare este scrisa atat pentru server, cat si pentru client. Pentru controlul CustomValidator trebuie definite o proprietate si o metoda. Proprietatea este ClientValidationFunction care defineste numele functiei din interfata client care trebuie apelata pentru a executa operatia de validare. Metoda care trebuie definita este OnServerValidate care specifica ce functie din interfata server trebuie apelata pentru executarea rutinei de validare.

ValidationSummary – Colecteaza mesajele de eroare definite de fiecare control de validare din pagina si le afiseaza pe toate in acelasi loc. Proprietatile asociate cu controlul ValidationSummary sunt :

DisplayMode – defineste modul in care cor fi afisate pe ecran mesajele de eroare. Cele trei optiuni de afisare sunt BulletList, List si SingleParagraph.

HeaderText – defineste textul care va fi afisat deasupra listei mesajelor de eroare.

ShowMessageBox – defineste daca datele din sinteza mesajelor sunt afisate (sau nu) intr-o caseta de mesaje pop-up in urma unei apelari prin JavaScript.

ShowSummary – defineste daca mesajele va fi afisat alaturi de alte elemente din pagina.

In acest capitol am prezentat cel mai nou mediu de dezvoltare pentru Web creat de Microsoft, Tehnologia ASP.NET. Am discutat despre urmatoarele aspecte:

Avantajele ASP.NET fata de alte tehnologii exitente

Ce este ASP.NET?

WebForms (formularele de Web), o tehnologie ASP.NET care ii permite programatorului sa creeze pagini de Web dinamice, pe baza codului de executie

Modul de functionare a tehnologiei ASP.NET

Elementele constitutive ale unui WebForms si tratarea evenimentelor in WebForms

Controalele de server folosite in formularele de Web (HtmlControls, WebControls)

Validarea in ASP.NET (Controale de validare)

Tehnologia pe care platforma .NET o ofera prin ASP.NET, alaturi de limbajul C#, un limbaj elegant si totodata performant, robust si productiv, si de cea mai recenta tehnologie Microsoft pentru accesul la date ADO.NET, va conduce la dezvoltarea aplicatiilor Web complexe pentru organizatii mari, intreprinderi care vor putea interopera folosindu-se de serviciile Web.

ASP.NET, prin WebForms, imprumuta stilul de programare Visual Basic folosind form-uri si evenimente si il transpune pe Web oferind productivitate maxima in construirea aplicatiilor Web. Mai mult, modelul abstract orientat pe obiecte al mediului ASP.NET va conduce la o dezvoltare rapida a componentelor unei aplicatii Web, deci la aplicatii cu interfete utilizator bogate in posibilitati de prezentare a informatiilor.

ASP.NET a fost dezvoltat pentru a lucra asemenea editoarelor WYSIWYG (What You See Is What You Get) HTML, cu utilitare de programare ca Micosoft Visual Studio.NET, mediu care pe langa un GUI pe care dezvoltatorii il pot utiliza pentru a adauga controale server in paginile WebForms, ofera suport integrat complet pentru depanarea aplicatiilor Web.

In ASP.NET, mediul prin care se obtine accesul si se manevreaza datele dintr-o baza de date este ADO.NET.

In continuare as dori sa va prezint cea mai recenta tehnologie Microsoft pentru accesul la date, ADO.NET. Voi prezenta posibilitatile de lucru cu bazele de date prin ASP.NET si ADO.NET.

2.4 ADO.NET

Aproape orice aplicatie creata pentru domeniul comercial foloseste o anumita forma de stocare a datelor. Indiferent daca folositi o foaie de calcul din Excel, un fisier de text sau un sistem de gestionare a bazelor de date relationale (RDBMS) cum ar fi SQL Server, operatiile de stocare si de incarcare a datelor sunt esentiale pentru succesul aplicatiei.

In acest capitol voi prezenta posibilitatiile de lucru cu date prin ASP.NET si ADO.NET.

2.4.1 Ce este ADO.NET?

La crearea aplicatiilor pentru Web, accesul in bazele de date se realizeaza de regula, din serverul de Web propriu-zis. Exista anumite situatii in care legatura la baza de date va fi facuta printr-un al server, dar in general nu se realizeaza nici o legatura la baza de date din calculatorul utilizatorului.

ASP.NET si alte limbaje pentru crearea aplicatiilor de Web au un set de instrumente care pot fi folosite pentru accesul intr-o baza de date. Aceste instrumente permit conectarea la o baza de date si manevrarea datelor pe care le contine aceasta, cu ajutorul limbajului SQL sau a unui alt instrument care creeaza o interfata cu datele respective. In ASP.NET, mediul prin care se obtine accesul si se manevreaza datele dintr-o baza de date este ADO.NET.

ADO din ADO.NET vine de la ActiveX Data Objects. Acesta este cea mai recenta versiune a tehnologiei universale Microsoft pentru accesul la date, care le permite programatorilor sa poata lucra cu aproape orice program pentru baze de date de pe piata.

In ADO.NET exista numeroase spatii de nume care pot fi folosite de programatori in lucrul cu date si cu bazele de date. Doua astfel de spatii de nume importante sunt obiectul DataSet si setul Managed Provider. Obiectul DataSet este o componenta de baza pentru manevrarea datelor din bazele de date. El reprezinta un set complet de date dntr-o baza de date, care cuprinde tabele, constrangeri si relatii dintre tabele. Spre deosebire de versiunile anterioare ale tehnologiei ADO, obiectele DataSet din ADO.NET pot contine mai multe seturi de inregistrari, iar inregistrarile respective pot fi manevrate in cadrul obiectului DataSet.

A doua parte a mediului ADO.NET este setul Managed Provider. Acesta defineste tipurile de legaturi si mediaza comunicatiile dintre aplicatie, obiectul DataSet si baza de date. In prezent exista doua tipuri de componente Managed Provider: SQL Server Managed Provider si OleDB Managed Provider. SQL Server Managed Provider furnizeaza toate instrumentele necesare pentru comunicarea eficienta intre aplicatie si baza de date Microsoft SQL Server. OleDB Managed Provider furnizeaza toate instrumentele necesare pentru comunicarea eficienta intre aplicatie si toate sursele de date compatibile cu OleDB.

2.4.2 Accesul la date prin ADO.NET

System.Data, System.Data.SqlClient si System.Data.OleDb sunt spatiile de nume care definesc accesul in baza de date prin ADO.NET. Pentru a folosi ADO.NET la accesul in baza de date va trebui sa importati aceste spatii de nume in aplicatie.

System.Data este spatiul de nume general care contine toate clasele ce formeaza nucleul arhitecturii mediului ADO.NET.

System.Data.OleDb este spatiul de nume al setului ADO.NET Managed Provider pentru toate sursele de date compatibile OLE DB.

System.Data.SqlClient este spatiul de nume pentru SQL Server Managed Provider. Acest spatiu de nume a fost scris special pentru Microsoft SQL Server si a marit avantajele in privinta performantei fata de versiunile anterioare de SQL Server.

2.4.2.1 Conectarea la o baza de date SQL Server

La crearea unei aplicatii in ASP.NET trebuie sa va connectati la o baza de date pentru extragerea sau manevrarea datelor. Cu ajutorul mediului ADO.NET puteti realiza cu usurinta accesul in baza de date si sa lucrati cu datele folosind o multime de mijloace. ADO.NET ofera o paleta bogata de facilitati puternice pentru lucrul cu date in paginile ASP.NET.

Primul pas in lucrul cu orice baza de date este conectarea la baza de date. Cand o aplicatie trebuie sa foloseasca date, se leaga la baza de date, iar datele sunt transmise catre aplicatie prin legatura stabilita.

In cazul mediului ADO.NET exista doua moduri de connectare la o baza de date, iar folosirea unuia dintre ele depinde de tipul de date cu care se stabileste legatura. In cazul in care connectarea se face la o baza de date Microsoft SQL Server, se foloseste obiectul SqlConnection; daca se face connectarea la un alt tip de baza de date, cum ar fi Oracle, se foloseste obiectul OleDbConnection. Spatiile de nume necesare pentru conectarea la bazele de date SQL Server si manevrarea datelor sunt System.Data si System.Data.SqlClient.

In continuare voi prezenta pe scurt obiectele necesare pentru accesul la datele dintr-o baza de date SQL Server : SqlConnection, SqlCommand, SqlDataReader.

Obiectul SqlConnection

Cand vreti sa va connectati din aplicatie la o baza de date Microsoft SQL Server, trebuie sa folositi obiectul SqlConnection. Pentru a folosi acest obiect trebuie mai intai sa imporati spatiul de nume System.Data.SqlClient in aplicatie, folosind cuvantul-cheie Import. Dupa adaugarea acestui spatiu de nume, veti avea acces la obiectul clasa SqlConnection.

Obiectul SqlConnection are o multitudine de proprietati si metode care pot fi folosite la construirea aplicatiei.

Cand se creeza o legatura la o baza de date SQL Server, legatura poate fi definita cu ajutorul clasei SqlConnection. O alta varianta este folosirea proprietatii ConnectionString:

SqlConnection conn = new SqlConnection();

conn.ConnectionString = ”server=localhost; user id=sa; pwd=; database=db”; conn.Open();

Se poate folosi si o comanda directa pentru proprietatea ConnectionString, prin introducerea valorii sirului legaturii la declararea obiectului SqlConnection. Pentru aceasta se foloseste urmatoarea sintaxa: SqlConnection conn = new SqlConnection (”server= localhost; user id=sa; pwd=; database=ECommerce”);

Obiectul SqlCommand

Dupa ce am realizat legatura la baza de date, trebuie gasita modalitatea de executie a interogarilor in SQL. Pentru acesta, in ADO.NET poate fi folosit obiectul SqlCommand.

Obiectul SqlCommand are rolul de purtator de date prin legatura creata de obiectul SqlConnection la baza de date. El este format din mai multe proprietati si metode care il ajuta pe programator la manevrarea datelor.

Pentru a initializa obiectul SqlCommand trebuie folosita urmatoarea sintaxa:

SqlCommand myCommand = new SqlCommand(mySqlQuery, mySqlConn),

unde: mySqlQuery este instructiunea din SQL care trebuie executata, iar mySqlConn este denumirea obiectului SqlConnection care va fi folosit ca legatura la baza de date.

De exemplu, pentru a extrage toate randurile tabelului Items din baza de date E-Commerce, trebuie folosit urmatorul cod:

string mySqlQuery = "SELECT * FROM Items";

SqlConnection myConn = new SqlConnection(”server=localhost;

user id=sa; pwd=; database=ECommerce”);

SqlCommand myCommand = new SqlCommand(mySqlQuery, myConn);

myConn.Open();

SqlDataReader myReader = myCommand.ExecuteReader(); …

myConn.Close();

Daca vreti sa executati o instructiune SQL care nu returneaza nici un rand de date (de exemplu, o interogare UPDATE, o instructiune INSERT sau o instructiune DELETE), trebuie sa folositi metoda ExecuteNonQuery a obiectului SqlCommand. De remarcat ca trebuie deschisa in mod explicit legatura atunci cand se foloseste obiectul SqlCommand pentru apelarea metodei ExecuteNonQuery.

Acest lucru este valabil si daca se apeleaza o interogare pentru returnarea de inregistrari dintr-o sursa de date. De retinut ca trebuie inchisa in mod explicit legatura la sursa de date dupa fiecare apelare a bazei de date. Desi orice legatura deschisa la o baza de date va fi in cele din urma inchisa in mod automat, exista riscul depasirii numarului de legaturi permise la o sursa de date. Intr-un astfel de caz, aplicatia va da o eroare din cauza imposibilitatii de a lucra cu baza de date.

Daca in loc sa actualizati, vreti sa extrageti inregistrarile dintr-o baza de date, trebuie sa folositi un al treilea obiect pentru plasarea datelor respective. In mod normal se foloseste un obiect DataSet pentru plasarea acestor date. In DataSet sunt plasate seturi de date deconetate, care sunt pastrate la dispozitia aplicatiei pana cand sunt eliminate de aplicatie. Dar se poate folosi si obiectul SqlDataReader pentru a extrage inregistrari dintr-o baza de date.

Obiectul SqlDataReader

Obiectul SqlDataReader este folosit pentru generarea unui grup de inregistrari forward-only si read-only. Caracteristica forward-only se refera la faptul ca se poate face trecerea printre inregistrari numai intr-o singura directie: de la inceput spre sfarsit. Caracteristica read-only se refera la faptul ca datele nu pot fi actualizate prin obiectul SqlDataReader. Obiectul SqlCommand are nevoie de un anumit tip de container in care sa plaseze datele extrase din baza de date. Obiectul SqlDataReader este containerul de date pentru obiectul SqlCommand.

SqlDataReader are o multime de proprietati si metode la care puteti apela.

Iata sintaxa pentru folosirea obiectului SqlDataReader:

SqlDataReader myReader = myCmd.ExecuteReader();

Acest cod creeaza o noua instanta a obiectului SqlDataReader. Pentru ca datele sa fie anexate obiectului SqlDataReader, se executa comanda myCmd.ExecuteReader(). Dupa apelul metodei ExecuteReader fara generarea de erori, obiectul SqlDataReader va contine datele specificate in proprietatea CommandText a obiectului SqlCommand.

2.4.2.2 Manevrarea datelor din bazele de date

In subcapitolul anterior am prezentat cum se realizeaza conectarea la o baza de date si cum se extrag inregistrari cu ajutorul obiectelor SqlCommand. De asemenea am prezentat notiunile fundamentale pentru folosirea obiectului SqlDataReader in vederea afisarii pe ecran a datelor extrase. In acest subcapitol voi prezenta folosirea instructiunilor SQL parametrizate pentru manevrarea dinamica a bazelor de date si colectia Parameters a clasei SqlCommand.

ASP.NET simplifica in mod semnificativ manevrarea dinamica a bazelor datelor pe baza datelor introduse de utilizator prin introducerea instructiunilor SQL parametrizate. Vom folosi o proprietate a clasei SqlCommand, colectia Parameters.

Parametrizarea clasei SqlCommand ofera mai multe avantaje. Ea ajuta la validarea datelor, mareste lizibilitatea codului, asigura o flezibilitate sporita datorita modelului orietat pe obiecte si, cel mai important, foloseste declaratii explicite pentru tipul de date. Deoarece informatiile despre tipul de date sunt compilate in codul ASP.NET, definirea tipului de date nu este facuta la executie de SQL Server, ceea ce mareste viteza de executie.

Clasa SqlParameters

Clasa SqlParameters are metodele Add, Clear, Contains, Remove si urmatoarele proprietati:

Count: Aceasta proprietate returneaza numarul de parametri din colectie.

Item: Aceasta proprietate returneaza obiectul SqlParameter cu atributul specificat.

Clasa SqlParameter

Clasa SqlParameter are urmatoarele proprietatile:

Direction – Returneaza sau defineste daca parametrul este de intrare, de iesire, bidirectional sau un parametru de valoare returnata.

ParameterName – Returneaza sau defineste denumirea obiectului SqlParameter.

SourceColumn – Returneaza sau defineste denumirea coloanei-sursa asociata setului de date si folosita pentru incarcarea sau returnarea unei valori.

Value – Returneaza sau defineste valoarea parametrului.

Exemplu de folosire a instructiunilor SQL parametrizare:

string mySqlQuery = "SELECT * FROM Items ” +

WHERE CategoryID = @pCategoryID";

SqlConnection myConn = new SqlConnection(”server=localhost; user

id=sa; pwd=; database=ECommerce”);

SqlCommand myCommand = new SqlCommand(mySqlQuery, myConn);

SqlParameter pCategoryID = new SqlParameter( ”@pCategoryID”,

SqlDbType.Int,4);

pCategoryID.Value = 1001; myCommand.Parameters.Add(pCategoryID);

sau:

myCmd.Parameters.Add(new SqlParameter("@pCatID",SqlDbType.Int) );

myCommand.Parameters[”@pCategoryID”].Value = 1001;

La adaugarea unui parametru SQL in colectia Parameters a obiectului SqlCommand trebuie specificati numele, tipul, marimea parametrului, si de asemenea i se poate atribui o valoare care de cele mai multe ori va fi citita dintr-un formular Web. Aceasta este o modalitate simpla prin care se pot folosi comenzile SQL parametrizate pentru selectarea, inserarea, actualizarea si stergerea inregistrarilor dintr-o baza de date (manevrarea dinamica a datelor). O alta modalitate de optimizare a comenzilor SQL parametrizate este prin implementarea procedurilor stocate cu ajutorul programului SQL Server.

Executarea procedurilor stocate SQL Server

Executia procedurilor stocate in mediul ADO.NET seamana foarte mult cu executia unei instructiuni SQL. Exista totusi cateva deosebiri seminificative. Prima deosebire este ca, atunci cand cream obiectul SqlCommand, folosim o trimitere la denumirea procedurii stocate in loc sa introducem intructiunea SQL. A doua deosebire este ca, dupa ce am creat obiectul SqlCommand, trebuie sa atribuim valoarea StoredProcedure prorietatii CommandType:

SqlCommand myCmd = new SqlCommand(”my_procedure”, myConnection);

myCmd.CommandType = CommandType.StoredProcedure;

De asemenea denumirea parametrilor din colectia Parameters a obiectului SqlCommand trebuie sa corespunda cu parametrii declarati in procedura stocata. Se poate stabili si directia fiecarui parametru prin proprietarea Direction a obiectului SqlParameter care poate avea valoarea ParameterDirection.Input sau ParameterDirection.Output. Se pot atribui valori parametrilor prin proprietatea Value.

2.4.3 Seturile de date ADO.NET

Unul dintre elementele fundamentale ale arhitecturii ADO.NET este setul de date.

In acest subcapitol voi prezenta unul dintre blocurile structurale principale ale mediului ADO.NET, obiectul DataSet, proprietatile si metodele sale, precum si obiectele sale corespondente, obiectul DataTable, obiectul DataColumn, obiectul DataRow si obiectul DataRelation, fiecare dintre ele jucand un rol esential in crearea si manevrarea obiectului DataSet. De asemenea voi prezenta cum se poate modifica si actualiza o baza de date cu ajutorul obiectului DataSet prin intermediul obiectului DataAdapter.

2.4.3.1 Obiectele pentru citirea datelor din ADO.NET

Obiectul DataSet

Principalul obiect pentru manevrarea datelor din ADO.NET este setul de date. Setul de date (DataSet) este o structura complexa care contine mai multe obiecte. In figura 2.5 este prezentata o ierarhie a componentelor care alcatuiesc un DataSet.

Figura 2.5 Componentele unui DataSet.

Obiectul DataSet poate fi definit ca un sector cache in memoria pentru date, cu o structura similara unei baze de date. Seamana foarte mult cu o baza de date pentru ca este format din obiecte DataTable, care la randul lor pot fi asociate intre ele cu ajutorul obiectelor DataRelation. Obiectele DataTable sunt foarte asemanatoare ca marime si structura cu tabelele obisnuite din bazele de date, iar obiectele DataRelation seamana foarte mult cu relatiile prin cheie straina.

Spre deosebire de versiunile anterioare ale mediului ADO, obiectul DataSet din ADO.NET inregistreaza datele numai in format XML si intr-un mediu fara stari. Principalul avantaj al folosirii datelor fara stare este ca programatorii care folosesc limbaje de programare compatibile cu XML, cum ar fi Java, C#, pot folosi setul de date XML din aplicatia dumneavoastra in aplicatiile lor.

Pentru a folosi obiectul DataSet trebuie inclus in aplicatie spatiul de nume corespunzator System.Data. Spatiul de nume System.Data asigura si accesul la diferitele obiecte folosite pentru generarea unui set de date. Aceste obiecte sunt DataTable, DataRelation, DataColumn, DataRow si DataAdapter. In acest subcapitol voi prezenta pe scurt fiecare din aceste obiecte.

Obiectul DataTable

Obiectul DataTable reprezinta un tabel cu date dintr-un set de date. Este format dintr-o colectie de coloane, numita DataColumnCollection, derivata din obiectul DataColumn, si o colectie de randuri, numita DataRowCollection, derivata din obiectul DataRow. Colectia DataColumnCollection defineste schema sau structura acestui tabel. DataRowCollection contine datele tabelului si actualizeaza starea datelor din tabel, urmarind fiecare schimbare a lor. De asemenea, contine o copie completa in starea lor initiala, in caz ca modificarile operate asupra datelor ar fi anulate.

Obiectul DataColumn

Obiectul DataColumn este un element-cheie pentru definirea schemei unui tabel. Schema tabelului ii defineste structura si tipul de date ce pot fi plasate in fiecare coloana. Obiectul DataColumn are urmatoarele proprietati importante: AllowDBNull, AutoIncrement, ColumnName, DataType, ReadOnly. Obiectul DataColumn are metodele OnPropertyChanging, care declanseaza evenimentul OnPropertyChanging, si VerifyUnique, care returneaza o valoare pentru a verifica daca valoarea unei coloane este distincta.

Obiectul DataRow

Colectia DataRowCollection a obiectului DataTable contine datele plasate in tabelul de date. Obiectul DataRow lucreaza impreuna cu obiectul DataColumn, definind schema pentru datele plasate in obiectul DataRow. Metodele obiectului DataRow sunt modul prin care datele dintr-un tabel sunt vizualizate, inserate, sterse, actualizate.

Obiectul DataRelation

Obiectul DataRelation este folosit pentru crearea relatiei intre doua obiecte DataTable. Aceasta relatie este configurata intr-un obiect DataColumn din fiecare obiect DataTable care are exact acelasi tip de date. Dupa stabilirea relatiei, obiectul DataRelation va valida toate introducerile de date pentru a verifica daca indeplinesc constrangerile definite de relatia creata. Daca intr-un rand se insereaza un tip de date incorect, obiectul DataRelation va capta eroarea, va marca inserarea ca fiind incorecta si va declansa o eroare de exceptie.

2.4.3.2 Comunicarea cu DataSet

Obiectul DataAdapter

Nu se poate discuta despre DataSet fara sa mentionam una dintre utilizarile sale fundamentele: comunicarea cu baza de date. Daca dorim sa populam obiectul DataSet dintr-o baza de date sau sa actualizam o baza de date dintr-un set de date, trebuie sa folosim o clasa speciala DataAdapter (clasele SqlDataAdapter sau OleDbDataAdapter), incluse in mediul .NET, pentru a facilita transferul datelor din setul de date in baza de date si invers. Trebuie mentionat ca exista cate un „data adapter” pentru fiecare provider. Tipul obiectului DataAdapter, SqlDataAdapter sau OleDbDataAdapter, depinde de sursa de date din care se doreste extragerea datelor.

Aceasta clasa stie cum sa „adapteze” datele dintr-o sursa de date RDBMS la formatul obiectului DataSet si invers. Stie cum sa transfere informatia din DataSet in baza de date asociata efectuand operatiile necesare (insert, update, delete). Imaginati-va ca DataAdapter este un container care detine comenzile bazei de date. Aici sunt pastrate obiectele care executa operatiile de selectare, actualizare, inserare, stergere (SELECT, UPDATE, INSERT, DELETE) asupra bazei de date. In figura urmatoare este prezentat mecanismul de comunicare dintre DataSet si baza de date prin intermediul obiectului DataAdapter.

Figura 2.6 Comunicarea DataSet – Database

Pentru extragerea datelor dintr-o baza de date intr-un set de date este nevoie de un obiect DataAdapter, care este de fapt un „canal” de comunicare.

DataAdapter este o clasa abstracta de baza care defineste functionalitatile de baza pe care trebuie sa le aiba orice astfel de clasa.

In tabelele 2.1 si 2.2 sunt prezentate proprietatile si metode obiectului DataAdapter.

Tabelul 2.1 Proprietatile obiectului DataAdapter

Tabelul 2.2 Metodele obiectului DataAdapter

2.4.4 Rezumat ADO.NET

In acest capitol v-am prezentat strategiile de lucru cu bazele de date in ADO.NET. ADO.NET porneste de la un model in care utilizatorul deschide o conexiune, executa operatiile dorite (selectare date, modificare date) apoi inchide conexiunea.

In concluzie exista doua strategii de lucru cu bazele de date in ADO.NET:

1. Executarea operatiilor direct in baza de date. Pentru aceasta se utilizeaza un obiect de tip Command. Daca obiectul Command returneaza date (SELECT …), acestea pot fi stocate intr-un obiect de tip DataReader.

Avantaje:

posibilitatea executiei comenzilor SQL de tip Data Definition Language(DDL);

overhead redus (obiectele de tip DataSet utilizeaza cantitati mari de memorie);

productivitate la programare (in cele mai multe cazuri).

2. Stocarea datelor in memorie, intr-un obiect de tip DataSet (obiect pastrat in memorie, cu care se poate lucra si dupa deconectarea de la sursa de date). Aceasta strategie implica si crearea unui obiect de tip DataAdapter cu care se preiau datele de la sursa de date. In final datele pot fi scrise in baza de date utilizand, de asemenea, un obiect de tip DataAdapter.

Avantaje:

posibilitatea de a lucra cu mai multe tabele simultan;

manipularea datelor din mai multe surse de date simultan (din baze de date diferite, fisiere XML etc.);

facilitarea schimbului de date cu alte aplicatii (componente) prin XML;

legarea usoara la diverse controale (data-binding);

utilizarea datelor fara reinterogarea bazei de date;

posibilitatea generarii unor clase care sa reprezinte structura DataSet-ului. Obiectele astfel definite fac lucrul cu datele extrem de usor.

Exemple de folosire a strategiilor de lucru cu bazele de date prin ADO.NET in aplicatiile ASP.NET sunt prezentate in Capitolul 10 „Anexe”.

3. Memoriu Justificativ

La proiectarea arhitecturii aplicatiei si implementarea proiectului s-a urmarit realizarea cerintelor specificate in obiectivul acestei lucrari. Prin lucrarea de fata s-a urmarit studiul, proiectarea si implementarea unei aplicatii de comert electronic pe Internet ca o alternativa la solutiile existente in prezent.

Obiectivul propus a fost acela de dezvoltare a unei aplicatii de comert electronic care sa permita realizarea operatiunii de vanzare prin intemediul unui magazin virtual pe Internet.

Pe langa implementarea functiilor de baza pe care trebuie sa le ofere orice aplicatie de comert electronic (magazin virtual) s-a stabilit ca si obiectiv implementarea unor functionalitati suplimentare drept contributii personale la proiect si care sa diferentieze aplicatia de solutiile existente.

Obiectivul propus a fost acela de realizare a partii ”vizibile” a unui magazin virtual (partea de Internet) fara a implementa partea de administrare a magazinului care va fi obiectivul unui viitor proiect. Aceasta deoarece in urma studiului efectuat s-a observat ca interfata cu utilizatorul este foarte importanta si de aceasta depinde in mare masura succesul aplicatiei. Astfel s-a insistat pe realizarea unei interfete cu utilizatorul cat mai prietenoasa si mai placuta care sa fie cat mai usor de utilizat.

Desi exista mai multe tehonologii Web prin care se putea realiza o astfel de aplicatie, am ales, ASP.NET, datorita facilitatilor oferite in realizarea unei astfel de aplicatii si avantajelor pe care le prezinta fata de tehnologiile existente.

In acest capitol precedent au fost descrise si explicate tehnologiile folosite in lucrarea de fata, toate aceste pentru o mai buna intelegere a modului de operare si functionare a aplicatiei.

In acest capitol voi prezinta detaliat modul de implementare si de realizare al obiectivului propus, modelul aplicatie realizate, arhitectura si nivelele sistemului, contributiile personale relativ la tema aleasa.

3.1 Consideratii generale

Inainte de a descrie arhitectura aplicatiei sunt necesare cateva prezizari. Dat fiind faptul ca in zilele noastre prin intermediul comertului electronic, o organizatie poate avea clienti in orice colt al lumii au fost necesare cateva masuri speciale. Una dintre acestea este afisarea preturilor in valuta dorita de client. Aceasta deoarece unui client ii este mult mai usor sa vada preturile in valuta proprie decat in cea a organizatie.

Orice organizatie care are ca obiect de activitate comertul, fie el prin Internet sau in mod clasic, are ca scop obtinerea unui profit. Din acest motiv o organizatie va introduce anumite taxe pentru activitatile pe care le desfasoara. Aceste taxe sunt astfel definite incat sa acopere toate cheltuielile necesare acelei activitati. In cazul in care se efectueaza vanzarea unui produs la doi clienti din tari diferite este de asteptat ca taxele percepute celor doi clienti sa difere. Astfel pentru fiecare tara se stabilesc taxele percepute.

Un alt factor care trebuie luat in considerare este acela ca orice organizatie trebuie sa-si stimuleze clientii fideli. Astfel in cazul in care se observa ca un client comanda mai multe produse si devine client fidel, este de asteptat ca sa i se ofere preturi diferentiate pentru anumite produse specifice.

Este de asteptat ca unii clienti sa doreasca comandarea unor cadouri. In acest caz este foarte probabil ca produsele vor fi livrate la o adresa iar plata sa se faca la alta. Pentru ca acest lucru sa fie posibil s-a dezvoltat un sistem care permite ca fiecare comanda sa fie trimisa la o adresa specificata de client.

Clientii vor dori sa aiba o istorie a comenzilor facute si sa poata verifica in orice moment care este starea comenzilor. Pentru aceasta s-a implementat o sistem care sa-i ofere clientului toate informatiile despre contul sau. (datele personale, comenzile facute).

De asemenea datorita folosirii din ce in ce mai mult a dispozitivelor mobile (telefoane celulare, Pocket PC-uri), clientii vor dori sa aiba posibilitate sa-si verifice starea comenzilor, si sa fie la curent cu noile produse aparute, cu ofertele promotionale ale organizatiei prin intermediul acestor dispozitive. Pentru aceasta s-a dezvoltat un sistem care sa permita accesul la aplicatie de pe un dispozitiv mobil.

Astfel s-a incercat dezvoltarea unor sisteme care sa-i permita utilizatorului cat mai facilitati.

3.2 Arhitectura aplicatiei

Aplicatia realizata este o aplicatie muti-tier, distribuita de tip enterprise. Arhitectura aplicatiei este impartita in patru nivele logice: Web (Prezentare) , Business Facade, Business Rules (Regulile de business) , Data Access (Accesul la date).

Nivelul Web (PL) – Furnizeaza accesul clientilor la aplicatie. Acest nivel contine formularele web ASP.NET (WebForms) si toate clasele (code-behind) necesare pentru implementarea interfetei cu utilizatorul. Prin intermediul acestui nivel clientii au acces la facilitatile oferite de aplicatie. Reprezinta nivelul de prezentare al aplicatie.

Nivelul Business Facade (BFL) – Furnizeaza nivelului prezentare Web intefetele (metodele) necesare pentru a administra conturile clientilor, explora categoriile, vizualiza produsele, cumpara produse si altele. Acest nivel este folosit ca nivel de izolare, separand interfata utilizator de implementarea diverselor functii de business; reprezinta o „fatada” a functionalitatilor oferite de aplicatie.

Nivelul Business Rules (BRL) – Contine implementarea regulilor logice si de business ale aplicatiei. Regulile de business valideaza conturile utilizatorilor si comenzile efectuate de acestia.

Nivelul Data Access (DAL) – Furnizeaza serviciile de acces la date nivelului de reguli de business (Business Rules). Prin intermediul acestui nivel se realizeaza accesul la baza de date din SQL Server. Implementeaza clasele de access la baza de date.

Nivelul Business Facade si Business Rules furnizeaza logica aplicatiei si pot fi privite ca un singur nivel Business Logic Layer (BLL) care impreuna cu nivelul de acces la date Data Access Layer (DAL) alcatuiesc Middle-Tier-ul aplicatiei care preia datele din baza de date (Data-Tier), le proceseaza si le trimite Nivelului Web (Presentation-Tier) pentru a fi prezentate clientilor.

In urmatoarea diagrama este prezentata arhitectura aplicatiei realizate si interactiunile dintre principalele nivele.

Figura 3.1 Arhitectura aplicatiei de comert electronic

Sagetile pot fi interpretate ca "… using …". De exemplu, nivelul regulilor de business (Business Rules) foloseste nivelul de acces la date (Data Access) pentru a stabili o conexiune cu baza de si pentru a apela procedurile stocate din Sql Server.

In plus fata de cele 4 nivele descrise, aplicatia contine de asemenea nivelul Common care contine seturile de date folosite pentru pasarea informatiilor, datelor dintre diferite nivele.

In continuarea voi prezenta pe larg fiecare din cele patru nivele.

3.3 Nivelul prezentare – Web

Nivelul prezentare reprezinta interfata utilizator (UI) a aplicatie prin intermediul careia, clientii au acces la aplicatia de comert electronic. O aplicatie de comert electronic (magazin virtual) permite clientilor selectarea de produse dintr-un catalog, vizualizarea si cautarea unor produselor, plasarea lor intr-un „cos virtual” (shopping cart), si trimiterea ordinului de cumparare a produselor continute in cosul virtual. Pentru toate acestea s-a realizat o interfata cat mai simpla si mai prietenoasa care sa ofere clientilor cat mai multe informatii despre produsele pe care le cumpara.

Urmatoarea diagrama de activitate de nivel superior descrie activitatile si optiunilor disponibile clientilor care acceseaza site-ul de comert electronic (aplicatia realizata).

Figura 3.2 Diagrama de activitate a aplicatiei

Un client care acceseaza site-ul web al aplicatiei se asteapta sa vada o interfata utilizator care sa contina:

Link-uri sau bare de navigare pentru optiunile comune de navigare.

Un catalog de produse organizat pe categorii si subcategorii.

Un mecanism de cautare avansata a unui produs in functie de anumite criterii.

O descriere detaliata a unui produs selectat si posibilitatea de adaugarea in cosul virtual.

O vedere detaliata a „cosului virtual” care sa-i permita modificarea si actualizarea continutului acestuia.

Un mecanism de inregistrare si identificare a clientilor pe baza unei parole.

O vedere care permite actualizarea informatiilor din contul creat, precum si o vedere a tuturor ordinurilor de cumparare efectuate.

O vedere detaliata a comenzilor inainte ca acestea sa fie trimise. Afisarea totalului de plata si posibilitatea de introducere a informatiilor legate de plata si livrare, toate acestea prin intermediul unui asistent.

O vedere care permite confirmarea comezilor inainte de a fi trimise.

In plus fata de aceste cerinte ale interfetei utilizator, aplicatia realizata ofera de asemenea si cerintele de securitate necesare, cum ar fi: se permite accesul la anumite functionalitati doar utilizatorilor inregistrati, fara a restrictiona accesul pentru „vizitatorii” site-ului.

Modelul cazurilor de utilizare este reprezenatat in diagrama din figura urmatoare.

Figura 3.3 Cazurile de utilizare

3.3.1 Proiectarea interfetelor utilizator

Interfata cu utilizatorul este creata cu ajutorul formularelor Web ASP.NET si a controalelor utilizator (User Controls) folosinf mediul vizual Visual Studio .NET.

In cadrul aplicatiei, anumite elemente apar in fiecare ecran, de aceea s-a creat pe langa formulare un set de controale utilizator care incapsuleaza anumite functionalitati cum ar fi, cautare produse, explorare de categorii, oferte promotionale ale produse, meniu de navigare.

Pagina principala (Home)

Primul lucru pe care un utilizator il vede la accesarea site-ului este pagina principala a aplicatiei. In figura urmatoare este prezentata interfata si principalele elemente ale paginii.

Figura 3.4 Pagina principala a aplicatiei cu optiunile de meniu existente

Aceasta pagina este alcatuita din 5 controale utilizator care vor fi folosite in majoritatea paginilor realizate, iar in partea din mijloc se afla continutul paginii. Dupa acest model au fost realizate si celelalte interfete utilizator, ceea ce se schimba este doar partea din mijloc a paginii (continutul) iar unele controale vor fi dezactivate sau isi vor schimba starea in functie de context.

Pagina principala a site-ului ofera utilizatorilor informatii despre categoriile de produse comercializate si prezinta un top cu cele mai cumparate produse, cele mai noi produse si cele care au pretul cel mai bun. In partea de sus a paginii se afla un meniu de navigare care ii ofera utilizatorului posibilitatea sa se plimbe printre paginile site-ului, iar in partea stanga este un meniu care afiseaza categoriile de produse, si un motor de cautare. Aceasta pagina este punctul de pornire pentru vizualizarea si cumpararea produselor.

Controalele utilizator

Deoarece controalele din pagina principala apar si in celelalte interfete realizate voi prezenta pe scurt functionalitatea fiecarui control:

Header Control – reprezinta partea de sus a paginilor din interfata. Aici sunt afisate principalele butoane de navigare ale site-ului, o poza cu adresa site-ului (logo) si tot aici se va afisa si numele utilizatorului loginat, precum si valuta in care vor fi afisate preturile produselor. Unele din butoanele de navigare vor fi activate sau dezactivate in functie de valoarea unui obiect care indica daca utilizatorul este logat sau nu. Controlul contine o proprietate prin care se poate seta numele utilizatorului dupa loginare.

Footer Control – partea de jos a paginilor din interfata. Aici vor fi afisate link-urile de genul, politica site-ului, despre noi, ajutor, si altele. Acest control mai contine si un panel (container) care va fi afisat in paginile care in care sunt afisate preturi ale produselor. Acest panou contine ratele de schimb ale principalelor valute: cursul dollar – euro si lira – euro. De asemenea daca utilizatorul este logat este afisata rata de schimb euro – valuta in care sunt afisate preturile.

Categories Control – meniu de navigare pentru categoriile de produse oferite. Acest control afiseaza intr-un control server DataList categoriile extrase din baza de date. Categoriile sunt afisate pe doua nivele: primul nivel contine categoriile parinte, iar al doilea subcategoriile. La selectarea unei categorii parinte este apelata o comanda care afiseaza subcategoriile care fac parte din aceea categorie, si redirecteaza raspunsul spre pagina de produse, afisand toate produsele care fac parte din categoria parinte selectata. La plimbarea de pe o pagina pe alta se pastreaza categoria selectata.
Datorita faptului ca informatiile din acest control sunt prezentate dinamic pe baza datelor extrase din baza de date, acestea pot varia in functie de categoriile existente. Astfel pot fi comercializate orice tip de produse, grupate in categorii si subcategorii.

Search Control – control care ofera un motor de cautare a produselor. Produsele pot fi cautate dupa un text anume introdus in caseta Look for. Textul va fi cautat in numele produsului, descrierea acestuia, detaliile produsului, furnizor, categoria din care face parte. De asemenea rezultate pot fi filtrate dupa o categorie aleasa dintr-o lista. Parametrii de filtrare sunt transmisi prin Query String catre pagina care afiseaza rezultatele cautarii. (SearchResults.aspx). Daca se doreste cautarea avansata a unui produs dupa mai multe criterii este oferit link-ul Advanced Search.

PromItems Control – ofertele de produse promotionale ale site-lui. Acest control are o proprietate Mode prin care se poate seta tipul de produse afisate: cele mai cumparate produse, produsele cele mai noi, produsele cu cel mai bun pret. In functie de valoarea proprietatii Mode se apeleaza o metoda care returneaza un set de date continad produsele promotionale. S-a implementat un mecanism prin care un produs daca a aparut la cele mai cumparate produse sa nu mai poata aparea si la cele mai noi produse sau la cel mai bun pret chiar daca indeplineste criteriul de selectare lasand loc altor produse. Pentru fiecare tip de oferte promotionale se afiseaza doar primele 5 produse gasite. Setul de date rezultat este legat dinamic la sursa de date a unui Repeater care pe baza unui sablon afiseaza numele produsului si pretul acestuia. Daca nu s-a gasit nici un rezultat atunci se ascunde repeater-ul.

Aceste controale pot fi privite ca niste „module” care pot fi folosite in orice pagina este nevoie de ele. Fiecare control are asociata o clasa (code-behind) care implementeaza functionalitatea controlului, proprietatile acestuia si trateaza evenimentele generate de controalele server folosite.

Alte controale proiectate pentru interfata utilizator si folosite in formulare de web sunt: ItemsControl, NewItemsControl, RegistrationControl, DeliveryAddressControl, LoginControl, OrderControl, ShoppingCartControl. Aceste controale vor fi prezentate in cadrul interfetelor in care apar si unde sunt folosite. S-au folosit controale utilizator deoarece ofera o separare mai clara a codului unui formular de web prin impartirea lui in module, permit refolosirea lor in mai multe formulare, eficientizeaza procesul de realizare a aplicatiei, asigura un caracter unitar pentru interfata cu utilizatorul.

Pagina de autentificare (Login)

Pagina folosita pentru identificarea utilizatorului. Identificarea utilizatorului se face dupa adresa de mail si o parola aleasa de acesta. Aceasta pagina contine doar trei controale utilizator: Header, Footer si LoginControl. Controlul de login se ocupa de autentificarea utilizatorului.Controlul LoginControl este format din doua panouri:

Primul panou contine controalele server pentru introducerea adresei de mail si a parolei, si doua butoane „Login” si „New Customer” pentu loginare, respectiv crearea unui nou cont. Mai contine si controale de validare, care verifica daca s-au introdus valori in campurile respective, daca s-a introdus o adresa de mail corecta, si daca datele furnizate exista in baza de date si sunt corecte. Acest panou este tot timpul vizibil.

Al doilea panou contine un mesaj care apare daca clientul este logat si apasa inca o data butonul de „Login” Se afiseaza mesajul si doua butoane „Continue” – daca clientul vrea sa se logineze cu alt nume de utilizator sau sa-si creeze un nou cont (se face automat logout si este afisata pagina de login), si „Cancel” – se renunta si se reintoarce la pagina precedenta. Inital acest panou este invizibil.

Daca datele introduse sunt corecte si utilizatorul este autentificat se creeaza in session un obiect CustomerData care contine informatiile utilizatorului si de asemenea se creeaza un obiect SavedCart, care contine produsele din cosul virtual salvate de utilizator in baza de date pentru o vizita ulterioara (daca acestea exista). Dupa aceea utilizatorul este redirectat spre pagina principala sau spre pagina de unde a fost apelata pagina de login.

Modul in care utilizatorul va fi tratat in timpul procesului de cumparare depinde in mare masura de modul in care el face autentificarea. Din momentul in care cumparatorul este inregistrat el beneficiaza de mai multe facilitatii.

Pagina de inregistrare sau actualizare informatii (Register)

In cazul in care utilizatorul este un client nou acesta are posibilitatea de a se inregistra. Acest lucru se face prin apasarea butonului „New Customer” din pagina de login sau prin link-ul „Register”. Datele pe care trebuie sa le introduca un client pot fi grupate in 4 categorii:

Informatii de contact cum ar fi numele, prenumele, adresa, orasul, tara, codul postal, numar de telefon. La aceasta adresa clientul va primi ordinul de plata. Aceste informatii sunt obligatorii.

Informatii despre contul creat. (adresa de mail si parola). Acestea sunt obligatorii.

Informatii despre modul de plata. (credit card). Aceste informatii sunt optionale putand fi introduse doar in momentul trimiterii ordinului de cumparare.

Alte informatii. Aici se poate alege valuta in care vor fi afisate preturile produselor. Selectarea unei valute este obligatorie.

Pagina este formata din doua panouri: unul in care utilizatorul trebuie sa introduca datele si un panou de confirmare dupa inregistrare sau actualizare. Informatiile afisate in aceste panouri depind de optiunea aleasa de utilizator. Daca se creeaza un cont nou atunci toate campurile vor fi goale si se va afisa butonul de „Register”, iar daca utilizatorul alege optiunea „Update Registration” atunci campurile vor fi completate cu datele utilizatorului si apare butonul de „Update”. Si mesajul de confirmare va fi in functie de optiunea aleasa.

Clasa care implementeaza pagina contine doar metodele care trateaza evenimentele de apasare a butoanelor si afiseaza sau ascunde panourile.

Pagina contine controlul RegistrationControl care realizeaza crearea de noi utilizatori sau actualizarea conturilor existente. Contine metode care extrag informatiile din baza de date si le afiseaza in campurile text sau in liste, care salveaza datele introduse de utilizator daca acestea au fost validate si nu sunt erori, actualizeaza informatiile utilizatorului.

Dupa inregistrare clientul va primi un mesaj de confirmare si va fi automat logat putand continua cumpararea prin apasarea butonului „Continue”.

Pagina contul meu (MyAccount)

Aceasta pagina contine informatii referitoare la contul utilizatorului si este vizibila doar utilizatorilor loginati. Aici se poate ajunge prin apasarea butonului „My Account”. Pagina contine un link care scoate afara utilizatorul „LogOut”, un link care duce la pagina de actualizare informatii utilizator „Update Your Accout” si un tabel care contine o lista a comenzilor efectuate de utilizator, ordonate descrescator dupa data. Sunt afisate informatii despre data cand s-a facut comanda, suma totala de plata, starea comenzii, si un link care duce la o pagina detaliu comanda in care se afiseaza toate detaliile referitoare la aceea comanda. Pagina detaliu ofera posibilitatea de tiparire la imprimanta a comenzii intr-un format printabil. Daca utilizatorul nu are facuta nici o comanda atunci se afiseaza mesajul „You have no orders to display” .

Pagina de produse (Items)

In momentul in care utilizatorul alege o categorie din lista de categorii i se prezinta lista produselor care fac parte din aceea categorie. Clientul are doua optiunii:

Daca alege o categorie parinte i se prezinta intr-un tabel cu paginare toate produsele care fac parte din categoria respectiva.

Daca alege o subcategorie i se prezinta detaliat cele mai noi 5 produse din categoria respectiva si apoi un tabel cu paginare in care sunt prezentate toate produsele.

In figura urmatoare este prezentata interfata realizata pentru lista de produse, si o descrierea elementele continute:

Figura 3.5 Lista de produse

Unele din aceste elemente pot sa nu apara depinzand daca utilizatorul este logat sau este doar un „vizitator” al site-ului. De exemplu, coloana cu preturile in valuta clientului nu apare.

Continutul paginii este generat dinamic in functie de optiunea utilizatorului. Pentru aceasta s-au folosit doua controale utilizator in plus fata de cele prezenatate in pagina principala. Aceste controale sunt ItemsControl (afiseaza lista de produse prezentata in figura) si NewItemsControl ( afiseaza primele 5 noi produse din subcategoria selectata).

ItemsControl contine un DataGrid, iar NewItemsControl un Repeater care are un sablon de afisare a produselor noi.

In code-behind-ul controlului ItemsControl sunt implementate toate proprietatile si metodele necesare pentru functionarea acestuia:

Incarcarea produselor din baza de date intr-un set de date, modificarea setului de date, conversia preturilor si legarea dinamica a setului la data grid, afisarea butoanelor de navigare, tratarea evenimentelor la apasarea unui buton sau executarea unei comenzi cum ar fi sortarea, sau adaugarea unui produs in cos, afisarea preturilor promotionale, afisarea preturilor in valuta clientului, paginare.

In code-behind-ul controlului NewItemsControl sunt implementate:

O metoda care leaga dinamic datele din setul de date care contine produsele noi, la sursa de date a repeater-ului pnetru a fi afisate, o metoda care trateaza comanda de apasare a butonului „AddToCart” care adauga un produs in cos, proprietati prin care se acceseaza sau seteaza campurile clasei.

Principiul de implementare al paginii de produse este urmatorul: la incarcarea paginii se verifica daca utilizatorul este logat pentu a sti daca se afiseaza preturile preferentiale si preturile in valuta clientului. Se apeleaza o metoda care verifica daca se afiseaza produsele pentru o subcategorie si in acest caz se afiseaza ambele controale utilizator, sau daca se afiseaza doar produsele din categoria parinte. Se apeleaza metodele care activeaza controalele. Se apeleaza o metoda care afiseaza poza si numele categoriei, subcategoriei. Daca nu s-a gasit nici un produs se afiseaza mesajul „No Items found”.

Adaugarea unui produs in cosul virtual se face prin apasarea butonului „Add” sau a butonului „Add To Cart” pentru produsele noi. Se apeleaza o metoda care adauga produsul intr-un „cos virtual”. Principiul de adaugare si mentinere al cosului virtual va fi explicat la pagina de vizualizarea a cosului. Ori de cate ori un produs va fi adaugat in cosul virtual se va afisa continutul cosului, utilizatorul urmand a alege operatia urmatoare.

In cazul in care clientul doreste mai multe informatii despre un produs anume apasa pe numele acestuia si este afisata o pagina detaliu produs. Sunt oferite informatii suplimentare despre produs si se ofera posibilitatea de specificare a cantitatii dorite.

In figura urmatoarea este prezentata pagina detaliu produs si elementele ei principale.

Pagina detaliu produs (Item)

Pagina cos virtual (ShoppingCart)

In aceasta pagina se va afisa continutul cosului virtual la un moment dat. Cosul virtual se creeaza in momentul in care utilizatorul adauga un produs in cos. Cosul virtual este mentinut intr-un obiect Cart in session.

Pentru administrarea cosului virtual s-a implementat clasa Cart, care ajuta la manipularea datelor din cosul virtual. Aceasta clasa are proprietati care verifica daca cosul este gol, returneaza produsele continute in cos, precum si metode care verifica daca datele pot fi scrise in setul de date asociat cosului virtual, adauga un produs in cos, actualizeaza un produs, sterge un produs, actualizeaza cosul virtual, sterge toate produsele din cos, calculeaza sub-totalul cosului, salveaza in baza de date produsele din cos, incarca in cos produsele salvate.

Pentru a face cat mai usor lucrul cu obiectele din session s-a implementat o clasa de baza PageBase, care are doua proprietati Customer, returneaza sau seteaza datele utilizatorului loginat mentinut in session, si Order, care returneaza sau seteaza datele referitoare la comanda, mentinuta in session, pe care utilizatorul urmeaza sa o trimita. Aceste proprietati adauga sau sterg valoarea unei cheii a obiectul Session. Aceasta clasa mai contine si o metoda care returneaza un obiect Cart reprezentand cosul virtual. Aceasta metoda returneaza obiectul Cart, mentinut in Session daca acesta exista, daca nu este se creeaza un nou obiect care se adauga in Session si se verifica daca setul de date asociat obiectului Cart poate fi scris, daca este creat si pot adaug date in el. Astfel la adaugarea primul produs in cos, se creeaza cosul virtual care este apoi mentinut in Session si poate fi prelucrat in continuare.

Aceasta este o solutie foarte buna de mentinere a „cosului virtual” deoarece nu se apeleaza la baza de date pentru a manipula produsele din cosul virtual. Cosul este tinut intr-un set de date (DataSet), care este de fapt echivalentul unei baze de date. Se apeleaza la baza de date numai in cazul in care utilizatorul doreste sa salveze produsele din cos pentru o vizita ulterioara. S-a implementat acesta metoda deoarece pot fi multi utilizatorii care doar „viziteaza” site-ul, adauga produse in cos dar nu trimit comanda.

In figura urmatoarea este prezentata pagina cos virtual si elementele ei principale.

Figura 3.7 Cosul virtual

Pagina cos virtual (ShoppingCart) extrage mai intai cosul virtual din Session. Daca acesta exista atunci se afiseaza continutul lui, iar daca nu se afiseaza un mesaj. Daca utilizatorul este logat se verifica daca acesta are salvat un cos virtual dintr-o vizita anterioara si i se ofera posibilitatea de a incarca produsele salvate, in cosul curent. Pagina contine un control ShoppingCartControl care se ocupa de manevrarea cosului.

Pagina CheckOut

Aceasta este pagina prin care utilizatorul trimite ordinul de cumparare. Din pagina cos virtual daca utilizatorul doreste sa cumpere produsele apasa pe butonul „CheckOut” si este trimis catre pagina CheckOut pentru a confirma si trimite comanda. In figura urmatoarea este prezentata panoul „ConfirmOrder” si elementele lui principale.

Figura 3.8 Confirmarea si trimiterea comenzii

Aceasta este pagina cea mai complexa a aplicatiei si care contine cea mai multa informatie.

Fiind o pagina complexa s-a incercat impartirea ei in mai multe panouri care alcatuiesc un fel de wizard (asistent). Pentru utilizator este mult mai usor sa-i fie prezentata informatia pe rand si nu toata odata. Aceste panouri sunt afisate sau ascunse in functie de pasul curent la care se afla cumparatorul in procesul de trimitere a comenzii.

Astfel operatia de trimitere a comenzii necesita mai multe etape. Pasii pe care trebuie sa-i parcurga utilizatorul care doreste sa trimita ordinul de cumparare sunt urmatorii:

Pasul 1: Actualizare informatii utilizator – adresa la care se trimite plata si informatiile referitoare la modul de plata. Adresa cumparatorului este completata pe baza informatiile din baza de date. Daca unele date nu mai sunt valide acesta este momentul in care se pot schimba.

Pasul 2: Adresa unde vor fi livrate produsele – utilizatorul specifica adresa la care vor fi trimise produsele. Daca este aceeasi adresa ca la pasul 1 utilizatorul are posibilitatea sa marcheze o casuta si automat vor fi completate datele pentru adresa de livrare.

Pasul 3: Confirmare cos virtual – sunt prezentate produsele din cosul virtual selectate de cumparator, la care se adauga taxele percepute si se calculeaza un total de plata. Clientul verifica daca aceste date sunt corecte si confirma acest lucru.

Pasul 4: Confirmare Comanda – utilizatorului i se prezinta toate datele introduse pentru efectuarea comenzii. Clientul trebuie sa verifice daca aceste date sunt corecte si sa confirme trimiterea comenzii. Acesta etapa este prezentata in figura 3.8.

Pasul 5: Comanda s-a efectuat – utilizatorului i se prezinta un mesaj precum si informatii referitoare la comanda care s-a inregistrat in baza de date. (identificatorul comenzii, data comenzii, starea comenzii, totalul de plata). Clientul poate relua tot procesul de cumparare afisandu-se link-ul „Do you want to shop some more?”.

Acesti pasi sunt afisati in permanenta in partea stanga a paginii. Aceasta impartire in 5 pasi face trimiterea comenzii mult mai usoara. Informatiile afisate la fiecare pas sunt pastrate intr-un panou (panel) care se activeaza in momentul in care utilizatorul a ajuns la pasul respectiv. Astfel pagina contine 5 panouri. In partea de jos sunt afisate in permanenta 3 butoane care-l ajuta pe client sa treaca de la un pas la altul, sa confirme corectitudinea informatiilor, sau sa renunte la procesul de cumparare. Aceste butoane sunt: „Previous” (pasul precedent), „Next” (pasul urmator) si „Cancel” (anularea comenzii). Daca utilizatorul trebuie sa confirme ceva atunci butonul „Next” devine „Confirm”.

Daca utilizatorul apasa butonul „Cancel” atunci este este redirectat spre pagina principala, sunt sterse informatiile referitoare la comanda, dar nu se sterge continutul cosului virtual, utilizatorul putand actualiza cosul si trimite o noua comada.

Controale utilizator folosite in aceasta pagina sunt: RegistrationControl, DeliveryAddress Control, ShoppingCartControl, OrderControl.

Acestea sunt principale interfete utilizator ale aplicatiei realizate. Alte aspecte importante ale nivelului prezentare pe care doresc sa le prezint sunt modul de tratare a erorilor si securitatea aplicatiei.

3.3.2 Tratarea erorilor

O aplicatie multi-nivel, cum este proiectul realizat, poate detecta erori la orice nivel si apoi sa paseze erorile prin diferite nivele. De exemplu, o eroare la nivelul de acess la date care apare ca raspuns la o eroare de interogare SQL poate fi eventual afisata utilizatorului prin intermediul unei pagini de la nivelul prezentare.

Pentru tratarea erorilor aplicatiei, care pot sa apara in momentul utilizarii s-a gasit o solutie prin folosirea mecanismului de erori individualizate din ASP.NET (custom errors).

Pentru afisarea mesajelor de eroare care pot sa apara, aplicatia foloseste pagina de eroare ErrorPage specificata in fisierul de configurare Web.config la sectiunea <customErrors> astfel: <customErrors mode="On" defaultRedirect="ErrorPage.aspx"></customErrors>

La aparitia unei erori in cadrul aplicatiei utilizatorul este redirectat la pagina de eroare in care se afiseaza un mesaj de eroare personalizat, fara a prezenta detaliat eroarea sau exceptia care a generat eroarea. Aceasta deoarece pentru utilizatori este neplacut sa vada sursa erorii aparute si codul care a generat aceea eroarea.

Totusi pentru a vedea mesajele de eroare aparute si pentru ca administratorul aplicatiei sa rezolve aceste erori s-a gasit o solutie prin implementarea unui sistem de tratare a erorilor aplicatei la nivel global.

Toate erorile si exceptiile aparute sunt prinse in metoda Application_Error din fisierul Global.asax.cs.

Daca apare o eroare atunci continutul stivei si URL care a generat eroarea sunt scrise in Event Log sistemului de operare, prin apelul metodei Log a clasei implementate Error. In acest fel administratorul aplicatie poate vedea sursa care a generat erorea si poate incerca sa o rezolve.

Metoda implementata este urmatoarea:

protected void Application_Error(Object sender, EventArgs e) {

string err = " E-Commerce Error \n\n";

err += "request: "+ Request.Url.ToString() +"\n\n";

err += "Stack Trace: \n" +Server.GetLastError().ToString();

// scrie mesajul de eroare in App Event Log din WINNT

ECommerce.Web.Error.Log(err);

}

3.3.3 Securitatea aplicatiei

Unul dintre cele mai importante aspecte legate de programarea aplicatiilor pentru Web il reprezinta siguranta aplicatiilor. Securitatea aplicatiei realizate se bazeaza pe sistemul de securitate integrat al ASP.NET – autentificarea ASP.NET. Aplicatia implementeaza autentificarea pe baza de formulare care redirecteaza utilizatorii neautorizati la un formular care le cere un nume de utilizator si o parola. Dupa ce aplicatia verifica datele de autentificare introduse de utilizator, se creeaza un fisier cookie de autentificare, pentru a mentine informatiile de autentificare pentru utilizatorul curent pentru sesiunea curenta.

Autentificarea bazata pe formulare este activata de introducerea in fisierul Web.config (fisierul de configurarea al unei aplicatii Web) a unei intrari care arata astfel:

<authentication mode="Forms">

<forms name=".ADUAUTH" loginUrl="Login.aspx" protection="All"> </forms>

</authentication>

<authorization> <allow users="*"/> </authorization>

unde: .ADUAUTH reprezinta numele cookie-ului de autentificare.

Atributul loginUrl specifica formularul de autentificare al aplicatiei, pagina spre care va fi redirect utilizatorul de fiecare data cand acesta doreste sa acceseze resursele aplicatiei pentru care nu este permis accesul anonim.

Aplicatia are configurate trei pagini Web pentru care accesul este restrictionat utilizatorilor neautentificati: MyAccount, OrderDetails, CheckOut.

Pentru a realiza aceste restrictii, trebuie creata cate o intrare pentru fiecare pagina in fisierul Web.config, asa cum se prezinta mai jos.

<location path="CheckOut.aspx">

<system.web>

<authorization> <deny users="?"/> </authorization>

</system.web>

</location>

Semnul „?” este utilizat pentru a specifica utilizatorii anonimi (utilizatorii neautentificati). Cand un utilizator doreste sa acceseze oricare dintre aceste pagini, securitatea bazata pe formulare ASP.NET redirectioneaza automat utilizatorul catre pagina de login si va continua acest lucru pana cand utilizatorul se autentifica prin e-mail si parola. Dupa autentificare utilizatorul este redirectionat spre pagina pe care a dorit sa o acceseze.

Aplicatia ofera un mecanism de securitate ridicat atat prin folosirea autentificarii si autorizarii din ASP.NET cat si prin sistemul de securitate din Windows si IIS.

3.3.4 Interfata utilizator pentru dispozitivele mobile

Un avantaj pe care il prezinta aplicatia realizata fata de alte aplicatii de acest gen este suportul pentru dispozitivele mobile (telefoane celulare, pocket pc).

S-a implementat un sistem care sa-i permita clientului accesul la contul sau prin intermediul telefonului celular. Clientul sa-si poata verifica situatia comenzilor sale, si sa poata fi la curent cu noile produse aparute, cu ofertele promotionale ale organizatiei, toate acestea prin intermediul unui dispozitiv mobil. In acest fel clientii vor fi foarte multumiti de calitatea serviicilor oferite de site-ul de comert electronic. Pentru a implementa aceasta facilitate s-a folosit pachetul Microsoft Mobile Internet Toolkit. Modul de proiectare a paginilor se asemana cu cel al paginilor ASP.NET.

Pagina Mobile

Aceasta este pagina prin care se ofera clientului accesul la contul sau de pe telefonul mobil. Pagina este un formular web mobile, care contine mai multe tag-uri <mobile:form>. Toate controale definite in aceasta pagina sunt prefixate de spatiul de nume „mobile”. Acesta contine controalele server pentru dispozitivele mobile.

Deoarece se pot folosi mai multe formulare in aceeasi pagina s-a creat doar o singura pagina care contine urmatoarele formulare: formularul de login, pagina principala (home), comenzile efectuate, starea comenzilor, produsele speciale, cele mai cumparate produse, cele mai noi produse, cel mai bun pret, detaliu produs. Pentru fiecare din acestea s-a definit un formular mobile. Aceast lucru este posibil pentru a se evita crearea de multe pagini mici, deoarece dispozitivele mobile au ecrane mici pe care nu se poate afisa multa informatie si atunci se prefera crearea unei pagini care contine mai multe formulare.

Cand un client acceseaza pagina pentru prima data este afisat in mod implicit primul formular. Se poate programa navigarea la alte formulare prin setarea proprietatii ActiveForm a paginii mobile sau se pot crea link-uri prin care se poate naviga prin formularele declarate.

Descrierea modului de functionare pentru pagina mobile

La accesarea paginii mobile este afisat primul formular „Login” prin care se cere autentificarea utilizatorului. Utilizatorul trebuie sa-si introduca adresa de email si parola. Daca datele introduse sunt corecte atunci se activeaza urmatorul formular „HomePage”, pagina principala care contine meniul aplicatiei, posibilitatile pe care le are utilizatorul. De aici utilizatorul poate decide optiunea pe care o doreste. Meniul contine link-uri spre comenzile efectuate de client, spre produsele speciale oferite, si link-ul de parasire a aplicatiei LogOut. In functie de optiunea aleasa se activeaza unul din formularele declarate.

Daca se alege afisarea comenzilor efectuate atunci se activeaza formularul „RecentOrders”. Acesta contine o lista cu toate comenzile clientului ordonate dupa data. Utilizatorul poate selecta o comanda si sa apese butonul „Check Status” pentru a verifica starea comenzii efectuate. Se activeaza formularul „OrderStatus” care contine informatiile referitoare la comanda precum si starea acesteia.

Daca utilizatorul doreste sa vada produsele speciale oferite (cele mai cumparate si cele mai noi produse, pretul cel mai bun) apasa pe link-ul „Special Items” din meniu si se va activa formularul „SpecialItems”. Acesta contine o lista cu paginare a produselor speciale. In partea de jos a paginii sunt afisate butoanele de navigare prin paginile de produse, precum si numarul paginii curente din numarul total de paginii. La selectarea unui produs din lista este activat formularul „ItemDetails” in care sunt afisate toate informatiile despre produs.

Daca utilizatorul doreste sa vada numai un anumit tip de produse speciale, atunci el are posibilitatea sa aleaga unul din submeniurile meniului „Special Items”. Optiunile sunt cele mai cumparate produse, produsele cele mai noi si cele care au pretul cel mai bun. Pentru fiecare din aceste optiuni s-a definit cate un formular care se activeaza in momentul selectarii

optiunii. Aceste formulare sunt: „MostPopularItems”, „NewestItems”, „BestPrices”.

Daca utilizatorul doreste sa nu mai fie loginat el poate alege optiunea „LogOut” care sterge datele referitoare la utilizator si afiseaza pagina de login.

Din oricare formular utilizatorul are posibilitatea sa se reintoarca la meniul principal prin apasarea butonului „Home”. In acest caz se activeaza iar formularul homepage.

Code-behind-ul Mobile.aspx.cs contine logica acestei paginii si implementeaza metodele de tratare a evenimentelor. Spatiul de nume pentru aceasta clasa este ECommerce.Web.Mobile.

In figura urmatoare sunt prezentate interfetele utilizator realizate pentru dispozitivele mobile.

Figura 3.9 Interfetele utilizator pentru dispozitive mobile

Toate clasele implementate (code-behind) din Nivelul prezentare (Web) a fost grupate in spatiul de nume ECommerce.Web si sunt compilate in biblioteca ECommerce.Web.dll. Aceste clase reprezinta logica paginilor de Web realizate. Nivel prezentare depinde de toate celelate nivele implementate si are acces la functionalitatile oferite de aceste nivele doar prin intermediul nivelului Business Facade. In continuare voi prezenta acest nivel.

3.4 Nivelul Business Facade

Acest nivel furnizeaza nivelului prezentare (Web) interfetele (metodele) necesare pentru administrarea conturile clientilor, explorarea categoriile, vizualizarea produsele, cumpararea produselor si interfete pentru toate functionalitatile pe care le ofera aplicatia.

Acest nivel este folosit ca nivel de izolare, separand interfata utilizator de implementarea diverselor functii de business; reprezinta o „fatada” a functionalitatilor oferite de aplicatie.

Nivelul reprezinta punctul de comunicare dintre nivelul prezentare si regulile de business ale aplicatie, logica aplicatiei (middle-tier). Nivelul Business Facade:

Primeste datele introduse de utilizator de la nivelul prezentare (WebUI).

Foloseste nivelul de acces la date pentru a apela metodele de acces la date.

Paseaza cererile nivelului Business Rules care contine regulile aplicatiei.

Returneaza raspunsurile de la nivelul de reguli catre nivelul prezentare.

Returneaza rezultatele la cererile provenite de la nivelul prezentare.

Acest nivel reprezinta functionalitatea aplicatiei, organizat in jurul cazurilor de utilizare principale ale sistemului. Fiecare metoda reprezinta o cale diferita dintr-un caz de utilizare.

In cadrul acestui nivel s-au implementat 4 clase in care sunt definite principalele interfete. Aceste clase sunt: CountrySystem, CustomerSystem, ItemSystem, OrderSystem.

CountrySystem

Aceasta clasa cuprinde interfetele pentru returnarea tarilor si a valutelor existente in baza de date. S-au definite 4 metode care apeleaza metoda echivalenta de la nivelul de acces la date pentru a returna rezultatele. Aceste metode sunt:

GetCountries – returneaza un set de date continad toate tarile.

GetCountryByID – returneaza informatiile referitoare la tara care are ID specificat.

GetCurrencies – returneaza un set de date continad valutele existente si ratele de conversie raportate la euro.

GetCurrencyByID – returneaza informatiile referitoare la valuta care are ID specificat.

CustomerSystem

Aceasta clasa defineste interfetele pentru autentificarea si inregistrarea utilizatorilor aplicatie.

Fiecare din metodele implementate paseaza datele primite nivelului de reguli de business pentru a verifica daca sunt respectate regulile aplicatiei. Aceste metode sunt urmatoarele:

GetCustomerByEmail – returneaza informatiile despre utilizator pe baza adresei de email si a parolei. Aceste informatii sunt primite de la nivelul de reguli.

CreateCustomer – inregistrare utilizator nou. Aceasta metoda preia datele transmise de nivelul prezentare, creeaza un set de date cu informatiile despre utilizator, dupa care il paseaza obiectul creat nivelul de reguli pentru a verifica daca datele sunt corecte si utilizatorul poate fi inregistrat. Returneaza adevarat daca operatia s-a executat cu succes si fals in caz contrar si ca parametru de iesire obiectul utilizator creat.

UpdateCustomer – actualizare informatii utilizator. Returneaza adevarat daca operatia s-a executat cu succes si fals in caz contrar. Este apelata metoda de la nivelul de reguli care verifica daca datele primite pot fi actualizate.

ItemSystem

Clasa defineste interfetele pentru sistemul de produse al organizatiei. Metodele definite aici apeleaza nivelul de acees la date pentru a returna seturile de date cerute de nivelul prezentare. Metodele implementate sunt urmatoarele:

GetItemsByCategory – returneaza un set de date continad produsele unei categorii.

GetItemByID – retuneaza informatiile unui produs pe baza ID specificat.

GetNewItemsByID – returneaza un set de date cu produsele noi ale unei categorii.

GetSearchItems – returneaza un set de date cu produsele gasite dupa cautare.

GetAdvancedSearchItems – returneaza un set de date cu produsele gasite dupa o cautare avansata bazata pe mai multi parametrii.

PriceConversion – retuneaza un set de date continad produsele cu conversia pretului in valuta speficata. Se primesc ca parametrii de intrare setul de date pentru care se aplica la fiecare produs rata de conversie.

SetPromotions – returneaza un set de date cu produse, pentru care se actualizeaza un camp Promo specificand daca produsul este nou, s-au pentru produsul respectiv utilizatorul curent are un pret special.

MostPopularItems – returneaza cele mai cumparate produse.

NewestItems – returneaza cele mai noi produse oferite.

BestPrices – returneaza produsele care au cel mai bun pret.

GetCategories – returneaza un set de date cu toate categoriile de produse existente.

GetCategoryName – returneaza numele categoriei parinte si a subcategoriei.

GetSuppliers – returneaza un set de date cu toti furnizorii de produse.

LoadItemsInCart – incarca intr-un set de date toate produsele salvate in baza de date de catre utilizator pentru o vizita ulterioara. Aceste produse sunt incarcate intr-un cos virtual temporar utilizatorul putand alege ce va face cu acest cos. Produsele sunt returnate de catre o metoda de la nivelul acces la date.

InsertItemInCart – paseaza setul de date continad produsele din cosul virtual al utilizatorului curent nivelului acees la date pentru a fi salvate in baza de date.

OrderSystem

Clasa defineste interfetele pentru sistemul de trimitere a comenzilor de catre utilizatori aplicatiei. Sunt apelate metodele de la nivelul acces la date pentru a realiza operatiile cerute.

Metodele implementate sunt urmatoarele:

AddOrder – paseaza informatiile referitoare la o comada nivelului de reguli pentru a o insera in baza de date daca sunt respectate regulile. Returneaza numarul de inregistrare al comenzii daca operatia s-a efectuat cu succes.

AddOrderLines – paseaza un rand dintr-o comanda nivelului de reguli pentru a fi inserat in baza de date.

GetCustomerOrders – returneaza toate comenzile efectuate de clientul specificat.

GetOrderDetails – returneaza informatiile referitoare la comanda specificata.

InsertDeliveryAddress – apeleaza o metoda de la nivelul acces la date care insereaza datele referitoare la adresa de livrare a comenzii in baza de date.

RemoveDeliveryAddress – apeleaza metoda care sterge o adresa de livrare.

UpdateDeliveryAddress – apeleaza metoda care actualizeaza datele referitoare la adresa de livrare a comenzii.

LoadShippingAddress – returneaza informatiile referitoare la o adresa de livrare.

GetCountryTaxes – apeleaza o metoda de la nivelul de reguli care returneaza un set de date cu taxele care se aplica pentru comanda specificata.

GetOrderTaxes – apeleaza metoda de la nivelul de acces la date care returneaza setul de date cu taxele care s-au aplicat unei comenzii.

GetSubTotalTaxes – returneaza valoarea totala a taxelor aplicate.

Clasele de la acest nivel sunt grupate in spatiul de nume ECommerce.BusinessFacade si compilate in biblioteca ECommerce.BusinessFacade.dll.

In figura de mai jos este prezentata diagrama de clase pentru nivelul Business Facade, grupate intr-un pachet si componenta care contine aceste clase.

Figura 3.9 Diagrama de clase a nivelului Business Facade

3.5 Nivelul regulilor de business – Business Rules

Nivelul Business Rules contine implementarea regulilor logice si de business ale aplicatiei care valideaza conturile utilizatorilor si comenzile efectuate de acestia. Acest nivel contine doar cateva din regulile de business ale sistemului, multe din acestea fiind inglobate in procedurile stocate din baza de date si la nivelul prezentare prin controalele de validare. Nivelul regulilor de business:

Primeste cererile de la nivelul Business Facade

Proceseaza cererile conform regulilor stabilite

Foloseste nivelul de acces la date pentru a aduce sau trimite date de la baza de date

Paseaza rezultatele procesarii catre nivelul Business Facade.

Pentru a verifica regulile de business ale aplicatiei s-au implementat doua clase.

Clasa Customer

Aceasta clasa defineste regulile de business referitoare la utilizatorii aplicatiei. Metodele declarate aici preiau datele transmise de nivelul BusinessFacade, le proceseaza conform regulilor si returneaza un rapuns. Sunt folosite metodele declarate la nivelul de acces la date pentru a accesa datele din baza de date. S-au implementat urmatoarele metode:

GetCustomerByEmail – returneaza un obiect de tip CustomerData pe baza adresei de email. Se obtin datele referitoare la client pe baza adresei de email si se verifica daca parola introdusa de acesta este egala cu parola existenta in baza de date. In caz afirmativ se returneaza obiectul continad datele utilizatorului.

CheckExistingCustomer – metoda verifica daca mai exista in baza de date un utilizator cu aceeasi adresa de email. Se foloseste la inserarea unui nou utilizator.

Insert – insereaza un nou utilizator in baza de date. Se verifica daca nu mai exista o inregistrare cu aceeasi adresa de email. Daca nu exista atunci se transmite obiectul care contine informatiile despre utilizator nivelulul de acces la date pentru a fi inserat in baza de date. Metoda returneaza adevarat daca operatia s-a executat cu succes si fals in caz contrar.

Update – actualizeaza datele referitoare la utilizator. Se verifica adresa de email si daca mai exista o adresa cu acelasi nume se verifica daca aceasta apartine aceluiasi utilizatorului. Daca sunt indeplinite toate regulile de actualizare atunci se apeleaza metoda de la nivelul acces la date care realizeaza actualizarea informatiilor. Metoda returneaza adevarat daca operatia s-a executat cu succes si fals in caz contrar.

Clasa Order

Aceasta clasa defineste regulile de business care sunt folosite pentru comenziile clientilor. S-au implemenatat urmatoarele metode pentru a verifica regulile asociate comenzilor:

InsertOrder – verifica datele referitoare la comanda inainte de a fi inserata in baza de date. Verifica pentru fiecare produs din comanda cantitatea si pretul sa fie pozitive si calculeaza subtotalul si verifica daca acesta este la fel cu cel pe care-l contine obiectul OrderData primit ca parametru. Daca datele sunt valide se apeleaza metoda de la nivelul acces la date care insereaza comanda in baza de date. Daca operatia s-a efectuat cu succes se returneaza ID comenzii inserate, in caz contrar 0.

InsertOrderLines – insereaza un produs din comanda in baza de date. Returneaza adevarat daca operatia s-a efectuat cu succes si fals in caz contrar.

CalculateTaxes – calculeaza taxele care se aplica pentru comanda primita ca parametru. Returneaza un obiect TaxData care contine taxele aplicate comenzii si subtotalul pentru fiecare taxa.

CalculateTotalTaxes – calculeaza total taxelor aplicate unei comenzii.

Figura 3.10 Diagrama de clase a nivelului Business Rules

3.5 Nivelul de acces la date – Data Access

Nivelul Data Access furnizeaza serviciile de acces la date. Prin intermediul acestui nivel se realizeaza accesul la baza de date din SQL Server. Implementeaza clasele de acces la baza de date. Accesul la date se face prin ADO.NET. Nivelul de acces la date:

Primeste o cerere de la nivelul regulilor de business pentru a accesa baza de date.

Foloseste procedurile stocate pentru a incarca si trimite date la baza de date.

Returneaza rezultatul interogarii bazei de date nivelului regulilor de business.

S-a folosit SQL Server pentru optimizarea performantei. Strategia de acces la date a aplicatiei realizate se concentreaza pe urmatoarele aspecte:

Mutarea procesarii asupra datelor mai degraba decat mutarea datelor spre procesare. Pentru aceasta se folosesc procedurile stocate pentru toate procesarile asupra datelor.

Mentinerea resurselor bazei de date un timp cat mai scurt.

Pentru conectarea la baza de date se pastreaza in fisierul de configurare al aplicatiei Web.config sirul de conectare la baza de date astfel:

<appSettings>

<add key="ConnectionString" value="server=HOMECALI;user

id=ECommerce_login;password=commerce;database=E-Commerce"/>

</appSettings>

Valoarea acestui sir va fi stabilita la instalarea aplicatiei in functie de valorile care se introduc la instalare si de serverul unde se va instala baza de date. Acesta valoare va fi folosita de toate obiectele SqlConnection declarate la acest nivel in felul urmator:

SqlConnection conn = new SqlConnection();

conn.ConnectionString =

ConfigurationSettings.AppSettings["ConnectionString"];

De asemenea s-au folosit obiecte SqlDataAdapter pentru comunicarea cu baza de date si obiecte SqlCommand pentru apelul procedurilor stocate.

S-au implementat urmatoarele clase de acces la baza de date: Categories, Items, Customers, Suppliers, ShoppingCartDA, Countries, Currencies, Taxes, DeliveryAddressDA, Orders. Aceste clase contin metode apelate de catre nivelele superioare de reguli de business si care returneaza o valoare sau un set de date rezultat in urma executarii unei procedurii stocate. Toate clasele implementate folosesc obiecte de tip DataSet definite la nivelul Common cum ar fi CategoryData, ItemData, CustomerData.

Modul de implementare a claselor de la acest nivel este urmatorul:

Fiecare clasa implementata are ca si camp al clasei un obiect SqlDataAdapter (daCategories, daItems, daOrders) prin care se realizeaza comunicarea cu baza de date si transferul datelor dintre DataSet si baza de date. De asemenea clasele care executa si operatii de inserare, stergere, actualizare au definite ca si campuri ale clasei obiecte de tip SqlCommand (loadCommand, insertCommand, updateCommand) prin care se executa procedurile stocate.

Aceste obiecte SqlCommand contin numele procedurii stocate care trebuie executata, parametrii procedurii si sunt asignate obiectului SqlDataAdapter prin intermediul proprietatilor acestuia (SelectCommand, InsertCommand, UpdateCommand). Pentru transferul datelor se folosesc metodele obiectului SqlDataAdapter care primesc ca si parametru un obiect DataSet definit la nivelul Common. Aceste metode sunt Fill, Update. Dupa apelul acestor metode se returneaza setul de date obtinut in urma apelului.

In cazul operatiile de insert si update cand nu trebuie returnat un set de date, se verifica daca setul de date nu contine erori in urma apelului metodei si se returneaza un mesaj de eroare sau identificatorul randului care a fost inserat in tabela din baza de date.

Pentru seturile de date care contin mai mult de un tabel se defineste prin intermediul obiectului SqlDataAdapter o mapare a tabelelor rezultate in urma comunicarii cu baza de date prin folosirea proprietatii TableMappings.

In continuare voi prezenta metodele implementate de fiecare dintre aceste clase.

Clasa Categories

Clasa defineste metodele de acces la categoriile de produse. In constructorul clasei se creeaza obiectul conexiune, obiectul adapter, obiectul command si se defineste maparea tabelelor pe care le va contine setul de date rezultat. S-au definit 2 metode:

GetCategories – returneaza un set de date CategoryData care contine doua tabele, in primul tabel fiind categoriile parinte, iar al doilea tabel contine subcategoriile.

GetCategoryName – returneaza numele categorie parinte si a subcategorie.

In figura 3.11 este prezentata diagrama de clase pentru nivelul Data Access, grupate intr-un pachet si componenta care contine aceste clase.

Figura 3.11 Diagrama de clase a nivelului Data Access

Clasa Items

Clasa defineste metodele de acces la produsele magazinului virtual. In constructorul clasei se creeaza obiectul conexiune, obiectul adapter, obiectul command si se stabilesc numele tabelelor pe care le va contine setul de date rezultat. Toate metodele returneaza in urma aplelului un set de date ItemData care contine un tabel cu produse si un tabel cu preturile speciale al clientului pentru produsele respective, daca acestea exista.

S-au implementat urmatoarele metode:

GetItemsByCategoryID – returneaza toate produsele unei subcategorii sau toate produsele care fac parte dintr-o categorie parinte.

GetItemByID – returneaza informatiile referitoare la un singur produs

GetNewItemsByCategoryID – returneaza produsele noi ale unei subcategorii.

GetSearchItems – returneaza produsele gasite in urma unei cautarii dupa categorie si un text specificat. Cei doi parametrii sunt optionali. In acest caz se returneaza toate produsele existente.

GetAdvancedSearchItems – returneaza produsele gasite in urma unei cautarii avansate dupa mai multe criterii, cum ar fi, identificatorul produsului, numele, furnizorul, categorie, pret minim, pret maxim, produsele noi, un text. Acesti parametrii sunt optionali, iar filtrare se poate face dupa unul sau mai multi parametrii.

GetMostPopularItems – returneaza un top al celor mai cumparate produse.

GetNewestItems – returneaza un top al celor mai noi produse.

GetBestPricesItems – returneaza un top al produselor care au pretul cel mai bun si care nu fac parte din produsele cele mai cumparate sau cele mai noi.

Clasa Customers

Clasa defineste metodele de acces la informatiile despre clientii magazinului. Prin intermediul acestei clase se pot inregistra noi clienti, actualiza datele clientiilor existenti sau autentifica clientii. Campurile clasei sunt un obiect SqlDataAdapter si trei obiecte SqlCommand, pentru incarcarea, inserarea si actualizarea datelor. Constructorul clasei creeaza obiectul adapter si stabileste tabelul din setul de date rezultat.

S-au implementat urmatoarele metode:

LoadCustomerByEmail – returneaza datele clientului dupa adresa de email.

InsertCustomer – insereaza un nou client in baza de date. Metoda primeste ca parametru un obiect CustomerData continand informatiile despre utilizator, declara si initializeaza parametrii obiectului insertCommand cu aceste valori, dupa care apeleaza metoda Update a obiectului daCustomers care realizeaza transferul datelor din setul de date in baza de date. Se verifica daca operatia s-a executat cu succes si se returneaza o valoare adevarat, iar in caz contrar se returneaza fals.

UpdateCustomer – actualizeaza datele referitoare la un client.

Clasa Suppliers

Clasa defineste o singura metoda GetSuppliers care returneaza un set de date continad informatiile despre furnizorii produselor.

Clasa ShoppingCartDA

Clasa defineste metodele de acces la „cosul de produse” salvat de client in baza de date pentru o vizita ulterioara. S-au implementat doua metode:

LoadItemsInCart – returneaza un set de date ShoppingCartData care contine produsele salvate de client in baza de date.

InsertItemInCart – insereaza un produs in „cosul pe produse” din baza de date pentru a fi pastrate pentru o vizita ulterioara.

Clasa Countries

Clasa defineste metodele de acces la tarile existente in baza de date. Constructorul clasei este asemanator cu cel al claselor prezentate. S-au implementat doua metode:

GetCountries – returneaza un set de date CountryData cu toate tarile existente.

GetCountryByID – returneaza datele referitoare la o anumita tara.

Clasa Currencies

Clasa defineste metodele de acces la valutele existente in baza de date. Constructorul clasei creeaza obiectele de acces la baza de date si stabileste maparea tabelelor din setul de date. Setul de date CurrencyData rezultat contine un tabel cu valutele existente si un alt tabel cu rata de conversie a valutelor raportat la euro. S-au implementat doua metode:

GetCurrencies – returneaza un set de date CurrencyData cu toate valutele existente in baza de date si ratele de conversie a acestora raportate la euro.

GetCurrencyByID – returneaza datele referitoare la o valuta specificata si rata de conversie raport la euro.

Clasa Taxes

Clasa defineste metodele de acces la taxele stabilite pentru fiecare tara. S-au implementat doua metode:

GetCountryTaxes – returneaza un set de date TaxData cu toate taxele care se aplica pentru tara respectiva.

GetOrderTaxes – returneaza un set de date care contine taxele care au fost aplicate unei comenzii. Se primeste ca parametru un sir de id-uri de taxe. (CSV).

Clasa DeliveryAddressDA

Clasa defineste metodele de acces la adresele de livrare a comenziilor efectuate. Modul de implementare al clasei este asemanator cu clasa Customers. S-au definit urmatoarele metode:

LoadShippingAddress – returneaza un set de date DeliveryAddressData continad informatiile despre o adresa de livrare pe baza unui identificator.

InsertDeliveryAddress – insereaza datele referitoare la o adresa de livrare. Metoda returneaza adevarat daca operatia s-a efectuat cu succes sau fals in caz contrar si are un parametru de iesire reprezentand identificatorul adresei inserate.

UpdateDeliveryAddress – actualizeaza datele unei adrese de livrare.

RemoveDeliveryAddress – sterge o adresa de livrare pe baza identificatorului primit ca parametru de intrare.

Clasa Orders

Clasa defineste metodele de acces la comenzile efectuate de clienti. Constructorul clasei defineste obiectul adapter si stabileste maparea tabelelor din setul de date, care va contine un tabel cu comenziile efectuate (Orders) si un tabel cu produsele comenziilor (OrderLines).

S-au implementat urmatoarele metode:

InsertOrder – insereaza o noua comanda in baza de date. Datele referitoare la comanda sunt luate dintr-un set de date OrderData primit ca parametru.

InsertOrderLines – insereaza un rand din comanda in baza de date.

GetCustomerOrders – returneaza un set de date OrderData cu toate comenzile unui client pe baza id-ului clientului.

GetOrderDetails – returneaza toate datele referitoare la o comanda pe baza unui identificator primit ca parametru de intrare.

Clasele de la acest nivel de acces la date sunt grupate in spatiul de nume ECommerce.DataAccess si compilate in biblioteca ECommerce.DataAccess.dll.

3.6 Nivelul Common

In plus fata de cele 4 nivele principale descrise, aplicatia contine de asemenea si nivelul Common care ofera seturile de date folosite de toate celelalte nivele pentru pasarea informatiilor, datelor dintre diferite nivele. Acest nivel contine clase care definesc modelul obiectual pentru tabelele existente in baza de date. La acest nivel sunt definite toate seturile de date cu care lucreaza aplicatia. S-au implemenat urmatoarele clase: CategoryData, CountryData, CurrencyData, CustomerData, DeliveryAddressData, ItemData, OrderData, ShoppingCartData, SupplierData, TaxData.

Aceste clasele sunt grupate in spatiul de nume ECommerce.Common.Data si compilate in biblioteca ECommerce.Common.Data.dll.

Modul de implementare al acestor clase este urmatorul:

Fiecare clasa mosteneste clasa DataSet si prin aceasta obiectele clasei sunt seturi de date.

Toate clasele au declarate constante de tip sir de caractere prin care se definesc numele coloanele tabelelor din baza de date si au implementata o metoda numita BuildDataTables care este apelata in constructorul clasei.

Aceasta metoda creeaza un obiect DataTable avand numele constantei definite, o colectie de coloane, adauga la colectie coloane avand numele constantelor definite, specificand pentru fiecare coloana tipul ei, dupa care adauga la colectia Tables a obiectului this tabelul definit. Daca setul de date contine mai multe tabele se instantiaza un nou obiect DataTable care se adauga la colectia Tables si se adauga la obiect alte coloane.

Obiectele instanta ale acestor clase sunt trimise ca parametrii la metodele de acces la date si sunt apelate in metodele Fill, Update ale obiectului adapter care comunica cu baza de date. Dupa executarea procedurii stocate aceste obiecte vor contine tabele cu valorile rezultate din interogarea SQL. Prin intermediul acestor clase avem definit un model obiectual al tabelelor din baza de date .

Aceste nivele prezenatate alcatuiesc arhitectura aplicatiei. Fiecare nivel a fost definit ca un proiect in mediul de dezvolatare al aplicatie, Visual Studio .NET si au grupate toate intr-o solutie „ECOMMERCE” si un proiect de tip Enterprise. Au fost configurat fiecare proiect in parte, stabilite bibliotecile, spatiile de nume si dependentele dintre proiecte.

3.7 Modul de implementare – Diagrame UML

Pentru a vedea cum interactioneaza nivelele aplicatiei implementate, modul de comunicare dintre acestea, voi prezenta cateva diagrame de interactiune, care descriu comportarea obiectelor din punct de vedere al colaborarilor.

Voi prezenta prin diagrame de secventiere cateva din cazurile de utilizare al aplicatiei: explorarea categoriilor, cautarea produselor, autentificarea utilizatorilor.

3.7.1 Diagrame de secventiere

Explorarea categoriilor

Figura 3.12 Diagrama de secventiere pentru cazul de utilizare Explorarea Categoriilor

Diagrama de secventiere vizualizeaza modul in care se deplaseaza controlul de la obiect la obiect intre nivelele aplicatiei pentru extragerea categoriilor parinte si a subcategoriilor din baza de date, legarea lor la o sursa de date DataList si tratarea evenimentelor care apar la selectarea unei categorii. Acest control apare aproape in toate paginile realizate.

Cautarea produselor (Search)

Figura 3.13 Diagrama de secventiere pentru cazul de utilizare Cautarea Produselor

Autentificarea utilizatorilor (Login)

Figura 3.14 Diagrama de secventiere pentru cazul de utilizare Login

3.7.2 Arhitectura statica a sistemului

Figura 3.15 Modelul static al sistemului. Diagrama de clase

3.8 Arhitectura bazei de date

Aproape orice aplicatie creata pentru domeniul comercial foloseste o anumita forma de stocare a datelor. Pentru aplicatia de comert electonic realizata s-a folosit sistemul de gestiune a bazelor de date relationale (RDBMS) SQL Server 2000.

Datele aplicatiei sunt stocate intr-o baza de date relationala. Baza de date contine mai multe tabele intre care s-au stabilit relatii de legatura. In figura … este prezentata arhitectura bazei de date relationale a aplicatiei, si relatiile de legatura dintre tabele. Tabele folosite in sistem pot fi grupate in mai multe categorii: tabele generale, tabele de legatura, tabele pentru gestionarea produselor, tabele pentru gestionarea clientilor, tabele pentru gestionarea comenzilor. Aceste tabele constituie entitatile bazei de date create.

In continuare voi prezenta structura acestor tabele precum si explicarea diagramei bazei de date prezentata in figura de mai jos, descrierea entitatilor, atributelor si a relatiilor dintre ele.

3.8.1 Tabele generale

Tabele generale sunt folosite pentru gestionarea tarilor, a valutelor, a taxelor sistemului.

Countries – tarile cunoscute in sistem. Atributele care caracterizeaza aceasta entitate sunt: CountryID (identificatorul tarii, cheia primara a tabelului) , CountryName (numele tarii), CurrecnyID (valuta oficiala a tarii respective), Description (o scurta descriere a tarii).

Currencies – valutele cunoscute de catre sistem si in care vor fi afisate preturile produselor. Atributele definite sunt: CurrencyID (cheia primara a tabelului, identificatorul unic al valutei), CurrencyName (numele valutei), Image (o poza a valutei), Description (sucrta descriere), Symbol (simbolul valutei).

CurrencyRates – ratele de schimb ale valutelor folosite raportate la euro. Atributele definite sunt: CurrencyID (identificatorul valutei) , EffectiveDate (data la care rata de schimb este valida), CurrencyRate (rata de schimb a valutei).

Taxes – taxele existente in cadrul organizatiei respective. Atributele entitatii definite sunt: TaxID (identificatorul unic al taxei), TaxName (numele taxei), Description (o scurta descriere a taxei respective).

Figura 3.16 Arhitectura bazei de date relationale a aplicatiei

3.8.2 Tabele de legatura

CountryTaxes – se pastreaza taxele aferente fiecarei tarii. Este un tabel de legatura intre tabelul Countries si Taxes, care contine urmatoarele atribute: CountryTaxID (identificatorul unic al unui rand, cheia primara), CountryID (tara), TaxID (taxa), TaxType (tipul taxei care poate fi 1 – Amount, 2 – Percent), TaxValue (valoarea taxei). O tara poate avea asociate mai multe taxe.

CustomerItemPrice – se pastreaza preturile preferentiale pe care le pot avea clientii pentru anumite produse. Este un tabel de legatura intre tabelul Items si Customers, care contine urmatoarele atribute: CustomerID (identificatorul clientului), ItemID (identificatorul produsului), PricePerUnit (pretul pe unitatea de masura), ValidDate (data pana la care este valabil pretul respectiv). Cheia primara a tabelului este combinatia CustomerID, ItemID.

3.8.3 Tabele pentru produse

Categories – categoriile de produse existente in sistem. Atributele sunt: CategoryID (identificatorul unic al categoriei, cheia primara), CategoryName (numele categoriei), Description (scurta descriere a categoriei), ImageFile (numele fisierului cu poza categoriei), ParentCategoryID (identificatorul categoriei parinte).

Items – se pastreaza informatiile referitoare la produsele existente. Fiecare produs are urmatoarele atribute: ItemID (identificatorul unic al produsului, cheia primara), ItemName (numele produsului), SupplierID (furnizorul produsului), CategoryID (categoria din care face parte produsul), ItemStock (cantitatea existenta in stoc), ItemUnit (unitatea de masura), UnitPrice (pretul pentru o unitate produs), Image (poza produsului), Details (detalii, specificatii tehnice referitoare la produs), Description (o scurta descriere a produsului), IsNewItem (specifica daca produsul este nou).

Suppliers – evidenta furnizorilor de produse. Atributele definite sunt: SupplierID, CompanyName, ContactName, ContactTitle, Address, City, PostalCode, CountryID, Phone, Email, BankAccount, BankName, Description.

ShoppingCart – se pastreaza „cosul de produse” salvat de client pentru o vizita ulterioara. Datele din acest tabel vor fi pastrate pentru fiecare client timp de 5 zile dupa care vor fi sterge. Atributele definite sunt: ShoppingCartID (cheia primara), CustomerID (identificatorul clientului), ItemID (identificatorul produsului), ItemName, Quantity (cantitatea dorita), UnitPrice (pretul unitar), DateCreated (data cand produsul a fost adaugat in tabela).

3.8.4 Tabele pentru clienti

Customers – se pastreaza informatiile despre clientii magazinului virtual. Atributele care caracterizeaza aceasta entitate sunt: CustomerID (identificatorul clientului, cheia primara), CustomerName (numele clientului), Address (adresa clientului), City, PostalCode, CountryID (identificatorul tarii), Phone, Email (adresa de email, folosita si la login), Password (parola folosita la autentificare), CardType, CardNumber, ExpiredDate (date referitoare la modul de plata), CurrencyID (valuta in care vor fi afisate preturile produselor), Description, CustomerStatus (starea clientului, 1 – Normal Customer, 2 – Doubtfoul Customer, 3 – Blocked Customer).

CustomerDeliveryAddress – se pastreaza adresele la care se face livrarea produselor cumparate de clientii. Este utila in cazul in care se doreste trimiterea unui cadou. Atributele definite sunt: DeliveryAddressID (identificatorul adresei, cheia primara), CustomerID (identificatorul clientului), Name (numele persoanei unde se trimit produsele), Address, City, PostalCode, CountryID, Phone.

3.8.5 Tabele pentru comenzi

Pentru gestionarea ordinelor de cumparare se folosesc 2 tabele. Un tabel contine informatiile generale referitoare la ordinul de cumparare, iar alt tabel contine cate o inregistrare pentru fiecare produs care face parte dintr-o comanda.

Orders – pastreaza informatiile referitoare la comenzile clientilor. Atributele care caracterizeaza aceasta entitate sunt: OrderID (identificatorul unic al comenzii, cheia primara), CustomerID (identificatorul clientului), DeliveryAddressID (identificatorul adresei de livrare), CountryTaxIDs (un sir de identificatorii de taxe aplicate comenzii, unei comenzii i se pot aplica mai multe taxe), TaxesValue (valoarea totala a taxelor aplicate), CardType (tipul cartii de credit cu care se face plata), CardNumber (numarul cartii de credit), ExpiredDate (data la care expira credit card-ul), OrderDate (data la care s-a facut ordinul de cumparare), OrderStatus (starea curenta a comenzii), OrderTotalPrice (valoarea totala a comenzii efectuate, incluzand taxele, pretul total pe care il plateste clientul).
Starea unei comenzii poate fi urmatoarea: 1 – Submitted (comanda a fost trimisa de client), 2 – Accepted (comanda a fost acceptata), 3 – Returned (comanda este returnata din diverse motive), 4 – Shipped (comanda a fost trimisa catre client), 5 – Closed (comanda a fost inchisa).

OrderLines – se pastreaza informatiile referitoare la o comanda, produsele care sunt comandate, cate o linie, un rand pentru fiecare produs. Atributele definite sunt: OrderLineID (cheia primara, identificatorul liniei din comanda), OrderID (identificatorul comenzii), ItemID (produsul), UnitPrice (pretul unitar), Quantity (cantitatea dorita).

3.8.6 Relatiile dintre tabele

Fiind o baza de date relationala sau stabilit relatii de tip 1:1, 1:N, M:N intre tabelele bazei de date. Aceste relatii sunt prezentate in diagrama entitate-relatie (DER) din figura urmatoare:

Figura 3.17 Diagrama entitate-relatie

In diagrama entitate-relatie (DER) din figura X sunt definite urmatoarele relatii intre tabele:

Relatie 1:1 intre entitatile Currencies si CurencyRates in sensul ca fiecare valuta are o singura rata de schimb.

Relatie 1:N intre entitatile Currencies si Countries in sensul ca o valuta poate sa fie pentru mai multe tari, dar o tara are o singura valuta.

Relatie 1:N intre entitatile Currencies si Customers in sensul ca o singura valuta poate fi aleasa de mai multi clienti pentru afisarea preturilor.

Relatie 1:N intre entitatile Countries si Customers in sensul ca dintr-o tara fac parte mai multi clientii, dar un client poate sa aiba o singura tara.

Relatie 1:N intre entitatile Countries si Suppliers in sensul ca dintr-o tara fac parte mai multi furnizorii, dar un furnizor poate sa aiba o singura tara.

Relatie 1:M intre entitatile Countries si CountryTaxes in sensul ca o tara poate avea asociate mai multe taxe.

Relatie 1:N intre entitatile Taxes si CountryTaxes in sensul ca o taxa se poate aplica in mai multe tari.

Relatie M:N intre entitatile Countries si Taxes prin tabelul de legatura CountryTaxes in sensul ca tarile pot avea mai multe taxe si taxele se pot aplica in mai multe tari.

Relatie 1:N intre entitatile Categories si Items in sensul ca o categorie poate avea mai multe produse, dar un produs poate apartine unei singure categorii.

Relatie 1:N recursiva a entitatii Categories in sensul ca o categorie parinte poate avea mai multe subcategorii.

Relatie 1:N intre entitatile Suppliers si Items in sensul ca un furnizor furnizeaza mai multe produse, dar un produs apartine unui singur furnizor.

Relatie 1:M intre entitatile Items si CustomerItemPrice in sensul ca un produs poate avea mai multe preturi preferentiale pentru clienti.

Relatie 1:N intre entitatile Customers si CustomerItemPrice in sensul ca un client poate avea mai multe produse pentru care are preturi preferentiale.

Relatie M:N intre entitatile Items si Customers in sensul ca mai multe produse pot avea preturi preferentiale pentru mai multi clienti si invers.

Relatie 1:M intre entitatile Items si ShoppingCart in sensul ca un produs poate sa apara de mai multe ori in „cosul” salvat de clientii in baza de date pentru o vizita ulterioara.

Relatie 1:N intre entitatile Customers si ShoppingCart in sensul ca un client poate avea mai multe produse pastrate in „cosul” din baza de date.

Relatie M:N intre entitatile Items si Customers prin tabelul de legatura ShoppingCart in sensul ca mai multe produse pot fi salvate de mai multi clienti si invers.

Relatie 1:N intre entitatile Customers si CustomerDeliveryAddress in sensul ca un client poate sa aiba mai multe adrese de livrare a produselor.

Relatie 1:1 intre entitatile Orders si CustomerDeliveryAddress in sensul ca o comanda poate sa aiba o singura adresa de livrare.

Relatie 1:N intre entitatile Customers si Orders in sensul ca un client poate sa aiba mai multe comenzi, dar o comanda are un singur client.

Relatie 1:M intre entitatile Items si OrderLines in sensul ca un produs poate sa apara in mai multe comenzii si implicit in tabela care contine liniile unei comenzii.

Relatie 1:N intre entitatile Orders si OrderLines in sensul ca o comanda poate contine mai multe produse.

Relatie M:N intre entitatile Items si Orders in sensul ca mai multe produse pot fi comandate de mai multi clienti si invers.

3.8.7 Procedurile stocate

Deoarece operatiile de stocare si incarcare a datelor sunt esentiale pentru succesul aplicatiei s-au folosit pentru operatiile cu baza de date procedurile stocate. O lista a procedurilor stocate implemenatate este prezentata in tabelul urmator.

Tabelul 3.1 Procedurile stocate din baza de date a aplicatiei

4. Caiet de sarcini

In acest capitol sunt prezentate datele tehnice referitoare la mediul de utilizare, caracteristicile functionale, necesitatile hardware si software de instalare a aplicatei.

4.1 Cerinte hardware

Cerintele hardware necesare pentru instalarea si rularea fara probleme a aplicatiei sunt:

Procesor : Pentium II, 450 MHz (recomandat Pentium III, 600 MHz)

Memorie RAM : Windows 2000 Professional – 96 MB; Windows 2000 Server – 192 MB; Windows XP Professional — 160 MB (recomandat: 128 MB pentru Professional, 256 MB pentru Server, 192 MB pentru XP Professional)

Spatiu disponibil pe HDD : spatiu minim de 1,5 GB pentru instalarea componentelor software necesare aplicatiei, serverului de baza de date.

Sistem de operare : Windows 2000, Windows XP, sau Windows NT 4.0

Video : 800×600, 256 culori (recomandat 1024×768, High Color 16-bit)

4.1 Cerinte software

Cerintele software necesare pentru instalarea si rularea aplicatiei sunt urmatoarele:

Sistem de operare : Microsoft Windows 2000 SP2, Windows XP Professional (recomandat: Windows 2000 Server)

RDBMS : Microsoft SQL Server 2000 cu mod mixt de autentificare (SQL Server si Windows) si utilitarele osql.exe si bcp.exe (necesare pentru kit-ul de instalare).

Server de Web : Internet Information Server (IIS 5.0)

Pachetul Microsoft .NET Framework SDK

Pachetul Microsoft Mobile Internet Toolkit

Microsoft Data Access Components (MDAC) 2.6 sau 2.7, Internet Explorer 5.5 (6.0)

Pentru intretinerea aplicatiei se recomanda instalarea mediul de dezvoltare Microsoft Visual Studio .NET

Nu sunt necesare configurari suplimentare ale produselor software pentru instalarea aplicatiei.

5. Manual de operare

5.1 Instalare

Pentru instalarea aplicatiei este necesar rularea kit-ului de instalare ECommerceSetup.msi.

Ca o contributie personala la tema aleasa s-a implementat un kit de instalare al aplicatiei.

Acesta contine toate operatiile necesare pentru instalarea fara probleme a aplicatiei.

Astfel programul de instalare permite stabilirea numelui directorului virtual unde se va instala aplicatia, a portului pe care ruleaza aplicatia, copierea fisierelor sursa, crearea bazei de date, a tabelelor, a procedurilor stocate, copierea datelor in tabele, si de asemenea se configureaza fisierul de configurare web.config pentru conexiunea la baza de date, cu datele introduse de utlizator (numele bazei de date, numele serverului, utilizator, parola).

Prin dezvoltarea acestui kit de instalare s-a dorit a face procesul de instalare cat mai usor posibil si fara a necesita alte setari suplimentare ale aplicatiei. Modul de realizarea a kit-ului de instalare si pasii care trebuie efectuati pentru instalarea cu succes a aplicatiei sunt prezentati in subcapitolul 8.7 din „Anexe”. Pentru ca aplicatia sa se poata instala si sa functioneze in bune conditii trebuie indeplinite ceritele software descrise in capitolul anterior.

Dupa instalare se poate stabili securitatea aplicatiei la nivel de server (IIS) precum si stabilirea paginii de default a aplicatiei (Home.aspx). De asemenea se poate crea un nou site web pentru aplicatie si mutarea aplicatiei in site-ul creat. Toate acestea se realizeaza din IIS.

5.2 Utilizare

Daca instalarea aplicatiei s-a efectuat cu succes singurul lucru de care este nevoie pentru rularea aplicatiei este un browser de Web (IE 5.5). Se tasteaza adresa site-ului, care contine numele calculatorului gazda pe care s-a instalat aplicatie, sau a site-ului, numele directorului virtual al aplicatiei si pagina principala a aplicatiei Home.aspx (de exemplu, http://HOMECALI/ECommerce/Home.aspx). Clientul poate naviga printre paginile site-ului pentru a se inregistra si trimite ordinul de cumparare a produselor dorite. Daca se doreste verificarea comenziilor prin intermediul unui dispozitiv mobil este nevoie de un telefon mobil sau pocket pc si conditia ca utilizatorul sa se fi inregistrat pe site-ul aplicatiei.

5.3 Metode de testare si verificare

Deoarece aplicatiile dezvoltate pot contine erori, se impune depistarea si eliminarea acestora. Cum aplicatiile complexe se realizeaza pe module, fiecare modul trebuie testat mai intai separat pentru a i se elimina erorile, iar dupa aceea urmeaza testarea de ansamblu, pentru a se vedea cum se comporta si daca isi indeplineste functiile in cadrul aplicatiei.

Prin testare se face o verificare a corectitudinii aplicatiei pentru un set limitat de date de intrare. Daca setul de date de intrare este complet, adica acopera toate cazurile de utilizare posibile, atunci se poate spune ca programul este corect. Practic, insa, nu se pot testa toate combinatiile posibile pentru datele de intrare si de aceea testarea ramane o metoda ce demonstreaza, dar nu garanteaza, corectitudinea aplicatie.

Avantajul folosirii metodei testarii este faptul ca programul se executa in mediul sau real, corespunzator utilizarii lui finale si deci se poate urmari comportamentul programului si din alte puncte de vedere decat al rezultatelor propuse, cum este de exemplu: timpul de raspuns, memoria ocupata, eventualele blocaje. Se pot evalua de asemenea perfomantele aplicatiei.

Cu cat erorile sunt detectate mai tarziu, cu atat costul eliminarii lor este mai mare, motiv pentru care s-a cautat sa se elaboreze mai multe tehnici de testare. Testarea de jos in sus este metoda clasica de testare, ea constand in testarea modulelor, urmata in final de testarea intregului sistem ca un tot unitar.

Testarea de sus in jos este posibila numai in cazul unei conceperi descendente (programare structurata) a sistemului informatic sau a produsului program, ea efectuandu-se pe masura realizarii modulelor, incepand cu modulul principal, apoi cu cele din primul nivel subordonat.

Metoda de testare mixta presupune aplicarea simultana a celor doua metode de testare. Alegerea strategiei de testare depinde foarte mult de felul cum s-a conceput realizarea proiectului. Intr-o abordare de realizare a produsului program ascendenta, testarea de jos in sus este cea mai potrivita, in timp ce testarea de sus in jos se aplica unui proiect realizat prin metoda programarii structurale. In proiectul de fata realizat s-a aplicat metoda de testare de jos in sus, o testare functionala a aplicatiei.

Testare finala a aplicatiei realizare s-a efectuat pe o retea de calculatore din incinta unei firmei. S-a realizat o testare riguroasa a tuturor facilitatilor oferite de catre apliatiei, atat de catre autorul aplicatie pe propriul calculator, cat si de catre tester-ul firmei. De asemena aplicatia a fost data spre folosire si altor persoane pentru testare.

Testarea a cuprins in primul rand testarea programului de instalare. S-a urmarit daca aplicatia se instaleaza corect si poate fi folosita fara probleme dupa instalare. Apoi s-a urmarit realizarea tuturor cazurilor de utilizare posibile. S-a testat functionalitatea aplicatiei, si interfata utilizator. S-a urmarit corectitidunea afisarii informatiilor, aranjarea lor in pagina, modul de afisare a informatiile importante, usurinta in utilizare.

S-au ales pe rand toate optiunile posibile pe care le are un utilizator neinregistrat care doreste sa se „plimbe” prin paginile site-ului. S-a testat corectitudinea link-urilor afisate si a paginilor spre care duc acestea si posibilitatea de reintoarcere la pagina precedenta cu pastrarea parametrilor de filtrare s-au a datelor afisate. S-a testat securitate oferita de aplicatie pentru un utilizator inregistrat, optiunile oferite pentru utilizatorii inregistrati.

S-a testat si impelmentarea regulilor de business ale aplicatiei referitoare la utilizatori, comenzile efectuate de acestia. S-a testat si validarea formularelor la datele introduse de utilizator. Cum se comporta aplicatia la erorile generate intentionat de catre tester. Daca mesajele de eroare afisate sunt simple si ajuta utilizatorul.

S-a testat cazul de utilizare pentru timiterea ordinului de cumparare, tot procesul de cumparare prin intermediul magazinului. S-au adaugat produse in „cosul virtual”, s-a testat corectitudinea datelor din cos si a calculelor efectuate asupra preturilor, totalul de plata afisat, s-au completat formularele din checkout si s-a trimis comanda. S-a urmarit comportarea aplicatiei la accesul concurent al utilizatorilor, stabilitatea, performanta, timpul de raspuns la cererile clientilor.

Pentru testarea comportamentului aplicatiei pe dispozitivele mobile s-a folosit un emulator de la Nokia, Nokia Mobile Browser prin care s-a putut simula comportamentul aplicatiei pe telefoanele celulare.

Astfel prin metodele de testare aplicate s-a urmarit comportamentul aplicatiei in conditii reale de utilizare si daca sunt indeplinite toate obiectivele aplicatiei si sunt realizate toate cerintele unei astfel de aplicatii.

6. Concluzii

Ideea de a dezvolta o aplicatie de comert electronic a fost o provocare, care mi-a oferit sansa de a imbina cunostintele acumulate de-a lungul anilor de studiu cu studiul celei mai noi tehnologii pentru dezvoltarea de aplicatii Web.

Prin lucrarea de fata s-a studiat domeniul comertului electronic, s-au proiectat, realizat si implementat urmatoarele obiective si cerinte functionale ale aplicatiei:

S-au implementat functiile de baza pe care trebuie sa le ofere orice aplicatie de comert electronic (magazin virtual): inregistrarea clientilor, consultarea unui catalog de produse, cautare avansata a produselor, adaugarea produselor in cosul virtual, vizualizarea produselor cu paginare, afisarea detaliilor produselor, trimiterea ordinului de cumparare.

S-a realizat un mecanism de mentinere a produselor in „cosul virtual”, adaugare/stergere de produse din cos fara a folosi accesul la baza de date.

S-a realizat salvarea „cosului virtual” in baza de date pentru o vizita ulterioara cu posibilitatea de incarcare a produselor salvate.

S-a realizat posibilitatea clientului de a-si alege valuta in care doreste sa-i fie afisate preturile produselor. Preturile vor fi afisate in permanenta in euro si in valuta clientului.

S-a implementat un mecanism de afisare a preturilor preferentiale pe care le au unii clienti.

S-a realizat un modul de afisare a ofertelor promotionale de produse.

S-a proiectat si implementat posibilitatea clientilor de a face cadouri. O comanda poate sa fie trimisa la o adresa specficata de client.

S-a realizat un wizard pentru completarea si trimiterea ordinului de cumparare pentru a face procesul cat mai usor.

Un sistem de taxe aplicate comenzilor in functie de tara in care se face livrarea.

S-a realizat un modul prin care fiecare client are un cont in care poate vedea situatia comenzilor sale si poate sa-si tipareasca la imprimanta comanda facuta.

S-a implementat un sistem care sa-i permita clientului accesul la contul sau, vizualizarea ofertelor promotionale si verificarea comenzilor toate aceste prin intermediul unui dispozitiv mobil (telefon celular).

S-a realizat un kit de instalare a proiectului, de configuare a aplicatiei si a bazei de date.

Pot afirma in urma testelor efectuate ca proiectul realizat indeplineste toate obiectivele propuse, este stabil, usor de utilizat si corespunde necesitatilor unei firme care doreste sa-si inceapa o activitate de comert electronic. O aplicatie de comert electronic este absolut necesara pentru orice organizatie care are o activitate de comert.

Performantele proiectului realizat sunt comparabile cu cele ale majoritatii aplicatiilor de acest fel de pe piata. Acest lucru insa nu este concludent, neputand rula aplicatia in conditii reale de lucru, adica pe Internet, testele fiind facute pe o retea locala de calculatoare. Totusi urmarind aplicatiile existente in acest moment pe Internet si care au la baza platforma .NET pot afirma ca performantele proiectului realizat vor fi bune si in conditii reale de lucru.

Posibilitati de dezvoltare ulterioara

Din start orice aplicatie este astfel realizata, incat ulterior sa se poate dezvolta in diverse si noi directii. De ce acest lucru? Deoarece, dintr-un moment in altul nevoile utilizatorilor se pot schimba sau unele module ale aplicatiei pot sa se modifice, iar aplicatia trebuie sa poata tine pasul cu aceste schimbari.

Prima posibilitate de dezvoltare a aplicatiei care este absolut necesara consta in dezvoltarea si implementarea partii de administrare pentru aplicatia realizata. O solutie utila pentru partea de administrare ar putea fi urmatoarea:

Magazinul virtual sa permita vanzarea produselor de la mai multi furnizori, nu doar din cadrul unei singure organizatii. Astfel partea de administrare trebuie sa se implementeze pe idea ca prin intermediul aplicatiei diferiti vendori vor putea sa-si vanda produsele lor.

Trebuie definite tipurile de utilizatori ai partii de administrare: administratorii, operatorii (care valideaza produsele vendorilor si intretin functionarea magazinului) si vendorii care prin intermediul partii de administrare isi expun produsele pe Internet.

Pentru a putea diferentia utilizatorii si drepturile lor va fi nevoie de implementarea unui sistem de securitate: pentru fiecare ecran realizat se stabilesc drepturile posibile asupra lui, se definesc rolurile posibile pentru fiecare tip de utilizator si se stabileste pentru fiecare rol drepturile pe care le are asupra ecranelor. Se asigneaza fiecarui utilizator un rol.
Astfel administratorii pot sa aiba drepturi de modificare, de stergere, de adaugare, toate drepturile posibile definite, pe cand vendorii pot sa aiba access doar la anumite informatii destinate numai acestora, fara a avea acces la informatiile de administrare.

Vendorii vor putea sa-si adauge produsele noi, care vor fi verificate de operatori si care le vor accepta sau respinge. De asemenea sa poata vedea starea produselor grupate pe categorii (numarul de produse acceptate, cumparate, stoc-ul disponibil) si starea comenzilor efectuate de clienti, totalul comenzilor platite si livrate, etc.

Vendorii vor putea vedea toti clientii care au cumparat produsele lor, precum si o statistica pentru fiecare client, pentru a putea stabili preturi preferentiale pentru clientul respectiv la anumite produse.

Implementarea unui sistem de taxe configurabil, care sa permita vendorilor sa-si stabileasca taxele care se aplica produselor lui.

Implementarea unui sistem prin care un produs poate sa aiba asociate mai multe poze, care sa fie vizibile in partea de Internet. Pentru acesta trebuie ca vendorii sa poata sa-si adauge pentru fiecare produs mai multe poze. Se va face upload la pozele de pe calculatorul vendorului pe serverul aplicatiei.

Implementarea unui serviciu Web de actualizarea automata a ratelor de schimb valutar.

Acestea sunt doar cateva dintre posibilitatile de dezvoltare ale aplicatiei privind partea de administrare.

Posibilitatile de dezvoltare privind partea de Internet ar putea fi: implementarea unui sistem de plata electronic, globalizarea site-ului, oferind posibilitatea de afisare a informatiilor intr-o limba de circulatie internationala, implementarea unui serviciu web de actualizare automata a ratelor de schimb pentru valutele folosite. De asemenea vor aparea o serie de probleme de securitate fiind astfel necesara imbunatarirea securitatii sistemului. Desigur, toate acestea sunt doar cateva posibilitati de dezvoltare ale proiectului realizat, pe care autorul le poate intui.

Dat fiind domeniul atat de vast al comertului electronic se pot introduce o multitudine de facilitati noi aplicatiei. Necesitatea acestora va aparea in momentul folosirii aplicatiei in lumea reala a comertului electronic. Nu este exclus faptul ca unele module realizate sa nu acopere toate necesitatile unei anume organizatii. Ceea ce s-a incercat prin dezvoltarea unei astfel de aplicatii a fost stabilirea unui punct de plecare in dezvoltarea cu adevarat a unei aplicatii utile unui numar cat mai mare de organizatii.

8. Anexe

8.1 Procedurile stocate SQL Server

CREATE PROCEDURE usp_ShoppingCart_Insert

@pCustomerID int = null , @pItemID int , @pItemName varchar(100),

@pQuantity smallint, @pPrice decimal AS

DELETE FROM ShoppingCart

WHERE DateCreated < ( getdate() – 5 ) OR ItemID NOT IN

(SELECT ItemID FROM Items WHERE ItemID = ShoppingCart.ItemID)

OR Quantity > (SELECT ItemStock FROM Items

WHERE ItemID = ShoppingCart.ItemID )

– Insert Values into the ShoppingCart table

INSERT ShoppingCart (CustomerID,ItemID,ItemName,Quantity,UnitPrice)

SELECT @pCustomerID,@pItemID,@pItemName,@pQuantity,@pPrice

CREATE PROCEDURE usp_Orders_SelectOne

@pOrderID int AS

SELECT * FROM Orders WHERE OrderID = @pOrderID

SELECT OrderID, OrderLines.ItemID, ItemName, OrderLines.UnitPrice,

OrderLines.Quantity,

(OrderLines.UnitPrice * OrderLines.Quantity) AS Total

FROM OrderLines

LEFT OUTER JOIN Items ON Items.ItemID = OrderLines.ItemID

WHERE OrderID = @pOrderID

CREATE PROCEDURE usp_Orders_SelectByCustomerID

@pCustomerID int AS

SELECT * FROM Orders WHERE CustomerID = @pCustomerID

ORDER BY OrderDate DESC

CREATE PROCEDURE usp_Orders_Insert

@pOrderID int OUTPUT, @pCustomerID int,@pDeliveryAddressID SmallInt,

@pCountryTaxIDs VarChar(200), @pTaxesValue decimal (20,2),

@pCardType varchar(50), @pCardNumber varchar(30),

@pExpiredDate varchar(7), @pOrderStatus TinyInt,

@pOrderTotalPrice decimal (20,2) AS

– Insert Values into the Orders table

INSERT Orders (CustomerID,DeliveryAddressID,CountryTaxIDs,

TaxesValue,CardType,CardNumber,ExpiredDate,OrderStatus,

OrderTotalPrice)

SELECT @pCustomerID,@pDeliveryAddressID,@pCountryTaxIDs,

@pTaxesValue,@pCardType,@pCardNumber,@pExpiredDate ,

@pOrderStatus,@pOrderTotalPrice

– Get the new Order Identifier, return as OUTPUT param

SELECT @pOrderID = @@IDENTITY

CREATE PROCEDURE usp_OrderLines_Insert

@pOrderID int,@pItemID int,@pUnitPrice decimal,@pQuantity smallint

AS

– Insert Values into the OrderLines table

INSERT OrderLines (OrderID, ItemID,UnitPrice,Quantity)

SELECT @pOrderID,@pItemID,@pUnitPrice, @pQuantity

CREATE PROCEDURE usp_Items_SelectOne

@pItemID int = NULL,@pCustomerID int = NULL AS

SELECT ItemID,ItemName,Items.SupplierID,CategoryID,ItemStock, ItemUnit, UnitPrice, Image, Details, Items.Description,

IsNewItem, CompanyName AS SupplierName

FROM Items

LEFT OUTER JOIN Suppliers ON Items.SupplierID = Suppliers.SupplierID

WHERE ItemID = @pItemID

SELECT * FROM CustomerItemPrice

WHERE ItemID = @pItemID AND

CustomerID = @pCustomerID AND ValidDate >= getdate()

CREATE PROCEDURE usp_Items_SelectByCategoryID

@pCategoryID smallint = NULL, @pCustomerID int = NULL AS

SELECT * FROM Items WHERE CategoryID = @pCategoryID

ORDER BY CategoryID, ItemName, UnitPrice

SELECT * FROM CustomerItemPrice WHERE ItemID IN

(SELECT ItemID FROM Items WHERE CategoryID = @pCategoryID)

AND CustomerID = @pCustomerID AND ValidDate >= getdate()

CREATE PROCEDURE usp_Items_AdvancedSearch

@pItemID Int = null, @pItemName Varchar(100) = null, @pSupplierID Int = null, @pCategoryID SmallInt = null, @pMinPrice int = null,

@pMaxPrice int = null, @pNewItems bit = null, @pText VarChar(200) = null AS

DECLARE @pSearchText varchar(200)

DECLARE @pString nvarchar(500)

SET @pSearchText = '%' + @pText + '%'

SET @pString = 'SELECT * FROM Items WHERE '

IF @pItemID IS NOT NULL SET @pString = @pString+ 'ItemID=' +ltrim(str(@pItemID)) + ' AND '

IF @pItemName IS NOT NULL SET @pString = @pString + 'ItemName="' + @pItemName +'" AND '

IF @pSupplierID IS NOT NULL SET @pString = @pString + 'SupplierID=' +ltrim(str(@pSupplierID)) +' AND '

IF @pCategoryID IS NOT NULL SET @pString = @pString + 'CategoryID=' +ltrim(str(@pCategoryID)) + ' AND '

IF @pMinPrice IS NOT NULL SET @pString = @pString + 'UnitPrice>=' + ltrim(str(@pMinPrice)) + ' AND '

IF @pMaxPrice IS NOT NULL SET @pString = @pString + 'UnitPrice<=' + ltrim(str(@pMaxPrice)) + ' AND '

IF @pNewItems IS NOT NULL SET @pString = @pString + 'IsNewItem=' + ltrim(str(@pNewItems)) + ' AND '

IF @pText IS NOT NULL

SET @pString = @pString + '(ItemName LIKE "' +( @pSearchText)

+ '" OR ' + 'Details LIKE "' + (@pSearchText )+ '" OR ' +

'Description LIKE "' + (@pSearchText )+ '" )'

SET @pString = rtrim(@pString)

IF (right(@pString,5) = "WHERE")

SET @pString = replace(@pString,"WHERE","")

ELSE IF (right(@pString,3) = "AND")

SET @pString = substring(@pString,0,len(@pString)-3)

SET @pString = @pString + 'ORDER BY CategoryID, ItemName, UnitPrice'

EXEC sp_executesql @pString

CREATE PROCEDURE usp_Customer_Update

@pCustomerID int = NULL, @pCustomerName varchar(100) = NULL ,

@pAddress varchar(150) = NULL, @pCity varchar(50) = NULL,

@pPostalCode varchar(10) = NULL, @pCountryID smallint = NULL,

@pPhone varchar(20) = NULL, @pEmail varchar(100) = NULL,

@pPassword varchar(50) = NULL, @pCardType varchar(50) = NULL,

@pCardNumber varchar(30) = NULL, @pExpiredDate varchar(7) = NULL,

@pCurrencyID smallint = NULL, @pDescription varchar(4000) = NULL

AS

UPDATE Customers

SET CustomerName = @pCustomerName, Address = @pAddress, City = @pCity, PostalCode = @pPostalCode, CountryID = @pCountryID,

Phone = @pPhone, Email = @pEmail, Password = @pPassword, CardType = @pCardType, CardNumber = @pCardNumber, ExpiredDate = @pExpiredDate,

CurrencyID = @pCurrencyID,Description = @pDescription

WHERE Customers.CustomerID = @pCustomerID

CREATE PROCEDURE usp_CountryTaxes_SelectOrderTaxes

@pCountryTaxesIDs varchar(1000) = null AS

DECLARE @CountryTaxesIDs varchar (2000)

SET @CountryTaxesIDs = 'SELECT CountryTaxID,CountryID, CT.TaxID,

TaxName, TaxType, TaxValue

FROM CountryTaxes CT

LEFT OUTER JOIN Taxes ON CountryTaxes.TaxID = Taxes.TaxID

WHERE CountryTaxID IN (' + @pCountryTaxesIDs + ') '

EXECUTE (@CountryTaxesIDs )

CREATE PROCEDURE usp_Categories_SelectSubCategories

@pCategoryID smallint AS

SELECT * FROM Categories WHERE ParentCategoryID = @pCategoryID

AND CategoryID <> @pCategoryID

8.2 Fisierul de configurare Web.config

<?xml version="1.0" encoding="utf-8"?>

<configuration>

<appSettings>

<add key="ConnectionString" value="server=HOMECALI; user

id=ECommerce_login;password=commerce;database=E-Commerce"/>

</appSettings>

<system.web>

<!– CUSTOM ERROR MESSAGES –>

<!– enable custom errors for the application –>

<customErrors mode="Off" defaultRedirect="ErrorPage.aspx">

</customErrors>

<compilation defaultLanguage="c#" debug="false"/>

<!– security –>

<authentication mode="Forms">

<forms name=".ADUAUTH" loginUrl="Login.aspx" protection="All">

</forms>

</authentication>

<authorization> <allow users="*"/> </authorization>

<sessionState mode="InProc"

stateConnectionString ="tcpip=127.0.0.1:42424"

sqlConnectionString="data source=127.0.0.1;user

id=sa;password=" cookieless="false" timeout="20"/>

<globalization requestEncoding="utf-8" responseEncoding="utf-8"/>

<!– MOBILE CONFIG –>

<httpRuntime useFullyQualifiedRedirectUrl="true"/>

<!– SPECIFY COOKIELESS DATA DICTIONARY TYPE This is required

for forms authentication to work on cookieless devices. –>

<mobileControls cookielessDataDictionaryType="System.Web.Mobile.CookielessData"/>

<deviceFilters>

<filter name="isHTML32" compare="PreferredRenderingType" argument="html32"/>

</deviceFilters>

</system.web>

<!– set secure paths –>

<location path="CheckOut.aspx"> <system.web> <authorization> <deny users="?"/> </authorization> </system.web> </location>

<location path="OrderDetails.aspx"> <system.web> <authorization>

<deny users="?"/> </authorization> </system.web> </location>

<location path="MyAccount.aspx"> <system.web> <authorization>

<deny users="?"/> </authorization> </system.web> </location>

</configuration>

8.3 Clasele nivelului Data Access

Clasa Customers

using System; using System.Configuration; using System.Data;

using System.Data.SqlClient; using ECommerce.Common.Data;

namespace ECommerce.DataAccess { // Customers Data Access

public class Customers {

protected SqlDataAdapter daCustomers;

private SqlCommand loadCommand;

private SqlCommand insertCommand;

private SqlCommand updateCommand;

public Customers(){

// Create the DataAdapter

daCustomers = new SqlDataAdapter();

daCustomers.TableMappings.Add("Table",

CustomerData.CUSTOMERS_TABLE);

} // Retrieves the customer with the provided email address.

public CustomerData LoadCustomerByEmail(string email) {

CustomerData data = new CustomerData();

// Construct the command since we don't have it already

if (loadCommand == null) {

loadCommand = new SqlCommand();

loadCommand.Connection = new SqlConnection(

ConfigurationSettings.AppSettings["ConnectionString"]);

loadCommand.CommandType = CommandType.StoredProcedure;

loadCommand.CommandText = "usp_Customers_SelectOneByEmail";

loadCommand.Parameters.Add("@pEmail",SqlDbType.VarChar,50)

.Value = email;

} daCustomers.SelectCommand = loadCommand;

daCustomers.Fill(data); return data;

}

// Inserts a new customer into the database.

public bool InsertCustomer(CustomerData customer) {

if ( daCustomers == null) { throw new Exception(); }

if (insertCommand == null ) {

// Construct the command since we don't have it already

insertCommand = new SqlCommand();

insertCommand.Connection = new SqlConnection(

ConfigurationSettings.AppSettings["ConnectionString"]);

insertCommand.CommandType = CommandType.StoredProcedure;

insertCommand.CommandText = "usp_Customer_Insert";

// Customer parameters;

insertCommand.Parameters.Add("@pCustomerID",SqlDbType.Int);

insertCommand.Parameters.Add("@pCustomerName",SqlDbType.VarChar,100)

insertCommand.Parameters.Add("@pAddress",SqlDbType.VarChar,150);

insertCommand.Parameters.Add("@pCity",SqlDbType.VarChar,50);

insertCommand.Parameters.Add("@pPostalCode",SqlDbType.VarChar,10);

insertCommand.Parameters.Add("@pCountryID",SqlDbType.SmallInt);

insertCommand.Parameters.Add("@pPhone",SqlDbType.VarChar,20);

insertCommand.Parameters.Add("@pEmail",SqlDbType.VarChar,100);

insertCommand.Parameters.Add("@pPassword",SqlDbType.VarChar,50);

insertCommand.Parameters.Add("@pCardType",SqlDbType.VarChar,50);

insertCommand.Parameters.Add("@pCardNumber",SqlDbType.VarChar,30);

insertCommand.Parameters.Add("@pExpiredDate",SqlDbType.VarChar,7);

insertCommand.Parameters.Add("@pCurrencyID",SqlDbType.SmallInt);

insertCommand.Parameters.Add("@pDescription",SqlDbType.VarChar,4000)

insertCommand.Parameters.Add("@pCustomerStatus",SqlDbType.TinyInt);

// Define the parameter mappings from the data table in the dataset.

insertCommand.Parameters["@pCustomerID"].SourceColumn =

CustomerData.CUSTOMERID_FIELD;

insertCommand.Parameters["@pCustomerID"].Direction =

ParameterDirection.Output;

insertCommand.Parameters["@pCustomerName"].SourceColumn =

CustomerData.CUSTOMERNAME_FIELD;

insertCommand.Parameters["@pAddress"].SourceColumn =

CustomerData.ADDRESS_FIELD;

insertCommand.Parameters["@pCity"].SourceColumn =

CustomerData.CITY_FIELD;

insertCommand.Parameters["@pPostalCode"].SourceColumn =

CustomerData.POSTALCODE_FIELD;

insertCommand.Parameters["@pCountryID"].SourceColumn =

CustomerData.COUNTRYID_FIELD;

insertCommand.Parameters["@pPhone"].SourceColumn =

CustomerData.PHONE_FIELD;

insertCommand.Parameters["@pEmail"].SourceColumn =

CustomerData.EMAIL_FIELD;

insertCommand.Parameters["@pPassword"].SourceColumn =

CustomerData.PASSWORD_FIELD;

insertCommand.Parameters["@pCardType"].SourceColumn =

CustomerData.CARDTYPE_FIELD;

insertCommand.Parameters["@pCardNumber"].SourceColumn =

CustomerData.CARDNUMBER_FIELD;

insertCommand.Parameters["@pExpiredDate"].SourceColumn =

CustomerData.EXPIREDDATE_FIELD;

insertCommand.Parameters["@pCurrencyID"].SourceColumn =

CustomerData.CURRENCY_FIELD;

insertCommand.Parameters["@pDescription"].SourceColumn =

CustomerData.DESCRIPTION_FIELD;

insertCommand.Parameters["@pCustomerStatus"].SourceColumn =

CustomerData.CUSTOMERSTATUS_FIELD;

}

daCustomers.InsertCommand = insertCommand;

daCustomers.Update(customer);

// Check for table errors to see if the insert failed.

if (customer.HasErrors) {

customer.Tables[CustomerData.CUSTOMERS_TABLE].

GetErrors()[0].ClearErrors(); return false;

} else { customer.AcceptChanges(); return true; }

}

// Update Customer Information

public bool UpdateCustomer(CustomerData customer) {

if ( daCustomers == null) { throw new Exception(); }

if (updateCommand == null ) {

// Construct the command since we don't have it already

updateCommand = new SqlCommand();

updateCommand.Connection = new SqlConnection(

ConfigurationSettings.AppSettings["ConnectionString"]);

updateCommand.CommandType = CommandType.StoredProcedure;

updateCommand.CommandText = "usp_Customer_Update";

// Customer parameters; updateCommand.Parameters.Add("@pCustomerID",SqlDbType.Int);

updateCommand.Parameters.Add("@pCustomerName",SqlDbType.VarChar,100)

updateCommand.Parameters.Add("@pAddress",SqlDbType.VarChar,150);

updateCommand.Parameters.Add("@pCity",SqlDbType.VarChar,50);

updateCommand.Parameters.Add("@pPostalCode",SqlDbType.VarChar,10);

updateCommand.Parameters.Add("@pCountryID",SqlDbType.SmallInt);

updateCommand.Parameters.Add("@pPhone",SqlDbType.VarChar,20);

updateCommand.Parameters.Add("@pEmail",SqlDbType.VarChar,100);

updateCommand.Parameters.Add("@pPassword",SqlDbType.VarChar,50);

updateCommand.Parameters.Add("@pCardType",SqlDbType.VarChar,50);

updateCommand.Parameters.Add("@pCardNumber",SqlDbType.VarChar,30);

updateCommand.Parameters.Add("@pExpiredDate",SqlDbType.VarChar,7);

updateCommand.Parameters.Add("@pCurrencyID",SqlDbType.SmallInt);

updateCommand.Parameters.Add("@pDescription",SqlDbType.VarChar,4000)

// Define the parameter mappings from the data table in the dataset.

DataRow rowCustomer =

customer.Tables[CustomerData.CUSTOMERS_TABLE].Rows[0];

updateCommand.Parameters["@pCustomerID"].Value =

rowCustomer[CustomerData.CUSTOMERID_FIELD];

updateCommand.Parameters["@pCustomerName"].Value =

rowCustomer[CustomerData.CUSTOMERNAME_FIELD];

updateCommand.Parameters["@pAddress"].Value =

rowCustomer[CustomerData.ADDRESS_FIELD];

updateCommand.Parameters["@pCity"].SourceColumn =

CustomerData.CITY_FIELD;

updateCommand.Parameters["@pPostalCode"].SourceColumn =

CustomerData.POSTALCODE_FIELD;

updateCommand.Parameters["@pCountryID"].SourceColumn =

CustomerData.COUNTRYID_FIELD;

updateCommand.Parameters["@pPhone"].SourceColumn =

CustomerData.PHONE_FIELD;

updateCommand.Parameters["@pEmail"].SourceColumn =

CustomerData.EMAIL_FIELD;

updateCommand.Parameters["@pPassword"].SourceColumn =

CustomerData.PASSWORD_FIELD;

updateCommand.Parameters["@pCardType"].SourceColumn =

CustomerData.CARDTYPE_FIELD;

updateCommand.Parameters["@pCardNumber"].SourceColumn =

CustomerData.CARDNUMBER_FIELD;

updateCommand.Parameters["@pExpiredDate"].SourceColumn =

CustomerData.EXPIREDDATE_FIELD;

updateCommand.Parameters["@pCurrencyID"].SourceColumn =

CustomerData.CURRENCY_FIELD;

updateCommand.Parameters["@pDescription"].SourceColumn =

CustomerData.DESCRIPTION_FIELD;

}

daCustomers.UpdateCommand = updateCommand;

daCustomers.Update(customer);

// Check for table errors to see if the update failed.

if (customer.HasErrors) {

customer.Tables[CustomerData.CUSTOMERS_TABLE]

.GetErrors()[0].ClearErrors(); return false;

} else { customer.AcceptChanges(); return true; }

} } }

Clasa Items

using System; using System.Configuration; using System.Data;

using System.Data.SqlClient; using ECommerce.Common.Data;

namespace ECommerce.DataAccess {// Data Access Items

public class Items {

protected SqlDataAdapter daItems;

public Items() {

// Create the SqlConnection

SqlConnection conn = new SqlConnection();

conn.ConnectionString = ConfigurationSettings

.AppSettings["ConnectionString"];

// Create the DataAdapter

daItems = new SqlDataAdapter();

//Create the SelectCommand

daItems.SelectCommand = new SqlCommand();

daItems.SelectCommand.Connection = conn;

daItems.TableMappings.Add("Table", ItemData.ITEMS_TABLE);

daItems.TableMappings.Add("Table1",

ItemData.CUSTOMERITEMSPRICE_TABLE);

} // Retrives a dataset containing all items for a category.

public ItemData GetItemsByCategoryID (short categoryID,int

customerID,string type) {

ItemData data = new ItemData();

SqlCommand command = daItems.SelectCommand;

command.CommandType = CommandType.StoredProcedure;

if ( type == "SubCategory" ) {

command.CommandText = "usp_Items_SelectByCategoryID";

}

else {

command.CommandText = "usp_Items_SelectAllByParentCategoryID";

}

command.Parameters.Add("@pCategoryID",SqlDbType.SmallInt)

.Value = categoryID;

command.Parameters.Add("@pCustomerID",SqlDbType.SmallInt)

.Value = customerID;

daItems.Fill(data); return data;

}

// Item Details

public ItemData GetItemByID(int itemID,int customerID) {

ItemData data = new ItemData();

SqlCommand command = daItems.SelectCommand;

command.CommandType = CommandType.StoredProcedure;

command.CommandText = "usp_Items_SelectOne";

command.Parameters.Add("@pItemID",SqlDbType.Int).Value = itemID;

command.Parameters.Add("@pCustomerID",SqlDbType.Int)

.Value = customerID;

daItems.Fill(data); return data;

}

// Get New Items for a specified category.

public ItemData GetNewItemsByCategoryID (short categoryID,

int customerID) {

ItemData data = new ItemData();

SqlCommand command = daItems.SelectCommand;

command.CommandType = CommandType.StoredProcedure;

command.CommandText = "usp_Items_SelectNewByCategoryID";

command.Parameters.Add("@pCategoryID",SqlDbType.SmallInt)

.Value = categoryID;

command.Parameters.Add("@pCustomerID",SqlDbType.Int)

.Value = customerID;

daItems.Fill(data); return data;

}

public ItemData GetSearchItems(short categoryID, string text) {

ItemData data = new ItemData();

SqlCommand command = daItems.SelectCommand;

command.CommandType = CommandType.StoredProcedure;

command.CommandText = "usp_Items_Search";

command.Parameters.Add("@pCategoryID",SqlDbType.SmallInt);

command.Parameters.Add("@pText",SqlDbType.VarChar,200);

if (categoryID != 0) {

command.Parameters["@pCategoryID"].Value = categoryID;

}

if (text != null){ command.Parameters["@pText"].Value = text;}

daItems.Fill(data); return data;

}

public ItemData GetAdvancedSearchItems(int itemID, string itemName,

int supplierID, short catID, int minPrice,

int maxPrice, bool newItems, string searchText) {

ItemData data = new ItemData();

SqlCommand command = daItems.SelectCommand;

command.CommandType = CommandType.StoredProcedure;

command.CommandText = "usp_Items_AdvancedSearch";

command.Parameters.Add("@pItemID",SqlDbType.Int);

command.Parameters.Add("@pItemName",SqlDbType.VarChar,100);

command.Parameters.Add("@pSupplierID",SqlDbType.Int);

command.Parameters.Add("@pCategoryID",SqlDbType.SmallInt);

command.Parameters.Add("@pMinPrice",SqlDbType.Int);

command.Parameters.Add("@pMaxPrice",SqlDbType.Int);

command.Parameters.Add("@pNewItems",SqlDbType.Bit);

command.Parameters.Add("@pText",SqlDbType.VarChar,200);

if (itemID != 0) { command.Parameters["@pItemID"].Value = itemID;}

if (itemName != null) {

command.Parameters["@pItemName"].Value = itemName; }

if (supplierID != 0) {

command.Parameters["@pSupplierID"].Value = supplierID; }

if (catID != 0){command.Parameters["@pCategoryID"].Value = catID;}

if (minPrice != 0) {

command.Parameters["@pMinPrice"].Value = minPrice; }

if (maxPrice != 0) {

command.Parameters["@pMaxPrice"].Value = maxPrice; }

if (newItems){command.Parameters["@pNewItems"].Value = newItems; }

if (searchText != null) {

command.Parameters["@pText"].Value = searchText; }

daItems.Fill(data); return data;

}

// The Most Popular items

public ItemData GetMostPopularItems() {

ItemData data = new ItemData();

SqlCommand command = daItems.SelectCommand;

command.CommandType = CommandType.StoredProcedure;

command.CommandText = "usp_Items_MostPopular";

daItems.Fill(data); return data;

}

// The Newest Items

public ItemData GetNewestItems() {

ItemData data = new ItemData();

SqlCommand command = daItems.SelectCommand;

command.CommandType = CommandType.StoredProcedure;

command.CommandText = "usp_Items_SelectNewestItems";

daItems.Fill(data); return data;

}

// The Best Prices Items

public ItemData GetBestPricesItems() {

ItemData data = new ItemData();

SqlCommand command = daItems.SelectCommand;

command.CommandType = CommandType.StoredProcedure;

command.CommandText = "usp_Items_BestPrices";

daItems.Fill(data); return data;

} } }

Clasa Orders

using System; using System.Configuration; using System.Data;

using System.Data.SqlClient; using ECommerce.Common.Data;

namespace ECommerce.DataAccess { // Orders Data Access.

public class Orders {

protected SqlDataAdapter daOrders;

private SqlCommand insertCommand;

private SqlCommand loadCommand;

public Orders(){

// Create the DataAdapter

daOrders = new SqlDataAdapter();

daOrders.TableMappings.Add("Table",OrderData.ORDERS_TABLE);

daOrders.TableMappings.Add("Table1",OrderData.ORDERLINES_TABLE);

}

// Inserts a new order into the database.

public int InsertOrder(OrderData order) {

if ( daOrders == null) { throw new Exception(); }

if (insertCommand == null ) {

// Construct the command since we don't have it already

insertCommand = new SqlCommand();

insertCommand.Connection = new SqlConnection(

ConfigurationSettings.AppSettings["ConnectionString"]);

insertCommand.CommandType = CommandType.StoredProcedure;

insertCommand.CommandText = "usp_Orders_Insert";

// Customer parameters;

insertCommand.Parameters.Add("@pOrderID",SqlDbType.Int);

insertCommand.Parameters.Add("@pCustomerID",SqlDbType.Int);

insertCommand.Parameters.Add("@pDeliveryAddressID",

SqlDbType.SmallInt);

insertCommand.Parameters.Add("@pCountryTaxIDs",

SqlDbType.VarChar,200);

insertCommand.Parameters.Add("@pTaxesValue",SqlDbType.Decimal);

insertCommand.Parameters.Add("@pCardType",SqlDbType.VarChar,50);

insertCommand.Parameters.Add("@pCardNumber",SqlDbType.VarChar,30);

insertCommand.Parameters.Add("@pExpiredDate",SqlDbType.VarChar,7);

insertCommand.Parameters.Add("@pOrderStatus",SqlDbType.TinyInt);

insertCommand.Parameters.Add("@pOrderTotalPrice",SqlDbType.Decimal);

// Define the parameter mappings from the data table in the dataset.

DataRow row = order.Tables[OrderData.ORDERS_TABLE].Rows[0];

insertCommand.Parameters["@pOrderID"].Value =

row[OrderData.ORDERID_FIELD];

insertCommand.Parameters["@pOrderID"].Direction = ParameterDirection.Output;

insertCommand.Parameters["@pCustomerID"].Value = (int)

row[OrderData.CUSTOMERID_FIELD];

insertCommand.Parameters["@pDeliveryAddressID"].Value = (short)

row[OrderData.DELIVERYADDRESSID_FIELD];

insertCommand.Parameters["@pCountryTaxIDs"].Value =

row[OrderData.COUNTRYTAXIDS_FIELD].ToString();

insertCommand.Parameters["@pTaxesValue"].Value = (decimal)

row[OrderData.TAXESVALUE_FIELD];

insertCommand.Parameters["@pCardType"].Value =

row[OrderData.CARDTYPE_FIELD].ToString();

insertCommand.Parameters["@pCardNumber"].Value =

row[OrderData.CARDNUMBER_FIELD].ToString();

insertCommand.Parameters["@pExpiredDate"].Value =

row[OrderData.EXPIREDDATE_FIELD].ToString();

insertCommand.Parameters["@pOrderStatus"].Value = (byte)

row[OrderData.ORDERSTATUS_FIELD];

insertCommand.Parameters["@pOrderTotalPrice"].Value = (decimal)

row[OrderData.ORDERTOTALPRICE_FIELD];

}

daOrders.InsertCommand = insertCommand;

daOrders.Update(order);

// Check for table errors to see if the insert failed.

if (order.HasErrors) {

order.Tables[OrderData.ORDERS_TABLE]

.GetErrors()[0].ClearErrors(); return 0; }

else { order.AcceptChanges(); return (int)

insertCommand.Parameters["@pOrderID"].Value; } }

// Inserts order lines into the database.

public bool InsertOrderLines(DataRow orderLine){

bool returnValue = false;

SqlCommand cmd = new SqlCommand();

cmd.Connection = new SqlConnection(

ConfigurationSettings.AppSettings["ConnectionString"]);

cmd.CommandType = CommandType.StoredProcedure;

cmd.CommandText = "usp_OrderLines_Insert";

// Order Lines Prameters

cmd.Parameters.Add("@pOrderID",SqlDbType.Int);

cmd.Parameters.Add("@pItemID",SqlDbType.Int);

cmd.Parameters.Add("@pUnitPrice",SqlDbType.Decimal);

cmd.Parameters.Add("@pQuantity",SqlDbType.SmallInt);

cmd.Parameters["@pOrderID"].Value = (int)

orderLine[OrderData.ORDERID_FIELD];

cmd.Parameters["@pItemID"].Value = (int)

orderLine[OrderData.ITEMID_FIELD];

cmd.Parameters["@pUnitPrice"].Value = (decimal)

orderLine[OrderData.UNITPRICE_FIELD];

cmd.Parameters["@pQuantity"].Value = (short)

orderLine[OrderData.QUANTITY_FIELD];

cmd.Connection.Open();

// Execute the insert

int ret = (int) cmd.ExecuteNonQuery();

cmd.Connection.Close();

if (ret > 0) { returnValue = true;}

return returnValue;

}

// Get All orders for a specific customer

public OrderData GetCustomerOrders(int customerID){

OrderData data = new OrderData();

// Construct the command since we don't have it already

if (loadCommand == null){

loadCommand = new SqlCommand();

loadCommand.Connection = new SqlConnection(

ConfigurationSettings.AppSettings["ConnectionString"]);

loadCommand.CommandType = CommandType.StoredProcedure;

loadCommand.CommandText = "usp_Orders_SelectByCustomerID";

loadCommand.Parameters.Add("@pCustomerID",SqlDbType.Int)

.Value = customerID;

}

daOrders.SelectCommand = loadCommand;

daOrders.Fill(data); return data;

}

// Get Order Details

public OrderData GetOrderDetails(int orderID) {

OrderData data = new OrderData();

// Construct the command since we don't have it already

if (loadCommand == null){

loadCommand = new SqlCommand();

loadCommand.Connection = new SqlConnection(

ConfigurationSettings.AppSettings["ConnectionString"]);

loadCommand.CommandType = CommandType.StoredProcedure;

loadCommand.CommandText = "usp_Orders_SelectOne"; loadCommand.Parameters.Add("@pOrderID",SqlDbType.Int)

.Value = orderID;

}

daOrders.SelectCommand = loadCommand;

daOrders.Fill(data); return data;

} } }

8.4 Clasele nivelului Business Rules

Clasa Customer

using System; using System.Data;

using ECommerce.Common;

using ECommerce.Common.Data;

using ECommerce.DataAccess;

namespace ECommerce.BusinessRules {

public class Customer {

// Retrieve a customer given the customer's email and password.

public CustomerData GetCustomerByEmail(string email,

string password) {

if ((email != String.Empty) || (password != String.Empty)) {

// Get the customer dataSet

CustomerData dataSet;

Customers customerDataAccess = new Customers();

dataSet = customerDataAccess.LoadCustomerByEmail(email);

// Verify the customer's password

DataRowCollection rows =

dataSet.Tables[CustomerData.CUSTOMERS_TABLE].Rows;

if ((rows.Count == 1) &&

rows[0][CustomerData.PASSWORD_FIELD].Equals(password) )

{ return dataSet; }

} return null;

}

// Inserts a new customer True if successful; otherwise false;

public bool Insert (CustomerData customer) {

// Get the row

DataRow row =

customer.Tables[CustomerData.CUSTOMERS_TABLE].Rows[0];

bool result = true;

// Email verification. Ensure that it does not already exist

in the database.

CustomerData existingCustomer =

CheckExistingCustomer(row[CustomerData.EMAIL_FIELD]

.ToString());

if ( existingCustomer == null ) {

Customers customersDA = new Customers();

result = customersDA.InsertCustomer(customer);

} else { // Email is not unique

row.SetColumnError(CustomerData.EMAIL_FIELD, "Email Not

Unique");

row.RowError = "Invalid Fields"; result = false;

}

return result; // Return the result of the operation

}

public bool Update (CustomerData customer) {

// Get the row

DataRow row =

customer.Tables[CustomerData.CUSTOMERS_TABLE].Rows[0];

bool result = true;

// Email verification. Ensure that it does not already exist

in the database.

CustomerData existingCustomer =

CheckExistingCustomer(row[CustomerData.EMAIL_FIELD]

.ToString());

if ( existingCustomer != null ) {

// Email is not unique – make sure the email address

belongs this customer

if (row[CustomerData.CUSTOMERID_FIELD].ToString() !=

existingCustomer.Tables[CustomerData.CUSTOMERS_TABLE]

.Rows[0][CustomerData.CUSTOMERID_FIELD].ToString()) {

// CustomerID does not match, duplicate email address !

row.SetColumnError(CustomerData.CUSTOMERID_FIELD, "Email

Not Unique");

row.RowError = "Invalid Fields";

result = false;

}

} if (result) { // Update the customer

Customers customersDA = new Customers();

result = customersDA.UpdateCustomer(customer); }

return result;

}

private CustomerData CheckExistingCustomer(String emailAddress) {

// Get the customer

Customers customersDataAccess = new Customers();

CustomerData existingCustomer =

customersDataAccess.LoadCustomerByEmail(emailAddress);

// See if there is a customer associated with this email

if (null != existingCustomer) {

if (existingCustomer.Tables[CustomerData.CUSTOMERS_TABLE]

.Rows.Count == 1) {

return existingCustomer;

}

} return null;

} } }

8.5 Clasele nivelului Business Facade

Clasa CustomerSystem

using System; using System.Data;

using ECommerce.DataAccess;

using ECommerce.Common.Data;

using ECommerce.BusinessRules;

namespace ECommerce.BusinessFacade {

// This class contains the business facade for the customer system.

public class CustomerSystem {

public CustomerSystem() {}

// Retrieve a customer given the customer's email and password.

public CustomerData GetCustomerByEmail(string email,

string password) {

return (new BusinessRules.Customer())

.GetCustomerByEmail(email,password);

}

// Creates a new customer.

public bool CreateCustomer( String customerName,String address,

String city, String postalCode, short countryID,

String phone, String email, String password,

String cardType, String cardNumber, String expiredDate,

short currencyID,String description, byte customerStatus,

out CustomerData custData ) {

// Create a new row

custData = new CustomerData();

DataTable table = custData.Tables[CustomerData.CUSTOMERS_TABLE];

DataRow row = table.NewRow();

// Fill input data into new row

row[CustomerData.CUSTOMERNAME_FIELD] = customerName;

row[CustomerData.ADDRESS_FIELD] = address;

row[CustomerData.CITY_FIELD] = city;

row[CustomerData.POSTALCODE_FIELD] = postalCode;

row[CustomerData.COUNTRYID_FIELD] = countryID;

row[CustomerData.PHONE_FIELD] = phone;

row[CustomerData.EMAIL_FIELD] = email;

row[CustomerData.PASSWORD_FIELD] = password;

row[CustomerData.CARDTYPE_FIELD] = cardType;

row[CustomerData.CARDNUMBER_FIELD] = cardNumber;

row[CustomerData.EXPIREDDATE_FIELD] = expiredDate;

row[CustomerData.CURRENCY_FIELD] = currencyID;

row[CustomerData.DESCRIPTION_FIELD] = description;

row[CustomerData.CUSTOMERSTATUS_FIELD] = customerStatus;

table.Rows.Add(row); // Add to table

// Insert the customer using the business rules

return (new BusinessRules.Customer()).Insert(custData);

}

public bool UpdateCustomer ( CustomerData customer ) {

return (new BusinessRules.Customer()).Update(customer);

}

} }

Clasa ItemSystem

using System; using System.Data;

using ECommerce.DataAccess;

using ECommerce.Common.Data;

using ECommerce.BusinessRules;

namespace ECommerce.BusinessFacade{

// This class contains the business facade for the item system.

public class ItemSystem {

public ItemSystem() {}

public ItemData GetItemsByCategory (short categoryID,

int customerID, string type) {

Items itemsDataAccess = new Items();

return itemsDataAccess.

GetItemsByCategoryID(categoryID,customerID,type);

}

// Get an item for a specified item id.

public ItemData GetItemByID(int itemID,int customerID){

Items itemsDataAccess = new Items();

return itemsDataAccess.GetItemByID(itemID,customerID);

}

// Get New Items for a specified category.

public ItemData GetNewItemsByID (short categoryID,int customerID){

Items itemsDataAccess = new Items();

return itemsDataAccess.

GetNewItemsByCategoryID(categoryID,customerID);

}

// Search

public ItemData GetSearchItems(short categoryID, string text) {

Items itemsDataAccess = new Items();

return itemsDataAccess.GetSearchItems(categoryID,text);

}

// Advanced Search

public ItemData GetAdvancedSearchItems(int itemID, string itemName, int supplierID, short catID, int minPrice,

int maxPrice, bool newItems, string searchText){

Items itemsDataAccess = new Items();

return itemsDataAccess.GetAdvancedSearchItems(itemID, itemName,supplierID,catID,minPrice,

maxPrice,newItems,searchText);

}

// Get a dataset containing Items with CurrencyPrice.

// (Prices show in Customer Currency)

public ItemData PriceConversion(ItemData itemSet,

decimal currencyRate) {

DataTable tableItems = itemSet.Tables[ItemData.ITEMS_TABLE];

foreach ( DataRow row in tableItems.Rows){

// Price Conversion

row[ItemData.CURRENCY_PRICE] = (decimal) ((decimal)

row[ItemData.UNITPRICE_FIELD] * currencyRate);

}

return itemSet;

}

// Get a dataset containing Items Promo. ( Price or New Item)

public ItemData SetPromotions(ItemData itemSet) {

// Items DataTable

DataTable tableItems = itemSet.Tables[ItemData.ITEMS_TABLE];

// CustomerItemPrice Table

DataTable tableCustomerItemPrice = itemSet.Tables

[ItemData.CUSTOMERITEMSPRICE_TABLE];

foreach (DataRow datarow in tableItems.Rows) {

datarow[ItemData.PROMO_FIELD] = 0; // Implicit

if (datarow[ItemData.ISNEW_FIELD].ToString() == "True" ){

datarow[ItemData.PROMO_FIELD] = 1; //New

} else {

foreach (DataRow row in tableCustomerItemPrice.Rows){

// Check to see if Customer have a special price for item if ( row[ItemData.ITEMID_FIELD].ToString() ==

datarow[ItemData.ITEMID_FIELD].ToString()) {

datarow[ItemData.PROMO_FIELD] = (decimal)

row[ItemData.PRICEPERUNIT_FIELD];

}

}

}

}

return itemSet;

}

public ItemData MostPopularItems() {

Items itemsDataAccess = new Items();

return itemsDataAccess.GetMostPopularItems();

}

public ItemData NewestItems() {

Items itemsDataAccess = new Items();

ItemData itemsNewest = itemsDataAccess.GetNewestItems();

ItemData result = new ItemData();

short supID = 0; int count = 0;

foreach(DataRow row in itemsNewest.Tables

[ItemData.ITEMS_TABLE].Rows){

if (supID != Int16.Parse(row[ItemData.SUPPLIERID_FIELD] .ToString())) {

supID = Int16.Parse(row[ItemData.SUPPLIERID_FIELD]

.ToString());

count = count + 1;

DataRow newrow =

result.Tables[ItemData.ITEMS_TABLE].NewRow();

newrow[ItemData.ITEMID_FIELD] =

row[ItemData.ITEMID_FIELD];

newrow[ItemData.ITEMNAME_FIELD] =

row[ItemData.ITEMNAME_FIELD];

newrow[ItemData.SUPPLIERID_FIELD] =

row[ItemData.SUPPLIERID_FIELD];

newrow[ItemData.COMPANYNAME] = row[ItemData.COMPANYNAME];

newrow[ItemData.CATEGORYID_FIELD] =

row[ItemData.CATEGORYID_FIELD];

newrow[ItemData.CATEGORYNAME] =

row[ItemData.CATEGORYNAME];

newrow[ItemData.ITEMSTOCK_FIELD] = row[ItemData.ITEMSTOCK_FIELD];

newrow[ItemData.UNITPRICE_FIELD] =

row[ItemData.UNITPRICE_FIELD];

newrow[ItemData.IMAGE_FIELD] = row[ItemData.IMAGE_FIELD];

newrow[ItemData.DETAILS_FIELD] =

row[ItemData.DETAILS_FIELD];

newrow[ItemData.DESCRIPTION_FIELD] =

row[ItemData.DESCRIPTION_FIELD];

result.Tables[ItemData.ITEMS_TABLE].Rows.Add(newrow);

}

if (count > 5 ) break;}

return result;

}

public ItemData BestPrices() {

Items itemsDataAccess = new Items();

return itemsDataAccess.GetBestPricesItems();

}

// Categories. Retrives a dataset containing the categories

public CategoryData GetCategories() {

Categories accessCategories = new Categories();

return accessCategories.GetCategories();

}

public CategoryData GetCategoryName(short categoryID){

Categories accessCategories = new Categories();

return accessCategories.GetCategoryName(categoryID); }

// Suppliers

public SupplierData GetSuppliers() {

return ( new Suppliers() ).GetSuppliers();

}

// Shopping Cart System

// Load Items in ShoppingCart for logged customer.

public ShoppingCartData LoadItemsInCart(int customerID) {

return ( new ShoppingCartDA()).LoadItemsInCart(customerID);

}

// Inserts an Item into the ShoppingCart table.

public bool InsertItemInCart(ShoppingCartData cart) {

return ( new ShoppingCartDA()).InsertItemInCart(cart);

}

} }

Clasa OrderSystem

using System; using System.Data;

using ECommerce.DataAccess;

using ECommerce.Common.Data;

using ECommerce.BusinessRules;

namespace ECommerce.BusinessFacade {

// This class contains the business facade for the order system.

public class OrderSystem {

public OrderSystem() { }

public int AddOrder(OrderData order){

return (new BusinessRules.Order()).InsertOrder(order);

}

// Add order lines

public bool AddOrderLines(DataRow orderLine) {

return (new BusinessRules.Order()).InsertOrderLines(orderLine);

}

// Get Orders for a specific customer

public OrderData GetCustomerOrders(int customerID) {

Orders orders = new Orders();

return orders.GetCustomerOrders(customerID); }

// Get Order Details

public OrderData GetOrderDetails(int orderID) {

Orders orders = new Orders();

return orders.GetOrderDetails(orderID);

}

// Insert Shipping Address

public bool InsertDeliveryAddress(DeliveryAddressData delivery,

out short deliveryAddressID){

DeliveryAddressDA daDelivery = new DeliveryAddressDA();

return daDelivery.InsertDeliveryAddress(delivery,

out deliveryAddressID);

}

// Remove Delivery Address

public bool RemoveDeliveryAddress(short deliveryID) {

DeliveryAddressDA daDelivery = new DeliveryAddressDA();

return daDelivery.RemoveDeliveryAddress(deliveryID);

}

// Update Shipping Address

public bool UpdateDeliveryAddress(DeliveryAddressData delivery) {

DeliveryAddressDA daDelivery = new DeliveryAddressDA();

return daDelivery.UpdateDeliveryAddress(delivery);

}

// Load Shipping Address

public DeliveryAddressData LoadShippingAddress(short

deliveryAddressID){

DeliveryAddressDA daDelivery = new DeliveryAddressDA();

return daDelivery.LoadShippingAddress(deliveryAddressID);

}

// Get Country Taxes

public TaxData GetCountryTaxes(OrderData order) {

return (new BusinessRules.Order()).CalculateTaxes(order);

}

public TaxData GetOrderTaxes(string CSV) {

return (new Taxes()).GetOrderTaxes(CSV);

}

public Decimal GetSubTotalTaxes(TaxData taxes) {

return (new BusinessRules.Order()).CalculateTotalTaxes(taxes);

}

} }

8.6 Nivelul Prezentare – Web

Clasa Error

using System; using System.Diagnostics;

namespace ECommerce.Web { // Helper functions for errors.

public class Error {

protected const string EVENT_LOG_SOURCE = "E-Commerce";

// Log message to Application Log.

public static void Log(string message) {

EventLog eventLog = null;

// make sure we have an Event Log

if (!(EventLog.SourceExists(EVENT_LOG_SOURCE)) ) {

EventLog.CreateEventSource(EVENT_LOG_SOURCE, "Application");

}

if (eventLog == null ) {

eventLog = new EventLog("Application");

eventLog.Source = EVENT_LOG_SOURCE;

}

// log the message

eventLog.WriteEntry(message,System.Diagnostics.

EventLogEntryType.Error);

} } }

Clasa PageBase

using System; using System.Data; using System.Web;

using System.Web.UI;

using ECommerce.Common;

using ECommerce.Common.Data;

namespace ECommerce.Web {

public class PageBase : System.Web.UI.Page {

private const String KEY_CACHECART = "Cache:ShoppingCart:";

private const String KEY_CACHECUSTOMER = "Cache:Customer:";

private const String KEY_CACHESAVEDCART = "Cache:SavedCart";

private const String KEY_CACHEORDER = "Cache:Order:";

public PageBase () {}

// Property Customer is used to get or set the

// data for the logged on customer.

public DataSet Customer {

get{ return (DataSet) (Session[KEY_CACHECUSTOMER]);}

set{ if (value == null) {Session.Remove(KEY_CACHECUSTOMER);

} else { Session[KEY_CACHECUSTOMER] = value; }

}

}

// Property Order is used to get or set the

// data for the order.

public DataSet Order {

get { return (DataSet) (Session[KEY_CACHEORDER]); }

set { if ( value == null ){

Session.Remove(KEY_CACHEORDER);

} else { Session[KEY_CACHEORDER] = value; }

}

}

// Retrieves the Cart for the session,

// Create if it does not already exist.

public Cart ShoppingCart() { return ShoppingCart(true); }

//Retrieves the Cart for the session, optionally forcing it to

//be created if it does not already exist.

public Cart ShoppingCart(bool forceCreate) {

// Try to get the cart from the Session

Cart returnValue = (Cart)(Session[KEY_CACHECART]);

if (returnValue == null) {

// If there is no cart, create it now

returnValue = new Cart();

// Save it for later

Session.Add(KEY_CACHECART, returnValue);

}

if ( forceCreate ) returnValue.EnsureWritable();

return returnValue;

}

public Cart SavedCart {

get { return (Cart) (Session[KEY_CACHESAVEDCART]);}

set { if ( value == null ){

Session.Remove(KEY_CACHESAVEDCART);

} else { Session[KEY_CACHESAVEDCART] = value; }

}

} } }

Clasa Cart (”cosul virtual”)

using System;

using System.Web;

using System.Data;

using ECommerce.BusinessFacade;

using ECommerce.Common.Data;

using ECommerce.DataAccess;

namespace ECommerce.Web {

// Cart. Helper class used to manage shopping cart data

public class Cart { // Shopping cart data variable

private ShoppingCartData cartData;

private ShoppingCartData prevCartData;

// Constructor

public Cart() {}

// Make sure that the cart can actually be written to.

public void EnsureWritable(){

if (cartData == null){cartData = new ShoppingCartData();}

}

// Property IsEmpty is used to get whether the cart is empty.

// Returns true if the cart is empty, false otherwise.

public bool IsEmpty{

get { return (cartData == null) ? true :

(ShoppingCartItems.Rows.Count == 0); }

}

// Adds an Item to the shopping cart.

public void AddItem(int itemID, string itemName,

short quantity, decimal price) {

DataTable cartTable = ShoppingCartItems;

DataView itemSource = new DataView(cartTable);

// Search for item, check to see if the item

// has already been ordered

itemSource.RowFilter = "ItemID= " + itemID.ToString();

if (itemSource.Count > 0){

DataRowView sourceRow = itemSource[0];

short count = (short) (sourceRow[ShoppingCartData.

QUANTITY_FIELD]);

// maximum allowed for any specific item is 100

if (count < 100) { count += quantity;

sourceRow[ShoppingCartData.QUANTITY_FIELD] = count;

sourceRow[ShoppingCartData.PRICE_FIELD] = price;

sourceRow[ShoppingCartData.ITEMTOTAL_FIELD] =

(Decimal)sourceRow[ShoppingCartData.PRICE_FIELD] *

count; }

} else {

//It's a new item

DataRow itemRow = cartTable.NewRow();

itemRow[ShoppingCartData.ITEMID_FIELD] = itemID;

itemRow[ShoppingCartData.ITEMNAME_FIELD] = itemName;

itemRow[ShoppingCartData.QUANTITY_FIELD] = quantity;

itemRow[ShoppingCartData.PRICE_FIELD] = price;

itemRow[ShoppingCartData.ITEMTOTAL_FIELD] = price *

quantity;

cartTable.Rows.Add(itemRow); //Add it to the table

}

}

// Updates the Item in the shopping cart.

public void Update(int itemID, short quantity) {

int itemsCount = ShoppingCartItems.Rows.Count;

DataRow row;

for (int i = 0; i < itemsCount; i++){

row = ShoppingCartItems.Rows[i];

if ( Int32.Parse(row[ShoppingCartData.

ITEMID_FIELD].ToString()) == itemID ) {

row[ShoppingCartData.QUANTITY_FIELD] = quantity;

row[ShoppingCartData.ITEMTOTAL_FIELD] = (Decimal)

row[ShoppingCartData.PRICE_FIELD] * quantity;

break;

}

}

}

// Updates the Items in the shopping cart.

public void UpdateItems() {

int quantity;int itemsCount = ShoppingCartItems.Rows.Count;

DataRow row;

for (int i = 0; i < itemsCount; i++){

row = ShoppingCartItems.Rows[i];

quantity = Int32.Parse(row[ShoppingCartData.

QUANTITY_FIELD].ToString());

if (quantity < 1){ row.Delete(); itemsCount–;i–;}

else {

row[ShoppingCartData.ITEMTOTAL_FIELD] = (Decimal)

row[ShoppingCartData.PRICE_FIELD] * quantity;

}

}

}

// Removes the item from the cart

public void Remove(int itemID) {

int itemsCount = ShoppingCartItems.Rows.Count;

DataRow row;

for (int i = 0; i < itemsCount; i++) {

row = ShoppingCartItems.Rows[i];

if ( Int32.Parse(row[ShoppingCartData.

ITEMID_FIELD].ToString()) == itemID) {

row.Delete();break;

}

}

}

// Removes all items from the cart.

public void RemoveAllItems(){

ShoppingCartItems.Rows.Clear();

}

// Cart Sub-Total

public decimal GetSubTotal(){

decimal subTotal =0;

DataTable cartTable = ShoppingCartItems;

foreach(DataRow row in cartTable.Rows) {

subTotal += (Decimal)

(row[ShoppingCartData.ITEMTOTAL_FIELD]);

} return subTotal;

}

// Save Cart for next visit.

public void SaveCart() {

bool retValue = false;

int custID = Int32.Parse((new PageBase()).Customer.Tables [CustomerData.CUSTOMERS_TABLE].Rows[0]

[CustomerData.CUSTOMERID_FIELD].ToString() );

int itemsCount = ShoppingCartItems.Rows.Count;

DataRow row;

for (int i = 0; i < itemsCount; i++){

row = ShoppingCartItems.Rows[i];

row[ShoppingCartData.CUSTOMERID_FIELD] = custID;

}

retValue = (new ItemSystem()).InsertItemInCart(cartData);

if (retValue){RemoveAllItems();}

}

// Property ShoppingCartItems is used to get the ShoppingCartData.

public DataTable ShoppingCartItems{

get{return cartData.Tables[ShoppingCartData.

SHOPPINGCART_TABLE];}

}

// Methods for Saved Cart

public void LoadPrevItemsInTempCart(int custID){

prevCartData = new ShoppingCartData();

prevCartData = (new ItemSystem()).LoadItemsInCart(custID);

}

// Load Items from Saved Cart into Current Shopping Cart.

public void LoadItemsInCurrentCart() {

Cart savedCart = (new PageBase()).SavedCart;

foreach(DataRow savedRow in savedCart.TempCartItems.Rows){

int itemID = (int)

savedRow[ShoppingCartData.ITEMID_FIELD];

string itemName = savedRow[ShoppingCartData.

ITEMNAME_FIELD].ToString();

short quantity = (short) savedRow[ShoppingCartData.

QUANTITY_FIELD];

decimal price = (decimal)savedRow[ShoppingCartData.

PRICE_FIELD];

this.AddItem(itemID,itemName,quantity,price);

}

(new PageBase()).SavedCart = null;

}

public bool IsTempCartEmpty {

get { return (prevCartData == null) ? true :

(TempCartItems.Rows.Count == 0); }

}

public DataTable TempCartItems {

get { return prevCartData.Tables[ShoppingCartData.

SHOPPINGCART_TABLE];}

} } }

8.7 Realizarea programului de instalare

Proiectul pentru kit-ul de instalare al aplicatiei

Instalarea aplicatiei – Kit-ul de instalare

1. 2.

Rulare ECommerceWebSetup Setarea directorului virtual

3. 4.

Setare Baza de date Confirmare instalare

5. 6.

Aplicatia se instaleaza Instalare completa

Clasa pentru instalarea bazei de date si configurare

Clasa DatabaseInstall

using System; using System.Diagnostics;

using System.Xml; using System.IO;

using System.Data; using System.ComponentModel;

using System.Data.SqlClient; using System.Collections;

using System.Configuration.Install;

using System.Windows.Forms;

[RunInstaller(true)]

public class DatabaseInstall : Installer {

public void AddDBTable(string strDBName,string

serverName,string userID, string password) {

SqlConnection connection = new SqlConnection();

connection.ConnectionString="server="+serverName+"; user

id="+userID+"; pwd="+password+";

Integrated Security=SSPI";

try{

connection.Open();

SqlCommand cmd=new SqlCommand();

cmd.Connection=connection;

cmd.CommandType=CommandType.Text;

cmd.CommandText = "CREATE DATABASE " + strDBName;

cmd.ExecuteNonQuery();

} catch (Exception ex){

MessageBox.Show("Connection failed:\r" + ex.Message

, "Microsoft SQL Server", MessageBoxButtons.OK,

MessageBoxIcon.Stop);

throw new InstallException("Connection failed:\r" +

ex.Message);

} finally { connection.Close();}

}

public override void Install(IDictionary savedState) {

// Create Database

base.Install(savedState);

AddDBTable(this.Context.Parameters["dbname"],

this.Context.Parameters["dbserver"], this.Context.Parameters["dbuser"],

this.Context.Parameters["dbpassword"]);

// Run setup.bat – script for database

ProcessStartInfo startupInfo = new ProcessStartInfo ();

startupInfo.FileName = "cmd.exe";

startupInfo.WorkingDirectory = this.Context.Parameters["Dir"]

+ "Database\\sql\\";

startupInfo.Arguments = @"/C setup.bat " +

this.Context.Parameters["dbname"] + " " + this.Context.Parameters["dbserver"];

startupInfo.UseShellExecute = false;

startupInfo.RedirectStandardOutput = false;

startupInfo.RedirectStandardError = false;

startupInfo.CreateNoWindow = true;

startupInfo.WindowStyle = ProcessWindowStyle.Minimized;

Process process = Process.Start (startupInfo);

process.WaitForExit ();

// Write ConnectionString in web.config

System.IO.FileInfo FileInfo = new

System.IO.FileInfo(this.Context.Parameters["Dir"]+

"\\Web.config");

if (!FileInfo.Exists) {

throw new InstallException("Missing config file");

}

System.Xml.XmlDocument XmlDocument = new

System.Xml.XmlDocument();

XmlDocument.Load(FileInfo.FullName);

bool FoundIt= false;

foreach (System.Xml.XmlNode Node in

XmlDocument["configuration"]["appSettings"] )

{

if (Node.Attributes.GetNamedItem("key").Value ==

"ConnectionString")

{

Node.Attributes.GetNamedItem("value").Value = "server=" + this.Context.Parameters["dbserver"] + "; user id=" + this.Context.Parameters["dbuser"] + "; pwd=" + this.Context.Parameters["dbpassword"] + ";database=" + this.Context.Parameters["dbname"];

FoundIt = true;

}

}

if (!FoundIt) {

throw new InstallException("Config file did not contain

a ServerName section");

}

XmlDocument.Save(FileInfo.FullName);

}

}

8.7 Mediul de dezvoltare al aplicatiei – VS.NET

7. Bibliografie

Similar Posts