I dette kapitel vil flere videregående teknikker indenfor ASP-programmering blive beskrevet. Det drejer sig blandt andet om at udvide ASP-serveren med egne komponenter eller komponenter fra tredjepart. I kapitlet vil det også blive beskrevet, hvordan man læser og skriver filer fra ASP-programmer. Kapitlet omhandler også transaktioner, som er en udvidelse af det almindelige sessionsbegreb. Endelig gennemgås også, hvordan man kan lave indstillinger, der gælder for alle ens ASP-sider ved hjælp af filen global.asa.
Du læser en gammel bog
Den bog, du læser her, er fra 1999, og mange ting kan have ændret sig siden da.
Vi håber, at du stadig kan finde relevant information i den.
Hvis du vil læse aktuelle oplysninger om den aktuelle version af ASP.NET, anbefaler vi
bogen Programming ASP.NET 4.0
Filer
Filhåndtering blev kort introduceret i kapitel 3. Introduktionen i kapitel 3 var imidlertid blot en teoretisk forklaring af de forskellige fil-begreber, der findes inden for ASP. I dette afsnit bliver teorien suppleret med praksis, og det bliver gennemgået, hvordan man anvender filer fra ASP. Det vil sige, hvordan man læser og skriver filer fra ASP-programmer. Filadgang er en væsentlig del af det at udvikle applikationer – har man ikke mulighed for at gemme oplysninger, er det umuligt at lave omfattende og anvendelige programmer. Selv om ASP også giver adgang til at gemme oplysninger i databaser, er det ofte lettere – og hurtigere – at gemme oplysninger i en fil i stedet for at oprette en database.
Selv om begrebet fil altid angiver en fil, der er lagret på medie, findes der i ASP-terminologi flere forskellige former for filer. Det er dog ikke selve filerne, der er forskellige, men blot den måde, man angiver deres navn på.
De forskellige former for filer er gennemgået i kapitel 3, og i dette afsnit vil de blot kort blive resumeret. Et fysisk filnavn er angivelse af en fil med det filnavn, den har på computeren, og som man kan finde den med i f.eks. Windows Stifinder. Et virtuelt filnavn er angivelse af en fil med det navn, den har på web-serveren. Det er det navn, man bruger, til at finde filen fra sin web-browser.
Uafhængigt af om man bruger et fysisk eller et virtuelt filnavn, kan man vælge at angive en fil med dens relative eller absolutte filnavn. Med et relativt filnavn angiver man navnet på filen i forhold til placeringen af det dokument, man refererer filen fra. Angiver man således det relative filnavn minfil.asp fra filen /dokumenter/enandenfil.asp, vil det angive filen /dokumenter/enandenfil.asp. Vælger man derimod at angive filnavnet absolut som /filer/enandenfil.asp, vil det altid være filen i biblioteket /filer, der bliver refereret – ligegyldigt hvilket bibliotek den aktuelle fil befinder sig i.
Filsystemet
For at kunne læse og skrive filer på web-serveren er det en god ide at kunne få oplysninger om det filsystem, der indeholder filerne. Til at give oplysninger om filsystemet findes komponenten FileSystemObject. Man får et objekt af den ved at skrive
Server.CreateObject(“Scripting.FileSystemObject”);
FileSystem-objektet har kun et element. Det hedder Drives og indeholder oplysninger om de drev, der er tilsluttet ASP-serveren. Bemærk, at man kun kan få oplysninger om filsystemet på serveren – ASP giver ikke mulighed for at få oplysninger om filsystemet på de besøgendes computere.
Drives-elementet i FileSystem-objektet indeholder en række Drive-objekter, som indeholder oplysninger om det pågældende drev. Oplysningerne ses af nedenstående tabel.
| Navn | Beskrivelse |
| AvailableSpace | Angiver hvor meget ledig plads, der er på drevet (i bytes). |
| DriveLetter | Angiver det bogstav, drevet har i filsystemet. |
| DriveType | Angiver typen af drevet. Mulige værdier er
0: Ukendt 1: Flytbar 2: Lokal (fixed) 3: Netværksdrev 4: CD-ROM 5: RAM-drev |
| FileSystem | Angiver filsystemet (for eksempel FAT, FAT32, NTFS eller CDFS). |
| FreeSpace | Angiver hvor meget ledig plads der er på drevet. |
| IsReady | Angiver om drevet er klar til at blive læst. |
| Path | Angiver stien til drevet. |
| RootFolder | Returnerer et Folder-objekt, der repræsenterer rodfolderen på drevet. |
| SerialNumber | Angiver serienummeret på drevet. |
| ShareName | Angiver drevets netværksnavn. |
| TotalSize | Angiver størrelsen på drevet (i bytes). |
| VolumeName | Angiver drevets navn. |
Tabel 4.1:.Oplysninger i Drive-objektet.
RootFolder-objektet giver adgang til en ny type objekt: Folder-objektet. Ligesom Drive-objektet, indeholder Folder-objektet en række oplysninger. De ses af nedenstående tabel.
| Navn | Beskrivelse |
| Attributes | Angiver folderens egenskaber. Disse kan være en kombination af
0: Normal 1: Skrivebeskyttet 2: Skjult 4: System 8: Drev 16: Bibliotek 32: Arkiv 64: Alias 128: Komprimeret |
| DateCreated | Angiver det tidspunkt, folderen blev oprettet. |
| DateLastAccessed | Angiver hvornår folderen sidst blev åbnet. |
| DateLastModified | Angiver hvornår folderen sidst blev ændret. |
| Drive | Angiver det drev, folderen ligger på. |
| Files | En liste over de filer, der findes i folderen. |
| Folders | En liste over de foldere, der findes i folderen, med mulighed for at tilføje foldere. |
| IsRootFolder | Angiver om folderen er roden af drevet. |
| Name | Angiver folderens navn. |
| ParentFolder | Returnerer et Folder-objekt, der repræsenterer den folder, denne folder er i. |
| Path | Angiver stien til folderen. |
| ShortName | Angiver folderens korte navn (8.3-navn). |
| ShortPath | Angiver stien til folderen med korte navne. |
| Size | Angiver størrelsen på folderen og alle foldere i folderen. |
| SubFolders | En liste over de foldere, der findes i folderen. |
Tabel 4.2: Oplysninger i Folder-objektet.
Folder-objektet gør det også muligt at kopiere, slette og flytte folderen – det sket med metoderne Copy, Delete og Move.
Som nævnt kan man få en oversigt over de filer, en mappe indeholder, med Files. Denne liste indeholder en række File-objekter. Ligesom Drive og Folder indeholder File en række oplysninger.
| Navn | Beskrivelse |
| Attributes | Angiver filens egenskaber efter samme system som ved Folder-objektet. |
| DateCreated | Angiver det tidspunkt filen blev oprettet. |
| DateLastAccessed | Angiver hvornår filen sidst blev tilgået. |
| DateLastModified | Angiver hvornår filen sidst blev ændret. |
| Drive | Angiver drevbogstavet på det drev, filen ligger på. |
| Name | Angiver navnet på filen. |
| ParentFolder | Returnerer et Folder-objekt, som angiver den folder, der indeholder filen. |
| Path | Angiver filens sti. |
| ShortName | Angiver filens korte navn. |
| ShortPath | Angiver filens sti med korte navne. |
| Size | Angiver filens størrelse. |
| Type | Angiver filens type. |
Tabel 4.3: Oplysninger i File-objektet.
Med de tre objekter er det muligt at lave en total oversigt over filsystemet på serveren. Normalt vil man naturligvis ikke give besøgende fra hele verden oplysninger om filsystemet, men det kan være særdeles anvendeligt, hvis man selv har behov for at fjernstyre serveren. Nedenstående eksempel viser, hvordan man kan lave en sådan oversigt.
<% @Language=JavaScript %>
<body>
<ul>
<%
drivetype = new Array();
drivetype[0] = “Ukendt”;
drivetype[1] = “Flytbar”;
drivetype[2] = “Lokal”;
drivetype[3] = “Netværksdrev”;
drivetype[4] = “CD-ROM”;
drivetype[5] = “RAM-drev”;
stack = new Array();
filsystem = Server.CreateObject(“Scripting.FileSystemObject”);
drev = new Enumerator(filsystem.Drives);
while (!drev.atEnd()) {
Response.write(“<li>” + drev.item().DriveLetter);
Response.write(” – ” + drev.item().VolumeName);
Response.write(” [” + drivetype[drev.item().DriveType] + “]”);
Response.write(” (” + Math.round((drev.item().FreeSpace * 100 / drev.item().TotalSize)) + “% ledig)”);
if (!drev.item().IsReady) {
Response.write(” ikke klar”);
} else {
printFolders(drev.item().RootFolder, 0);
}
drev.moveNext();
}
function printFolders(folder, sp) {
Response.write(“<ul>”);
Response.write(“<li>”);
if (folder.Name != “”) {
Response.write(folder.Name);
} else {
Response.write(“\\”);
}
subfolders = new Enumerator(folder.SubFolders);
while (!subfolders.atEnd()) {
stack[sp] = subfolders;
printFolders(subfolders.item(), sp+1);
subfolders=stack[sp];
subfolders.moveNext();
}
files = new Enumerator(folder.Files);
while (!files.atEnd()) {
Response.write(“<li>” + files.item().Name);
files.moveNext();
}
Response.write(“</ul>”);
}
%>
</ul>
</body>
At læse en fil
Filsystem-objektet gør det muligt at åbne en fil for læsning. Det gøres ved hjælp af metoden OpenTextFile. Når man skal læse en fil, er det nok at angive navnet på filen som parameter. Det vil sige, at en fil kan åbnes med nedenstående linier:
filsystem = Server.CreateObject(“Scripting.FileSystemObject”);
in = filsystem.OpenTextFile(“c:\\autoexec.bat”);
OpenTextFile-metoden returnerer en TextStream. TextStream-objekter indeholder følgende metoder:
| Metode | Beskrivelse |
| Close() | Lukker den åbne fil efter endt læsning. |
| Read(antal tegn) | Læser et antal tegn fra filen. |
| ReadAll() | Læser hele filen. |
| ReadLine() | Indlæser en linie fra filen. |
| Skip(antal tegn) | Springer over et bestemt antal tegn ved læsning fra filen. |
| SkipLine() | Springer over en linie ved læsning fra filen. |
Tabel 4.4: Metoder i TextStream-objektet..
TextStream-objektet indeholder også nogle metoder, der kan bruges til at skrive til en fil – disse bliver gennemgået senere.
Når man læser fra filen, er det rart at kunne se, hvornår hele filen er indlæst. Til det kan man bruge variablen AtEndOfStream. Når den er true, er hele filen indlæst. TextStream-objektet indeholder også værdierne AtEndOfLine, Column og Line, der henholdsvis angiver, om indlæsningen er ved slutningen af en linie, positionen på linien og liniens nummer.
Nedenstående eksempel viser, hvordan man kan læse indholdet af en fil på serveren og returnere det i et HTML-dokument til brugeren.
<% @language=JavaScript %>
<body>
<b>Indholdet af filen er:</b>
<p>
<%
filsystem = Server.CreateObject(“Scripting.FileSystemObject”);
stream = filsystem.OpenTextFile(“f:\\tf\\asp\\eksempler\\kapitel4\\data\\liste.txt”);
while (!stream.AtEndOfStream) {
tekst = stream.readLine();
Response.write(tekst + “<br>”);
}
stream.close();
%>
</body>
Da det er en tekstfil, der bliver indlæst, er det nødvendigt at tilføje HTML-kommandoen <br> efter hver linie – ellers ville alle linierne i tekstfilen blive vist på én linie i HTML -dokumentet.
Afvikling af ovenstående eksempel vil give en HTML -side svarende til nedenstående billede:
Figur 4.1: Visning af indholdet af en fil.
At skrive en fil
Metoden OpenTextFile kan også bruges til at åbne en fil for skrivning. Her skal man blot bruge flere parametre. Den komplette syntaks for OpenTextFile er:
OpenTextFile(filnavn, tilstand, opret, format);
Filnavn er navnet på den fil, der skal åbnes. Tilstand angiver den tilstand, filen skal åbnes i. 1 angiver læsning, 2 angiver skrivning, mens 8 angiver tilføjelse. Opret er enten sand (true) eller falsk (false) afhængig af, om filen skal oprettes, hvis den ikke allerede eksisterer. Hvis denne parameter ikke er true, bliver der ikke oprettet en ny fil, hvis der ikke allerede eksisterer en fil med samme navn. Format angiver filens format. Her kan man vælge mellem 0, der angiver ASCII-format, -1 der angiver unicode-format og -2 der angiver styresystemets normale format.
Bemærk, at man ikke behøver angive alle parametrene.
Når man har åbnet filen for skrivning, har man adgang til yderligere metoder i TextStream-objektet. Disse metoder ses i nedenstående tabel.
| Metode | Beskrivelse |
| Close() | Lukker filen efter endt skrivning. |
| Write(streng) | Skriver strengen. |
| WriteLine(streng) | Skriver strengen og tilføjer et linieskift. Hvis man blot vil skrive et linieskift til filen, behøver man ikke angive en streng. |
| WriteBlankLines(antal) | Skriver et antal tomme linier til filen. |
Tabel 4.5: Skrive-relaterede metoder i TextStream-objektet.
Nedenstående eksempel viser, hvordan man kan skrive en fil fra et ASP-dokument.
<% @language=JavaScript %>
<body>
<%
filsystem = Server.CreateObject(“Scripting.FileSystemObject”);
stream = filsystem.OpenTextFile(“f:\\tf\\asp\\eksempler\\kapitel4\\data\\nyfil.txt”, 2, true);
stream.writeLine(“linie 1”);
stream.writeLine(“linie 2”);
stream.writeLine(“linie 3”);
stream.close();
%>
Filen er nu skrevet. Klik <a href = “data/nyfil.txt”>her</a> for at se den.
</body>
Når ASP-programmet er afviklet, kan man se indholdet af den nye fil i browseren – som forventet ser det således ud:
Figur 4.2: Indholdet af en fil oprettet fra ASP.
En simpel tæller
Når man har mulighed for at læse og skrive filer, kan man gemme information persistent. Det vil sige, at man kan gemme oplysninger, så de kan bruges af flere forskellige brugere, og bliver husket selv om serveren bliver genstartet.
En typisk – og simpel – anvendelse er en tæller. Selv om de fleste besøgende er forholdsvis ligeglade med, hvor mange der har været der før dem, er det rart for indehaveren af web-stedet at vide, hvor mange besøgende der er. Derfor kan man sætte en tæller på sin side. Tælleren bliver talt en op for hver gang siden bliver vist.
Ved at gemme tællerens værdi i en fil sikrer man, at tælleren ikke bliver nulstillet, når serveren bliver lukket.
Følgende eksempel viser, hvordan man kan lave en simpel tæller. Eksemplet indlæser tællerens værdi fra en fil, tæller den op og viser værdien på siden. Herefter bliver den nye værdi gemt i filen.
<body>
<% @Language = JavaScript %>
<%
filsystem = Server.CreateObject(“Scripting.FileSystemObject”);
instream = filsystem.OpenTextFile(“f:\\tf\\asp\\eksempler\\kapitel4\\data\\counter.txt”);
count = instream.ReadLine();
instream.close();
count = Math.floor(count) + 1;
out = filsystem.OpenTextFile(“f:\\tf\\asp\\eksempler\\kapitel4\\data\\counter.txt”, 2, true);
out.WriteLine(count);
out.close();
%>
Denne side er blevet besøgt <%=count%> gange.
</body>
Inkludering af filer
Udover at kunne læse og skrive filer kan man også inkludere dem i sine ASP-filer. Den eller de inkluderede filer bliver indsat på en bestemt position i ASP-filen præcis som de er – det vil sige ufortolkede.
Ved at bruge denne teknik kan man genbruge sin ASP-kode. Det vil sige, at man kan flytte de dele af ASP-koden, der bliver brugt flere steder, ud i selvstændige filer og inkludere disse, de steder de skal bruges. Det har den fordel, at man kan nøjes med at have koden ét sted – så sparer man diskplads, og man kan nøjes med at ændre ét sted, hvis der skal ændres noget i koden.
Typiske anvendelser af inkluderede filer er menuer, der skal være på alle sider, og ASP-kode, der skal være på alle sider – eksempelvis statistik-kode.
Man kan inkludere filer på to forskellige måder. Man kan enten inkludere fysiske filer eller virtuelle filer. Vil man inkludere en fysisk fil, skriver man
<!– #include file=”filnavn” —>
Filnavn angiver et fysisk navn på en fil – eksempelvis c:\web\includefil.asp.
Man kan også vælge at inkludere en fil med dens virtuelle navn – så skriver man
<!– #include virtual=”filnavn” –>
I dette tilfælde angiver filnavn et virtuelt filnavn, som for eksempel /web/includefil.asp.
Globale oplysninger
Den HTTP-protokol, som bruges til at kommunikere mellem web-serveren og brugerens browser, indeholder ingen oplysninger om tilstand. Det vil sige, at man ikke ud af protokollen kan se, om den samme bruger henter adskillige sider fra samme web-sted. Dette giver en række problemer, idet det kan være essentielt at vide, hvilken bruger der henter en bestemt side. Man kan eksempelvis forestille sig en side, der viser indholdet af brugerens indkøbskurv i en e-butik. Hvis serveren ikke ved, hvilken bruger, der sender forespørgslen, hvordan skal den så kunne vise indholdet af den rigtige indkøbskurv?
Version 1.1 af HTTP-protokollen – som blandt andet bruges i IIS 4.0 – indeholder dog nogle muligheder for at tilføje tilstandsoplysninger til forespørgslerne.
Selv om der tales om at tilføje tilstand til HTTP-protokollen og til forespørgslerne skal det holdes klart, at det er web-applikationens tilstand, der er interessant. Applikationer kan indeholder megen funktionalitet, og en applikations tilstand angiver således, hvor i denne funktionalitet applikationen befinder sig i øjeblikket. Det kan eksempelvis være et e-handelssystem, hvor applikationen befinder sig mellem tilføjelse af varer til indkøbskurven og indsendelse af den endelige ordre.
En applikation kan imidlertid være i forskellige tilstande overfor forskellige brugere på samme tid. En applikations tilstand skal derfor ikke opfattes som én fast tilkendegivelse af applikations status, men snarere som en dynamisk mængde af oplysninger om forskellige statuser applikationen i øjeblikket befinder sig i.
Ydermere skal man være opmærksom på, at en tilstand ikke lever evigt. En tilstand bør kun leve lige så længe, som brugeren er på web-stedet. Det er normalt at bruge begrebet session til at dække den periode, en bruger befinder sig på web-stedet – det vil sige, fra hun får vist den første side, til hun får vist den sidste. Applikationens tilstand afhænger af denne session, idet sessionen afgør tilstandens levetid. På den anden side er sessionen selv en del af applikationens tilstand.
Applikationens tilstand skal således opdeles i to områder. Den globale del, som vedrører hele applikationen og alle dens brugere, og den sessionsafhængige del, der kun berører en enkelt bruger. Et eksempel på sessionsafhængig tilstand kan være en brugers indkøbskurv.
ASP håndterer disse forskellige tilstande med objekterne Application og Session, der henholdsvis indeholder applikationsafhængige oplysninger og sessionsafhængige oplysninger.
Begivenheder
Objekterne Application og Session kan starte en række begivenheder. Disse begivenheder kan eksempelvis optræde, når en bruger besøger web-stedet for første gang. I filen global.asa kan man skrive metoder, der automatisk bliver udført, når disse begivenheder optræder. Det drejer sig om metoderne Application_onStart, Application_onEnd, Session_onStart og Session_onEnd.
Metoden Application_onStart udføres automatisk, når applikationen startes. Det er altid web-serveren, der sørger for opstart af en applikation. I denne metode kan man lægge initialiseringskode, som kun skal udføres en gang for hele applikationen. Det kan eksempelvis dreje sig om initialisering af variable, der er fælles på tværs af sessioner.
Application_onEnd udføres, når applikationen stoppes. Det er også web-serveren, der sørger for at stoppe en applikation – alt efter hvilken web-server, man har, kan der være mulighed for at stoppe en applikation gennem web-serverens brugergrænseflade. I Application_onEnd-metoden vil man typiske lægge kode, der rydder op efter applikationen. Har man allokeret hukommelse til sin applikation, bør man frigive den her.
Session_onStart-metoden bliver udført, når en session påbegyndes. Det vil sige, når en ny bruger tilgår web-stedet. I Session_onStart kan man initialisere de variable, der bruges på sessionsbasis. Det vil sige oplysninger, der er knyttet til hver session, og derigennem til hver bruger af web-stedet. Det kan eksempelvis dreje sig om en indkøbskurv, som typisk vil blive nulstillet i Session_onStart.
Den sidste af de fire begivenheder er Session_onEnd. Denne begivenhed opstår, når en session ophører med at eksistere. Der kan være flere grunde til, at en session skal stoppes. Det kan skyldes, at metoden Session.Abandon er blevet udført. Det kan også skyldes, at brugeren har været inaktiv så længe, at hendes session er udløbet. Dette sker sædvanligvis efter 20 minutters inaktivitet, men kan ændres ved hjælp af Session.Timeout, som vil blive gennemgået senere i dette kapitel. Afbrydelse af en session med Session.Abandon-metoden anvendes typisk, hvis brugeren direkte beder om at få sin session stoppet. Det kan være, at brugeren har bedt om at forlade web-stedet, eller at ordren er blevet indsendt, og der derfor ikke længere er grund til at opretholde den eksisterende session.
Variabler
Udover at håndtere begivenheder indeholder Session-objektet en række variabler, som man kan bruge til at tilpasse sessionen. Det drejer sig om variablerne CodePage, SessionID og Timeout.
CodePage angiver hvilken code page, de genererede HTML-dokumenter skal benytte. En code page er en tabel, som indeholder de tegn, der findes i et bestemt sprog. Ved at tildele CodePage-variablen en værdi, kan man angive, hvilken code page, browseren skal bruge, når indholdet af siden vises. Nedenstående eksempel sætter code page til 1252.
Session.CodePage = 1252;
Variablen SessionID bruges til at identificere den igangværende session. Man kan bruge SessionID til at identificere brugeren af web-stedet. Man skal dog være opmærksom på, at værdien af SessionID kun er garanteret at være unik inden for en enkelt instans af applikationen. Hvis applikationen bliver genstartet, kan det forekomme, at en session tildeles den samme værdi som en tidligere session.
Timeout-variablen angiver, hvor mange minutter brugeren må være inaktiv, før sessionen afbrydes. Standardværdien for denne variabel er 20 minutter. Hvilken værdi, der er den rigtige for et web-sted, afhænger i høj grad af pågældende web-steds type. Hvis et web-sted har megen trafik, kan det være nødvendigt at nedsætte timeout-tiden, så man undgår, at der bruges alt for mange ressourcer i sessioner.
Applikations- og sessionsvariable
Man kan også bruge Application og Session-objekterne til at opbevare oplysninger for sig. Det gør man ved hjælp af de såkaldte applikations- og sessionsvariable. En applikationsvariabel er tilgængelig i hele applikationen, mens en sessionsvariabel kun er tilgængelig indenfor en bestemt session.
Man sætter en applikationvariabel ved at skrive
Application(“variabelnavn“) = værdi;
hvor variabelnavn er navnet på applikationsvariablen, og værdi er den værdi, variablen skal tildeles. Når man skal bruge værdien af en applikationsvariabel, skriver man blot
Application(“variabelnavn“);
Således vil nedenstående eksempel udskrive værdien af applikationsvariablen navn.
Response.Write(Application(“navn”));
Sessionsvariabler håndteres på samme måde. Her skriver man blot Session i stedet for Application. Det vil sige at
Session(“variabelnavn“) = værdi;
tildeler en sessionsvariabel en værdi, mens
Response.Write(Session(“navn”));
udskriver indholdet af sessionsvariablen navn.
Nedenstående eksempel viser, hvordan man kan bruge applikations- og sessionsvariable.
<% @Language = JavaScript %>
<%
if (Request.QueryString(“abandon”) == “true”) {
Session.abandon();
Response.Redirect(“sessioncount.asp”);
}
if (Session(“antal”) == null) {
Session(“antal”) = 0;
}
if (Application(“antal”) == null) {
Application(“antal”) = 0;
}
appAntal = Application(“antal”);
appAntal = appAntal + 1;
Application (“antal”) = appAntal;
sesAntal = Session(“antal”);
sesAntal = sesAntal + 1;
Session(“antal”) = sesAntal;
%>
<body>
Du har besøgt denne side <%=sesAntal%> gang(e) i denne session.<br>
Siden er blevet vist <%=appAntal%> gang(e), mens applikationen har kørt.
<p>
Klik <a href = “sessioncount.asp?abandon=true”>her</a> for at slette din session og starte en ny.
</body>
Eksemplet viser, hvordan man kan tælle, hvor mange gange brugeren har besøgt siden i den nuværende session, ligesom man kan tælle, hvor mange gange siden er blevet vist, mens applikationen har kørt. Af hensyn til afprøvningen af eksemplet er der tilføjet en mulighed for, at brugeren selv kan vælge at afslutte sin session.
Trådsikkerhed
Man skal være opmærksom på, at der er en omkostning ved at anvende sessioner. Ikke alene tager håndteringen af sessionerne tid – sessioner medfører også, at det kun er én forespørgsel, der bliver behandlet ad gangen. Normalt vil web-serveren prøve at behandle så mange forespørgsler som muligt på samme tid, så man kan sørge for, at web-serveren altid arbejder, også når den for eksempel venter på oplysninger fra databasen – så vil den benytte lejligheden til at behandle en anden forespørgsel imens. Når der anvendes sessioner, er dette ikke muligt, da der i så fald kan opstå inkonsistens.
Man kan derfor vælge at vurdere, om der måske er dele af ens web-sted, der ikke behøver sessionshåndteringen. Hvis der er det, kan man slå sessionshåndteringen fra på de sider. Det gør man ved at skrive
<% @EnableSessionState=False %>
i starten af ASP-dokumentet.
Et andet område, man skal være opmærksom på, er de problemer, der kan opstå, når flere sessioner kører samtidigt i samme applikation. Hvis to ASP-programmer forsøger at ændre den samme variabel på samme tid, kan der opstå problemer, idet variablen kun kan holde en værdi, og derfor bliver nødt til at se bort fra den ene opdatering. Problemet eksisterer også, hvis en ASP-side forsøger at læse en variabel, mens en anden ASP-side forsøger at ændre den. Det kan betyde, at den forkerte værdi, bliver indlæst, og at de beregninger, der foretages med den pågældende værdi, derfor bliver forkerte. Hvis værdien ændres midt i en beregning, kan det desuden betyde, at resultatet af beregningen bliver inkonsistent.
Derfor kan man låse applikationsvariabler. Det gør man ved at skrive
Application.Lock();
Når man har låst applikationsvariblerne, er man sikker på, at man er den eneste, der tilgår dem. Man kan herefter foretage sine opdateringer eller læsninger, hvorefter man kan frigive applikationsvariablerne ved at skrive
Application.Unlock();
Formålet med at låse applikationsvariablerne er at sikre, at andre ikke kan tilgå dem. Dette betyder dog også, at man ikke skal holde dem låst længere tid end højst nødvendigt. Så længe man selv har låst applikationsvaraiblerne, har andre ikke mulighed for at tilgå dem, og andre ASP-sider kan således ikke behandles imens.
Cookies
Cookies er små mængder data, der kan gemmes på klientens computer. Cookies er indført i HTTP 1.1-protokollen, og browsere, der understøtter denne standard, kan således bruge cookies.
Cookies fungerer ved, at web-serveren beder browseren sætte en cookie. Denne cookie returneres, som en del af svaret til browseren. Ved alle senere kald til den samme server, vil browseren inkludere cookien. Det betyder, at man på denne måde kan identificere brugeren. Derfor bruges cookies ofte til at håndtere sessioner.
Man kan imidlertid også bruge cookies til at gemme oplysninger, som skal opbevares længere end en session. Man kan for eksempel forestille sig, at man gerne vil give brugeren mulighed for at gemme indholdet af sin indkøbskurv og afslutte bestillingen senere.
Man skal dog være opmærksom på nogle ting, hvis man vælger at bruge cookies. Nogle brugere vælger at slå cookies fra, så deres browser ikke sender cookies til serveren. Der har været skrevet meget om, at cookies udgør en sikkerhedsrisiko. Cookies kan dog ikke bruges til at trække oplysninger fra computeren – det eneste, der kan gemmes, er de oplysninger, brugeren selv indtaster. Cookies kan heller ikke bruges til at få afviklet farlige eller virusinficerede programmer på brugerens computer. Cookies bliver blot gemt – de bliver aldrig udført. Derfor kan det regnes som ufarligt at gemme cookies – det eneste problem, brugeren har, er, at de optager en smule plads på harddisken.
At sætte en cookie
I ASP befinder cookies sig både i Response- og Request-objektet. Response-objektet indeholder de cookies, man vil sætte, mens Request-objektet indeholder de cookies, der i forvejen er sat, og som sendes til web-stedet.
Vil man sætte en ny cookie, skal man således gøre det i Response-objektet. Dette objekt indeholder en samling af cookies – denne samling har navnet Response.cookies. For at sætte en cookie behøver man blot at skrive
Response.cookies(“navn“) = værdi;
Der hører imidlertid mere til en cookie end dens værdi. Man kan også angive, hvor længe cookien skal eksistere. Som det blev nævnt tidligere, er nogle cookies kun interessante i et kort stykke tid, mens andre kan være interessante længe. Derfor kan man bruge variablen expires til at angive, hvornår cookien skal udløbe – det vil sige holde op med at være gyldig. Når en cookie ikke længere er gyldig, vil den ikke blive sendt med i en request fra browseren. Angiver man ikke noget udløbstidspunkt på en cookie, vil den udløbe, når browseren lukkes.
En cookies udløbstidspunkt kan sættes således:
Response.cookies(“navn“).expires = tidspunkt;
Cookies kan være tilgængelige på forskellige måder. Nogle cookies er kun tilgængelige for den side, der sætter dem, mens andre cookies er tilgængelige for hele web-stedet. En cookies tilgængelighed kontrolleres af variablerne domain og path. Domain-variablen angiver det domæne, cookien skal være tilgængelig på. Dette vil typisk være navnet på web-stedet – eksempelvis www.tekniskforlag.dk. På denne måde vil alle sider på www.tekniskforlag.dk få cookien tilsendt. Man kan være mere specifik og også angive en sti – det gøres med path-variablen. Ved at sætte den til eksempelvis bog, vil det kun være sider i stien www.tekniskforlag.dk/bog, der vil modtage cookien. Nedenstående eksempel viser, hvordan man kan sætte cookien som beskrevet i det ovenstående.
Response.cookie(“mincookie”) = “minværdi”;
Response.cookie(“mincookie”).domain = “www.tekniskforlag.dk”;
Response.cookie(“mincookie”).path = “/bog”;
Hvis man har et sikkert web-sted, kan man også angive, at cookien kun skal sendes over en sikker forbindelse – typisk en SSL-forbindelse. Det kan man angive ved at sætte variablen secure til true. For at angive, at cookien fra ovenstående eksempel kun må sendes over en sikker forbindelse, kan man skrive
Response.cookie(“mincookie”).secure = true;
Når man bruger cookies, skal man være opmærksom på, at man skal sætte alle cookies, før man begynder at generere HTML-kode. Det skyldes, at cookies skal angives i starten af HTTP-svaret.
At læse en cookie
Der er imidlertid ikke meget ved at kunne sætte en cookie, hvis man ikke kan læse den igen. Det gøres gennem Request-objektet, der som nævnt indeholder de cookies, der sendes fra browseren. Fremgangsmåden er stort set den samme som ved Response-objektet. For at læse en cookie skriver man
Request.cookies(“cookie”);
Fremgangsmåden kan også bruges til at kontrollere, om en cookie er sat. Hvis man får værdien undefined, når man spørger om værdien af en cookie, betyder det, at cookien ikke er sat.
Integration af komponenter
Selv om scriptsprogene giver mange muligheder for at skrive avancerede ASP-programmer, og de komponenter, der er indbygget i IIS, giver yderligere muligheder, kan man komme i en situation, hvor man ikke kan klare sig med de eksisterende muligheder.
For at afhjælpe denne situation er der i IIS mulighed for at bruge andre komponenter end de indbyggede. Dette kan være komponenter, man selv har udviklet, eller komponenter fra tredjepart. De komponenter, der kan integreres i IIS, skal være COM-komponenter. Disse komponenter skrives typisk i programmeringssprog som C++ eller Delphi. Udvikling af disse komponenter er en forholdsvis kompliceret sag, og det ligger uden for rammerne af denne bog at beskrive det. Dette afsnit vil i stedet koncentrere sig om, hvor man kan finde komponenter, der allerede er udviklet, og hvordan man kan bruge disse og egenudviklede komponenter fra ASP.
Komponenter fra tredjepart
Der er mange, som har udviklet komponenter, der kan bruges i ASP. Det gælder både store, kommercielle virksomheder, hvis kerneområde er komponentudvikling, og hobbyprogrammører, der gør det for at løse deres egne problemer, og derudover gør komponenterne tilgængelige for andre. Komponenterne kan typisk – ligesom andet programmel – inddeles i tre kategorier: kommercielle komponenter, shareware-komponenter og freeware-komponenter. De kommercielle komponenter koster penge at bruge, mens shareware-komponenter er gratis at prøve, men koster penge, hvis man vil bruge dem. Freeware-komponenterne er fuldstændigt gratis. Man kan finde en lang række shareware- og freeware-komponenter på Internet. Man kan eksempelvis kigge på adressen
http://msdn.microsoft.com/workshop/server/components/catalog.asp.
Figur 4.3: På Internet kan man finde mange ActiveX-komponenter.
Man skal imidlertid tænke på, at det er en tillidssag at installere programmel fra tredjepart. Typisk har man ikke andre end programmørens ord for, hvad programmet gør. Langt de fleste komponentprogrammører er naturligvis hæderlige mennesker, men man kan sagtens forestille sig, at en ondsindet programmør vil forklæde en virus som en ASP-komponent. Derudover skal man også tænke på, at ASP-programmører også er mennesker, og at det er menneskeligt at fejle. Det kræver ikke en særlig stor fejl i en ASP-komponent at lægge web-serveren ned, hvorefter hele web-stedet ikke længere er tilgængeligt. Hvis man driver et stort web-sted, som skal være tilgængeligt døgnet rundt, året rundt, er det derfor vigtigt at vælge en komponent, der er udviklet af en programmør eller en virksomhed, som man har tillid til. Kan man ikke få tilstrækkelig tillid til udvikleren af komponenten, er man nødt til at lade komponenten gennemgå en grundig test for at sikre, at komponenten er stabil og ikke har uønskede bivirkninger.
Netop risiciene ved at installere komponenter fra ukendte kilder har gjort, at mange web-hoteller ikke vil lade deres klienter installere komponenter. Til gengæld har mange web-hoteller installeret en del komponenter, som ikke normalt er en del af IIS.
Installation
For at IIS kan finde de komponenter, der skal bruges, skal de være installeret korrekt. Det vil sige, at der skal findes en registrering af dem i Windows’ registreringsdatabase. Anvender man en komponent fra tredjepart, vil registreringen ske som en naturlig del af installationen af den pågældende komponent.
Hvis man selv udvikler komponenter, vil der typisk være en funktion i udviklingsværktøjet, der foretager registreringen.
Implementering i ASP
De komponenter, man selv har installeret, tilgås på præcis samme måde, som de komponenter, der er præinstalleret. Det vil sige, at man kan lave en instans af komponenten ved at skrive
obj = Server.CreateObject(navn);
Navn skal være det navn, man har valgt at registrere komponenten under. Herefter kan man kalde de metoder, som komponenten indeholder på objektet obj. Hvis komponenten eksempelvis indeholder en metode, der hedder evaluate, kan man kalde den ved blot at skrive
obj.evaluate();
Et eksempel
I dette eksempel vil det blive gennemgået, hvordan man kan bruge komponenten JMail fra Dimac. Denne komponent gør det muligt at afsende meddelelser fra ASP. I IIS er der indbygget en tilsvarende komponent, men JMail har væsentligt flere muligheder, hvilket gør den interessant.
JMail kan hentes på HTTP://tech.dimac.net.
Når man har hentet Jmail, kan man installere komponenten ved at afvikle installationsprogrammet. Dette installerer den dll-fil, der indeholder komponenten, og opretter en registrering af komponenten i registreringsdatabasen i Windows. Herefter er man klar til at bruge komponenten fra ASP.
I dette eksempel vil en HTML-side blive anvendt. På denne side kan brugeren udfylde en formular, der svarer til en e-mail. Brugeren har mulighed for at indtaste e-mail-adresse på modtageren, egen e-mail-adresse, overskrift, beskeden, samt at vælge om hun vil modtage en kvittering, når beskeden bliver modtaget.
HTML-koden, der generer siden, ser således ud:
<html>
<body>
<h1>Afsend post</h1>
<form name = mail action=sendmail.asp method=post>
<table>
<tr>
<td>Modtager</td>
<td><input type=text name=modtager></td>
</tr>
<tr>
<td>Afsender</td>
<td><input type=text name=afsender></td>
</tr>
<tr>
<td>Overskrift</td>
<td><input type=text name=overskrift></td>
</tr>
<tr>
<td valign=top>Besked</td>
<td><textarea name=besked cols=40 rows=10></textarea>
</tr>
<tr>
<td>Kvittering?</td>
<td><input type=checkbox value=kvittering>Ja</td>
</tr>
<tr>
<td colspan=2 align=center><input type=submit value=Afsend></td>
</tr>
</table>
</body>
</html>
I Internet Explorer får man siden vist som nedenstående figur.
Figur 4.4: Formular til afsendelse af post.
På Dimacs hjemmeside kan man se dokumentationen af komponenten. Denne dokumentation indeholder blandt andet beskrivelse af den lange række metoder og variabler, JMail indeholder. Det betyder, at man let kan skrive et ASP-dokument, som kalder komponentens metoder. Nedenstående ASP-program modtager dataene fra formularen og afsender en besked ved hjælp af JMail. Som det fremgår af eksemplet, er det uhyre let at benytte tredjepartskomponenter med ASP.
<% @language=javascript %>
<%
mailer = Server.CreateObject(“JMail.SMTPMail”);
mailer.ServerAddress = “post.tele.dk”;
mailer.Sender = Request.Form(“afsender”);
mailer.Subject = Request.Form(“overskrift”);
mailer.Body = Request.Form(“besked”);
if (Request.Form(“kvittering”) != null) {
mailer.ReturnReceipt = true;
} else {
mailer.ReturnReceipt = false;
}
mailer.addRecipient(Request.Form(“modtager”));
if (mailer.execute()) {
Response.write(“Beskeden er afsendt.”);
} else {
Response.write(“Der opstod en fejl. “);
Response.write(mailer.ErrorMessage);
}
%>
Transaktioner
Dette afsnit omhandler transaktioner. Transaktioner er en særdeles central del af at bygge en omfattende web-applikation, der kan samarbejde med eksisterende systemer. Man kan eksempelvis forestille sig en Internet-bank, hvor selve web-stedet arbejder sammen med bankens eksisterende systemer.
Før teorien bag transaktioner bliver gennemgået er det imidlertid en god idé at starte med at definere, hvad en transaktion egentligt er. En transaktion er en mængde opgaver, som enten bliver fuldført eller ikke fuldført – det er ikke muligt at udføre en transaktion delvis. Man kan således sige, at en transaktion er atomar, da den ikke kan deles. En transaktion kan dog bestå af mange delopgaver, men det gælder, at alle delopgaver skal være fuldført, for at transaktionen er fuldført. Er alle delopgaver ikke fuldført, er transaktionen ikke fuldført, og det skal betyde, at ingen delopgaver er udført. Det skal således være muligt at fortryde udførelsen af en eller flere delopgaver, hvis det viser sig, at en efterfølgende delopgave ikke kan udføres. Denne teknik kaldes rollback. Nødvendigheden af rollback kan for eksempel ses i et banksystem. Hvis en transaktion er “overfør 100 kroner fra konto 1 til konto 2”, kan den deles op i delopgaverne “hæv 100 kroner fra konto 1” og “sæt 100 kroner ind på konto 2”. Hvis den første delopgave går godt (100 kroner hæves fra konto 1), men delopgave 2 fejler (pengene kan ikke indsættes på konto 2), bliver indehaveren af konto 1 nok ret utilfreds, hvis han opdager, at pengene er hævet fra hans konto, men ikke indsat på modtagerens. Derfor skal det være muligt at sætte systemet tilbage i den tilstand, det havde, før transaktionen startede, hvis en delopgave fejler.
Applikationer, der arbejder sammen med transaktionssystemer, består oftest af komponenter. I den forbindelse findes der to forskellige slags komponenter: applikationskomponenter og datakomponenter.
Applikationskomponenter indeholder forretningslogik. Det vil sige, at det er applikationskomponenterne, der ved, hvordan tingene skal gøre. For at blive ved bankeksemplet kan et eksempel på en applikationskomponent være en renteberegningskomponent, der tilskriver renter. Komponenten ved, hvordan sammenhængen mellem indskud og rente er, ligesom den ved, at rentesatserne kan afhænge af, om kunden er aktionær i banken.
Datakomponenter giver adgang til de virkelige data. Det kan for eksempel være kunder og konti. En kundekomponent kunne således være ansvarlig for at indlæse kundens oplysninger fra en database og præsentere dem på en fornuftig måde for resten af systemet.
For at håndtere transaktioner har man et transaktionshåndteringssystem. Microsoft Transaction Server (MTS) er et eksempel på et sådant system – MTS vil blive beskrevet yderligere senere. Transaktionshåndteringssystemet sikrer, at transaktionerne har nogle bestemte egenskaber. Disse egenskab kaldes ACID-egenskaberne, der er et akronym af de engelske ord atomicity, consistency, isolation og durability.
Atomicity betyder, at transaktionen er atomar – det vil sige at den enten er fuldørt eller slet ikke påbegyndt.
Consistency betyder, at fuldførelsen af en transaktion altid efterlader systemet i en gyldig tilstand. Hvis systemet er i en gyldig tilstand, når transaktionen starter, skal det også være i en gyldig tilstand, når transaktionen er udført, da transaktionen enten vil være udført korrekt eller slet ikke påbegyndt.
Isolation betyder, at transaktionen har den opfattelse, at den er den eneste, der er under udførsel. Det betyder, at transaktionen ikke behøver at tage højde for, at der kan være andre transaktioner, der arbejder på de samme data. Dette er vigtigt, da det ikke kan garanteres, at systemet har en gyldig tilstand, mens en transaktion er under udførsel. Derfor skal de ændringer, en transaktion foretager, holdes skjult for andre transaktioner, indtil man ved, at transaktionen er fuldført korrekt, og at ændringerne derfor er permanente. Havde man ikke denne garanti, kunne man risikere, at transaktion 1 ændrede nogle data, som transaktion 2 herefter indlæste og arbejdede på. Herefter fejler transaktion 1, hvilket som nævnt betyder, at de data, transaktionen har ændret, skal ændres tilbage til de værdier, de havde før. Det vil sige, at de data, transaktion 2 har indlæst, ikke længere er korrekte, men det er transaktion 2 ikke klar over. Derfor arbejder denne transaktion videre, og fuldføres korrekt, hvorefter transaktionens data gemmes, selv om de egentlig er baserede på forkerte oplysninger. Når alle transaktioner er isolerede, kan dette ikke ske.
Durability betyder, at de ændringer, en transaktion foretager, er varende. Det vil sige, at der findes teknikker, som sikrer, at der ikke mistes oplysninger – heller ikke ved systemnedbrud.
Microsoft Transaction Server
Som det fremgår af ovenstående, er det ikke en simpel proces at implementere transaktionsstyring. Heldigvis er det meste af arbejdet gjort i programmet Microsoft Transaction Server (MTS). MTS er en del af Microsoft Internet Information Server.
Ved installationen af Microsoft Transaction Server bliver der installeret en genvej ved navn Transaction Server Explorer. Denne genvej starter Microsoft Management Console (MMC). Det er gennem dette program, transaktionsserveren administreres.
Figur 4.5: Microsoft Management Console.
En af transaktionsserverens opgaver er at håndtere komponenter, der kan tilgås fra transaktionerne. Man skal derfor tilføje komponenterne til transaktionsserveren – dette gøres gennem MMC.
I MTS er alle komponenter organiseret i pakker. En pakke komponenter er en gruppe komponenter, der hører logisk sammen – typisk vil man vælge at lade alle komponenter til en applikation ligge i den samme pakke. Vil man oprette en ny applikation, skal man først oprette en ny pakke. En ny pakke oprettes i MMC ved at højreklikke på punktet Installerede komponenter i venstre del af hovedvinduet i MMC og vælge Ny pakke.
Figur 4.6: Tilføjelse af en ny pakke i MMC.
Man bliver herefter spurgt, om man vil oprette en ny pakke eller installere komponenter fra tredjepart. Vælger man at oprette en tom pakke, bliver man bedt om at indtaste det navn, der skal identificere pakken. Det næste skridt er at vælge den bruger, pakken skal afvikles af. Her kan man vælge mellem Interaktiv bruger og en bestemt bruger. Vælger man interaktiv bruger, bliver pakken afviklet under den bruger, der er logget ind på systemet på kørselstidspunktet.
Når disse spørgsmål er besvaret, bliver pakken tilføjet til listen over installerede pakker. Den nye pakke indeholder nu to mapper: Komponenter og roller.
For at tilføje komponenter skal man højreklikke på mappen komponenter og vælge Ny komponent. Dette vil starte guiden Komponent.
Figur 4.7: Guiden Komponent.
Komponenten giver mulighed for at vælge at tilføje nye komponenter eller for at importere komponenter, der allerede er registrerede. Vælger man at tilføje en ny komponent, vil man blive bedt om at angive den eller de filer, der indeholder de komponenter, der skal tilføjes. Hver gang man tilføjer en fil, vil indholdet af filen blive vist i guidens vindue.
Figur 4.8: Tilføjelse af en komponent.
Vælger man i stedet at tilføje komponenter, der allerede er registreret, til ens pakke, bliver man præsenteret for en liste over de komponenter, der er registreret på computeren, og man kan vælge en eller flere af disse komponenter.
Figur 4.9: Import af komponenter.
Når komponenten er blevet tilføjet, kan man se dens navn i træet i venstre side af vinduet. Hvis man går dybere ind i træet, vil man se, at MMC giver mulighed for at se de forskellige komponenters grænseflade – det vil sige, hvilke metoder de understøtter. Denne funktionalitet kan være praktisk, når man skal skrive programmer eller ASP-sider, der anvender komponenterne.
Efter at man har installeret de ønskede komponenter, kan man konfigurere dem. Det gør man ved at vælge pakken i venstre side af vinduet, og derefter højreklikke på komponenten i højre side af vinduet. Fra den lokalmenu, der vises, skal man vælge Egenskaber. Egenskabsvinduet indeholder tre faner, hvor fanen Transaktion er den mest interessante. Her kan man vælge komponentens forhold til transaktioner. Betydningen af de forskellige indstillingsmuligheder bliver gennemgået grundigere i næste afsnit – i dette afsnit er det tilstrækkeligt at konkludere, at komponenterne som standard har den indstilling, at de ikke understøtter transaktioner. Man bør derfor ændre denne indstilling, hvis man planlægger at bruge komponenten i forbindelse med transaktioner.
Figur 4.10: Egenskaber for en komponent.
Transaktioner og ASP
For at en ASP-side kan blive betragtet som en komponent i transaktionssammenhæng, er der en række krav, som skal være opfyldt. Disse krav hænger sammen med de ACID-egenskaber, der blev beskrevet tidligere. For at sikre at transaktionerne har disse egenskaber, er det nødvendigt, at enhver komponenet i transaktionen angiver, hvornår den er succesfuldt afsluttet. Dette er for at sikre, at transaktionen kan rulles korrekt tilbage.
Som det blev beskrevet i ovenstående afsnit, er MTS bygget op omkring komponenter. Bruger man ASP til at implementere transaktioner, kan man opfatte ASP-siden som en komponent. Det er imidlertid ikke alle ASP-sider, der automatisk bliver til transaktionskomponenter. For at angive, at en side skal være en komponent, skal siden indledes med linien
<% @TRANSACTION = type %>
Typen angiver den form for komponent, siden skal være. Nedenstående tabel viser, hvilke forskellige typer der findes, og hvad de angiver.
| Type | Beskrivelse |
| Required | Angiver at denne ASP-side skal afvikles i en transaktion. Hvis der ikke allerede er en transaktion aktiv, vil MTS oprette en transaktion. |
| Requires_New | Angiver at ASP-siden skal afvikles i en ny transaktion. MTS opretter automatisk en ny transaktion. |
| Supported | Angiver at ASP-siden kan være en del af en transaktion, men at den ikke nødvendigvis skal være det. MTS starter ikke en ny transaktion, hvis der ikke allerede er en transaktion. |
| Not_Supported | Angiver at ASP-siden ikke understøtter transaktioner. Hvis siden bliver afviklet som en del af en transaktion, vil den blive afviklet på samme måde, som hvis den ikke var del af en transaktion. |
Tabel 4.6: Oversigt over transaktionstyper
Almindelige transaktionskomponenter får en lang række oplysninger af MTS. ASP-sider har også mulighed for at få disse oplysninger – det sker gennem den komponent, der hedder ObjectContext.
ObjectContext-objektet indeholder de metoder, man skal bruge til at angive, at en ASP-side er blevet udført. Objektet indeholder to metoder: SetComplete og SetAbort. SetComplete-metoden bruges til at angive, at komponenten ikke vil blokere for udførslen for hele transaktionen. Metoden bør således kaldes, når ASP-siden har udført sin opgave uden at opdage nogen fejl. SetComplete bliver automatisk udført, når alle kommandoerne i ASP-siden er blevet udført, og SetAbort ikke er blevet kaldt. SetAbort bruges nemlig til at angive, at komponenten har opdaget en fejl, som gør, at transaktionen skal stoppes og rulles tilbage. Nedenstående eksempel viser, hvordan man kan skrive en simpel ASP-side, som gør brug af ObjectContext-objektet.
<% @transaction = required language = javascript %>
<html>
<body>
<%
// Tæl hvor mange transaktioner der er udført
Application.lock();
count = Application(“transactioncount”);
if (count == null) {
count = 0;
}
count++;
Application(“transactioncount”) = count;
Application.unlock();
// Udfør transaktionen
obj = Server.createObject(“test.MinKomponent”);
obj.execute();
// Angiv om transaktionen blev udført korrekt
if (obj.successful()) {
ObjectContext.SetComplete();
Response.write(“Transaktion fuldført!”);
} else {
ObjectContext.SetAbort();
Response.write(“Transaktionen fejlede!”);
}
%>
</body>
</html>
Eksemplet gør brug af en testkomponent – test.MinKomponent – som har to metoder: execute og successful. Metoden execute kører komponenten, der udfører selve transaktionen, mens successful angiver, om transaktionen blev udført korrekt.
Selv om MTS gør det muligt at få ASP-sider behandlet som komponenter, er der dog nogle forskelle på den måde, ASP-sider og rigtige komponenter behandles på. Den væsentligste er, at de ændringer, siden foretager, ikke automatisk bliver rullet tilbage, hvis transaktionen fejler. For at en transaktion, der indeholder ASP-sider, kan garanteres at have ACID-egenskaberne, er det således nødvendigt selv at implementere tilbagerulning. De ændringer, man foretager gennem objekter oprettet med Server.CreateObject, bliver overvåget af MTS, og disse ændringer bliver derfor automatisk tilbagerullet, hvis transaktionen fejler. Foretager man derimod ændringer i sessions- eller applikationsvariabler, er man nødt til selv at tilbagerulle ændringerne i tilfælde af en transaktionsfejl.
For at kunne håndtere tilbagerulning er det nødvendigt at vide, om transaktionen er fejlet. Når det er afgjort, om en transaktion fejler eller bliver fuldført, kontrolleres det, om ASP-siden indeholder en af to metoder. Hvis transaktionen bliver fuldført, bliver metoden OnTransactionCommit udført. Implementerer man denne metode i sin ASP-side, bliver indeholdet af den automatisk udført, hvis transaktionen fuldføres. Hvis transaktionen derimod fejler, er det metoden OnTransactionAbort, som bliver udført. I denne metode kan man skrive de kommandoer, der tilbageruller eventuelle ændringer foretaget i ASP-siden.
Nedenstående eksempel viser, hvordan man kan lave en ASP-side, der håndterer fuldførelse og afbrydelse af en transaktion.
<% @transaction = supported language = javascript %>
<%
// Tæl hvor mange transaktioner der er udført
Application.lock();
count = Application(“transactioncount”);
if (count == null) {
count = 0;
}
count++;
Application(“transactioncount”) = count;
Application.unlock();
// …
function OnTransactionCommit() {
// registrer at endnu en transaktion er fuldført
Application.lock();
count = Application(“commitcount”);
count++;
Application(“commitcount”) = count;
Application.unlock();
}
function OnTransactionAbort() {
// rollback transactioncount
Application.lock();
count = Application(“transactioncount”);
count–;
Application(“transactioncount”) = count;
Application.unlock();
}
%>
Sammenfatning
I dette kapitel er en række videregående ASP-teknikker blevet forklaret. Det drejer sig blandt andet om persistent dataopbevaring med anvendelse af filer på serveren, samt midlertidig opbevaring på serveren med sessions- og applikationsbaserede variable.
I kapitlet er det også blevet gennemgået, hvordan man kan integrere ActiveX-komponenter med sine ASP-programmer. Anvendelse af komponenter i forbindelse med transaktionsstyring er også et af de emner, der er blevet forklaret i dette kapitel.
Du læser en gammel bog
Den bog, du læser her, er fra 1999, og mange ting kan have ændret sig siden da.
Vi håber, at du stadig kan finde relevant information i den.
Hvis du vil læse aktuelle oplysninger om den aktuelle version af ASP.NET, anbefaler vi
bogen Programming ASP.NET 4.0









