Entwickeln von Windows DNA-Anwendungen
mit dem COMCodebook – Teil 8
Yair Alan Griver
Übersetzt von Mathias Gronau
Teil 8 – Kodieren der Datenpräsentation mit einem serverseitigen
Script
In diesem Abschnitt beschäftigen wir uns
mit den Active Server Pages (ASP) und Dynamic HTML (DHTML) speziell im Internet Explorer. Die MSDN Library ist eine
hervorragende Referenz für DHTML und
das Dokumenten-Objekt-Modells des IE.
Wir werden auch einige Objekte des IIS Objekt Model kennen lernen. Zusätzliche Informationen finden sie in der MSDN Library unter dem Punkt Internet Information
Services SDK im Abschnitt Platform
SDK/Web Services.
Überblick über das Objektmodell für
ASP-Anwendungen
Bevor wir mit der Programmierung der Active Server Pages beginnen, lassen Sie uns
einen Blick auf die IIS-Objekte werfen, die
wir in unserer Anwendung einsetzen. Ich
werde sie hier nicht alle behandeln. Weitere
Informationen finden Sie in der MSDN
Library.
Das Server-Objekt
Das Server-Objekt bietet uns den Zugriff
auf Methoden und Eigenschaften auf dem
Server. Die meisten dieser Methoden und
Eigenschaften dienen als Hilfsfunktionen.
Wir wollen uns hier nur mit der Methode
CreateObject() beschäftigen, die unsere
Komponenten der mittleren Schicht instanziiert. Auf diese Weise erhalten wir eine Referenz auf unseren Ressource-Manager Attorney Note über eine Active Server Page:
12-19 Entwickeln von Windows DNA/Teil 8
Set obj =
Server.CreateObject("AttResMgr.Attorne
yNote")
Das Session-Objekt
Wahrscheinlich benötigen wir dieses Objekt
in unserer Beispielanwendung nicht; ich
möchte es aber doch erwähnen, da es sehr
wichtig ist. Sie können das Session-Objekt
zur Speicherung von Informationen einsetzen, die für eine bestimmte AnwenderSitzung benötigt werden. Wenn ein Anwender sich innerhalb einer Site bewegt, können
Variablen im Session-Objekt gespeichert
werden, die für die gesamte Session des Anwenders gelten. Sie können sich diese Variablen als für die gesamte Anwender-Sitzung
global vorstellen. Das Objekt besteht so lange wie die Session des Anwenders, als Vorgabe gelten 20 Minuten nach der letzten Anfrage des Anwenders. Anders gesagt: die Sitzung wird nach 20 Minuten der Inaktivität
beendet. Eine übliche Anwendung des Session-Objekts ist die Speicherung von Informationen über den Anwender. Beispielsweise können Sie den realen Namen des Anwenders speichern, um ihn auf untergeordneten Seiten anzuzeigen.
Session("UserFullName") = "Joe Shmoe"
Anschließend wollen Sie auf einer anderen
Seite der Anwendung den Namen anzeigen.
Sie schreiben einfach irgendetwas wie:
Hello <% =Session("UserFullName")%>!
Welcome back to this awesome web site!
Das Abfrage-Objekt
Das Abfrageobjekt empfängt die Werte, die
der Browser des Clients via HTTP-Request
FoxX Professional
Seite 1
an den Server gesandt hat. Der HTTPRequest umfasst viele Komponenten: Werte
von Formularen, Cookies, Abfragestrings
und die Umgebungsvariablen des Servers.
Das Abfrageobjekt verpackt den HTTPRequest in einfach anzusprechende Collections. Die beiden Collections, die wir benutzen werden, sind die Collection Form und
die Collection QueryString.
Die Collection Form empfängt die Werte
der Elemente des Formulars, die an den
HTTP-Request mit Hilfe der Methode
POST gesendet wurden. Erinnern Sie sich
noch an das Formular für die Suche nach
den Anwälten? Wenn der Anwender das
Formular abschickt, wird es an AttorneyList.asp gesandt. Wenn wir die Collection
Form auf AttorneyList.asp einsetzen, enthält
es die Elemente des Suchformulars, also alles zwischen den Tags <FORM> und
</FORM>. In einem HTML-Dokument
kann auch mehr als ein Formular vorhanden
sein. Sie können dir Formulare in der Collection wie die Elemente referenziern.
Um den Wert des Textfeldes lastname zu
erhalten würden wir schreiben:
<% cLastName =
Request.Form("lastname") %>
Die Collection QueryString empfängt die
Werte
der
Variablen
im
HTTPAbfragestring. Der HTTP-Abfragestring
wird durch die Werte gebildet, die auf das
Fragezeichen (?) folgen. Der Abfragestring
kann durch viele unterschiedliche Prozesse
erzeugt werden. Beispielsweise erzeugt ein
Hyperlink
<A HREF= "Attorney.asp?ID=12345">Berg,
James</A>
eine Variable mit dem Namen ID und dem
Wert 12345.
Um in unserem Beispiel den Wert von
QueryString auf dem Formular Attorney.asp
zu erhalten würden wir folgendes schreiben:
<% cID = Request.QueryString("ID") %>
12-19 Entwickeln von Windows DNA/Teil 8
Das Response-Objekt
Mit dem Response-Objekt können Sie Ausgaben an den Client senden. Das Objekt
enthält viele Methoden und Eigenschaften.
Ich behandle hier drei davon: die Methoden
Write und Redirect und die Eigenschaft Expires. Die Methode Write schreibt einen angegebenen String in die aktuelle HTTPAusgabe. Das ist mit dem Begriff „Daten an
den Browser senden“ gemeint.
<% Response.Write("<td>This is a
column of a table</td>")%>
Sie können auch Variablen senden:
<% Response.Write(cLastName)%>
Das ist das Gleiche wie:
<% =(cLastName)%>
Die Methode Redirect benötigen wir, wenn
wir den Browser auf eine andere URL umlenken wollen. Wir benötigen das häufig,
wenn wir die Anfrage eines Anwenders z. B.
auf der Seite processAttorney.asp abarbeiten
und den Browser auf die Seite Attorney.asp
zurückleiten wollen.
<% Response.Redirect("Attorney.asp")
%>
Jetzt möchte ich noch kurz auf die Eigenschaft Expires eingehen. Sie enthält die Zeitspanne bis eine Seite, die im Browser zwischengespeichert ist, ungültig wird. Wenn
der Anwender vor diesem Zeitpunkt wieder
auf die Seite geht, wird die zwischengespeicherte Seite angezeigt. Auf diese Weise kann
es möglich sein, dass der Anwender alte Daten angezeigt bekommt, wenn wir nicht dafür sorgen, dass die Seite sofort ungültig
wird.
<% Response.Expires = -1 %>
Damit wird der Browser angewiesen, die Seite jedes Mal vom Server abzurufen. Mit einem solchen Code sollten wir aber vorsichtig umgehen, da er vermehrte Zugriffe auf
den Server hervorruft. Daher sollte er nicht
in statischen Seiten eingesetzt werden.
FoxX Professional
Seite 2
Jetzt haben wir alle Teile des Objektmodells
kennen gelernt, das wir für unsere Anwendung einsetzen werden. Lassen Sie uns jetzt
unser virtuelles Verzeichnis im IIS einrichten.
Einrichten des virtuellen Verzeichnisses
Wir werden unsere Active Server Pages im
Verzeichnis \Interface unterhalb des Verzeichnisses \AttorneyApp speichern. Dieses
Verzeichnis müssen wir als virtuelles Webverzeichnis einrichten. Öffnen Sie den Internet Service Manager. Wenn Sie Windows
NT mit dem Option Pack 4 einsetzen finden
Sie ihn in Start/Programs/Windows NT
Option Pack 4/Personal Web Server (oder
Internet Information Services unter NT Server)/Internet Service Manager. Damit öffnen Sie die Microsoft Management Console
(MMC):
12-19 Entwickeln von Windows DNA/Teil 8
Klicken Sie mit der rechten Maustaste auf
„Default Web Site“ und wählen Sie im Kontextmenü „New/Virtual Directory“. Der
Assistent für das virtuelle Verzeichnis erscheint. Als Erstes müssen Sie den Namen
des virtuellen Verzeichnisses angeben. Dieses Verzeichnis müssen wir später im Browser eingeben, wenn wir zu unserer Site navigieren. Geben Sie „attapp“ ein und klicken
Sie auf „next“. Anschließend müssen Sie angeben, welches physikalische Verzeichnis
benutzt werden soll. Dies ist unser Verzeichnis
Flash\Codebook\Attorney
App\Interface. Sie können das Verzeichnis
visuell auswählen, indem sie auf die Schaltfläche „Browse“ klicken. Die letzte Seite des
Assistenten fragt nach den Rechten, die Sie
für das Verzeichnis vergeben wollen. Stellen
Sie sicher, dass die ersten drei Optionen aktiviert sind: Allow Read Access, Allow Script
Access und Allow Execute Access. Klicken
Sie auf die Schaltfläche „Finish“ und alles ist
eingerichtet. Das virtuelle Verzeichnis sollte
im linken Fenster der MMC und die Dateiliste im rechten Fenster
erscheinen,
etwa so wie in
unserer Abbildung. Jetzt
sind wir bereit,
unsere
Active Server
Pages zu programmieren.
FoxX Professional
Seite 3
Die Anwaltsliste (Suchergebnis)
Öffnen wir zunächst unsere Anwaltsliste in
Visual InterDev. Sie finden die Datei in
FLASH\Codedook\AttorneyApp\
Interface\AttorneyList.asp. Sie werden feststellen, dass ich bereits begonnen habe den
ASP-Code zu schreiben, der die RessourceManager in der mittleren Schicht instanziiert.
können wir auf die Felder und deren Werte
mit der Collection Request.Form zugreifen.
Da es sich bei der Search Criteria Ressource
oFilter um einen ADO-Recordset handelt,
greifen wir auf das Objekt oFilter mit den
Methoden des ADO-Recordset zu. In diesem Fall benutzen wir die Methode Find.
Mit der Methode Find durchsuchen wir die
Datensätze des Recordset nach dem gesuchten Namen. Anschließend setzen wir den
Value entsprechend des Wertes in unserer
Collection Form.
Filter.Find "Name =
'lastname'",,1,1
In den ersten Zeilen werden Variablen deklariert und es wird eine Referenz auf den
Ressource-Manager Attorney Note in der
Variablen obj erstellt. Anschließend lassen
wir uns vom Ressource-Manager eine Search
Criteria Ressource in Form eines Recordset
liefern. Sie sollten sich daran erinnern, wie
wir unsere Ressource erweitert haben, um
auch den Nachnamen der Anwälte geliefert
zu bekommen. Wir sollten jetzt also alle
Felder der Tabelle mit den Bemerkungen zu
den Anwälten erhalten, zuzüglich des Nachnamens des Anwalts.
Empfangen von Daten mit der Search
Criteria Ressource
Ich habe einen Abschnitt leer gelassen, in
dem wir den Code schreiben werden, der
unsere Search Criteria Ressource erstellt und
ihr die Suchkriterien des Anwenders übergibt. Da das vom Anwender ausgefüllte
Suchformular an diese Seite gesandt wurde,
12-19 Entwickeln von Windows DNA/Teil 8
Diese Codezeile führt eine
Suche vom Anfang des Recordset an nach einem Datensatz durch, in dem das
Feld Name den gleichen
Wert wie „lastname“ hat.
Diese Abfrage unterscheidet
nicht zwischen Groß- und
Kleinschreibung, so dass wir
auch Namen finden, die
durchgehend groß geschrieben sind. Wenn wir den Datensatz gefunden haben, positioniert ADO den Datensatzzeiger auf den
Datensatz und wir ändern den Wert folgendermaßen:
oFilter("Value") =
Request.Form("LastName")
Das Gleiche machen wir auch mit den anderen zwei Feldern. Unser Code für das Einfügen der Werte sollte in etwa so aussehen:
oFilter.Find "Name = 'lastname'",,1,1
oFilter("Value") =
Request.Form("LastName")
oFilter.Find "Name = 'note_name'",,1,1
oFilter("Value") =
Request.Form("Note_Name")
oFilter.Find "Name = 'note_text'",,1,1
oFilter("Value") =
Request.Form("note_text")
Jetzt wollen wir die Liste noch ordnen. Ich
habe mir gedacht, dass eine Sortierung nach
den Zeitpunkten, an denen die Bemerkungen geschrieben wurden, sinnvoll wäre. In
diesem Fall schreiben wir diesen Code:
FoxX Professional
Seite 4
oFilter.Find "Name = 'note_time'",,1,1
oFilter("Order") = "1"
oFilter("Option") = "DESC"
virtuelle Verzeichnis. Geben Sie in der
Adressleiste beispielsweise ein:
Die nächste Zeile Code sendet die Ressource in den Ressource-Manager, der einen
Recordset mit den aktuellen Daten zurücksendet, die unseren Suchkriterien entsprechen.
Sie sollten im Browser jetzt das Suchformular sehen. Geben Sie das Suchkriterium ein,
z. B. einen Nachnamen, der mit „K“ beginnt. Klicken Sie auf die Schaltfläche „Search“. Sie sollten dann folgendes im Browser
sehen:
Set rs = obj.getAttorneyNote
BySearchCriteria( oFilter )
Zum Abschluss müssen Sie sich
nur noch erinnern, dass Sie Ihre
Objektreferenzen so früh wie
möglich wieder freigeben, indem
Sie deren Werte löschen.
Set obj = Nothing
Set oFilter = Nothing
Anzeigen der Daten
Nachdem wir den Recordset in
der Variablen “rs” gespeichert haben, ist es
einfach die HTML-Tabelle mit den Daten
auf der Seite zu generieren.
<% Do While Not rs.EOF
Response.Write("<tr><td><a
href='cntAttorney.asp?ID=" &
Trim(rs("attorney_id")) & "'>" &
rs("FullName")& "</a></td>")
Response.Write("<td ><a
href=""Javascript:openNote('AttorneyNo
te.asp?Action=List&ID=" &
Trim(rs("attnote_id")) & "')"">" &
rs("note_time") & "</a></td>")
Das Formular mit den Bemerkungen
Response.Write("<td>" &
rs("note_name") & "</td></tr>")
rs.MoveNext
Loop
Set rs = Nothing
Empfangen der Daten
%>
Beachten Sie, dass der Code, der die Hyperlinks generiert, während der gleichen Zeit
die Daten satzweise in einer Schleife ausgibt.
Für die Generierung des Popup für die Bemerkungen werden wir etwas JavaScript einsetzen, das einen zweiten kleineren Browser
öffnet. Dazu aber später mehr.
Jetzt ist es an der Zeit, den Anfang unserer
Anwendung auszuführen. Wechseln Sie mit
Ihrem Browser in das von Ihnen erstellte
12-19 Entwickeln von Windows DNA/Teil 8
Das war doch gar nicht so schwierig. Sie
können mit der rechten Maustaste auf den
Browser klicken um sich den HTML-Code
anzusehen, der auf dem Server generiert und
an den Client gesendet wurde. Spielen Sie
ein Wenig mit den unterschiedlichen Suchkriterien und Sortiermöglichkeiten in der
Seite AttorneyList.asp herum, um ein Gefühl
dafür zu bekommen, wie das Programm arbeitet.
Wenn der Anwender auf das Erstellungsdatum der Bemerkung in der Liste klickt, wird
der Browser in dieses Formular umgelenkt.
Sie sollten bemerken, dass der generierte
Hyperlink sowohl den Namen des Formulars als auch den Abfragestring enthält, der
benötigt wird, wenn der Anwender auf das
Formular kommt. Klicken Sie mit der rechten Maustaste in den Browser während Sie
sich im Fenster mit den Abfrageergebnissen
befinden und lassen Sie sich die Sourcen anzeigen:
FoxX Professional
Seite 5
<a
href='Javascript:openNote("AttorneyNot
e.asp?Action=List&ID=001")'>3/9/00
10:40:20 AM</a>
Die JavaScript-Funktion openNote() finden
Sie im Unterverzeichnis jscripts in der Datei
notelist.js. Wir werden die Javascripts später
noch behandeln, ich wollte jetzt nur bemerken, dass dies die Funktion ist, die ausgeführt wird, wenn der Anwender auf einen
Hyperlink klickt. Die Funktion öffnet ein
weiteres kleineres Browserfenster und lenkt
es auf AttorneyNote.asp. Öffnen Sie AttorneyNote.asp in Visual InterDev. Die ersten
Zeilen empfangen die Daten vom
QueryString.
Wir suchen nach einer ID, einem Fremdschlüssel und/oder nach einer Variablen
„Action“. Diese drei Werte können vorhanden sein; es können aber auch ein oder zwei
Werte fehlen. Wenn Sie nach einer Variablen
in QueryString suchen, die nicht vorhanden
ist, wird ein leerer String zurückgegeben.
Enthält die Variable Action den Wert „List“,
werden die Schaltflächen „Add“ und „Delete“ nicht auf dem Formular angezeigt. Das
bedeutet, dass wir dem Anwender nur das
Speichern und den Abbruch erlauben, wenn
er
von
den
Suchergebnissen/AttorneyList.asp) kommt. Kommt er
dagegen vom Formular Attorney erhält er
sämtliche Möglichkeiten.
Set rsNote =
objNote.getAttorneyNotebyID(cID)
Damit wird einfach ein ADO-Recordset an
rsNote zurückgegeben.
Die HTML-Kontrollelemente mit unseren Daten füllen
Der Rest des Formulars benutzt die Werte
in rsNote, um Variablen zu setzen und die
Bemerkung im dafür vorgesehenen Bereich
anzuzeigen. Um Daten in einem HTMLEingabefeld zu platzieren, weisen wir dem
Attribut Value den Wert unserer Variablen
oder des Feldwert des Recordset zu. In unserem Fall belegen wir zum Ändern die Variable cDesc mit dem Wert von rxNote(„note_name“) und benutzen die Variable bei
der HTML-Eingabe so:
<input type="text" name="Subject"
size="20" maxlength="20" value="<%
=cDesc %>">
Werfen Sie noch einen Blick darauf, wie wir
die anderen Kontrollelemente des Formulars
mit Daten füllen. Anschließend lassen Sie
das Formular erneut ablaufen und stellen sicher, dass es arbeitet. Wählen Sie im Browser eine Bemerkung aus der Liste aus. Sie
sollten dann eine Darstellung wie diese sehen:
Die nächste Codezeile ruft die mittlere
Schicht auf und instanziiert den RessourceManager AttorneyNote.
Set objNote =
Server.CreateObject("AttResMgr.Attorne
yNote")
Als Nächstes muss ein neuer Datensatz angelegt oder ein existierender empfangen
werden. Welche Aktion auszuführen ist entscheiden wir daran, ob wir in unserem
QueryString eine ID haben oder nicht. Außerdem benötigen wir zumindest eine ID
zum Anlegen einer Bemerkung. Am Ende
enthält unser Recordset entweder einen leeren Datensatz oder einen mit Daten gefüllten. Kommt der Anwender von der Anwaltsliste, ändern wir einen Datensatz, so
dass die folgende Zeile ausgeführt wird:
12-19 Entwickeln von Windows DNA/Teil 8
Sie beginnen jetzt zu erkennen, wie einfach
die ganze Sache ist, oder? Unsere Komponenten erledigen die gesamte Kommunikation mit der Datenbank und übergeben uns
Ressourcen in Form von ADO-Recordsets.
FoxX Professional
Seite 6
Alles was uns in der Präsentationsschicht
Sorgen bereiten kann, ist das Aussehen der
Bildschirmmasken und das Anzeigen der
Daten für den und die Eingabe der Daten
vom Anwender.
Das Formular Attorney
Nachdem nun unser Formular mit den Bemerkungen arbeitet, wollen wir auch unser
Formular Attorney zum Laufen bringen.
Wenn der Anwender einen der Anwaltsnamen auswählt, wird er an das Formular Attorney weitergereicht, auf dem ein „Grid“
der Bemerkungen angezeigt wird. Für die
Anzeige der Daten werden drei ASPFormulare aufgerufen. Das erste Formular
ist Attorney.asp.
Empfangen der Daten aus der mittleren Schicht
Der Empfang der Daten aus der mittleren
Schicht ist in diesem Formular sehr einfach,
da wir nur prüfen müssen, ob QueryString
eine ID enthält oder nicht. Anders als beim
Formular mit den Bemerkungen müssen wir
uns nicht um Fremdschlüssel kümmern.
Öffnen wir Attorney.asp in Visual InterDev.
cID = Trim(Request.Querystring("ID"))
cAction =
Trim(Request.Querystring("Action"))
Wir suchen lediglich nach einer ID
und/oder einer Variablen Action. Die ID
teilt uns den Primärschlüssel des Anwalts
mit.
Die nächste Zeile ruft die mittlere Schicht
auf und instanziiert den Ressource-Manager
Attorney.
Set objAttorney =
Server.CreateObject("AttResMgr.Attorne
y")
Sie bemerken, dass dieses Formular dem mit
den Bemerkungen weitgehend entspricht.
Eigentlich ist es sogar noch einfacher. Wie
beim Formular Note müssen wir als Nächstes entweder einen neuen Datensatz anlegen
oder einen existierenden empfangen.
If cID = "" Then
'Adding
12-19 Entwickeln von Windows DNA/Teil 8
cAction = "Add"
'Tell the resource manager to
give me an empty recordset
Set rsAttorney =
objAttorney.getEmptyResource()
else
'Editing
'Tell the resource manager to
retrieve the Attorney record
Set rsAttorney =
objAttorney.getAttorneyByID(cID)
End If
'Say bu-bye to the resource manager.
It's done with its job.
Set objAttorney = Nothing
Dieses Formular füllt keine Vorgabewerte
aus, so dass auf den Recordset rsAttorney
für die Platzierung der Werte direkt zugegriffen werden kann:
<input type="text" name="lastname"
size="20" maxlength="20"
value="<%=rsAttorney("LastName")%>">
Werfen Sie einen Blick auf den Fuß des
Formulars. Sie bemerken, dass dort eine
verborgene Variable vorhanden ist. In dieser
Variablen wird die ID des Datensatzes gehalten, den wir ändern. Erinnern Sie sich,
dass HTML-Eingaben über das Attribut
„type“ verfügen, das wir auf „hidden“ setzen
können. Dadurch entsteht folgender
HTML-Code:
<input type="hidden" name="AttorneyID"
value="<%=cID%>">
Wir benutzen versteckte Felder, um Informationen von einem Formular zu einem anderen zu übergeben. In unserem Fall wird
das Formular processAttorney.asp aufgerufen, wenn das Formular Attorney.asp beendet wird. Wir müssen uns den Primärschlüssel des Datensatzes merken, um ihn speichern zu können. Versteckte Felder werden
auf dem HTML-Formular nicht angezeigt
und die Werte können nicht geändert werden, aber man kann sie über die Option
„Quelltext anzeigen“ des Browsers einsehen.
Das bedeutet, Sie sollten dort nie Passwörter
oder andere Informationen speichern, die
der Anwender nicht sehen soll. Die Speicherung der Primärschlüssel ist kein Sicherheitsproblem, da Anwender sich nur selten
Gedanken um die Primärschlüssel machen.
FoxX Professional
Seite 7
Das Formular processAttorney
Wenn der Anwender eine der Schaltflächen
im oberen Teil des Formulars Attorney anklickt werden alle Informationen zwischen
den Tags <FORM> und </FORM> an das
Formular processAttorney.asp gesendet.
Öffnen wir das Formular jetzt in Visual InterDev.
Wie Sie sehen, ist die erste Aktion die Prüfung, auf welche Schaltfläche geklickt wurde.
Die Namen unserer Schaltflächen sind alle
gleich: cmdAction. Daher können wir in der
Collection Request.Form() den Wert der
Schaltfläche cmdAction abfragen:
Dim cID, cAction
cID = Trim(Request.Form("AttorneyID"))
cAction = Request.Form("cmdAction")
Dieses Formular verarbeitet keinerlei Vorgabewerte, so dass beim Platzieren der Werte in die Eingabefelder direkt auf den Recordset rsAttorney zugegriffen werden kann.
Beachten Sie, dass wir auch den Wert des
versteckten Feldes AttorneyID empfangen.
Wenn die ID leer ist wissen wir, dass wir einen neuen Datensatz hinzufügen müssen,
andernfalls wird ein Datensatz geändert. Der
nächste Codeabschnitt ist eine CASEAnweisung, mit der die Aktionen in Abhängigkeit von der Schaltfläche cmdAction, die
der Anwender angeklickt hat, ausgeführt
wird.
Speichern des Datensatzes
Ich habe den Code zum Speichern der Daten in dem Formular für Sie bereits geschrieben. Später in diesem Abschnitt werden Sie den Code zum Speichern der Daten
des Formulars mit den Bemerkungen selbst
schreiben. Sehen wir uns kurz den Code von
processAttorney.asp an.
Zunächst einmal müssen wir den aktuellen
Datensatz empfangen oder die Daten für einen neuen Satz erfassen. Das bedeutet, dass
wir GetAttorneyByID() aufrufen und dabei
cID übergeben oder wir rufen GetEmptyRessource() auf und erhalten einen leeren
ADO-Recordset.
12-19 Entwickeln von Windows DNA/Teil 8
set objAttorney =
Server.CreateObject("AttResMgr.Attorne
y")
if cID <> "" then
set rs =
objAttorney.getAttorneyByID(cID) 'Came
from Edit
else
set rs =
objAttorney.getEmptyResource() 'Came
From Add
end if
set objAttorney = Nothing
Nun haben wir eine Ressource. Als Nächstes
müssen wir die Ressource mit den Werten
des Formulars füllen, die der Anwender eingegeben hat. Sämtliche Felder, die sich zwischen des Tags <FORM> und </FORM>
befinden, werden in eine Collection Form
gepackt. Die Namen der Felder innerhalb
der Collection richten sich nach den Namensattributen, die Sie Ihren HTMLEingaben gegeben haben. Hier die Zeile, mit
der wir den Nachnamen des Anwalts einstellen, den der Anwender eingegeben hat:
rs("LastName") =
Trim(Request.Form("LastName"))
Trim() entfernt am Anfang und am Ende
der Zeichenkette eventuell vorhandene
Leerzeichen. Das Attribut Name der Eingabe in Attorney.asp wird auf lastname eingestellt. Auf diese Weise referenzieren wir den
Nachnamen in der Collection des Formulars, die zwischen Groß- und Kleinschreibung unterscheidet. Sehen Sie sich an, wie
die anderen Felder der Ressource den Werten der Collection des Formulars zugeordnet
werden.
Nachdem wir unsere Ressource mit den
Werten des Formulars gefüllt haben, sind
wir bereit sie in der mittleren Schicht zu
speichern. Wird eine Ressource in der mittleren Schicht gespeichert, müssen auf dem
Client einige Schritte aufgerufen werden, um
die Daten von der Präsentationsschicht zu
den Ressource-Managern zu begleiten. Sie
erinnern sich: um die Speicherung mehrerer
Ressourcen zur gleichen Zeit zu erleichtern,
beispielsweise in einem Szenario, in dem
auch Daten in einer untergeordneten Tabelle
gespeichert werden müssen, können wir einen Ressource Manager Controller (RMC)
benutzen. Dieses Verarbeitungsobjekt dient
als Kontrollobjekt für die Ressource-
FoxX Professional
Seite 8
Manager, in denen wir Daten ablegen wollen. Aus diesem Grunde muss der RMC die
Ressource-Manager und deren Relationen
untereinander kennen, die in dem Speicherungsprozess angesprochen werden. Diese
Information stellen wir in Form eines XMLStream ein. Diesen XML-String senden wir
an die Methode Set_Up_Environment() des
RMC, die anschließend dem RMC mitteilt,
welche Ressource-Manager instanziiert werden müssen und richtet die Relationen zwischen ihnen in einem internen Array des
RMC ein.
Sehen wir uns an, wie das Save-XML aussehen
kann:
cXML
cXML
cXML
cXML
cXML
cXML
cXML
cXML
cXML
cXML
cXML
cXML
cXML
cXML
cXML
cXML
cXML
cXML
cXML
cXML
cXML
cXML
cXML
cXML
cXML
cXML
cXML
cXML
cXML
cXML
cXML
cXML
cXML
cXML
cXML
cXML
cXML
cXML
cXML
cXML
cXML
cXML
cXML
cXML
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
"<TABLE><STRUCTURE>"
cXML & "<FIELDDEF>"
cXML & "<FIELDNAME>CRMPNAME</FIELDNAME>"
cXML & "<FIELDTYPE>C</FIELDTYPE>"
cXML & "<FIELDLENGTH>30</FIELDLENGTH>"
cXML & "<FIELDDECIMALS>0</FIELDDECIMALS>"
cXML & "</FIELDDEF>"
cXML & "<FIELDDEF>"
cXML & "<FIELDNAME>CRMCLSNAME</FIELDNAME>"
cXML & "<FIELDTYPE>C</FIELDTYPE>"
cXML & "<FIELDLENGTH>30</FIELDLENGTH>"
cXML & "<FIELDDECIMALS>0</FIELDDECIMALS>"
cXML & "</FIELDDEF>"
cXML & "<FIELDDEF>"
cXML & "<FIELDNAME>CPARNTNAME</FIELDNAME>"
cXML & "<FIELDTYPE>C</FIELDTYPE>"
cXML & "<FIELDLENGTH>30</FIELDLENGTH>"
cXML & "<FIELDDECIMALS>0</FIELDDECIMALS>"
cXML & "</FIELDDEF>"
cXML & "<FIELDDEF>"
cXML & "<FIELDNAME>NSAVEORDER</FIELDNAME>"
cXML & "<FIELDTYPE>N</FIELDTYPE>"
cXML & "<FIELDLENGTH>2</FIELDLENGTH>"
cXML & "<FIELDDECIMALS>0</FIELDDECIMALS>"
cXML & "</FIELDDEF>"
cXML & "<FIELDDEF>"
cXML & "<FIELDNAME>CPARNTRELA</FIELDNAME>"
cXML & "<FIELDTYPE>C</FIELDTYPE>"
cXML & "<FIELDLENGTH>200</FIELDLENGTH>"
cXML & "<FIELDDECIMALS>0</FIELDDECIMALS>"
cXML & "</FIELDDEF>"
cXML & "<FIELDDEF>"
cXML & "<FIELDNAME>CPARNTRELA</FIELDNAME>"
cXML & "<FIELDTYPE>C</FIELDTYPE>"
cXML & "<FIELDLENGTH>200</FIELDLENGTH>"
cXML & "<FIELDDECIMALS>0</FIELDDECIMALS>"
cXML & "</FIELDDEF>"
cXML & "<FIELDDEF>"
cXML & "<FIELDNAME>CKEYFIELD</FIELDNAME>"
cXML & "<FIELDTYPE>C</FIELDTYPE>"
cXML & "<FIELDLENGTH>20</FIELDLENGTH>"
cXML & "<FIELDDECIMALS>0</FIELDDECIMALS>"
cXML & "</FIELDDEF>"
cXML & "</STRUCTURE>"
cXML
cXML
cXML
cXML
cXML
cXML
cXML
cXML
cXML
=
=
=
=
=
=
=
=
=
cXML
cXML
cXML
cXML
cXML
cXML
cXML
cXML
cXML
&
&
&
&
&
&
&
&
&
"<ROW>"
"<CRMPNAME>oAttorney</CRMPNAME>"
"<CRMCLSNAME>AttResMgr.Attorney</CRMCLSNAME>"
"<CPARNTNAME></CPARNTNAME>"
"<NSAVEORDER>0.00</NSAVEORDER>"
"<CPARNTRELA></CPARNTRELA>"
"<LPRIMARY>T</LPRIMARY>"
"<CKEYFIELD>Attorney_ID</CKEYFIELD>"
"</ROW>"
cXML = cXML & "</TABLE>"
Den XML-Stream Save kann man in zwei
Teile einteilen: die Tabellenstruktur (in grau)
12-19 Entwickeln von Windows DNA/Teil 8
und die Datendefinition (in Schwarz). Der
erste Teil beschreibt die Struktur der Daten,
FoxX Professional
Seite 9
die wir an den RMController senden. Diese
Definition der Tabellenstruktur ist optional.
Wenn Sie die Definition nicht an den
RMController senden, fügt die mittlere
Schicht sie Ihrem XML-Stream automatisch
hinzu. Der zweite Teil sind die aktuellen Daten. Wenn Sie sich den XML-String Attorney ansehen, werden Sie bemerken, dass er
nur die Daten, nicht aber die Tabellendefinition enthält. Da wir nur in eine einzelne Tabelle speichern haben wir nur einen Datensatz. Betrachten wir die Elemente des XMLStream einzeln:
Feld
Inhalt
<TABLE>
Dieses Paar Tag/Endtag definiert die Umgebung eines Ressource Manager Proxy
<STRUCTURE>
nal)
(optio-
Dieses Paar Tag/Endtag definiert die Struktur der Daten, die wir senden wollen
<FIELDDEF>
nal)
(optio-
Dieses Paar Tag/Endtag definiert ein einzelnes Feld
<FIELDNAME>
nal)
(optio-
Dieses Paar Tag/Endtag definiert den Feldnamen
<FIELDTYPE>
nal)
(optio-
Dieses Paar Tag/Endtag definiert den Feldtypen
<FIELDLENGTH> (optional)
Dieses Paar Tag/Endtag definiert die Feldlänge
<FIELDDECIMALS> (optional)
Dieses Paar Tag/Endtag definiert die Anzahl der Dezimalstellen des
Feldes
<ROW>
Dieses Paar Tag/Endtag definiert einen Datensatz, der an den
RMController gesendet wird
<CRMPNAME>
Dieses Paar Tag/Endtag definiert den Namen des Ressource- Manager
<CRMCLSNAME>
Dieses Paar Tag/Endtag definiert den Klassennamen des RessourceManagers
<CPARNTNAME>
Dieses Paar Tag/Endtag würde den übergeordneten RessourceManager definieren
<CPARNTRELA>
Werden mehrere Ressourcen gespeichert, werden hier die Relationen
zu den übergeordneten Ressourcen beschrieben
<NSAVEORDER>
Hier können Sie angeben, in welcher Reihenfolge die Ressource gespeichert wird, wenn mehrere Speicherungen ausgeführt werden
<LPRIMARY>
Ist dies der primäre Ressource-Manager (ganz oben in der Hierarchie)?
Der Primärschlüssel der Tabelle
arbeiten. Das heißt hier nichts anderes, als
In unserem Fall ist der XML-String einfach,
dass der RMC die Ressource an seinen Resda wir nur eine Ressource speichern. Es sind
source-Manager weiterleitet.
keine untergeordneten Ressourcen vorhanden, die unsere Ressource zu einer Primären
set oRMControl =
machen.
Server.CreateObject("AttResMgr.RMContr
<CKEYFIELD>
Nachdem wir diese Information haben,
werden wir das COM-Objekt RMController
instanziieren und das XML der Methode
Set_Up_Environment() übergeben. Anschließend können wir die Daten weiter ver12-19 Entwickeln von Windows DNA/Teil 8
oller")
oRMControl.set_up_environment
cXML
oRMControl.marshalldata rs,
"oAttorney"
FoxX Professional
Seite 10
oAttorney entspricht dem Namen, den wir
unserem Ressource-Manager Attorney im
XML-Element crmpname zugewiesen haben.
Der letzte Codeabschnitt führt das Speichern aus und prüft, ob wir einen neuen oder einen bereits vorhandenen Datensatz
speichern. Er stellt den Wert von cID auf
den Rückgabewert des Speicherns ein, so
dass wir ihn später noch zur Verfügung haben, wenn wir den Anwender wieder auf das
Formular Attorney lenken. Wenn die Speicherung erfolgreich abgeschlossen wurde
enthält cID den Primärschlüssel des Datensatzes. Schlägt das Speichern fehl enthält
<input type='reset' name='cmdAction'
Value='Cancel'
onclick='return(askToRestore())'>
Damit erstellen Sie eine HTML-Schaltfläche,
die nach einem Klick die Werte der Seite auf
ihre Originalwerte zurücksetzt. Nun könnten
Sie noch den Wunsch verspüren, ein JavaScript aufzurufen, das den Anwender
fragt, ob er sich sicher ist, dass er seine Änderungen verwerfen will. In unserem Beispiel wird das Formular, wenn die Funktion
askToRestore() .F. zurückgibt, nicht zurückgesetzt. Diese Methode des Abbruchs ist
sinnvoll, da sie keinen Zugriff auf den Server
erfordert.
Das Speichern der Ressource ist definitiv die
wichtigste und schwierigste Aktion, die Sie
auf dem Client ausführen müssen. Wir werden darauf später in diesem Abschnitt beim
Speichern des Formulars mit den Bemerkungen noch näher eingehen.
Die zweite Methode erfordert einen Aufruf
des Servers, hat aber den Vorteil, dass nicht
nur die Werte zurückgesetzt werden, sondern sie werden real neu vom Server geholt.
Nehmen wir an, ein Anwender ändert die
Daten und verwirft die Änderung. In der
gleichen Zeit hat aber auch ein anderer Anwender Änderungen am Datensatz vorgenommen und diese gespeichert. Der erste
Anwender bekommt dann nicht die aktuellen Daten angezeigt, sondern die Daten, die
der Datensatz enthielt, als er vom Anwender
aufgerufen wurde. Um die aktuellen Daten
zu erhalten, müssen Sie die Ressource vom
Server erneut abfragen und neu anzeigen. In
Attorney.asp benutzen wir diese Methode,
um zu zeigen welche Komponenten aufgerufen werden. Die Schaltfläche „Cancel“ ist
nur eine andere Schaltfläche für das Senden,
mit der das Formular an processAttorney.asp gesendet wird. Öffnen Sie processAttorney.asp in Visual InterDev. Scrollen
Sie bis zum CASE-Block „Cancel“:
Änderungen verwerfen
Case "Cancel"
if cID <> "" then
cID FILE_CANCEL (-3).
if cID = "" then
cAction = "SaveNew"
end if
cID = oRMControl.save()
cID = cStr(cID) 'Convert to
a string representation
set oRMControl = Nothing
set rs = Nothing
if cID <> "-3" and cAction
<> "SaveNew" then
Response.Redirect("Attorney.asp?
ID=" & cID & "&Action=Saved")
end if
Dem Anwender die Möglichkeit zu geben,
eine Änderung zu verwerfen oder wiederherzustellen ist ein nettes Feature, das Sie
einfach implementieren können. Wenn der
Anwender an einem Formular Änderungen
vorgenommen hat und möchte anschließend
die Originalwerte wieder herstellen, können
Sie ihm diese Funktionalität auf zwei Arten
anbieten. Die erste Möglichkeit ist sehr einfach. Sie geben an, dass Ihre Schaltfläche
„Cancel“ über eine Art „Reset“ verfügt.
12-19 Entwickeln von Windows DNA/Teil 8
Response.Redirect("Attorney.asp?
ID=" & cID & "&Action=Cancel")
end if
Wir leiten einfach die Anfrage mit den
QueryString-Werten ID und Action an das
Formular Attorney.asp um. Zusammenfassend gesagt werden die Anwaltsinformationen aus der Datenquelle neu geladen.
FoxX Professional
Seite 11
Hinzufügen eines neuen Anwalts
Auch das Anlegen eines neuen Anwalts ist
einfach. Alles was wir tun müssen ist, unser
Formular mit einer leeren ID im
QueryString aufzurufen. Gleich oben im
Formular prüfen wir, ob die ID leer ist oder
nicht. Ist dies der Fall rufen wir die Methode
GetEmptyRessource()
des
RessourceManagers auf. Sie sollten sich an folgenden
Code erinnern:
If cID = "" Then
'Adding
cAction = "Add"
'Tell the resource manager to
give me an empty recordset
Set rsAttorney =
objAttorney.getEmptyResource()
else
'Editing
'Tell the resource manager to
retrieve the Attorney record
Set rsAttorney =
objAttorney.getAttorneyByID(cID)
End If
Zunächst erstellen wir eine Referenz auf den
Ressource-Manager AttorneyNote in der
mittleren Schicht. Dann rufen wir die Methode Delete() auf und übergeben ihr den
Primärschlüssel cID. Am Ende geben wir
die Referenz auf den Ressource-Manager
wieder frei.
Anzeigen der Liste mit den Bemerkungen zu den Anwälten
Generieren einer Liste der Bemerkungen
Die Generierung der Liste mit den Bemerkungen ist einfach, wenn wir die ID des
Anwalts kennen. Öffnen wir AttorneyNoteGrid.asp und sehen wir uns an, wie diese
Aufgabe erledigt wird. Werfen Sie einen
Blick auf den Kopf des Formulars. Alles was
wir benötigen ist der Fremdschlüssel, um die
Liste durch einen Aufruf von GetAttorneyNoteByAttorneyID() zu erstellen.
Eigentlich ganz einfach. Der interessantere
Teil beim Anlegen eines neuen Anwalts ist
die Methodik der Eingabe. Da das Formular
Attorney.asp zur Laufzeit in cntAttorney.asp
enthalten ist, müssen wir einige Tricks anwenden, damit die Seite korrekt refresht
wird. Dafür benutzen wir ein clientseitiges
JavaScript. Das Besondere daran ist, dass wir
es über ein serverseitiges JavaScript generieren. Das behandeln wir aber später, wenn
wir zur Verwaltung von Formularen mit clientseitigen JavaScripts kommen.
Löschen eines Anwalts
Das Löschen eines Anwalts ist kein großes
Problem. Wir löschen Datensätze durch den
Aufruf der Methode Delete() des RessourceManagers, wobei wir der Methode den Primärschlüssel des zu löschenden Datensatzes
übergeben. Wenn wir einen Anwalt löschen
wollen, tun wir dies in processAttorney.asp:
Case "Delete"
if cID <> "" then
Set objAttorney =
Server.CreateObject("AttResMgr.Attorne
y")
objAttorney.Delete( cID )
Set objAttorney = Nothing
end if
cFK = Trim(Request.Querystring("ID"))
If cFK <> "" Then
Set objNotes =
Server.CreateObject("AttResMgr.Attorne
yNote")
Set rsNotes =
objNotes.GetAttorneyNoteByAttorneyID(
cFK )
Set objNotes = Nothing
End If
Jetzt verfügen wir in der Ressource rsNotes
über die Liste mit den Bemerkungen in
Form eines ADO-Recordset. Jetzt müssen
wir nur noch in einer Schleife durch den Recordset gehen und die Informationen in der
gleichen Art anzeigen, die wir bereits bei den
Suchergebnissen der Anwälte in AttorneyList.asp angewandt haben.
Do While Not rsNotes.EOF
Response.Write("<tr><td
width='185'><a href=""")
Response.Write("Javascript:openNote('A
ttorneyNote.asp?ID=" &
Trim(rsNotes("unique_id")) )
Response.Write("&FK=" & cFK & "')"">")
Response.Write(rsNotes("note_time") &
"</a></td>")
Response.Write("<td>" &
rsNotes("note_name") & "</td></tr>")
rsNotes.MoveNext
Loop
12-19 Entwickeln von Windows DNA/Teil 8
FoxX Professional
Seite 12
Der Aufruf der JavaScript-Funktion openNote(), mit dem wir das Fenster mit den
Notizen öffnen, ist der Gleiche wie bei AttorneyList.asp. Jetzt haben wir ein Anwaltsformular und eine Liste der Bemerkungen
programmiert; nun wollen wir sie zusammen
auf einem Formular platzieren und sie dem
Anwender anzeigen.
Einsatz des <IFRAME>
Als wir unser Formular Attorney entworfen
haben, war die Präsentation des Formulars
mit der Liste der Notizen eine wichtige Anforderung. Sie erinnern sich an das physikalische Modell unserer Web-Anwendung: wir
haben entschieden, dass die beste Möglichkeit für die Präsentation ein ContainerFormular ist, das beide Elemente zusammen
auf einer Seite hält. Dieses Formular ist unser cntAttorney.asp. Es enthält den
DHTML-Tag <IFRAME>, der den InlineFrame einrichtet, der die beiden Active Server-Seiten enthält. Dadurch erhalten wir die
Möglichkeit, die Liste der Bemerkungen
vom Anwaltsformular selbst zu trennen. Das
ist sinnvoll, wenn wir einen Teil des Formulars neu anzeigen müssen oder es dem Anwender ermöglichen wollen, noch offene
Änderungen am Anwalt zu haben, während
er die Notizen modifiziert. Öffnen wir die
Seite jetzt in Visual InterDev. Sehen Sie sich
den ersten Inline-Frame-Tag an, der das
Anwaltsformular einrichtet. Beachten Sie,
dass die QueryString-Variablen cID und
cAction, die wir an die Seite cntAttorney.asp
gesandt haben, an Attorney.asp übergeben
wurden:
<IFRAME name="frameAttorney"
src="Attorney.asp?ID=<%=cID%>&Action=<
%=cAction%>"
hspace="0" align="left"
frameborder="0" width="600"
height="249">
</IFRAME>
Das bedeutet, dass die Seite Attorney.asp in
einem 600 Pixel breiten und 249 Pixel hohen
Bereich auf der Seite erscheinen soll. Wenn
die Seite, die Sie innerhalb Ihres InlineFrame anzeigen, größer ist als der hier definierte Bereich erscheinen auf der Hauptseite
Scrollbars. Der Tag <IFRAME> hat viele
Attribute: name, source, height, width, frame
12-19 Entwickeln von Windows DNA/Teil 8
border und andere. Weitere Informationen
finden im Web Workshop oder unter
DHTML in der MSDN-Library.
Entwerfen eines „Grid“
Der nächste Abschnitt von cntAttorney.asp
hat mehrere Aufgaben. Zunächst prüfen wir
beim Anlegen eines neuen Anwalts, ob unsere Variable cID leer ist oder nicht. Ist sie leer
zeigen wir den Frame nicht an, der den Grid
mit den Bemerkungen enthält. Wenn wir einen Datensatz ändern, zeichnen wir zunächst die Spaltenüberschriften des Grid,
dann spezifizieren wir den Inline-Frame, der
die Inhalte des Grid generiert. Wir wollen
dem Anwender auch die Möglichkeit geben,
hier eine Bemerkung hinzuzufügen. Daher
generieren wir einen Hyperlink „Add Note“,
der das Formular für die Bemerkungen im
Hinzufügen-Modus öffnet. Wir wollen die
Spaltenüberschriften des Grid außerhalb des
<IFRAME> anordnen, so dass sie wenn der
Anwender herunterscrollt, stehen bleiben.
Hier der wichtigste Teil des Code, der den
Inline-Frame generiert, der die Seite AttorneyNoteGrid.asp anzeigt.
Response.Write(" <IFRAME
name='frameNotes'
src='AttorneyNoteGrid.asp?ID=" & cID )
Response.Write("' hspace='0'
align='left' FRAMEBORDER='0'
scrolling=yes width='600' ")
Response.Write(" height='75'
></IFRAME>")
Sie werden feststellen, dass die ID erneut
übertragen wird, dieses Mal in AttorneyNoteGrid. Die ID wird für die korrekte Generierung der Liste der Bemerkungen benötigt.
Dieser Frame ist 600 Pixel breit, aber nur 75
Pixel hoch. Daher wird ein Grid mit drei
sichtbaren Zeilen generiert und anschließend
beginnt der Frame zu scrollen. Bei der Ausführung dieser Formulare nach der Auswahl
eines Namens eines Anwalts in der Anwaltsliste sollten wir etwa folgendes erhalten:
FoxX Professional
Seite 13
Funktion ausführt. In
der Regel gibt es hier
vier Aktionen: Save,
Add,
Delete
und
Cancel.
Speichern der Bemerkung
Wir sehen hier drei Active Server-Pages:
cntAttorney.asp, Attorney.asp und AttorneyNoteGrid.asp. Der Anwender kann jetzt
mit dem Anwender und den dazugehörenden Bemerkungen gleichzeitig arbeiten.
Wenn der Anwender eine Bemerkung bearbeiten will, klickt er auf das dazu gehörende
Datum auf der linken Seite. Wenn er dem
Grid eine Bemerkung hinzufügen will, kann
er auf den Hyperlink „Add Note“ im Kopf
des Grid klicken.
Das Speichern der
Anmerkungen
geschieht genau wie im
Formular
Attorney.
Öffnen wir einmal processNote.asp. Sie werden bemerken, dass ich
den Abschnitt Save unserer CASE-Anweisung
leer gelassen habe, damit Sie ihn schreiben
können. Sie werden
sich erinnern, dass wir
den Vorgang des Speicherns eines Anwalts
in den vorhergehenden Abschnitten behandelt haben. Jetzt will ich Ihnen zeigen, wie
Sie Schritt für Schritt das Formular AttorneyForm speichern. Ich habe diesen Vorgang in acht Schritte aufgeteilt.
1.
In diesem Fall benutzen wir den
Ressource-Manager AttorneyNote.
Im CASE-Fall „Save“ geben Sie ein:
Verarbeitung der Bemerkungen
Nachdem wir unsere Anwaltsformulare korrekt zum Arbeiten gebracht haben, lassen Sie
uns detaillierter behandeln, wie wir Informationen im Bemerkungsformular hinzufügen/ändern/löschen können. Dies geschieht
in processNote.asp. Sie werden bemerken,
dass processNote.asp nicht viel Code enthält. Das liegt daran, dass wir ihn jetzt zusammen schreiben. Öffnen Sie die Seite processNote.asp in Visual InterDev. Genau wie
processAttorney.asp enthält auch processNote.asp nur serverseitigen Code, kein
HTML. ProcessNote.asp besteht im Grunde
nur aus einer CASE-Anweisung, die die
Schaltfläche cmdAction prüft, die der Anwender angeklickt hat und anschließend eine
12-19 Entwickeln von Windows DNA/Teil 8
Erstellen einer Referenz auf den
Ressource-Manager der mittleren
Schicht
Set objNote =
Server.CreateObject("AttResMgr.A
ttorneyNote")
2.
FoxX Professional
Empfangen eines bestehenden
Datensatzes oder einer leeren
Ressource
Wir müssen entweder eine leere Ressource oder einen bestehenden Datensatz empfangen. Die Entscheidung fällt bei der Prüfung, ob cID
leer ist oder nicht. Ist cID leer, speichern wir einen neuen Datensatz,
andernfalls einen bereits existierenden. Geben Sie folgenden Code ein:
if cID <> "" then
Seite 14
Set rs =
objNote.getAttorneyNoteByID(cID)
'Came from Edit
else
Set rs =
objNote.getEmptyResource() 'Came
From Add
end if
Set objNote = Nothing
3.
Überprüfung und Speicherung der
Daten innerhalb einer Transaktion
des MTS zu sichern (wenn die Anwendung unter dem Microsoft
Transaction Server läuft). Wir kommunizieren mit dem RMC über einen XML-String. In unserem Fall ist
es ein einfacher String, da wir nur eine Ressource speichern wollen, AttorneyNote. Es gibt keine übergeordneten Tabellen, die aus AttorneyNote die primäre Ressource machen. Würden wir im Element
cparntname eine übergeordnete Tabelle angeben sowie in cparntrela eine Relation, würden wir eine Hierarchie der Ressource-Manager der
mittleren Schicht einrichten.
Die Ressource mit den Werten
des Formulars füllen
Wir müssen die Ressource rs mit den
Werten der Collection Request.Form
füllen. Außerdem müssen wir den
Fremdschlüssel, der das verborgene
Feld AttorneyID gebildet hat, in das
Feld Note_ID einfügen. Sie werden
sich erinnern, dass ich am Anfang
dieser ASP-Seite die Variable cFK
erstellt habe, die wir hier benutzen
werden. Geben Sie den folgenden
Code ein:
cXML = cXML & "<ROW>"
cXML = cXML &
"<CRMPNAME>oAttorneyNote</CRMPNA
ME>"
cXML = cXML &
"<CRMCLSNAME>AttResMgr.AttorneyN
ote</CRMCLSNAME>"
cXML = cXML &
"<CPARNTNAME></CPARNTNAME>"
cXML = cXML &
"<NSAVEORDER>0.00</NSAVEORDER>"
cXML = cXML &
"<CPARNTRELA></CPARNTRELA>"
cXML = cXML &
"<LPRIMARY>T</LPRIMARY>"
cXML = cXML &
"<CKEYFIELD>Attnote_ID</CKEYFIEL
D>"
cXML = cXML & "</ROW>"
rs("Attorney_ID") = cFK
rs("Note_Name") =
Request.Form("Subject")
rs("Note_Text") =
Request.Form("Note")
if IsDate(Request.Form("Date"))
then
rs("note_time") =
CDate(Request.Form("Date"))
end if
Wir prüfen auch, ob die Daten im
richtigen Format vorliegen, bevor
wir den Wert eines ADO-Feldes einsetzen. Andernfalls würden wir einen
ADO-Fehler erhalten. Active Server
Pages geben alle Werte als Strings
zurück. Daher haben wir das Datumsformat mit der Funktion Cdate
in einen Sting umzuwandeln.
4.
Erstellen eines XML-Strings zum
Erstellen der Umgebung in der
mittleren Schicht
5.
Set oRMControl =
Server.CreateObject("AttResMgr.R
MController")
6.
Wir müssen den XML-String einrichten, um dem Ressource Manager
Controller (RMC) mitzuteilen, welche Ressourcen wir speichern wollen. Erinnern Sie sich, dass der RMC
die Aufgabe hat, durch die Instanziierung der Ressource-Manager mehrere Ressourcen zu sichern und die
12-19 Entwickeln von Windows DNA/Teil 8
Erstellen einer Instanz des Ressource Manager Controllers in der
mittleren Schicht
FoxX Professional
Einrichten der Umgebung und
Daten der mittleren Schicht übergeben
Jetzt müssen wir per XML unsere
Umgebungsinformationen an den
gerade instanziierten RMC senden.
Dies geschieht durch einen Aufruf
der Methode Set_Up_Environment()
des RMC. Anschließend wenden wir
die Daten mit Hilfe der Methode
Seite 15
MarshallData() in die Ressource rs in
der mittleren Schicht. Hier der dafür
benötigte Code:
wohl unseren RMC in der mittleren
Schicht als auch die Ressource auf
dem Client freigeben können. Dafür
benötigen Sie den folgenden Code:
oRMControl.set_up_environment
cXML
oRMControl.marshalldata rs,
"oAttorneyNote"
set oRMControl = Nothing
set rs = Nothing
oAttorneyNote entspricht dem Namen, den wir dem RessourceManager im XML-Element crmpname gegeben haben (drei Schritte
weiter oben).
7.
Dem RMController mitteilen,
dass die Daten gespeichert werden sollen
Nachdem sich die Daten in der mittleren Schicht befinden, sind wir bereit sie zu speichern.
cPrimKey = oRMControl.save()
Also ganz einfach. Natürlich sollten
wir prüfen, ob das Save vielleicht eine negative Zahl zurückgibt,
wodurch ein Fehler generiert würde.
Außerdem sollten wir dem Anwender in einem solchen Fall auch eine
Meldung anzeigen.
8.
Dem RMController mitteilen,
dass die Daten gespeichert werden sollen
Nachdem sich die Daten in der mittleren Schicht befinden, sind wir bereit sie zu speichern.
Damit haben Sie einen neuen Code geschrieben, der die Bemerkungen zu den Anwälten speichert. Dabei handelt sich um eine
der wichtigsten Aktionen, die Sie innerhalb
der Präsentationsschicht ausführen müssen.
Eine neue Bemerkung hinzufügen
Wenn der Anwender auf die Schaltfläche
„Add“ klickt, müssen wir ihn mit einer ID
als Fremdschlüssel zum Formular AttorneyNote umleiten. Den Fremdschlüssel finden wir im Abschnitt FK im QueryString am
Anfang des Formulars. Sie werden sich erinnern, dass wir beim Laden des Formulars
AttorneyNote.asp prüfen, ob wir über einen
leeren Primärschlüssel oder zumindest einen
Fremdschlüssel im QueryString verfügen. Ist
das der Fall, können wir GetEmptyRessource() aufrufen, um einen leeren Recordset
zu erhalten. Daher benötigen Sie im Abschnitt Add des CASE-Blocks in processNote.asp den folgenden Code:
Löschen einer Bemerkung
Zum Löschen einer Bemerkung sind lediglich drei einfache Schritte erforderlich:
1.
cPrimKey = oRMControl.save()
Also ganz einfach. Natürlich sollten
wir prüfen, ob das Save vielleicht eine negative Zahl zurückgibt,
wodurch ein Fehler generiert würde.
Außerdem sollten wir dem Anwender in einem solchen Fall auch eine
Meldung anzeigen.
9.
Unsere Objekte freigeben
Erstellen einer Referenz auf den
Ressource-Manager AttorneyNote in der mittleren Schicht
Wenn cID nicht leer ist setzen wir
eine Variable, um das RessourceManager-Objekt Attorney zu refernzieren:
Case "Delete"
if cID <> "" then
Set objNote =
Server.CreateObject("AttResMgr.A
ttorneyNote")
Zum Abschluss müssen wir unsere
Objektreferenzen
noch
auf
„Nothing“ setzen, so dass wir so12-19 Entwickeln von Windows DNA/Teil 8
FoxX Professional
Seite 16
2.
Aufruf der Methode Delete(), die
als Parameter den Primärschlüssel cID übergeben wird
Jetzt rufen wir die Methode Delete()
des Ressource-Managers Attorney
auf und übergeben ihr den Primärschlüssel aus dem QueryString, den
wir am Anfang des Formulars in die
Variable cID geschrieben haben:
objNote.Delete( cID )
3.
Freigeben unserer Referenz auf
das Ressource-Manager-Objekt
Set objNote = Nothing
End If
Das war es schon. Der Code gleicht exakt
dem für das Löschen der Anwälte. Lediglich
die Namen der Ressource-Manager sind anders.
einzufügen und es anschließend auszuführen. Beachten Sie jedoch, dass, wenn globalfuncs.asp HTML-Code enthält, das Formular eventuell nicht die gewünschten Ergebnisse bringt, da wir das HTML-Dokument
noch nicht mit dem Tag <HTML> begonnen haben. Sie können mit Hilfe von Include-Dateien so lange HTML in ein anderes
HTML-Dokument einfügen, wie das Ergebnis der zusammengeführten Dateien ein gültiges HTML-Dokument ergibt.
Da der Server Include-Dateien vor der Ausführung von Script-Anweisungen aufnimmt,
können Sie keine Script-Anweisung benutzen, um den Namen einer Include-Datei zu
erstellen. So würde zum Beispiel das folgende Script die Datei header.inc nicht öffnen,
da der Server versucht, die #includeAnweisung auszuführen, bevor er der Variablen name einen Dateinamen zuordnen
kann.
Einsetzen der serverseitigen Include-Dateien
<% name= "header.inc" %>
<!-- #include file="<%= name %>" -->
Wir benutzen die serverseitigen IncludeDateien, wenn wir die Inhalte einer Datei direkt in eine andere Datei auf dem Server
übernehmen wollen. Dieses Vorgehen ist
sinnvoll, wenn Sie Standardcodes definieren
wollen (HTML oder ASP), die in vielen Seiten Ihres Web genutzt werden. Z. B. könnten Sie vorhaben, einige serverseitige Scriptfunktionen zu definieren, die Sie dann in Ihren Active Server Pages einsetzen. Um Dateien in andere ASP- oder HTML-Dateien
zu übernehmen, verwenden Sie die Anweisung #include. Damit wird der Webserver
angewiesen, die Inhalte einer Datei in die
Seite zu übernehmen, bevor die ASP ausgeführt wird. Die übernommene Datei kann
jeden Inhalt besitzen, der innerhalb eines
HTML-Dokuments gültig ist, zum Beispiel:
Lassen Sie uns in unserem Containerformular Attorney (cntAttorney.asp) eine Referenz
auf eine Include-Datei erstellen, die einfach
einen ansprechenden Titel am oberen Teil
der Seite anzeigt. Wenn Sie einen Blick in
unser Verzeichnis Interface werfen, sehen
Sie dort die Datei header.inc. Diese Datei ist
für sich keine gültige HTML-Datei. Wenn
Sie sie in Notepad öffnen werden Sie bemerken, dass sie nur eine HTML-Tabelle,
kein ganzes HTML-Formular enthält:
<!-- #include file = "globalfuncs.asp"
-->
<html>
<head>
</head>
<body>
.
.
.
Damit wird der Webserver angewiesen,
sämtliche Inhalte der Seite globalfuncs.asp
vor dem Tag <HTML> des Dokuments
12-19 Entwickeln von Windows DNA/Teil 8
<table border="0" cellpadding="0"
cellspacing="1" width="570">
<tr class="menu">
<td><strong>Attorney Application
Demo</strong></td>
<td align="right"><a
href="default.asp">Back to
Search</a></td>
</tr>
</table>
Wir können die Datei nur benutzen, wenn
wir sie an einer speziellen Stelle innerhalb
der Datei cntAttorney.asp einfügen. Öffnen
Sie cntAttorney.asp in Visual InterDev. Wir
werden die Include-Datei hinter dem Tag
<BODY> einfügen:
FoxX Professional
Seite 17
<html>
<head>
<title>Attorney</title>
<link REL="stylesheet" TYPE="text/css"
HREF="style.css" />
<script LANGUAGE="JavaScript"
SRC="jscripts/notelist.js"></script>
</head>
<body class="dataform" >
<!-- #include file = "header.inc" -->
<table border="0" cellpadding="0"
cellspacing="0" width="600"><tr><td
valign="top">
.
.
.
Damit wird der Inhalt von header.inc an die
Position eingefügt, an der in cntAttorney.asp
die #include-Anweisung steht. Markieren Sie
einen Anwalt aus Ihrem Abfrageergebnis
und sehen Sie sich den Header oben auf der
Seite an.
Diese Technik können Sie einsetzen, um
Menüs, Ränder oder andere gleichbleibende
Inhalte in Ihren Webseiten einzufügen.
Schluss mit dem serverseitigen
ASP-Script
Nun haben wir die serverseitige Programmierung unserer webbasierten Anwendung
abgeschlossen. Wir haben die Search Criteria
Ressourcen eingesetzt, um das Empfangen
von Datensätzen aus der mittleren Schicht
flexibler zu gestalten. Außerdem haben wir
die
Funktionalitäten
Add/Update/Delete/Cancel erstellt. Wir
haben mit Hilfe des Tag <IFRAME> mehrere Formulare in einem Fenster des Browsers vereinigt. Zuletzt haben wir noch die
Thematik der serverseitigen Include-Dateien
angekratzt. Im nächsten Abschnitt werden
wir uns mit der Kontrolle des Browsers mit
Hilfe von clientseitigen JavaScripts beschäftigen.
12-19 Entwickeln von Windows DNA/Teil 8
FoxX Professional
Seite 18