Für Webanwendungen (Ityp ASPCLR) sind einige Besonderheiten zu berücksichtigen.
Da bei ASP.NET Seiten im Grunde für jede Anforderung der gleiche Code durchlaufen wird, muss es eine Möglichkeit geben sicherzustellen, dass die Anmeldung an der Infrastruktur (Register
) für einen Baustein nur einmal durchgeführt wird. Damit die Infrastruktur hierzu in der Lage ist, muss für die Webanwendung ein sog. HTTP Module
in der Web.Config
hinzugefügt werden.
<configuration> <system.web> .... Snip .... <httpModules> <add type="TeamWiSE.TAA.Web.Application,TeamWiSE.Runtime, Version=1.0.2.52, Culture=neutral, PublicKeyToken=d06ae338ad0eda87" name="TAA.Web.Application" /> </httpModules> .... Snip .... </system.web> </configuration>
Dieser Eintrag wird für den sog. classic mode verwendet. Wird die Webbanwendung in den sog. integrated mode1) verwendet, sieht der Eintrag so aus:
<configuration> <system.webServer> .... Snip .... <modules> <add type="TeamWiSE.TAA.Web.Application,TeamWiSE.Runtime, Version=1.0.2.52, Culture=neutral, PublicKeyToken=d06ae338ad0eda87" name="TAA.Web.Application" /> </modules> .... Snip .... </system.webServer> </configuration>
Damit ist die TAA Infrastruktur in der Lage, den Zustand der Anwendung (Session) zu verwalten, und der ASPX-Seite für den bereits registrierten Baustein den ModlEnv
zur Verfügung zu stellen. Dazu gibt es in der Namespace TeamWiSE.TAA.Web
eine Klasse Application
, mit einer statischen Methode ModlEnv
.
Nur wenn der übergebene Bausteinname mit dem des aktuellen Bausteins übereinstimmt, und dieser bereits einen Register
ausgeführt hat, liefert die Methode eine Referenz auf eine Instanz der Klasse ModlEnv
zurück. Entspricht der übergebene Name nicht dem des aktuellen Bausteins, oder ist dieser noch nicht registriert, liefert sie den Wert null
. Wenn der Name nicht übereinstimmt, wird außerdem eine Condition ZZTAAIM1(24)
gesetzt. Diese Condition wird ebenfalls gesetzt, wenn beim Register
festgestellt wird, dass ein anderes Modul bereits registriert ist. Deshalb empfiehlt es sich, in einer ASPX-Seite den untenstehenden Beispielcode zu verwenden um sich bei der Infrastruktur anzumelden.
Derr Kontext für eine Session wird beim Ende eines Requests auf die Festplatte zwischengespeichert, damit bei einem Prozesswechsel die Daten auch nach einem unerwartetem Tod des Worker-Prozesses noch verfügbar sind. Das Verzeichnis, in dem diese Dateien gespeichert werden, kann über das Registry Setting SessionStoreDir in der Config-Section angegeben werden. Wenn kein Verzeichnis eingetragen ist, werden die Dateien im TEMP-Verzeichnis gespeichert.
Außerdem wird der TAA Kontext zwischen 2 Serverrequests aus dem Hauptspeicher entfernt, wenn ein gewisses Intervall überschritten ist, damit bei längeren Sessions der Hauptspeicher nicht vollläuft. Dieses Zeitintervall (in Minuten) kann über das Registry setting SessionIdleTimeout in der Config-Section gesetzt werden. Ist dieser Wert nicht gesetzt, oder wird 0 eingetragen, wird der Kontext nach 5 Minuten bzw. dem Sessiontimeout aus der Web.Config aus dem Speicher entfernt.
Sollte die Session ablaufen, ohne dass der TAA Kontext mit einem Leave aufgeräumt wird, können die zwischengespeicherten Kontextdateien automatisch gelöscht werden. Hierzu gibt es den Registry-Eintrag SessionStoreCheckInterval. Hier wird (ebenfalls in Minuten) eingetragen, wie oft nach abgelaufenen Dateien gesucht werden soll. Ist der Eintrag nicht vorhanden, oder wird 0 eingetragen, dann werden solche abgelaufenen Dateien nicht automatisch gelöscht.
Es gibt auch einen Entrypoint taaSessionCheckStoreForTimeout in der TeamWiSE.RuntimeCore.dll, der mit dem Standard Windowsprogramm RUNDLL32.EXE aufgerufen werden kann. Diese Routine sucht nach abgelaufenen Dateien und löscht diese.
rundll32 TeamWiSE.RuntimeCore.dll,taaSessionCheckStoreForTimeout [Timeout]
Auf diese Weise kann alternativ oder zusätzlich über eigene oder Windows-Standard Scheduler-Mechanismen das Aufräumen angestoßen werden. Über das optionale Argument Timeout (Angabe in Minuten) kann mitgeteilt werden, wie alt die Dateien sein müssen, damit sie gelöscht werden dürfen. Ist dieses Argument nicht angegeben, oder 0, so wird der Sessiontimeout der Anwendung verwendet, in der die jeweiligen Kontextdaten angelegt wurden. Für das automatische Löschen durch die TAA-Infrastruktur kann dieser Wert in dem Registry-Eintrag SessionStoreCheckTimeout gesetzt werden.
Die hierfür verwendeten Conditions gehören ausnahmslos der Meldungsgruppe „ZZTAAIM1“ an und haben die Severity „Info“.
Code | gesetzt bei | Umschreibung |
---|---|---|
20 | doCall | Es soll ein Wechsel auf einen andere ASPX-Seite stattfinden. Das rufende Modul sollte sich die aktuelle Situation merken, damit es bei der erneuten Aktivierung an der richtigen Stelle weitermachen kann. |
21 | doCall | Es findet kein Wechsel auf eine andere APSX-Seite statt. |
22 | Register | Der Register ist für diese Session bereits erfolgt. |
23 | Register | Es ist noch kein Session-Kontext verfügbar; möglicherweise wartet die TAA-Infrastruktur gerade auf einen Register. |
24 | Register, modlEnv | Zur Zeit ist in dieser Session ein anderes Modul aktiv. Als Associations werden das aktive Modul („Module“) und die ASPX-Seite für das Modul („Page“) übergeben. Das aktuelle Modul kann entscheiden, ob auf die richtige ASPX-Seite geroutet oder eine Fehlermeldung produziert werden soll. |
try { envTAA.doCall("VO-I-GEVO-SPIEGEL", "ANZEIGEN"); } catch (TAACondition cnd) { if (cnd.cndGroup == "ZZTAAIM1" && cnd.cndCode == 20) { // ZZTAAIM(20) means another ASPX page will be activated, // and we've to quit, untill we're reactivated. return; } // ZZTAAIM(21) means call was successful, and we can continue, if (cnd.cndGroup != "ZZTAAIM1" || cnd.cndCode != 21)) { // error handling } } // Check state of called module
Wenn das gerufene Modul einen Unregister ausgeführt hat, sorgt die Infrastruktur dafür, dass die ursprüngliche ASPX Seite wieder angesteuert wird. Diese bekommt über die Methode ModlEnv der Klasse TeamWiSE.TAA.Web.Application den ModlEnv (siehe oben), und die Eigenschaft IsReentry an der ModlEnv-Instanz ist jetzt gesetzt, damit der Zustand des gerufenen Bausteins abgefragt werden kann.
try { // First ask TAA for the registered module envTAA = TeamWiSE.TAA.Web.Application.ModlEnv("VO-I-POSTKORB"); if (envTAA == null && !IsPostBack) { // As we're not in a postback event and apparently // haven't registered yet, do so now. envTAA = TeamWiSE.TAA.taaEnv.taaRegister("VO-I-POSTKORB"); // Set conditon class handler for class TAAWEB, so we get notified, // if another ASPX page will be activated. if (envTAA != null) envTAA.cndClassHdlIdSet("TAAWEB", 4711); } if (envTAA == null) { // error handling } } catch (TAACondition cnd) { if (cnd.cndGroup == "ZZTAAIM1" && cnd.cndCode == 24) { // ZZTAAIM(24) here, means another module is active or expected to register. // We can either redirect to that page, or produce an error. string sPage = (string) cnd.cndAssoc("Page"); cnd.cndRemove(); Response.Redirect(sPage, true); } // error handling }
Wenn für eine Webanwendung das HTTP-Module eingerichtet ist und die Webanwendung sich bei der TAA angemeldet hat, wird für jeden Request, der auf die Webanwendung ausgeführt wird, ein SessionResume
und SessionSuspend
Ereignis ausgelöst2). Diese 2 statischen Ereignisse sind an der Klasse TeamWiSE.TAA.Web.Application
definiert, und können z.B. in der Global.asax
beim Application_Start
bestückt, bzw. in Application_End
entfernt werden:
protected void Application_Start() { AreaRegistration.RegisterAllAreas(); RegisterGlobalFilters(GlobalFilters.Filters); RegisterRoutes(RouteTable.Routes); TeamWiSE.TAA.Web.Application.SessionResume += ApplicationOnSessionResume; TeamWiSE.TAA.Web.Application.SessionSuspend += ApplicationOnSessionSuspend; } protected void Application_End() { TeamWiSE.TAA.Web.Application.SessionResume -= ApplicationOnSessionResume; TeamWiSE.TAA.Web.Application.SessionSuspend -= ApplicationOnSessionSuspend; } private void ApplicationOnSessionResume(object sender, SessionEventArgs e) { TeamWiSE.TAA.Services.Info.Send("Session resume for " + e.ModlEnv.Name + "." + e.ModlEnv.ActiveEvent); } private void ApplicationOnSessionSuspend(object sender, SessionEventArgs e) { TeamWiSE.TAA.Services.Info.Send("Session suspend for " + e.ModlEnv.Name + "." + e.ModlEnv.ActiveEvent); }
Das Ereignis SessionResume
wird nicht sofort ausgelöst, sondern erst wenn die Webanwendung das 'ModlEnv'' zum ersten Mal während des Requests verlangt.