De foregående kapitler har beskrevet al den teori, der ligger bag udvikling af en ASP-applikation. I dette kapitel bliver det vist, hvordan man kan anvende ASP i praksis.
Kapitlet er bygget op omkring et eksempel på en e-handelsbutik, der sælger cd’er. For at kunne referere til butikken har den fået navnet Compact Discount – eventuelle ligheder med eksisterende e-handelsbutikker er naturligvis tilfældig og ganske utilsigtet.
Det er imidlertid ikke udvikling af hele applikationen, der bliver beskrevet i dette eksempel. For at lave en komplet e-handelsbutik er der mange ting, man skal tage højde for. Det gælder for eksempel integration med lagersystemer, økonomisystemer og lignende. Disse områder vil ikke blive beskrevet. Vi vil koncentrere os om web-delen af butikken.
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
Funktionalitet
I dette afsnit bliver det beskrevet, hvilken funktionalitet web-stedet skal have. Disse krav vil i store træk svare til de sider, web-stedet skal indeholde. De enkelte emner bliver beskrevet separat senere i dette kapitel.
Bemærk, at dette eksempel kun koncentrerer sig om den del af web-stedet, der er tilgængeligt for brugeren. Web-stedets administratorer vil naturligvis have brug for yderligere funktioner – eksempelvis til at vedligeholde albumdatabasen.
En analyse har afgjort, at web-stedet skal have følgende funktionalitet:
- Bestilling af varerne i indkøbskurven
- Søgning
- Tilføjelse af et album til indkøbskurven
- Visning af de mest solgte album.
- Visning af detaljer om et enkelt album
- Visning af kategorier
- Visning af oversigt over varerne i indkøbskurven.
For at forstå beskrivelsen af web-stedets funktionalitet er det nødvendigt at forstå begrebet indkøbskurv. En indkøbskurv i en e-butik svarer til en indkøbskurv i en almindelig butik. Kunder i e-butikken føjer varer til indkøbskurven ved at klikke på en knap på informationssiden om den pågældende vare. Når alle de ønskede varer er bestilt, vælger kunden at afsende sin ordre, og indkøbskurven tømmes.
Databasen
De oplysninger, der skal være tilgængelige på web-stedet, skal naturligvis gemmes i en database. Opbygningen af denne database er imidlertid ikke en helt triviel opgave – databasens opbygning vil derfor blive beskrevet i detaljer i dette afsnit. Afsnittet vil også beskrive, hvordan man foretager DSN-registrering af databasen, der bliver udviklet i Microsoft Access.
Opbygning af databasen
Første skridt i at designe en database er at definere, hvilke oplysninger der skal gemmes i databasen. Af hensyn til overskueligheden bliver databasen beskrevet i to dele: kundedelen og administratordelen.
De centrale elementer i e-butikken er cd’er (her kaldet album) , ordrer og kunder. Om det enkelte album skal man vide titel, udgivelsestidspunkt, pris, kategori, kunstner og hvilket pladeselskab, det er udgivet på. Derudover skal der også være en beskrivelse af albummet, så kunderne kan læse om cd’en, før de køber den. Databasen skal også indeholde en reference til en fil, der indeholder et billede af coveret – coveret skal vises, når kunden ser oplysninger om albummet. Der skal også være en forventet leveringstid tilknyttet albummet, så kunden kan se, om det er en cd, der er på lager, eller om man kan forvente en længere leveringstid. Endeligt skal der – af hensyn til kategorioversigten – være en angivelse af, hvilken kategori albummet tilhører.
Det skal også være muligt at se, hvilke numre der er på albummet. For hvert nummer på albummet skal der være albummets titel samt navnet på den kunstner, der har indspillet det pågældende nummer. Det kan måske virke overflødigt, at der både er kunstner på albummet og på nummeret, men det behøver ikke at være den kunstner, som står for albummet, der har indspillet alle numre på albummet.
Når en kunde bestiller album i butikken, skal ordren registreres i databasen. En ordre kan naturligvis bestå af et eller flere album, og for hvert album skal det registreres, hvilket album, der er købt, og i hvor mange eksemplarer. For hver ordre skal det naturligvis angives, hvilken kunde der har foretaget ordren. Om kunden skal man kende navn, adresse, postnummer, by og e-mail. For at gøre det muligt at genkende kunden, så denne er fri for at indtaste sin adresse hver gang, der foretages bestillinger, bør det også være muligt at lade brugeren angive et kodeord.
Dette kunne umiddelbart tyde på, at man skulle have to eller tre tabeller til at opbevare oplysninger om henholdsvis album, ordrer og kunder. Denne løsning har dog nogle ulemper. Hvis man samler album og numre i én tabel, bliver man nødt til at gentage albummets navn, kunstner, pris og så videre, for hvert nummer på albummet. Opdeler man i stedet album og numre i to tabeller og giver hvert album en unik identifikation, kan man nøjes med at gentage albummets identifikation for hvert nummer.
Problematikken er stort set den samme ved kunstnere i forhold til numre og album. En kunstner har typisk udgivet flere album og medvirker næsten med garanti på mere end et nummer. I stedet for at skulle indtaste kunstnerens navn for hvert nummer og album, er det lettere blot at indtaste kunstneren en gang, tildele denne en unik identifikation og fremover bruge denne identifikation til at identificere kunstnere i album- og nummer-tabellerne. Denne løsning gør det også muligt at kende forskel på to kunstnere, der har det samme navn.
Problemet gentager sig ved ordrerne. Som nævnt kan en ordre bestå af flere album, og der skal gemmes oplysninger om de enkelte album og samlet om ordren. Derfor kan man med fordel opdele ordrelinierne – de enkelte album – fra selve ordren, og blot lade hver linie indeholde en reference til selve ordren. I ordrelinierne gemmes de oplysninger, der kan optræde flere gange i hver ordre: albummet og antallet. I selve ordren gemmes de oplysninger, der kun optræder en gang: kundeoplysningerne.
Det blev stillet som et ønske tidligere, at kunden kun behøvede at indtaste sine oplysninger første gang, der blev handlet i e-butikken. Derfor skal kundeoplysningerne gemmes selvstændigt og ikke sammen med ordrerne. Hvis kundeoplysningerne var gemt sammen med ordrerne, ville man være nødt til at gå gennem samtlige ordrer for at genfinde kunden.
Ud over beskrivelserne af de centrale elementer i butikken er der nogle tabeller, det er rart at have af hensyn til web-designet. For eksempel vil e-butikkens forside blive brugt til at promovere særligt udvalgte album. Til disse album skal der være tilknyttet en særlig, salgsvenlig tekst, der skal vises på forsiden sammen med albummets cover.
Ovenstående beskrivelse giver nedenstående tabeller.
Album
| Feltnavn | Felttype | Kommentarer |
| ID | Tal | Unik identifikation af albummet |
| Titel | Tekst | |
| Udgivelse | Dato og klokkeslæt | |
| Pris | Tal | |
| Forside | Tekst | Adresse på billedfil af forsiden |
| Beskrivelse | Notat | |
| Kategori | Tal | Reference til kategoritabellen |
| Leveringstid | Tal | Leveringstid i date |
| Kunstner | Tal | Reference til kunstnertabellen |
| Pladeselskab | Tekst |
Nummer
| Feltnavn | Felttype | Kommentarer |
| ID | Tal | Unik identifikation af albummet |
| Titel | Tekst | |
| Kunstner | Tal | Reference til kunstnertabellen |
| Album | Tal | Reference til albumtabellen |
Kunstner
| Feltnavn | Felttype | Kommentarer |
| ID | Tal | Unik identifikation af albummet |
| Navn | Tekst |
Kategori
| Feltnavn | Felttype | Kommentarer |
| ID | Tal | Unik identifikation af albummet |
| Kategori | Tekst |
Ordrelinie
| Feltnavn | Felttype | Kommentarer |
| ID | Tal | Unik identifikation af ordrelinien |
| Album | Tal | Reference til album-tabellen |
| Antal | Tal | |
| Ordre | Tal | Reference til ordre-tabellen |
Ordre
| Feltnavn | Felttype | Kommentarer |
| ID | Tal | Unik identifikation af ordren |
| Kunde | Tal | Reference til kundetabellen |
| Dato | Dato og klokkeslæt |
Kunde
| Feltnavn | Felttype | Kommentarer |
| ID | Tal | Unik identifikation af kunden |
| Navn | Tekst | |
| Adresse | Tekst | |
| Postnummer | Tal | |
| Postdistrikt | Tekst | |
| Tekst | ||
| Kodeord | Tekst |
Forside
| Feltnavn | Felttype | Kommentarer |
| ID | Tal | Unik identifikation af albummet på forsiden. |
| Album | Tal | Reference til album-tabellen |
| Tekst | Notat | Beskrivelse af albummet, der skal vises på forsiden. |
Som det fremgår af ovenstående tabelbeskrivelser indeholder tabellerne en lang række referencer til andre tabeller. Disse referencer kaldes også relationer, og nedenstående figur 10.1 viser relationerne i databasen.
Figur 10.1. Relationer i databasen.
Registrering af DSN
Som nævnt i kapitel 5 er det nødvendigt at registrere databasen for at den kan tilgås fra ASP-siderne.
Registreringen foretages i Kontrolpanelet under det punkt, der hedder 32-bit ODBC. Under fanen System-DSN vælges tilføj, hvorefter databasen vælges. Databasens ODBC-navn skal også angives. I dette tilfælde bruges navnet compactdiscount.
Figur 10.2. Registrering af System-DSN.
Udvikling af ASP-siderne
I dette afsnit bliver udviklingen af de mest interessante sider af e-butikken beskrevet. De overvejelser, der ligger bag udviklingen af siderne, bliver beskrevet, ligesom sidernes kildetekst vil blive vist.
Generelt om designet
Det er altid god web-design-skik at holde siderne på det samme sted nogenlunde ens. I dette tilfælde er designet to hvide områder i hver side af skærmen samt butikkens logo øverst på siden. Det betyder, at en blank side kommer til at se således ud:
Figur 10.3. Blank side på web-stedet.
Da der således vil være en del kode, der skal bruges i alle siderne, vil det være en god ide at lægge denne kode ud i en selvstændig fil, som kan inkluderes i alle filerne. Denne fil kaldes header.html.
Generelt bliver der brugt en del include-filer for at minimere den mængde kode, der skal være i de enkelte sider. Dette gøres dels for at gøre eksemplerne mere overskuelige, men også fordi det er spild af tid at gentage den samme kode i flere forskellige sider. Indholdet af de anvendte include-filer vil blive vist i de følgende afsnit.
Sidehovedet (header.html)
Filen header.html bliver inkluderet i alle siderne i e-butikken. Siden sørger for at lave de hvide felter i højre og venstre side af skærmen og vise e-butikkens logo. Derudover oprettes menubjælken øverst i skærmen. Filen ser således ud:
<style type=”text/css”>
<!–
.headlink {
color: ffffff;
text-decoration: none;
font-size: smaller;
}
–>
</style>
<p>
<table width = 100%>
<tr>
<td width = 100 rowspan=2> </td>
<td align=center><a href=index.asp><img src=logo.gif alt=”Compact Discount” border=0></a>
<table width=100% ><tr>
<td bgcolor=Gray align=center width=33%><a href=kurv.asp>Se indkøbskurv</a></td>
<td bgcolor=Gray align=center width=33%><a href=afsend.asp>Afsend ordre</a></td>
<td bgcolor=Gray align=center width=33%><a href=help.asp>Hjælp</a></td>
</tr></table>
<p>
</td>
<td width = 100 rowspan=2>
</td>
</tr>
Databaseadgang (database.js)
Hovedparten af siderne i web-stedet skal tilgå databasen. Derfor er den kode, der skal bruges til at tilgå databasen, lagt ud i en selvstændig fil ved navn database.js. Denne fil indeholder en enkelt metode – createDatabaseConnection – der opretter og returnerer en forbindelse til databasen. Udover den pladsmæssige fordel ved kun at have denne kode ét sted, opnår man også en fordel, hvis man på et tidspunkt skifter database – så behøver man kun at ændre databasens navn et enkelt sted.
Filen database.js indeholder også en metode, der konverterer en JavaScript-dato til en SQL-dato.
Kildeteksten til database.js ser således ud:
<%
function createDatabaseConnection() {
con = Server.CreateObject(“ADODB.Connection”);
con.Open(“compactdiscount”);
return con;
}
function toSqlDate(date) {
return “‘” + date.getDate() + “-” + (date.getMonth() + 1) + “-” + date.getYear() + “‘”;
}
%>
Strenghåndtering (string.js)
JavaScript er som udgangspunkt ikke særligt godt til at håndtere tekststrenge. Der er derfor behov for nogle metoder, som kan arbejde på tekststrenge. Disse metoder findes i inkluderingsfilen string.js. Kildeteksten til denne fil er som følger:
<%
function strcmp(s1, s2) {
if (s1.length != s2.length) {
return false;
}
for (i = 0; i < s1.length; i++) {
if (s1[i] != s2[i]) {
return false;
}
}
return true;
}
%>
Forsiden (index.asp)
Formålet med forsiden er at byde kunden velkommen til web-stedet. Forsiden skal også give brugeren et overblik over web-stedets opbygning. Endeligt skal man ikke glemme formålet med hele web-stedet: at få kunden til at købe noget. Derfor skal forsiden også indeholde reklamer for særligt udvalgte album.
Forsiden opdeles ved hjælp af en tabel i to dele. Den venstre del af forsiden bruges til henvisninger til andre sider på web-stedet. Det drejer sig blandt andet om kategorioversigt og søgning. Kategorioversigten laves naturligvis på baggrund af de oplysninger, der ligger i kategoritabellen i databasen.
Figur 10.4. Forsiden.
Den højre side af forsiden indeholder selve teksten. Her startes med at kontrollere, om kunden har en cookie sat. I så fald er vedkommende logget ind. Cookien indeholder kundens kundenummer. Dette kundenummer kan man bruge til at finde kundens navn i databasen.
Hvis kunden ikke har en cookie, er vedkommende ikke logget ind, og vi ved ikke, hvem det er. Hvis kunden tidligere har handlet i e-butikken, kan vedkommende identificere sig selv ved at logge ind.
Dernæst vises der reklamer for særligt udvalgte album. Reklamen skal indeholde albummets cover, titel, kunstner, pris samt beskrivelse. Beskrivelsen – samt albummets id – hentes fra forsidetabellen, mens de øvrige oplysninger hentes fra albumtabellen. For at kunne hente disse oplysninger ud af databasen på den letteste måde, er der blevet oprettet en forespørgsel (et view) i databasen. Denne forespørgsel indeholder netop de oplysninger, der skal bruges. Dette view kaldes forsideview.
Kildeteksten til forsiden ser således ud:
<% @Language=JavaScript %>
<!– #include file=”database.js” –>
<%
con = createDatabaseConnection();
%>
<html>
<head>
<title>Velkommen til Compact Discount</title>
</head>
<!– #include file=”header.html” –>
<td>
<table>
<td width = 110>
<font size = -1>
<b>Kategorier:</b><br>
<%
// lav kategorioversigt
res = con.Execute(“SELECT * FROM Kategori ORDER BY Kategori”);
while (!res.EOF) {
Response.Write(“<a href = search.asp?kategori=”);
Response.Write(res.Fields(“ID”));
Response.Write(“>”);
Response.Write(res.Fields(“kategori”));
Response.Write(“</A><BR>”);
res.move(1);
}
%>
<p>
<b>Søg</b><br>
<form action=search.asp method=get>
Indtast søgeord:<br>
<input type=text name=tekst size=12><br>
<center><input type=submit value=”Søg”></center>
</form>
<b>Statistik</b><br>
<a href=mestsolgt.asp>Mest solgte album</a>
</td>
<!– slut på oversigt i venstre side af billedet –>
<td valign=top>
<%
// Kontrollér om brugeren har en cookie (= er logget ind)
if (Request.Cookies(“kundeid”) != “”) {
kundeid = Request.Cookies(“kundeid”);
Session(“kundeid”) = kundeid;
res = con.execute(“SELECT navn FROM kunde WHERE id=” + kundeid);
kundenavn = res.Fields(“navn”);
%>
Velkommen <%=kundenavn%>.
<%
} else {
%>
Velkommen til Computer Discount. Hvis du er registreret som kunde hos os, kan du
<a href=login.asp>logge ind</a> her.
<%
}
%>
<p>
<!– vis udvalgte cd’er –>
<table width = 100% >
<%
res = con.execute(“SELECT * FROM forsideview”);
while (!res.EOF) {
Response.write(“<tr><td valign=top>”);
Response.write(“<img src=”);
Response.write(res.Fields(“forside”));
Response.write(“</td><td valign=top><b>”);
Response.write(res.Fields(“Navn”));
Response.write(“: “);
Response.write(res.Fields(“Titel”));
Response.write(“</b><br>”);
Response.write(res.Fields(“tekst”));
Response.write(“<p>”);
Response.write(“<i>Køb den her for kun “);
Response.write(res.Fields(“pris”));
Response.write(“<p align=right>”);
Response.write(“<font size=-1>”);
Response.write(“<a href=info.asp?album=”);
Response.write(res.Fields(“ID”));
Response.write(“>Yderligere oplysninger</a></font>”);
Response.write(“</td></tr>”);
res.Move(1);
}
%>
</table> <!– udvalgte cd’er –>
</td>
</tr>
</table> <!– midtersektion –>
</table>
</body>
</html>
Informationssiden (info.asp)
Det skal naturligvis være muligt at se flere oplysninger om et album end de, der vises på kategorioversigterne og i søgeresultaterne. Når en bruger klikker på et album, bliver han præsenteret for en informationsside, der indeholder alle relevante oplysninger om albummet. Fra informationssiden skal det naturligvis også være muligt at tilføje albummet til indkøbskurven.
Figur 10.5. Informationssiden.
Siden info.asp starter med at hente de relevante oplysninger ud af albumtabellen. Dernæst hentes oplysninger fra kunstnertabellen, så kunstnerens navn også kan blive vist på siden.
Siden indeholder også en oversigt over de numre, der er på cd’en. For hvert nummer skal nummerets titel vises, samt kunstneren. Hvis man klikker på kunstneren, skal man sendes til søgesiden og få en oversigt over alle de album, kunstneren har indspillet numre på. Oplysningerne om nummeret ligger i nummertabellen, mens navnene på kunstnerne findes i kunstnertabellen. For at kombinere disse oplysninger vil man først skulle hente alle oplysningerne om albummet ud af nummertabellen, og derefter – for hvert nummer på albummet – hente kunstnerens navn ud af kunstnertabellen. Dette vil medføre en lang række forespørgsler til databasen, og det vil være forholdsvis langsommeligt. Derfor er der blevet oprettet endnu et view – kunstnerview – som kombinerer kunstnerne med numrene. Nummeroversigten på informationssiden bliver lavet ud fra dette view.
Muligheden for at købe albummet er implementeret ved hjælp af en formular med en knap. Formularen indeholder et skjult felt med albummets id. Når brugeren klikker på knappen, indsendes formularens data til siden tilfoj.asp, der sørger for at føje albummet til indkøbskurven.
Kildeteksten til informationssiden ser således ud:
<% @Language=JavaScript %>
<!– #include file=”database.js” –>
<%
con = createDatabaseConnection();
album_id = Request.QueryString(“album”);
res = con.Execute(“SELECT * FROM Album WHERE id=” + album_id);
titel = res.Fields(“Titel”);
%>
<html>
<head>
<title>Compact Discount [<%=titel%>]</title>
</head>
<!– #include file=”header.html” –>
<td>
<table width = 100%>
<tr>
<td>
<table>
<tr>
<td valign=top>
<img src=<%=res.Fields(“forside”)%> alt=<%=titel%>>
</td>
<td valign=top>
<%
kunstner_id = res.Fields(“Kunstner”);
kunstner_res = con.Execute(“SELECT Navn FROM Kunstner WHERE id=” + kunstner_id);
kunstner = kunstner_res.Fields(“Navn”);
%>
<b><%=kunstner%>: <%=titel%></b><br>
<font size=-1>
Udgivet: <%=res.Fields(“Udgivelse”)%><br>
Pris: <%=res.Fields(“Pris”)%> kr.<br>
Leveringstid: ca. <%=res.Fields(“Leveringstid”)%> dag(e).<br>
Kategori:
<%
kategori_id = res.Fields(“Kategori”);
kategori_res = con.Execute(“SELECT Kategori FROM kategori WHERE id=” + kategori_id);
kategori = kategori_res.Fields(“Kategori”);
%>
<a href=search.asp?kategori=<%=kategori_id%>><%=kategori%></a>
</font>
</td>
</tr>
</table>
<%=res.Fields(“Beskrivelse”)%><P>
Albummet indeholder følgende numre:
<ol>
<%
nummer_res = con.Execute(“SELECT Titel, Navn, Kunstner FROM Kunstnerview WHERE album=” + album_id);
while (!nummer_res.EOF) {
%>
<li><%=nummer_res.Fields(“Titel”)%> (<i><a href=search.asp?kunstner=<%=nummer_res.Fields(“Kunstner”)%>><%=nummer_res.Fields(“Navn”)%></a></i>)
<%
nummer_res.Move(1);
}
%>
</ol>
</td>
<td width=100>
<form action=tilfoj.asp method=post>
<input type=hidden name=album value=<%=album_id%>>
<center><input type=submit value=”Bestil album”></center>
<font size=-1>
Klik på ovenstående knap for at tilføje albummet til din indkøbskurv.
Du kan altid fjerne den fra indkøbskurven senere.
</font>
</td>
</tr>
</table>
</td>
</tr>
</table>
Tilføjelsessiden (tilfoj.asp)
Tilføjelsessiden er en af de sider, der lever en skjult tilværelse på web-stedet. Det vil sige, at den ikke indeholder oplysninger, der skal vises til brugeren. Det eneste, siden gør, er at tilføje et album til indkøbskurven, og derefter sende brugeren videre til indkøbskurvsoversigten.
Indkøbskurven gemmes i en række sessionsvariable. Dette giver mening, fordi indkøbskurven tilhører den bruger, der har den pågældende session. Sessionsvariablerne er opdelt i to kategorier: de, der angiver albumnumrene, og de, der angiver antallet af bestilte album. Albummene opbevares i variable med navnene Album0, Album1, Album2 osv. Antallene ligger i variable med navnene Antal0, Antal1, Antal2 osv. Det vil sige, at Album1 indeholder identifikationen af det antal, der skal købes, mens Antal1 angiver, hvor mange eksemplarer der skal købes af det pågældende album. Bemærk, at oplysningerne i indkøbskurven endnu ikke er ordrer, og derfor ikke opbevares i databasen.
Til at registrere, hvor mange forskellige album, der er købt, bruges sessionsvariablen AlbumAntal.
Siden tilfoj.asp får det album, der skal købes, med som parameter fra bestillingsformularen. Dernæst kontrolleres det, ved hjælp af sessionsvaraiblerne, om kunden i forvejen har bestilt et – eller flere – eksemplarer af albummet. Er det tilfældet bliver den pågældende antal-variabel talt op, så kunden nu har bestilt et eksemplar mere.
Har kunden ikke eksemplarer af albummet liggende i indkøbskurven, bliver albummet tilføjet, og sessionsvariablen albumantal bliver talt op.
Når dette er gjort, omdirigeres brugeren til siden kurv.asp, der viser indholdet af indkøbskurven. Kildeteksten til tilfoj.asp ser således ud:
<% @language=javascript %>
<%
// hent variable
album = Request.Form(“album”);
albumantal = Session(“albumantal”);
if (!(albumantal > 0)) {
albumantal = 0;
}
// kontroller om kunden allerede har bestilt et eksemplar af denne cd
found = false;
for (i = 0; i < albumantal; i++) {
if (Session(“album”+i) == album) {
antal = Session(“antal”+i);
antal++;
Session(“antal”+i) = antal;
found = true;
break;
}
}
if (!found) { // tilføj et nyt album til indkøbskurven
Session(“album”+albumantal) = “” + album;
Session(“antal”+albumantal) = 1;
albumantal++;
Session(“albumantal”) = albumantal;
}
Response.Redirect(“kurv.asp”);
%>
Indkøbskurven (kurv.asp)
Indkøbskurven viser de album, kunden har tilføjet til sin indkøbskurv. For hvert album vises antallet af bestilte eksemplarer, albummets titel, pris samt den samlede pris for de bestilte eksemplarer. Den samlede pris på alle albummene i indkøbskurven vises også.
Kunden skal naturligvis have mulighed for at ændre antallet af bestilte eksemplarer og for at fjerne et eller flere album fra indkøbskurven. I dette eksempel stilles denne funktionalitet til rådighed ved, at antallet af bestilte eksemplarer vises i et tekstfelt i en formular. For hvert album er der en knap, der hedder opdater, og ved at ændre på antallet i tekstfeltet og klikke på knappen, bliver antallet ændret. Hvis man vil fjerne et album fra indkøbskurven, skal man skrive 0 i antalfeltet og klikke på opdater.
Figur 10.6. Indkøbskurven.
Siden starter med at kontrollere, om der overhovedet er album i indkøbskurven. Er der ikke det, skrives teksten “Din indkøbskurv er tom”, og siden afsluttes.
Er der noget i indkøbskurven, oprettes der en formular for hvert album i indkøbskurven. Formularen indeholder et tekstfelt, hvor antallet af bestilte eksemplarer skrives, samt en knap. Når der klikkes på knappen, sendes oplysningerne fra formularen til rediger.asp, der sørger for at redigere antallet af bestilte eksemplarer.
For hvert album i indkøbskurven beregnes den samlede pris, og denne pris adderes til den samlede pris for hele indkøbskurven. Den samlede pris vises efter listen over albums i indkøbskurven.
Siden indeholder naturligvis også en henvisning til siden, der foretager afsendelsen af ordren.
Kildeteksten til kurv.asp ser således ud:
<% @Language=JavaScript %>
<!– #include file=”database.js” –>
<%
con = createDatabaseConnection();
%>
<html>
<head>
<title>Compact Discount [Indkøbskurv]</title>
</head>
<!– #include file=”header.html” –>
<td>
<h1>Indkøbskurv</h1>
<%
albumantal = Session(“albumantal”);
undefined = Session(“garbage”);
totalpris = 0;
if (albumantal == undefined || albumantal == 0) {
Response.write(“Din indkøbskurv er tom.”);
Response.end();
}
%>
Din indkøbskurv indeholder følgende album:<br>
<table width=100%>
<%
for (i = 0; i < albumantal; i++) {
if (Session(“antal”+i) == 0) {
continue;
}
%>
<form action=rediger.asp method=post>
<tr>
<td>
<input type=hidden name=album value=<%=i%>>
<input type=text name=antal value=<%=Session(“antal”+i)%> size=3>
</td>
<td>
<a href=info.asp?album=<%=Session(“album”+i)%>>
<%
res = con.execute(“SELECT Titel, Pris FROM Album WHERE id=” + Session(“album”+i));
%>
<%=res.Fields(“Titel”)%></a>
</td>
<td align=right>
<%
albumpris = res.Fields(“Pris”);
%>
<%=albumpris%> kr. pr. stk
</td>
<td align=right>
<%=Math.round(albumpris * Session(“antal”+i) * 100) / 100%> kr.
<%
totalpris += Math.round(albumpris * Session(“antal”+i) * 100) / 100;
%>
</td>
<td>
<input type=submit value=”Opdater”>
</td>
</form>
</tr>
<%
}
%>
<tr>
<td> </td>
<td><b>Total</b></td>
<td> </td>
<td align=right><b><%=totalpris%> kr.</td>
</tr>
</table>
<p>
Hvis du vil ændre antallet af bestilte album, så indtast det ønskede antal i feltet ved albummet og klik på knappen “Opdater”.
<p>
<b>Klikker du ikke på knappen “Opdater” bliver din opdatering ikke registreret!</b>
<p>Hvis du vil fjerne et album fra indkøbskurven, skal du indtaste 0 i feltet, og klikke på knappen “Opdater”.
<p>
Klik <a href=afsend.asp>her</a> for at afsende ordren.
</td>
</table>
Redigeringssiden (rediger.asp)
Ligesom tilføjelsessiden er redigeringssiden ikke synlig for brugeren. Siden ændrer antallet af købte eksemplarer af et album, og returnerer til indkøbskurven. Siden kontrollerer dog også, om alle album er blevet fjernet fra indkøbskurven. I så fald sættes albumantal til 0. Bemærk, at en sletning ikke medfører, at albumantal tælles ned. En sletning medfører blot, at antallet af eksemplarer af det pågældende album sættes til 0. Indkøbskurvsoversigten sørger for kun at vise de album, der er bestilt eksemplarer af.
Fordelen ved denne fremgangsmåde er, at man er fri for at flytte rundt på elementerne i indkøbskurven, hvis brugeren vælger at slette et element i midten.
Kildeteksten til redigeringssiden ser således ud:
<% @language=javascript %>
<%
album = Request.Form(“album”);
antal = Request.Form(“antal”);
Session(“antal”+album) = “” + antal;
if (antal == 0) { // kontroller om alle varer er slettet
albumantal = Session(“albumantal”);
found = false;
for (i = 0; i < albumantal; i++) {
if (Session(“antal”+i) != 0) {
found = true;
break;
}
}
if (!found) {
Session(“albumantal”) = 0;
}
}
Response.redirect(“kurv.asp”);
%>
Afsendelsessiden (afsend.asp)
På afsendelsessiden skal brugeren have mulighed for at afsende sin ordre. Inden brugeren får mulighed for dette, kontrollerer siden dog, at der rent faktisk er varer i indkøbskurven. Er indkøbskurven tom, får brugeren dette at vide, og der sker ikke yderligere. Hvis der er varer i indkøbskurven, bliver brugeren præsenteret for en oversigt over dem efter samme system som på siden med indkøbskurven, dog med den forskel at brugeren ikke har mulighed for at ændre antallet af bestilte album. Dette kan kun ske fra indkøbskurven, så derfor er der en henvisning til denne side.
Figur 10.7. Afsendelse af ordre.
Som nævnt tidligere håndterer web-stedet tilbagevendende kunder. Dette sker ved hjælp af cookies, som enten gemmes på brugerens harddisk eller sættes, når brugeren logger ind. På afsendelsessiden behøver tilbagevendende kunder ikke at udfylde felterne med navn, adresse og så videre – dette skal ske automatisk ved hjælp af oplysningerne fra databasen. Derfor kontrollerer siden, om cookien kundeid er sat. Er dette tilfældet, bruges værdien af cookien til at slå oplysninger om kunden op i databasen. Er cookien ikke sat, bliver kunden behandlet som en ny kunde og får mulighed for at blive registreret. For at blive dette skal kunden indtaste et kodeord.
Kildeteksten til afsendelsessiden ser således ud:
<% @Language=JavaScript %>
<!– #include file=”database.js” –>
<%
con = createDatabaseConnection();
%>
<html>
<head>
<title>Compact Discount [Afsend ordre]</title>
</head>
<!– #include file=”header.html” –>
<td>
<h1>Afsend ordre</h1>
<%
albumantal = Session(“albumantal”);
undefined = Session(“garbage”);
totalpris = 0;
if (albumantal == undefined || albumantal == 0) {
Response.write(“Din indkøbskurv er tom – der er derfor ingen ordre at afsende.”);
Response.end();
}
%>
Du er ved at afsende en ordre på følgende album:
<table width=100%>
<%
for (i = 0; i < albumantal; i++) {
if (Session(“antal”+i) == 0) {
continue;
}
%>
<tr>
<td>
<%=Session(“antal”+i)%>
</td>
<td>
<%
res = con.execute(“SELECT Titel, Pris FROM Album WHERE id=” + Session(“album”+i));
%>
<%=res.Fields(“Titel”)%>
</td>
<td align=right>
<%
albumpris = res.Fields(“Pris”);
%>
<%=albumpris%> kr. pr. stk
</td>
<td align=right>
<%=Math.round(albumpris * Session(“antal”+i) * 100) / 100%> kr.
<%
totalpris += Math.round(albumpris * Session(“antal”+i) * 100) / 100;
%>
</td>
</tr>
<%
}
%>
<tr>
<td> </td>
<td><b>Total</b></td>
<td> </td>
<td align=right><b><%=totalpris%> kr.</td>
</tr>
</table>
Hvis du ikke vil afsende denne ordre, skal du klikke <a href=kurv.asp>her</a> for at gå tilbage til din indkøbskurv og ændre indholdet.
<p>
Hvis du vil afsende ordren, skal du udfylde nedenstående felter og trykke på knappen nederst på denne side.
<p>
<%
// kontrollér om kunden er logget ind.
kundeid = Request.Cookies(“kundeid”);
if (kundeid == “”) {
navn = “”;
adresse = “”;
postnummer = “”;
by = “”;
email = “”;
} else {
res = con.execute(“SELECT navn, adresse, postnummer, by, email FROM kunde WHERE id = ” + kundeid);
navn = res.Fields(“navn”);
adresse = res.Fields(“adresse”);
postnummer = res.Fields(“postnummer”);
by = res.Fields(“by”);
email = res.Fields(“email”);
}
%>
<form name=afsend action=modtag.asp method=post>
<table>
<tr>
<td>Navn</td>
<td><input type=text name=navn value=”<%=navn%>”></td>
</tr>
<tr>
<td>Adresse</td>
<td><input type=text name=adresse value=”<%=adresse%>”></td>
</tr>
<tr>
<td>Postnummer</td>
<td><input type=text name=postnummer value=”<%=postnummer%>”></td>
</tr>
<tr>
<td>By</td>
<td><input type=text name=by value=”<%=by%>”></td>
</tr>
<tr>
<td>Email</td>
<td><input type=text name=email value=”<%=email%>”></td>
</tr>
<%
if (kundeid == “”) {
%>
<tr>
<td colspan=2>
Hvis du vil registreres som kunde hos os, skal du vælge et kodeord, og indtaste det i de nedenstående felter.
</td>
</tr>
<tr>
<td>Kodeord</td>
<td><input type=password name=kodeord1></td>
</tr>
<tr>
<td>Gentag kodeord</td>
<td><input type=password name=kodeord2></td>
</tr>
<%
}
%>
</td>
<tr>
<td> </td>
<td><input type=submit value=”Afsend ordre”></td>
</tr>
</table>
</form>
</body>
</html>
Modtagelsessiden (modtag.asp)
Modtagelsessiden bliver kaldt, når brugeren vælger at afsende sin ordre. Det er modtagelsessiden, der står for at registrere ordren i databasen. Modtagelsessidens opgaver kan opdeles i følgende:
- Kontrol af, om kunden er logget ind.
- I bekræftende fald skal kundens registrering i databasen opdateres med eventuelle nye oplysninger fra afsendelsessiden.
- Er kunden ikke logget ind, skal kunden oprettes.
- Hvis der allerede eksisterer en kunde med den samme e-mail-adresse, skal kunden bedes om at logge ind.
- Registrering af ordren.
- Oprettelse af en ny ordre.
- Registrering af de enkelte ordrelinier.
- Visning af resultat til brugeren.
Kontrollen af, om brugeren er logget ind, sker ved at teste, om cookien kundeid er sat. Er den det, konkluderes det, at brugeren er logget ind. Hvis kunden er logget ind, bliver oplysningerne opdateret. På denne måde registreres eventuelle ændringer i brugerens adresse automatisk. Oplysningerne opdateres ukritisk – det vil sige, at alle oplysningerne opdateres, også selvom de ikke er ændrede. På denne måde bliver man fri for at bruge tid på at sammenligne alle oplysningerne.
Når en ny kunde skal oprettes, bliver hans kodeord først kontrolleret. Kunden skal vælge et kodeord og indtaste det to gange – hvis de to kodeord ikke er ens, får kunden det at vide, og modtagelsessiden afbrydes.
Det kontrolleres også, om der allerede er registreret en kunde med den indtastede e-mail-adresse. E-mail-adresserne skal være unikke, og det kan derfor ikke tillades, at flere kunder bruger den samme adresse. Følgelig bliver brugeren bedt om enten at indtaste en anden e-mail-adresse, eller at logge ind.
Når kunden er opdateret eller oprettet, kan ordren registreres. Dette er imidlertid ikke helt trivielt. Som det blev beskrevet tidligere i dette kapitel, er ordrerne opdelt i en ordretabel og en ordrelinietabel. Ordretabellen består af kolonnerne id, kunde og dato, hvor id er et autonummereringsfelt, hvilket vil sige, at databasen selv udfylder feltet. Ordrens id bruges i ordrelinietabellen, hvor album, antal og ordre skal angives.
Problemet er blot, at det som nævnt er databasen, der bestemmer denne værdi – det vil sige, at den ikke kendes i ASP-programmet. Værdien kan ikke hentes ved hjælp af en SQL-forespørgsel, da netop id’et er den eneste nøgle i ordretabellen. Den samme kunde kan sagtens afsende flere ordrer den samme dag, og hvordan kan man så vide, hvilket id der hører til den ordre, man netop har registreret?
Den bedste fremgangsmåde er tilsyneladende at vælge det højeste id, og bruge dette. Denne fremgangsmåde er desværre ikke helt sikker. Hvis der er flere brugere på web-stedet samtidigt, kan man ikke være sikker på, hvilken bruger der har fået det højeste ordrenummer. Denne problematik er imidlertid blevet beskrevet tidligere, og her var løsningen at bruge Application.Lock. Dette er også løsningen i dette tilfælde. Ved at lave en lås på applikationsvariablerne sikres det, at der ikke er andre, der kan låse dem. Det vil sige, at to samtidige brugere på web-stedet ikke vil få lov til at oprette en ordre samtidigt. Dermed er det sikkert at antage, at det højeste ordrenummer er det aktuelle.
Herefter er der blot tilbage at registrere de enkelte ordrelinier, som er gemt i applikationsvariablene. Det skal dog kontrolleres, at der ikke bliver tilføjet ordrelinier med antallet 0 – dette angiver som nævnt tidligere, at albummet er fjernet fra indkøbskurven.
Som denne gennemgang har vist, er der tilfælde, hvor ordren ikke kan modtages. I disse tilfælde skal brugeren naturligvis have besked om det. Denne besked skal gives på en web-side, der selvfølgelig skal være designmæssigt magen til de øvrige sider på web-stedet. Hvis der skulle være en side for hver situation, ville der være en del gentagen kode. Derfor indeholder modtagelsessiden en metode, der viser resultatet til brugeren. Denne metode kan håndtere såvel fejlsituationer som en succesfuld modtagelse af ordren.
Kildeteksten til modtagelsessiden ser således ud:
<% @language=JavaScript %>
<!– #include file=”database.js” –>
<!– #include file=”string.js” –>
<%
OK = 0;
FORKERT_KODEORD = 1;
KUNDE_EKSISTERER = 2;
con = createDatabaseConnection();
// kontrollér først, om kunden er logget ind
id = -1;
if (Request.Cookies(“kundeid”) != “”) {
id = opdaterKunde(Request.Cookies(“kundeid”));
} else {
id = tilfojKunde();
}
// registrer ordren
Application.Lock();
con.execute(“INSERT INTO ordre (kunde, dato) VALUES (” + id + “, ” + toSqlDate(new Date()) +”)”);
res = con.execute(“SELECT id FROM ordre WHERE kunde=” + id + ” ORDER BY id DESC”);
ordrenummer = res.Fields(“id”);
Application.Unlock();
albumantal = Session(“albumantal”);
for (i = 0; i < albumantal; i++) {
sql = “INSERT INTO ordrelinie (album, antal, ordre) VALUES (“;
sql += Session(“album”+i);
sql += “, “;
sql += Session(“antal”+i);
sql += “, “;
sql += ordrenummer;
sql += “)”;
con.execute(sql);
}
printResult(OK);
function opdaterKunde(id) {
sql = “UPDATE kunde SET “;
sql += “Navn='” + Request.Form(“Navn”) + “‘, ”
sql += “Adresse='” + Request.Form(“Adresse”) + “‘, “;
sql += “Postnummer=” + Request.Form(“Postnummer”) + ” , “;
sql += “Postdistrikt='” + Request.Form(“By”) + “‘, “;
sql += “Email='” + Request.Form(“Email”) + “‘”;
sql += ” WHERE id=” + id;
con.execute(sql);
return id;
}
function tilfojKunde(id) {
// kontroller, at de to kodeord er ens
if (!strcmp(Request.Form(“kodeord1”),Request.Form(“kodeord2”))) {
printResult(FORKERT_KODEORD);
}
// kontrollér, at der ikke allerede eksisterer en kunde med den email-adresse
res = con.execute(“SELECT id FROM kunde WHERE email='” + Request.Form(“Email”) + “‘”);
if (!res.EOF) { // kunden eksisterer
printResult(KUNDE_EKSISTERER);
}
sql = “INSERT INTO kunde (Navn, Adresse, Postnummer, By, Email, Kodeord) VALUES (“;
sql += “‘” + Request.Form(“Navn”) + “‘, “;
sql += “‘” + Request.Form(“Adresse”) + “, “;
sql += Request.Form(“Postnummer”) + “, “;
sql += “‘” + Request.Form(“By”) + “‘, “;
sql += “‘” + Request.Form(“Email”) + “‘, “;
sql += “‘” + Request.Form(“Kodeord”) + “‘)”;
con.execute(sql);
res = con.execute(“SELECT id FROM kunde WHERE Email='” + Request.Form(“Email”) + “‘”);
return res.Fields(“id”);
}
function printResult(status) {
%>
<html>
<head>
<title>Compact Discount [Indkøbskurv]</title>
</head>
<!– #include file=”header.html” –>
<td>
<%
if (status == OK) {
%>
<h1>Ordrebekræftelse</h1>
Din ordre er nu blevet afsendt. Den har fået ordrenummer <%=ordrenummer%>. Opgiv venligst dette nummer, hvis du har spørgsmål angående din ordre.<p>
Eventuelle spørgsmål og kommentarer kan sendes til <a href=mailto:ordrer@compactdiscount.dk>ordrer@compactdiscount.dk</a>.
<p>
Tak fordi du handlede hos Compact Discount.
<p>
<%
} else if (status == FORKERT_KODEORD || status == KUNDE_EKSISTERER) {
%>
<h1>Fejl</h1>
Der opstod en fejl i forbindelse med afsendelse af din ordre. Din ordre er ikke afsendt!
<p>
<%
if (status == FORKERT_KODEORD) {
%>
De to indtastede kodeord var ikke ens. Hvis du vil registreres som kunde og blive genkendt, når du vender tilbage til Compact Discount, skal du vælge et kodeord og gentage dette på afsendelsessiden. Hvis du ikke vil registreres, skal du lade begge felter være blanke.
<p>
Klik <a href=afsend.asp>her</a> for at komme tilbage til afsendelssiden.
<%
} else {
%>
Der er allerede registreret en kunde med den angivne email-adresse (<%=Request.Form(“Email”)%>).
Hvis du har indtastet email-adressen korrekt, skal du <a href=login.asp>logge ind</a> ved at angive din email-adresse og dit kodeord. Hvis du ikke kan huske dit kodeord, kan du få det tilsendt i en email fra <a href=login.asp>log ind-siden</a>.
<p>
Hvis du vil indtaste en anden email-adresse, kan du gøre det på <a href=afsend.asp>afsendelsessiden</a>.
<%
}
}
%>
</td>
</tr>
</table>
</body>
</html>
<%
Response.End();
}
%>
Log ind-siden (login.asp)
Log ind-siden skal give brugeren mulighed for at tilkendegive, at vedkommende allerede er en registreret kunde, selvom der ikke er en cookie på maskinen. Dette kan være tilfældet, hvis brugeren bruger en anden maskine end vanligt, eller hvis brugeren har slettet sine cookies.
Hvis brugeren har glemt sit kodeord, kan han få dette tilsendt ved at angive sin email-adresse og markere feltet Send kodeord.
Figur 10.8. Log ind.
Når indholdet af formularen på log ind-siden indsendes, bliver siden checklogin.asp aktiveret. Denne side behandler log-in-proceduren.
Kildeteksten til login.asp ser således ud:
<% @Language=JavaScript %>
<!– #include file=”database.js” –>
<%
con = createDatabaseConnection();
%>
<html>
<head>
<title>Compact Discount [Log ind]</title>
</head>
<!– #include file=”header.html” –>
<td>
<h1>Log ind</h1>
Hvis du er en registreret kunde, kan du logge ind her på siden ved at indtaste din e-mail-adresse og dit kodeord. Du bliver automatisk registreret som kunde, første gang du bestiller hos os.
<p>
<form action=checklogin.asp method=post>
<table>
<tr>
<td>E-mail-adresse</td>
<td><input type=text name=email></td>
</tr>
<tr>
<td>Kodeord</td>
<td><input type=password name=kodeord></td>
</tr>
<tr>
<td> </td>
<td><input type=submit value=”Log ind”></td>
</tr>
</table>
</form>
</td>
</table>
</body>
</html>
Oversigten over mest solgte album (mestsolgt.asp)
En god inspiration til de, der ikke ved, hvad de skal købe, er en oversigt over de mest solgte album. Oversigten kan også være en kilde til at få flere besøgende på web-stedet, da nogle gerne vil følge med i, hvilke album der sælges for tiden.
Oversigtssiden er forholdsvis let at lave – den baseres på en SQL-forespørgsel, der udvælger de mest solgte album i rigtig rækkefølge – herefter behøver albummene blot at blive præsenteret for brugeren.
Kildeteksten til siden mestsolgt.asp ser således ud:
<% @Language=JavaScript %>
<!– #include file=”database.js” –>
<%
con = createDatabaseConnection();
%>
<html>
<head>
<title>Compact Discount [Mest solgte album]</title>
</head>
<!– #include file=”header.html” –>
<td>
<h1>Mest solgte album</h1>
På denne side kan du se en oversigt over de mest solgte album på Compact Discount. Listen er altid aktuel og opdateres, hver gang der placeres en ordre!
<p>
<ol>
<%
res = con.Execute(“SELECT Sum(Antal) AS TotalAntal, Album FROM Ordrelinie GROUP BY Album ORDER BY Sum(Antal) DESC”);
antal = 0;
while (!res.EOF) {
album = res.Fields(“Album”);
res2 = con.Execute(“SELECT Titel FROM album WHERE id = ” + album);
%>
<li><a href=info.asp?album=<%=album%>><%=res2.Fields(“Titel”)%></a></li>
<%
res.MoveNext();
antal++;
if (antal > 10) {
break;
}
}
%>
</ol>
</td>
</tr>
</table>
Søgesiden (search.asp)
Søgesiden kaldes, når brugeren foretager en søgning. Det kan ske på tre forskellige måder. Fritekstsøgning foretages, når brugeren indtaster et ord i søgefeltet på forsiden. Denne type søgning vil søge efter det pågældende ord i titler på såvel numre som album samt kunstnernavne.
Søgesiden kaldes også, når brugeren klikker på en kategori fra kategorioversigten – dette medfører en søgning på alle album i den pågældende kategori.
Den sidste søgemulighed er at klikke på et nummers kunstner på albuminformationssiden. Dette medfører en søgning på alle de album, der indeholder numre med den pågældende kunstner.
Alle disse former for søgning håndteres af den samme side for at give brugeren et ensartet søgeresultat uafhængigt af, hvilken søgning der foretages. Søgesiden er opbygget, så den adskiller kode, der er generel for alle søgeformer, fra kode der er specifik for en enkelt søgemetode.
De generelle elementer er eksempelvis udseendet af siden. Både opbygningen af siden og den måde, resultatet af søgningen præsenteres for brugeren på, er generel, og det er derfor den samme ASP-kode, der styrer disse elementer uafhængigt af søgeform. Ligegyldigt hvilken søgning, der foretages, skal brugeren præsenteres for navnene på de album, der opfylder søgekriterierne, samt albummenes kunstnere. Disse oplysninger skal naturligvis være henvisninger til yderligere oplysninger om de nævnte album.
Til gengæld er de SQL-forespørgsler, der skal foretages, meget specifikke, og der er derfor behov for tre forskellige programstumper til at definere disse.
Den første SQL-forespørgsel skal håndtere søgning på kunstnere – dette sker som nævnt, hvis man klikker på kunstnerens navn i albuminformationssiden. Parameteren til kunstnersøgningen er kunstner, og denne parameter angiver det unikke id, der identificerer kunstneren i databasen. Kunstnersøgning skal foretages både på album og numre – resultatet skal være de album, der har den pågældende kunstner som hovedkunstner, og de album, kunstneren har numre på. For at kunne foretage denne søgning, er det nødvendigt både at søge i album- og nummertabellerne. Derudover skal kunstnertabellen bruges for at kunne præsentere brugeren for kunstnerens navn. Da søgningen således skal kombinere flere forskellige tabeller, er der oprettet en forespørgsel (et view) i databasen. Denne forespørgsel kaldes kunstnersearch og er defineret således:
SELECT Album.Titel, Album.Kunstner, Nummer.Kunstner, Album.ID, Kunstner.Navn
FROM Kunstner INNER JOIN (Album INNER JOIN Nummer ON Album.ID = Nummer.Album) ON (Album.ID = Kunstner.ID) AND (Kunstner.ID = Nummer.Kunstner)
GROUP BY Album.Titel, Album.Kunstner, Nummer.Kunstner, Album.ID, Kunstner.Navn;
Den næste SQL-forespørgsel skal kunne søge på kategorier. Denne søgning skal på baggrund af et kategori-id, der gives med som parameter, kunne finde alle album i en bestemt kategori. Dette betyder, at der skal søges i album- og kunstnertabellerne. For at gøre denne søgning lettere er der oprettet en forespørgsel i databasen – denne forespørgsel har navnet kategorisearch og er defineret ved følgende SQL-forespørgsel:
SELECT Album.ID, Album.Titel, Kunstner.Navn, Album.Kategori
FROM Kunstner INNER JOIN Album ON Kunstner.ID = Album.Kunstner
GROUP BY Album.ID, Album.Titel, Kunstner.Navn, Album.Kategori;
Den sidste SQL-forespørgsel skal foretage fritekstsøgningen. Fritekstsøgningen skal foretages i album-, kunstner- og nummertabellerne, og derfor er der blevet oprettet en forespørgsel, der gør denne søgning lettere. Denne forespørgsel kaldes tekstsearch og kan beskrives ved denne SQL-forespørgsel:
SELECT Album.ID, Album.Titel, Kunstner.Navn, Nummer.Titel
FROM Kunstner INNER JOIN (Album INNER JOIN Nummer ON Album.ID = Nummer.Album) ON (Kunstner.ID = Nummer.Kunstner) AND (Kunstner.ID = Album.Kunstner)
GROUP BY Album.ID, Album.Titel, Kunstner.Navn, Nummer.Titel;
Efter udførslen af den korrekte SQL-forespørgsel er der kun tilbage at præsentere søgeresultatet. Kildeteksten til hele search.asp ser således ud:
<% @Language=JavaScript %>
<!– #include file=”database.js” –>
<%
con = createDatabaseConnection();
garbage = Request.QueryString(“xxx”);
%>
<html>
<head>
<title>Compact Discount [Søgeresultat]</title>
</head>
<!– #include file=”header.html” –>
<td>
<%
sql = “”;
if (Request.QueryString(“kunstner”) != garbage) {
// Søgning på kunstner fra en anden side.
// Kunstnerens id er angivet i kunstner.
// Dette er det eneste søgekriterium.
// Find de album, kunstneren har numre på.
kunstnerid = Request.QueryString(“kunstner”);
sql = “SELECT * FROM kunstnersearch WHERE nummer.kunstner = “;
sql += kunstnerid;
}
if (Request.QueryString(“kategori”) != garbage) {
// Søgning på kategori. Kategori angiver ikke kategoriens
// navn, men dens id. Dette er det eneste søgekriterium.
// Find alle album i denne kategori.
kategori = Request.QueryString(“kategori”);
sql = “SELECT * FROM kategorisearch WHERE kategori= ” + kategori;
}
if (Request.QueryString(“tekst”) != garbage) {
// søgning på fritekst (fra hovedsiden).
// søg på kunstner, nummer- og albumtitel
tekst = Request.QueryString(“tekst”);
sql = “SELECT DISTINCT album.titel, album.id, kunstner.navn FROM tekstsearch WHERE nummer.titel LIKE ‘%” + tekst + “%’ OR kunstner.navn LIKE ‘%” + tekst + “%’ OR album.titel LIKE ‘%” + tekst + “%'”;
}
res = con.Execute(sql);
%>
<h1>Søgeresultat</h1>
<%
if (res.EOF) {
%>
Der er ingen album, der opfylder søgekriterierne.
</td>
</tr>
</table>
</body>
</html>
<%
Response.End();
}
%>
Der er fundet følgende album, der opfylder søgekriterierne:
<p>
<%
while (!res.EOF) {
%>
<a href=info.asp?album=<%=res.Fields(“id”)%>><%=res.Fields(“Navn”)%>: <%=res.Fields(“Titel”)%></a><br>
<%
res.Move(1);
}
%>
</td>
</tr>
</table>
</body>
</html>
Afrunding
I dette kapitel er der blevet givet et større eksempel på, hvordan man kan benytte ASP til at lave et web-sted med e-handel. Selvom der er en lang række aspekter af komplet udvikling af web-steder, der ikke er medtaget i dette eksempel, er der benyttet en lang række af de teknikker, som er blevet beskrevet tidligere i denne bog.
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







