Sunteți pe pagina 1din 26

2. Aplicaii ASP.

NET
ASP.NET permite realizarea de aplicaii web complexe. Spre deosebire de celelalte tehnologii pe care le-ai studiat, realizarea aplicaiilor web n ASP.NET aduce o serie de avantaje importante: aplicaiile pot fi scrise utiliznd toate facilitile unor limbaje i medii de programare dezvoltate. n ceea ce urmeaz, vom realiza implementarea aplicaiilor ASP.NET n C#, dar exist posibilitatea implementrii acestora n multe alte limbaje; suntei obinuii cu tehnicile de scriptare. Ai ntlnit 2 astfel de tehnici, cea bazat pe limbajul JavaScript i respectiv cea bazat pe PHP. n primul caz, scriptarea se face la client, tehnica fiind numit client-side-scripting, iar n cel de-al doilea caz, scriptarea se face la nivelul serverului, fiind numit serverside-scripting. Fa de tehnicile uzuale de server-side-scripting, ASP.NET introduce i noiunea de server-side-controls. n tehnologiile uzuale, controalele sunt implementate manual i n plus programatorul trebuie s aib grij s implementeze modul de manifestare al acestora la aciunile utilizatorului. Problema este destul de complex n realitate, indiferent de locaia la care se face scriptarea. Aparent problema este relativ simpl n cazul scriptrii la client, de exemplu cu JavaScript. Se pot implementa n acest caz variabile care s rein coninutul de moment al controalelor i respectiv comportamentul acestora. Problema major apare din faptul c browserele implementeaz n mod diferit JavaScript i este destul de dificil de scris rutine care s funncioneze absolut similar pe toate browserele. O alternativ este de a scrie cod HTML simplu pentru controale i de a retrimite pagina spre server pentru refacerea ei n noul context. i n acest caz mecanismul este complicat, deoarece toate informaiile stocate n variabilele din pagin se vor pierde. ASP.NET rezolv aceast problem prin intermediul controalelor pe server. Aceste controale scripteaz codul HTML necesar afirii controlului n browser, dar, de asemenea, genereaz i funciile JavaScript i respectiv codul HTML ascuns care pstreaz starea controlului. Cnd utilizatorul acioneaz asupra controlului, informaia este furnizat napoi serverului, iar controlul proceseaz automat informaia i altereaz codul HTML astfel nct afiarea acestuia s se fac n noul context. probabil cel mai mare avantaj al ASP.NET este posibilitatea crerii de servicii web. La aceast problem vom reveni. 2.1 Crearea unei aplicaii simple Pentru crearea unei aplicaii simple ASP.NET vom crea un nou proiect (intitulat web1) de tip ASP.NET Web Application. Vom constata c se creaz un proiect cu o interfa diferit de cea cu care suntem obinuii i afieaz un text HTML (fig. 2.1). Este un nceput pentru pagina pe care urmeaz s o dezvoltm. Observm c aceast pagin poart denumirea Default.aspx. Va trebui s precizm mediului de programare c 30

Figura 2.1

aceast pagin este cea pe care dorim s-o depanm n caz de eroare, ea fiind pagina de start a aplicaiei. Pentru aceasta, apsm click dreapta pe Default.aspx n Solution Explorer i selectm Set as Start Page. Pagina afiat de Visual Studio ne prezint pagina cre va fi trimis spre browser. Aceasta poate fi abordat i n Designer, n mod grafic, selectnd tab-ul Design. Selectai-l i observai ce afiaz mediul. Haidei s revenim la tab-ul Source i s-i adugm cteva linii de cod:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="web1._Default" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Untitled Page</title> </head> <body> <form id="form1" runat="server"> <div> Cursuri urmate:

31

</div> <br> <div> Programare avansata in C# </div> </form> </body> </html>

Compilai i executai programul. Vom obine rezultatul din fig. 2.2. Cum funcioneaz? Simplu. Am creat un proiect Visual Studio i acesta s-a Figura 2.2 ocupat de tot ceea ce se petrece n spatele scenei, n aa fel nct pagina s poat fi scriptat i trimis spre browser. Este adevrat, n aceast pagin nc nu avem nimic dinamic, este o aplicaie foarte simpl, dar mecanismul este cel care este utilizat i pentru realizarea paginilor complexe. S ncercm acum s adugm componente dinamice paginii noastre. Dac revenim n Designer, vom avea imaginea Figura 2.3 din fig. 2.3: S ncercm s reeditm pagina n designer. Selectm i tergem textul Programare avansat n C# i adugm din Toolbox un control Label (fig. 2.4). S schimbm acum pentru controlul Label proprietatea Text n Curs i proprietatea ID n Curs. Acum, fie apsm dublu click n interiorul Designer-ului, fie selectm iconia de cod din Solution Explorer. Putem Figura 2.4 observa c trecerea ntre Designer i cod se face cu aceleai iconie care fceau trecerea ntre form i codul clasei asociate n proiectele de tip Windows Form. Am ajuns n zona de cod, n care se implementeaz codul care d caracterul dinamic al paginii. S modificm metoda Page_Load() ca mai jos:
protected void Page_Load(object sender, EventArgs e) { int an = DateTime.Now.Year; if (an == 2007) Curs.Text="Programare avanasata in C# - examen in anul "+an; else Curs.Text="Programare avanasata in C# - examen in anii 2007 - "+an; }

32

Compilai i executai programul. Vei obine pagina din fig. 2.4a. Dac vei intra n Settings i vei schimba anul, de exemplu la 2008 i vei da Refresh n browser, vei obine pagina din fig. 2.4b.

Figura 2.4a

Figura 2.4b

Cum funcioneaz? Putem observa c mesajul referitor la curs este dinamic. Ca o observaie important, controlul Label fiind un server-side-control, informaia referitoare la an este luat de pe server, calculatorul dumneavoastr funcionnd acum ca server de web. Cnd serverul construiete pagina, utilizeaz metoda Page_Load(). Aceasta extrage data curent prin intermediul metodei DateTime.Now() ntr-un obiect DateTime i respectiv obine anul curent din proprietatea Year a acestuia. Apoi, face comparaia i asociaz proprietii Text a controlului Label textul corespunztor. Apoi, face scriptarea. Dar cum ajunge alamentul activ s fie afiat n pagin? Pentru aceasta s revenim n tabul Source al Designer-ului. Observm ca Visual Studio a scriptat urmtorul cod:
<body> <form id="form1" runat="server"> <div> Cursuri urmate: </div> <br> <div> </form> </body> </html>
<asp:Label ID="Curs" runat="server" text="Curs"></asp:Label>&nbsp;</div>

Tag-ul <asp> implementeaz zona activ a codului. nainte ca fiierul s fie trimis spre browser, ASP.NET inspecteaz complet codul acestuia, pentru a determina prile statice i prile dinamice. Apoi, nlocuiete prile dinamice cu scriptarea HTML corespunztoare. n cazul nostru, elementul dinamic este proprietatea Text a controlului Label. n fapt, textul trimis spre browser (View Source) este urmtorul:
<div> Cursuri urmate: </div>

33

<br> <div> <span id="Curs">Programare avanasata in C# - examen in anul 2007</span>&nbsp;</div> </form> </body> </html>

Prin scrierea paginii web utiliznd Visual Studio, practic aceasta va fi codificat n 2 jumti: prima, salvat ntr-un fiier .aspx, va conine ablonul de desenare al paginii i va defini ce elemente active conine i unde apar acestea i respectiv o a doua jumtate, salvat ntr-un fiier .aspx.cs care conine codul de menipulare al evenimentelor. Sintetiznd, putem spune c modul de lucru este urmtorul: ASP.NET ncarc codul .aspx i caut elementele dinamice. Pentru aceasta, pstreaz n memorie imaginea HTML a paginii dar marcheaz fiecare linie din cod n care gsete elemente dinamice. Apoi, permite controalelor s-i pun propriul cod HTML n locul marcajelor. n cazul nostru, prin modificarea proprietii Text a controlului Label, i-am spus acestuia c atunci cnd ASP.NET i cere codul HTML corespunztor, s-l insereze n locul precizat:
<span id="Curs">Programare avanasata in C# - examen in anul 2007</span>

sau cu alte cuvinte, s insereze coninutul proprietii Text i s adauge tag-urile <span> i </span> n jurul acestuia. 2.2 Gestiunea informaiilor externe Unul din marile avantaje al utilizrii paginilor active este c dac dorim s adugm sau s schimbm coninutul paginii, nu e nevoie s rescriem codul HTML al acesteia. Astfel, noul coninut va trebui s fie stocat sub o form accesibil pentru scriptare i apoi adugat coninutului HTML. Metoda descris n continuare va stoca informaia n fiiere .xml, fr a fi nevoie s nelegem n detaliu structura acestora. S presupunem, de exemplu, ca am urmat mai multe cursuri, pentru care am dat examen la diferite momente. Informaiile legate de aceste examene le vom stoca n fiiere XML. Pentru ca infrastructura .NET s fie capabil s ncarce aceste fiiere, va trebui s precizm calea spre acestea. Dup cum tii, fiierele afiate ca pagini de web, vor trebui s fie stocate n directoare bine definite ale serverului de web. La fel i n cazul nostru. Pentru nceput, va trebui s aflm calea spre pagina Default.aspx. S Figura 2.5 adugm pentru aceasta un nou control Label. Vom aduga un nou control Label i la tab-ul Source vom aduga tag-urile <div> i <div/>:
<div>

34

<asp:Label ID="Curs" runat="server" text="Curs"></asp:Label>&nbsp;</div> <br> <div> </div> </form>

S modificm proprietatea Name pentru noul control n Cale i de asemenea s modificm funcia Page_Load() ca mai jos:
protected void Page_Load(object sender, EventArgs e) { Curs.Text = "Programare avanasata in C# - examen in anii 2007 - " + an; Cale.Text = " Calea spre server: " + Server.MapPath(""); }

Ce am fcut? Am apelat metoda Server.MapPath() care transform o cale virtual n www ntr-o cale fizic pe serverul de web. n acest fel am aflat unde este gzduit pagina noastr. Haidei s crem n directorul returnat un subdirector numit Cursuri. n acest director, s crem (eventual cu ajutorul Notepad) fiierul unu.xml, cu coninutul de mai jos:
<?xml version="1.0" ?> <InfCurs xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Titlu> CURS 1 </Titlu> <Detalii> Primul curs: Programare avansata in C#</Detalii> </InfCurs>

Un astfel de fiier va stoca informaia pe care o vom afia n pagina de web. Evident, n aceeai manier n care vom afia informaia dintr-un singur fiier, vom reui s afim i informaia din mai multe. Probabil tag-urile vi se par ciudate. Vom lmuri i acest lucru imediat. Primul pas este s ncrcm acest fiier. Pentru aceasta, va trebui s generm o metod de ncrcare ntr-o clas special, numit Global, care stocheaz date i metode globale, accesibile tuturor paginilor din aplicaia web. Aceast clas trebuie definit ntr-o pagin numit Global.asax. Pentru a aduga pagina, apsm click dreapta n Solution Explorer pe rdcin, apoi Add, Component i n final alegem Global Figura 2.6 Application Class. Cu aceasta, pagina Global.asax a fost adugat proiectului (fig. 2.6). Ca s putem ncrca fiierele .xml, va trebui ca n clasa Global s declarm o variabil care va stoca calea spre acestea. n codul Global.asax vom defini aceast cale:

35

public class Global : System.Web.HttpApplication { public static String CaleDirCurs;

Aceast cale, va trebui s fie completat la pornirea aplicaiei. La acel moment, se lanseaz automat n execuie o funcie numit Application_Start(), al crei schelet l putei vedea n cod. S modificm aceast funcie:
protected void Application_Start(object sender, EventArgs e) { CaleDirCurs = Server.MapPath("Cursuri"); }

Prin aceasta, am ncrcat variabila CaleDirCurs cu calea spre directorul unde am stocat fiierul .xml. Informaiile pe care dorim s le manipulm sunt: data asociat elementelor unui curs, titlul i detalii despre acestea. Pentru a manipula aceste informaii, vom aduga proiectului o nou clas, care s conin ca atribute mrimile pe care dorim s le manipulm. Fie InfCurs aceast clas (click dreapta pe rdcin n Solution Explorer, Add, Class i respectiv scriem numele clasei). De ce InfCurs? Mai inei minte structura fiierului .xml? Acolo marcajul exterior era <InfCurs></InfCurs>. Acest marcaj definete o structur de date care este descris n interior, de marcajele <Titlu></Titlu> i respectiv <Detalii></Detalii>. Aceste denumiri va trebui s le respectm i pentru noua clas. Obiectele acestei clase vor trebui serializate n i din fiiere .xml. V mai amintii ce trebuie s facem ca s permite lucrul cu fiiere i serializarea? Evident, s includem namespace-urile corespunztoare. Deci, n noua clas vom include
using System.Web.UI.HtmlControls; using System.IO; using System.Xml.Serialization; namespace web1 { public class InfCurs { } }

Acum s adugm structura de date a clasei i metodele care manipuleaz datele private:
public class InfCurs { private DateTime _data;

36

private String _titlu; private String _detalii; [XmlIgnore()] public DateTime Data { get { return _data; } set { _data = value; } } public String Titlu { get { return _titlu; } set { _titlu = value; } } public String Detalii { get { return _detalii; } set { _detalii = value; } } }

Ce am facut? nti am declarat trei variabile private n structura de date, conform informaiilor pe care dorim s le afim. Apoi, am generat pentru fiecare din cele 3 atribute funciile get() i set() care permit returnarea lor spre clasa apelant, respectiv completarea valorii lor. value este o mrime predefinit n mediu, pentru transferul de date. Observai c metodele get() i set() sunt prefixate de linii de tipul
public Tip Nume

unde Nume este numele tag-ului corespunztor din fiierul .xml iar Tip tipul cmpului asociat n structura de date a clasei. Linia [XmlIgnore()] specific faptul c urmtoarele linii (deci implementarea metodelor) sunt excluse de la serializare cnd sunt serializate obiectele clasei.

37

S revenim acum la Global.asax i s-i spunem i acestei clase c trebuie s lucreze cu fiiere i s permit serializarea:
using System.Web.SessionState; using System.IO; using System.Xml.Serialization;

S adugm acum acestei clase metoda care realizeaz efectiv deserializarea fiierului .xml i ncrcarea datelor acetuia n obiectele InfCurs:
public static InfCurs IncarcaCurs(String numfis) { String calefis = CaleDirCurs + "\\" + numfis; FileStream fi = new FileStream(calefis, FileMode.Open); XmlSerializer ser = new XmlSerializer(typeof(InfCurs)); InfCurs cursNou = (InfCurs)ser.Deserialize(fi); fi.Close(); return cursNou; }

Metoda returneaz un obiect InfCurs cu cmpurile din structura de date completate prin deserializarea informaiilor din fiierul .xml. Modul de implementare al metodei v este deja cunoscut, din capitolul 1. Metoda construiete irul calefis n care salveaz calea complet i numele fiierului din care se face deserializarea. Apoi construiete un FileStream asociat acestui fiier pe care-l deschide n citire i un nou deserialzator. Spre deosebire de decoderele binare utilizate n capitolul 1, acest deserializator este construit pentru formatul XML ca intrare, respectiv InfCurs ca ieire. Realizeaz deserializarea efectiv i returneaz obiectul rezultat. Acum urmeaz s construim interfaa pe care vom afia datele. S revenim n sursa Designer-ului i s adugm 2 noi tag-uri <div>:
<div> Cursuri urmate: </div> <br> <div></div> <div></div> <br>

Acum n Designer s adugm 2 noi controale Label, pentru care s schimbm proprietile ID n etTitlu i etDetalii (fig. 2.7). S apsm dublu click n pagina Designer-ului astel nct s revenim la codul care implementeaz evenimente i s modificm metoda Page_Load() ca mai jos: 38
Figura 2.7

protected void Page_Load(object sender, EventArgs e) { else Curs.Text = "Programare avanasata in C# - examen in anii 2007 - " + an; Cale.Text = " Calea spre fisier: " + Global.CaleDirCurs; InfCurs crs = Global.IncarcaCurs("unu.xml"); etTitlu.Text = crs.Titlu; etDetalii.Text = crs.Detalii; }

Ce face metoda? Afieaz calea spre fiier n eticheta n care anterior afia calea spre pagina Default.aspx. Apoi declar un obiect InfCurs al crui structur de date o ncarc cu informaia din fiierul unu.xml prin apelul metodei IncarcaCurs(). Apoi cmpurile Titlu i Detalii sunt afiate n controalele Label asociate. Observaie: Observai c dei cmpurile structurii de date din clasa InfCurs sunt _titlu i _detalii, am utilizat pentru obiectul crs denumirile Titlu i Detalii. Primele denumiri sunt denumiri interne clasei, acestea fiind fcute vizibile la nivelul interfeei automat, prin intermediul metodelor get() i set() sub denumirile publice. Compliai i executai prigramul. Ar trebui s obinei ceva similar fig. 2.8.

Figura 2.8

Dac dorii s verificai c ntr-adevr informaia este preluat din fiierul


unu.xml, nu avei dect s schimbai coninutul acestuia i s refreai pagina.

S completm acum i cmpul Data. Pentru aceasta, n Global.asax s modificm din metoda IncarcCurs():
public static InfCurs IncarcaCurs(String numfis) {

39

fi.Close(); cursNou.Data = new FileInfo(calefis).LastWriteTime; return cursNou; }

Ce am adugat? Am creat un obiect FileInfo pentru fiierul n care sunt stocate datele i am atribuit proprietatea LastWriteTime (timpul ultimei scrieri n fiier) cmpului Data. i acum s afim:
protected void Page_Load(object sender, EventArgs e) { etTitlu.Text = crs.Titlu; etDetalii.Text = crs.Data.ToString("dddd")+", "+ crs.Data.ToLongDateString()+" - " + crs.Detalii; }

Compilai i executai programul. 2.3 S mbuntim aspectul paginii Metoda cea mai simpl de creare a unui aspect plcut pentru pagin este utilizarea cascade style sheet (css). Acest mecanism l cunoatei de la cursul de pagini web, aa ca nu vom intra n amnunte. Primul pas pe cre trebuie sa l facem este s adugm o nou pagin de stiluri. Pentru aceasta, apsm click dreapta pe rdcin n Solution Explorer, Add, NewItem, i selectm Style Sheet. S dm numele pentru aceast pagin de stiluri Stil.css. Observaie: Putei folosi o pagin de stiluri existente. Pentru aceasta., apsai click dreapta n Solution Explorer, Add, ExistingItem, selectai fiierul .css dorit i apoi apsai butonul Add. S completm pagina de stiluri ca mai jos:
body { padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0px; padding-top: 0px; font-family:Verdana, Arial;

} .header { padding-right: 5px; padding-left: 5px; padding-bottom: 10px;

40

padding-top: 10px; background-color: #000099; font-weight: bold; font-size: 14pt; color: White; } .normal { padding-right: 5px; padding-left: 5px; font-size: 8pt; } .normalHeading { padding-right: 5px; padding-left: 5px; font-size: 12pt; font-weight:bold; } .crsTitlu { padding-right: 5px; padding-left: 5px; padding-bottom: 1px; padding-top: 1px; font-weight: bold; font-size: 10pt; color: White; background-color: #66cc99; } .crsData { font-weight: bold; color:#333399; font-size:8pt; } .crs { padding-right: 5px; padding-left: 5px; padding-top: 2px; font-size:8pt; }

Tot ce mai avem de fcut este s aplicm stilul fiierului HTML. S intrm n sursa Designer-ului i s modificm fiierul ca mai jos:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="web1._Default" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

41

<html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <link rel="stylesheet" href="Stil.css" /> <title>Untitled Page</title> </head> <body> <form id="form1" runat="server"> <div class="header"> Cursuri urmate: </div> <br> <div class="crsTitlu"> <asp:Label ID="etTitlu" runat="server" Text="Label"></asp:Label></div> <div class="crs"> <asp:Label ID="etDetalii" runat="server" Text="Label"></asp:Label></div> <br /> <hr color=#000000 /> <div class="normal"> <asp:Label ID="Curs" runat="server" Text="Curs"></asp:Label>&nbsp;</div> <br> <div class=normal> <asp:Label ID="Cale" runat="server" Text="Label"></asp:Label> </div> </form> </body> </html>

Compilai i executai programul. Vei obine rezltatul din fig. 2.9.

Figura 2.9

2.4 Afiarea unei colecii de informaii externe S vedem acum ce se poate face dac avem mai multe fiiere .xml care conin date. Pentru nceput, vom terge controalele Label etTitlu i etDetalii precum i tag-urile 42

<div> aferente i vom aduga n locul lor un control DataList (l gsii la seciunea Data al Toolbox), ca n fig.

2.10. Acesta este un control care permite adugarea n interiorul lui al altor controale. De asemenea, permite iterarea informaiilor din controalele din interior pentru toate datele de tipul specificat existente. S modificm propriertatea ID petru acest control n datalistCurs. Figura 2.10 Acum, s adugm controale n interiorul lui. Pentru aceasta, apsm click dreapta pe control i n meniul contextual alegem Edit Template i Item Templates. Controlul va fi afiat sub form tabelar, permind adugarea altor controale. S tragem acum un control Label n seciunea Item Templates. Pentru a

Figura 2.11a Figura 2.11b

respecta stilul de afiare, s modificm proprietatea CssClass al controlului Label n crsTitlu. Acum va trebui s precizm ce se afieaz n acest control. Pentru aceasta, apsm pe sgeata din partea dreapt-sus a controlului i alegem Edit Data Bindings (fig. 2.11a). Va fi afiat caseta de dialog din fig. 2.11b. n aceasta, avem grij ca la Bindable Properties: s fie selectat proprietatea Text i apoi introducem n caseta Code Expression textul:
DataBinder.Eval(Container,"DataItem.Titlu")

Acest text precizeaz c n faza de completare al controlului, proprietii Text al acestuia i se va atribui DataItem.Titlu, adic cmpul Titlu din obiectul conectat la control. Urmeaz s adugm nc 2 controale Label, ca n figura 2.12. Pentru controlul Label2 vom modifica proprietatea CssClass n crsData i vom introduce n caseta Code Expression textul

Figura 2.12

43

DataBinder.Eval(Container, "DataItem.DataInSir")

iar pentru controlul Label3, vom modifica proprietatea CssClass n crs i vom introduce textul
DataBinder.Eval(Container,"DataItem.Detalii")

Cu alte cuvinte, am precizat pentru fiecare control stilul de afiare luat din pagina de stiluri i respectiv cu cine este conectat. O mic problem apare la controlul Label2, pentru care conectarea nu se face la un cmp cunoscut al clasei InfCurs. Despre aceasta vom vorbi n cele ce urmeaz. Va trebui acum s adugm n fiierul Global.asax o metod care s permit ncrcarea tuturor fiierelor din directorul cu date:
public static InfCurs[] IncToateC() { DirectoryInfo subdirector = new DirectoryInfo(CaleDirCurs); FileInfo[] fisiere = subdirector.GetFiles(); InfCurs[] cursuri = new InfCurs[fisiere.Length]; int index = 0; foreach (FileInfo fis in fisiere) { cursuri[index] = IncarcaCurs(fis.Name); index++; } return cursuri; }

Cum lucreaz metoda? Pentru nceput creaz un obiect DirectoryInfo, numit subdirector, care reprezint tocmai directorul care conine fiierele. Apoi apeleaz pentru acesta metoda GetFiles(). S ne reamintim c aceast metod ncarc un ir de obiecte FileInfo cu fiierele din director (vezi cap. 1). Declar apoi un ir de obiecte InfCurs, de dimensiune egal cu dimensiunea irului de obiecte FileInfo, dup care incarc irul de obiecte InfCurs cu informaiile din fiecare fiier n parte, apelnd metoda IncarcaCurs() pentru deserializarea fiecrui fiier. n final, funcia returneaz irul de obiecte InfCurs. Practic, metoda va prelua fiecare fiier .xml din director, va deserializa informaia i o va salva n cte un obiect InfCurs din ir. Astfel, vom avea disponibil pentru afiare informaia din toate fiierele. Acum, n funcia Page_Load(), va trebui s eliminm seciunea care asociaz cmpurile obiectului fostelor controale Label i s asociem cmpurile tuturor obiectelor obinute prin deserializare controlului DataList. Astfel, vom terge liniile
InfCurs crs = Global.IncarcaCurs("unu.xml");

44

etTitlu.Text = crs.Titlu; etDetalii.Text = "<font class=crsData>" + crs.Data.ToString("dddd")+", "+crs.Data.ToLongDateString()+ "</font> - " + crs.Detalii;

i n locul lor vom aduga liniile:


protected void Page_Load(object sender, EventArgs e) { int an = DateTime.Now.Year; Cale.Text = " Calea spre fisier: " + Global.CaleDirCurs; InfCurs[] cursuri = Global.IncToateC(); datalistCurs.DataSource = cursuri; datalistCurs.DataBind();

Ce am fcut? Am ncrcat irul de obiecte InfCurs cursuri cu informaia deserializat, am precizat obiectului DataList sa-i ia informaiile din acest ir de obiecte InfCurs (ca surs) i s itereze pentru toate aceste obiecte i am conectat cele 2 obiecte ntre ele (datalistCurs i cursuri). Ce mai avem de fcut? S implementm proprietatea DataInSir pentru obiectele InfCurs. De ce e nevoie de aceasta. Pn acum data crerii fiierelor o afiam separat, n metoda Page_Load(). Deoarece acum vom manipula mai multe fiiere, data crerii va trebui s fie o proprietate intrinsec a obiectelor. Cum facem asta? Simplu. Adugm clasei InfCurs codul:
public String DataInSir { get { return Data.ToString("dddd") + ", " + Data.ToLongDateString(); } }

Proprietatea va putea fi doar citit (expune doar metoda get()). Proprietatea va conine data curent sub forma unui ir de caractere. Compilai i executai programul. 2.5 Adugarea fiierelor .xml Pn acum am completat fiierele .xml manual. Putem uor crea o pagin care s le creeze automat, prin mecanismul de serializare a obiectelor InfCurs. Pentru aceasta, la nceput, va trebui s adugm proiectului o nou pagin web: click dreapta pe rdcin n

45

Solution Explorer, Add, New Item i respectiv Web Form. S denumim aceast nou form Adaugare.aspx. S completm codul HTML pentru aceast pagin ca mai jos: <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Adaugare.aspx.cs" Inherits="web1.Adaugare" %> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <link rel="stylesheet" href="Stil.css" /> <title>Adaugare</title> </head> <body> <form id="form1" runat="server"> <div class="normalHeading"> Adaugare curs </div> <br /> <div class="normal"> <table cellspacing="0" cellpadding="3"> <tr> <td class="normal"> Titlu: </td> <td> </td> </tr> <tr> <td class="normal"> Detalii: </td> <td> </td> </tr> <tr> <td colspan="2" align="right"> </td> </tr> </table> </div> </form> </body> </html>

Ar trebui s obinei n Designer imaginea din fig. 2.13. Acum, s tragem dou controale TextBox n coloanele 2 din tabel (casetele mici din dreapta textelor Titlu i Detalii). S modificm proprietatea ID al controlului TextBox de sus n textTitlu si a controlului de jos n textDetalii. De asemnea, pentru controlul de jos, s modificm proprietatea

Figura 2.13

46

TextMode n MultiLine.

S adugm acum n ultima line (cea fr coloane) un control Button, pentru care s modificm proprietatea ID n OK i proprietatea Text n Salvare. Ar mai fi de fxut. Deoarece n general introducerea de texte implic i Figura 2.14 valiri, s validm cele 2 controale de tip TextBox ca s nu permit salvarea schimbrilor dect atunci cnd n ambele controale este introdus text. Pentru aceasta, n seciunea Validation al Toolbox, gsii un control RequiredFieldValidator i tragei 2 astfel de controale n dreapta fiecrui control TextBox. Pentru abmele controale, completai proprietatea ErrorMessage cu Completati campul!, iar proprietatea ControlToValidate cu textTitlu respectiv textDetalii (fig. 2.14). Va trebui acum s furnizm numele fiierului n care vor fi salvate informaiile din clasa InfCurs. Pentru aceasta, s intrm n codul acestei clase i s completm urmtoarele informaii:
public class InfCurs { private String _fisier; private DateTime _data; public String DataInSir { get { return Data.ToString("dddd") + ", " + Data.ToLongDateString(); } } public String Fisier { get { return _fisier; } set { _fisier = value; } }

Am adugat o proprietate intern care va stoca numele fiierului i modul de acces la aceast proprietate. Acum urmeaz s adugm clasei metoda care realizeaz serializarea informaiei n fiierul cu numele specificat de proprietatea Fisier:
public void Salvare() {

47

if (Fisier == null) Data = DateTime.Now; DirectoryInfo subdirector = new DirectoryInfo(Global.CaleDirCurs); FileInfo[] fisiere = subdirector.GetFiles(); Fisier = String.Format("{0:d2}{1:d2}{2:d4}_{3:d3}.xml", (int)Data.Day, (int)Data.Month, (int)Data.Year, fisiere.Length); String cale = Global.CaleDirCurs + "\\" + Fisier; FileInfo fi = new FileInfo(cale); if (fi.Exists == true) fi.Delete(); FileStream fs = new FileStream(fi.FullName, FileMode.Create); XmlSerializer ser = new XmlSerializer(this.GetType()); ser.Serialize(fs, this); fs.Close(); }

Primul lucru pe care trebuie s-l facem este s atribuim un nume fiierului. Acest nume trebuie s fie unic, dac numele exist deja, vom terge fiierul cu numele respectiv i vom crea unul nou. Numele fiierului este de forma zzllaaaa_nr.xml, unde primele 8 caractere reprezint data curent (preluat cu DateTimeNow) iar ultimele 3 al ctelea fiier din ziua respectiv este cel tocmai creat. Crem apoi obiectul DirectoryInfo pentru calea pe care se afl fiierele i aflm numele tuturor fiierelor existente deja n acel subdirector. Compunem numele complet al fiierului prin adugarea cii. Dac deja exist un fiier cu acest nume l tergem i deschidem un nou fiier n mod Create. Declarm un serializator XML cre serializeaz obiecte de tipul InfCurs (XmlSerializer ser = new XmlSerializer(this.GetType());) i serialzm obiectul curent n fiier. Cu aceasta, o nou intrare de tip XML este creat. Acum, ca de obicei, va trebui sa modificm funcia Page_Load() n aa fel nct s fie luate n considerare modificrile din clasa InfCurs. Nu vom modifica metoda Page_Load() din pagina Default.aspx, ci metoda din pagina Adaugare.aspx, pentru c aceasta se ocupa de crearea fiierelor i serializarea informaiei:
protected void Page_Load(object sender, EventArgs e) { if (IsPostBack == true) { InfCurs curs = new InfCurs(); curs.Titlu = textTitlu.Text; curs.Detalii = textDetalii.Text; curs.Salvare(); Response.Redirect("Default.aspx"); } }

Ce face metoda? Pentru nceput, testeaz metoda IsPostBack pentru pagina Adaugare.aspx. Aceast proprietate este true dac pagina a fost ncrcat ca urmare a cererii utilizatorului (apsarea butonului Salvare, n cazul nostru) i false dac a fost ncrcat pentru prima dat.. Dac da, se creaz un nou obiect InfCurs, ale crui cmpuri sunt completate din casetele de tip TextBox. Apoi este apelat metoda Salvare() pentru 48

crearea fiierului i serializarea obiectului i se navigeaz napoi n pagina Default.aspx, prin apelarea Response.Redirect(). Tot ce mai avem de fcut este s crem un link n pagina Default.aspx ctre pagina Adaugare.aspx.
</asp:DataList> <br /> <div class="Normal"> <a href="Adaugare.aspx"> Adaugare curs</a> </div> <br /> <br /> <hr color=#000000 /> <div class="normal"> <asp:Label ID="Curs" runat="server" Text="Curs"></asp:Label>&nbsp;</div> <br> <div class="normal">

Compilai i executai programul. Observai c putei crea fiiere n format XML fr sa mai fie nevoie s le completm manual. De fapt, care este mecanismul? Cnd apsm butonul Salvare, se petrec 2 lucruri. nti, codul de validare valideaz informaia din controalele din pagin, adic testeaz dac exist informaie n fiecare din controalele TextBox. Dac validrile sunt realizate, pagina este ncrcat. O dat cu ncrcarea paginii, este lansat n execuie metoda Load_Page(), care creaz un nou obiect InfCurs, deschide un fiier cu numele prezentat anterior i serializeaz ubiectul n acel fiier. Dup care, se revine la pagina principal. 2.6 Editarea fiierelor .xml Ar fi normal, ca un fisier XML odat creat, s poat fi editat. n cele ce urmeaz vom implementa mecanismul de editare al acestor fiiere. Pentru aceasta: intrm n Designer n pagina Default.aspx. selectm controlul DataList, s facem click dreapta pe el i n meniul contextual s alegem Edit Templates i Item Template. adugm un control Hyperlink n dreapta etichetei Label1. pentru acest control, modificm proprietatea cssClass n curs i proprietatea Text n Editare. apsm click pe sgeata din partea dreapt sus al contrulului si selectm din tabel Edit DataBindings. slectm proprietatea NavigateURL i n caseta Code expression: inserm textul:
"adaugare.aspx?Fisier="+DataBinder.Eval(Container,"DataItem.Fisier")

n Global.asax, n metoda IncarcaCurs(), inserm linia:

49

public static InfCurs IncarcaCurs(String numfis) { cursNou.Fisier = numfis; return cursNou; }

Acum s compilm i s executm programul. Observm c obinem rezultatul din fig. 2.15.

Figura 2.15

Ce se observ? n dreapta fiecrei intrri, a aprut un link, cu textul Editare. Acest text este cel introdus n proprietatea Text al controlului Hyperlink i apare cu stilul precizat n prorietatea cssClass. S apsm acum pe link-ul asociat unui fiier. De exemplu, dac apsm pe editarea primului fiier, vom obine rezultatul din fig. 2.16.

Figura 2.16

50

Observm c am intrat din nou n pagina Adaugare.aspx. Nu acesta este lucrul interesant. S privim mai atent la ce scrie n zona de adres a browserului (fig. 2.17):

Figura 2.16

Dac ne uitm cu atenie, observm c n textul scris n seciunea NavigateURL a controlului Hyperlink, componenta DataBinder.Eval(Container,"DataItem.Fisier") a extras numele fiierului coninut de proprietatea Fisier al obiectului InfCurs curent i l-a adgat textului adaugare.aspx?Fisier=, pentru a completa calea complet spre fiierul selectat. Astfel, fiierul a fost deschis i s-a afiat pagina de adugare. Este avident c pentru editarea coninutului fiierulu, casetele din pagina de adugare nu trebuie s fie goale, ca i n cazul adugrii unui nou fiier, ci trebuie s conin informaia deserializat din fiier. Pentru aceasta va trebui s modificm metoda Page_Load() a paginii Adaugare.aspx:
protected void Page_Load(object sender, EventArgs e) { if (IsPostBack == true) { InfCurs curs = new InfCurs(); if (Request.Params["Fisier"] != null) curs.Fisier = Request.Params["Fisier"]; curs.Titlu = textTitlu.Text; curs.Detalii = textDetalii.Text; curs.Salvare(); Response.Redirect("Default.aspx"); } else { String numfis=Request.Params["Fisier"]; if (numfis!=null) { InfCurs curs=Global.IncarcaCurs(numfis); textTitlu.Text=curs.Titlu; textDetalii.Text=curs.Detalii; } } }

S vedem nti ce se ntmpl pe ramura else. n acest caz, tim c IsPostBack este false, deci pagina a fost ncrcat pentru prima dat. Proprietatea Request.Params poate fi utilizat pentru a accesa parametrii scriptai n pagin, adic acei parametri care au fost trecui paginii pentru a fi afiai n procesul de scriptare. Ceea ce ne intereseaz pe noi n acest moment, este numele fisierului selectat, adic coninutul proprietii Fisier al obiectlui InfCurs curent. Este proprietatea pe care o vom transmite spre Request.Params. n mod evident, odat obinut numele fiierului, vom apela metoda IncarcCurs() pentru deserializarea coninutului acestuia i vom afia informaiile deserializate n casetele de tip TextBox.

51

Dar de ce am modificat i ramura corespunztoare IsPostBack==true? Pentru c va trebui s aflm dac avem vreun fisier deja selectat (Request.Params !=null). n acest caz, vom folosi din nou numele acestuia pentru a specifica fisierul n care se face salvarea n caz contrar (nu am ajuns n pagin prin Editare), metoda Salvare() va reconstitui numele fiierului din data curent. Dar pentru aceasta, trebuie s rescriem aceast metoda ca mai jos:
public void Salvare() { if (Fisier == null) { Data = DateTime.Now; DirectoryInfo subdirector = new DirectoryInfo(Global.CaleDirCurs); FileInfo[] fisiere = subdirector.GetFiles(); Fisier = String.Format("{0:d2}{1:d2}{2:d4}_{3:d3}.xml", (int)Data.Day,(int)Data.Month, (int)Data.Year, fisiere.Length); } String cale = Global.CaleDirCurs + "\\" + Fisier; FileInfo fi = new FileInfo(cale); if (fi.Exists == true) fi.Delete(); FileStream fs = new FileStream(fi.FullName, FileMode.Create); XmlSerializer ser = new XmlSerializer(this.GetType()); ser.Serialize(fs, this); fs.Close(); }

Ce am fcut? Am ters liniile cu bold din locul lor i le-am inserat n if. Aceasta pentru c este nevoie de completarea numelui fiierului doar dac nu este preluat deja prin mecanismul descris anterior. Compilai i executai programul. 2.7 Restricionarea accesului la pagina de web Pn n acest moment, orice utilizator poate accesa pagina de web, putnd att s vizualizeze informaia. Ct i s adauge noi fiiere i respectiv s le editeze. n mod normal, seciunea de adugare i respectiv editare trebuie s fie protejate. S implementm acum o metod prin care utilizatorul se poate autentifica nainte de a-i fi permise anumite operaii, respectiv adugarea i editarea. Acest mecanism se bazeaz pe noiumea de Sesiune. O sesiune permite serverului de web s asocieze un set de date cu un anumit tip de browser. Prin aceasta, browserul ramne, hai s spunem agat n prima pagin pe care o afieaz. Informaia utilizat pentru aceasta este unic i este utilizat ca i cheie de validare pentru accesul la urmtoarele pagini.

52

Serverul de web aga browserul prin utilizarea unui cookie. Un cookie este o secven de cod de dimensiune mic, trimis de server clientului la accesarea unei pagini de web i care este citit de fiecare dat cnd pagina de web este renrcat. LA primul apel al paginii de web, cookie-ul nu exist, astfel nct serverul de web va crea o nou sesiune i va plasa ID-ul acelei sesiuni ntr-un cookie, pe care-l va trimite apoi browserului. n principiu, se pote stoca diferite informaii ntr-un cookie, dar deoarece cu ct mai multa informaie este stocat, cu att mai mult memorie este necesar la server, uzual cookie+ul conine un numr minim de informaii. Bazat pe acest mecanism, s ncercm s restricionm accesul n adugare i editare. Informaia stocat n cookie este suficient s fie o simpl valoare boolean. Care s precizeze co utilizatorul are sau nu acces la aceste pagini. Orice sesiune este lansat la apelul primei pagini dintr-o cerere i ncepe prin lansarea n execuie a unei funcii numite Session_Start(), localizat n Global.asax. S adugm aceast funcie:
protected void Session_Start(Object sender, EventArgs e) { Session["permis"] = false; }

Proprietatea Session permite adugarea de variabile, numite variabile de sesiune. n funcie, noi am adugat o variabil numit permis, creia i-am atribuit valoarea false. Deci, la ncrcarea paginii Default.aspx, aceast variabil va fi fcut implicit false. S adugm acum proiectului o nou pagin de web, pe care o vom numi
Interzis.aspx. S completm codul acesteia cu urmtoarele linii: @ Page Language="C#" AutoEventWireup="true" CodeBehind="Interzis.aspx.cs" Inherits="web1.Interzis" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Untitled Page</title> </head> <body> <form id="form1" runat="server"> <div> Ne pare rau. Nu aveti dreptul sa accesati aceasta pagina <br /> <a href="Default.aspx">Continuare</a> </div> </form> </body> </html>

53

Acesat pagin va trebui s fie afiat dac se acceseaz pagina Adaugare.aspx (deci n adugare sau editare) fr ca utilizatorul s fie autentificat, n cazul nostru dac permis==false. Va trebui deci s testm valoarea permis n metoda Page_Load() din Adaugare.aspx:
protected void Page_Load(object sender, EventArgs e) { if ((bool)Session["permis"] == false) Response.Redirect("Interzis.aspx"); if (IsPostBack == true)

Este simplu de neles. Dac variabila permis are valoarea false, se afieaz pagina Interzis.aspx. Acum, tot ce mai avem de fcut este s realizm autentificarea utilizatorului. Pentru aceasta, s adugm o nou pagin web, numit Login.aspx. n Figura 2.17 Designer, s adugm pe aceast pagin un control TextBox i un control Button (fig. 2.17). Pentru controlul TextBox s scimbm proprietatea ID n textParola i TextMode n Password, iar pentru controlul Button proprietatea ID n btnLogin i Text n Login. S apsm acum dublu-click n Designer pentru a intra n zona de cod i s completm metoda Page_Load() ca mai jos:
protected void Page_Load(object sender, EventArgs e) { if (IsPostBack == true) { if (textParola.Text.CompareTo("nabucodonosor") == 0) Session["permis"] = true; Response.Redirect("Default.aspx"); } }

Ce face metoda? Compar textul din controlul textParola cu nabucodonosor. Dac coincide, seteaz valoarea variabilei permis la true. Aceasta va avea ca evect permiterea adugrii i editrii de fiiere. Apoi, se revine n pagina Default.aspx. Tot ce mai avem de fcut, este s crem m pagina principal un link spre aceast pagin. Deci, n Default.aspx adugm codul:
<br /> <div class="Normal"> <a href="Adaugare.aspx"> Adaugare curs</a> </div>

54

<div class="Normal"> <a href="Login.aspx"> Login</a> </div> <br />

Cu aceasta aplicaia este finalizat. Compilai i executai programul.

55