Für Webanwendungen gibt es spezielle Anforderungen, die berücksichtigt werden müssen. Für jeden Client wird eine Session gestartet, in dem ein- oder mehrmals ein Request angefordert wird. Für die Verarbeitung eines Request steht auf dem Webserver aber nur eine begrenzte Anzahl Ressourcen (Prozesse, Threads bzw. Zum Wörterbuch hinzufügen) zur Verfügung, die von dem Internet Information Server (IIS) für die unterschiedlichen Requests wiederverwendet werden. Dadurch können einzelne Requests innerhalb einer Session in unterschiedlichen AppDomains, Prozessen oder sogar auf unterschiedlichen Rechnern ausgeführt werden.
Außerdem werden je nach Programmiermodell (ASP.NET WebForms, MVC, …) für die Implementierung bestimmte Basisklassen vorausgesetzt, welche sich um die Aufbereitung des Ergebnisses (i.e. rendering) kümmern. An hiervon abgeleiteten Klassen müssen dann bestimmte Methoden implementiert bzw. übersteuert werden, welche von IIS für den jeweiligen Request aufgerufen werden.
Deswegen wird für WEBA
Bausteine keine Methode RunImplementation
erzeugt, welche für die Implementierung übersteuert werden muss. Statt dessen wird in der Basisklasse eine statische Methode GetSessionInstance
erzeugt, welche verwendet werden kann, um die Instanz während der Verarbeitung eines Requests zu liefern:
namespace WebApp { public class MySessionModule: HL.Modules.Weba.Twonly.HlWebaTest { ... public static MySessionModule Instance => GetSessionInstance<MySessionModule>(); ...
WEBA
gelten die gleichen Regeln für die Implementierungsspezifikation, allerdings muss als Implementierungstyp ASPCLR eingetragen werden.
Damit die Infrastruktur in der Lage ist, die richtige Instanz zu erzeugen und für die Verarbeitung eines Requests zur Verfügung zu stellen, muss die Implementierungsklasse in der Web.config
als sog. HTTP Module eingetragen werden. Je nachdem, ob die Web-Anwendung im sog. Classic Mode oder Intergrated Mode läuft, muss der Eintrag an unterschiedlichen Stellen erfolgen:
<system.web> <httpModules> <add type="WebApp.MySessionModule" name="HlWebaTestSessionModule" /> </httpModules> </system.web>
<system.webServer> <modules> <add type="WebApp.MySessionModule" name="HlWebaTestSessionModule" /> </modules> </system.webServer>
Web.config
automatisch vorgenommen, und ggf. bei Änderungen auch angepasst.
Die Infrastruktur legt beim jedem Request eine Instanz dieser Implementierungsklasse an. Wenn der Request beendet wird, werden die Daten (z.B. Objekteinhalte) für die Instanz gesichert und beim nächsten Request verwendet, um die neue Instanz zu initialisieren. Bevor ASP.NET dann die für Implementierung des Requests ermittelte Methode auslöst, wird die Methode BeginRequest
an der Instanz der Implementierungsklasse ausgelöst. Nachdem ASP.NET die Kontrolle zurückbekommt, und bevor die Daten gesichert werden, wird die Methode EndRequest
an der Instanz der Implementierungsklasse ausgelöst. Diese beiden Methoden können ggf. übersteuert werden, um entsprechend reagieren zu können.
Da es sich bei Bausteinen vom Typ WEBA
um Einstiegsbausteine handelt, können hier auch die Eigenschaften und Methoden, welche hier beschrieben sind, verwendet werden. Zusätzlich stehen die nachfolgend beschriebenen Eigenschaften und Methoden zur Verfügung.
protected Boolean IsReentry { get; };
Liefert false
für die 1. Anforderung in einer Sitzung, true
für alle nachfolgenden.
protected static T GetSessionInstance<T>() where T : SessionModule;
Liefert die für die aktuelle Sitzung zuständige Instanz der Klasse der dieser Web-Verbindungsbaustein implementiert
protected virtual void RequestBegin();
Wird am Anfang jede einzelne HTTP-Anforderung ausgelöst.
protected virtual void RequestEnd();
Wird am Ende jede einzelne HTTP-Anforderung ausgelöst
public void RestartSession(HttpContext httpContext);
Diese Methode kann verwendet werden1), um die aktuelle SessionModule-Instanz neu zu initialisieren, um z.B. geänderte Eigenschaften zu berücksichtigen. Die aktuelle HttpContext
-Instanz muss explizit übergeben werden.
Für ASP.NET Core steht die Eigenschaft HttpContext.Current
nicht mehr zur Verfügung. Siehe hier für die unterschiedliche Möglichkeiten, um auf die aktuelle HttpContext
Instanz zu zu greifen.
public void RestartSession();
Ruft die Methode RestartSession
mit HttpContext.Current
auf. Diese Methode kann nur in .NET Framework verwendet werden.
Dieser Abschnitt ist in Bearbeitung, und kann ggf. noch angepasst werden.
Für die Integration von HTTP Module und HTTP Handler unter ASP.NET Core spielt die Web.config
keine Rolle mehr, sondern die HTTP Pipeline wird mittels einer Reihe spezieller Extension-Methoden konfiguriert (Details). Für ASP.NET Core gibt es eine Klasse SessionModuleExtensions
2), in der Extension-Methoden für die Integration eines TAA SessionModule
in die Middleware definiert sind.
Diese Methoden können da verwendet werden wo Session State konfiguriert wird.
public static IServiceCollection AddSessionModule<T>(this IServiceCollection services, Action<SessionOptions> configure = null) where T : SessionModule
Fügt Dienste hinzu, die für die TAA SessionModule
-Unterstützung benötigt werden. Dazu gehören auch die Dienste, die für den session state erforderlich sind. Diese Methode kann anstatt AddSession(IServiceCollection, Action<SessionOptions>)
verwendet werden.
public static IApplicationBuilder UseSessionModule<T>(this IApplicationBuilder builder, SessionOptions options = null) where T : SessionModule
Fügt der Anforderungspipeline der Anwendung die TAA SessionModule
-Middleware hinzu. Dazu gehört auch die Middleware, die für den session state erforderlich ist. Diese Methode kann anstatt UseSession(IApplicationBuilder, Action<SessionOptions>)
verwendet werden.
Nachfolgend ein Beispiel, wie diese Methoden bei der Konfiguration eine ASP.NET Core MVC Anwendung verwendet werden:
public static void Main(string[] args) { var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllersWithViews(); builder.Services.AddSessionModule<WebaModule>(); var app = builder.Build(); // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Home/Error"); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.UseSessionModule<WebaModule>(); app.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); app.Run(); }
WEBA-Bausteine können auch, aber nur Serverseitig, in eine ASP.NET Core Blazor Anwendung verwendet werden3). Blazor verwendet aber kein session state, sondern die Benutzerdaten bzw. state werden Serverseitig in ein sog. Circuit
vorgehalten (Details). Daher können die Methoden für Session State nicht verwendet werden, und gibt es für Blazor eigene Extension Methoden für die Integration eines SessionModule
-Instanz mit einem Circuit
:
public static IServerSideBlazorBuilder AddCircuitSessionModule<T>(this IServerSideBlazorBuilder builder) where T : SessionModule, new()
Fügt Dienste hinzu, die für die TAA SessionModule
Unterstützung in eine ASP.NET Core Blazor Anwendung benötigt werden.
public static IApplicationBuilder UseCircuitSessionModule<T>(this IApplicationBuilder builder) where T : SessionModule, new()
Fügt der Anforderungspipeline der ASP.NET Core Blazor Anwendung die TAA SessionModule
Middleware hinzu.
Die Lebensdauer einer SessionModule
-Instanz ist mit der Lebensdauer des Circuit
verknüpft. Beim Instanziieren eines Circuit
wird auch eine SessionModule
angelegt und wird (intern) die Anmeldung bei der TAA vorgenommen. Sobald die Circuit
-Instanz aufgeräumt wird, wird auch die SessionModule
-Instanz bei der TAA abgemeldet, und aufgeräumt.
Nachfolgend ein Beispiel, wie diese Methoden bei der Konfiguration eine ASP.NET Core Blazor Anwendung verwendet werden:
public static void Main(string[] args) { // Add services to the container. var builder = WebApplication.CreateBuilder(args); builder.Services.AddRazorComponents() .AddInteractiveServerComponents() .AddCircuitSessionModule<WebaModule>(); var app = builder.Build(); // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Error"); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseAntiforgery(); app.UseCircuitSessionModule<WebaModule>(); app.MapRazorComponents<App>() .AddInteractiveServerRenderMode(); app.Run(); }
Damit auch in den Blazor Komponenten mittels dependency injection auf die SessionModule
-Instanz zugegriffen werden kann, wird eine Service Komponente CircuitSessionModuleAccessor<T>
registriert:
public sealed class CircuitSessionModuleAccessor<T> where T : SessionModule, new() { public T? GetSessionInstance(); public async Task<T?> GetSessionInstanceAsync(); }
Als Typargument T
wird der Name der Implementierungsklasse für das WEBA-Modul übergeben. e.g. CircuitSessionModuleAccessor<WebaModule>
.
public T? GetSessionInstance()
Liefert die, für das aktuelle Circuit
, zuständige Instanz der Implementierungsklasse des WEBA-Moduls.
public async Task<T?> GetSessionInstanceAsync()
Kreiert ein Task<T?>
der, für das aktuelle Circuit
, die zuständige Instanz der Implementierungsklasse des WEBA-Moduls liefert.
Nachfolgend ein Beispiel, wie diese Service verwendet wird:
@page "/" @rendermode InteractiveServer @inject CircuitSessionModuleAccessor<WebaModule> accessor; <PageTitle>Home</PageTitle> <h1>Hello, world!</h1> Welcome to your new app. @if (Name == null) { <p>Waiting for SessionModule</p> } else { <p>SessionModule: @Name</p> } @code { private string Name = null; protected override async Task OnInitializedAsync() { var modl = await accessor.GetSessionInstanceAsync(); Name = modl?.Name; } }