Skip to content

2. Eine kurze Einführung in ASP.NET

Hier möchten wir anhand einiger Beispiele die ASP.NET-Konzepte vorstellen, die später in diesem Dokument nützlich sein werden. Diese Einführung behandelt nicht die Feinheiten der Client/Server-Kommunikation in einer Webanwendung. Dazu können Sie Folgendes lesen:

Diese Einführung richtet sich an diejenigen, die schnell loslegen möchten und – zumindest anfangs – in Kauf nehmen, dass einige potenziell wichtige Punkte möglicherweise ungeklärt bleiben. Im weiteren Verlauf dieses Dokuments werden diese Punkte ausführlicher behandelt. Wer mit ASP.NET vertraut ist, kann direkt zu Abschnitt 3 springen.

2.1. Ein Beispielprojekt

2.1.1. Erstellen des Projekts

  • Erstellen Sie in [1] mit Visual Web Developer ein neues Projekt
  • Wählen Sie in [2] ein Visual C#-Webprojekt aus
  • Geben Sie unter [3] an, dass Sie eine ASP.NET-Webanwendung erstellen möchten
  • Geben Sie in [4] einen Namen für die Anwendung ein. Es wird ein Ordner für das Projekt mit diesem Namen erstellt.
  • Geben Sie unter [5] den übergeordneten Ordner des Projektordners [4] an
  • In [6] ist das erstellte Projekt
  • [Default.aspx] ist eine standardmäßig erstellte Webseite. Sie enthält HTML-Tags und ASP.NET-Tags
  • [Default.aspx.cs] enthält den Code zur Verarbeitung von benutzergelösten Ereignissen auf der im Browser angezeigten Seite [Default.aspx]
  • [Default.aspx.designer.cs] enthält die Liste der ASP.NET-Komponenten für die Seite [Default.aspx]. Jede auf der Seite [Default.aspx] platzierte ASP.NET-Komponente generiert eine Deklaration für diese Komponente in [Default.aspx.designer.cs].
  • [Web.config] ist die Konfigurationsdatei für das ASP.NET-Projekt.
  • [References] ist die Liste der vom Webprojekt verwendeten DLLs. Diese DLLs sind Klassenbibliotheken, die das Projekt benötigt. In [7] befindet sich die Liste der DLLs, die standardmäßig in den Projektreferenzen enthalten sind. Die meisten davon sind nicht erforderlich. Wenn das Projekt eine DLL benötigt, die nicht in [7] aufgeführt ist, kann diese über [8] hinzugefügt werden.

2.1.2. Die Seite [Default.aspx]

Wenn Sie das Projekt mit [Strg-F5] ausführen, wird die Seite [Default.aspx] in einem Browser angezeigt:

  • in [1] die URL des Webprojekts. Visual Web Developer verfügt über einen integrierten Webserver, der beim Ausführen eines Projekts gestartet wird. Er lauscht auf einem zufälligen Port, in diesem Fall 1490. Der Standard-Lauscherport ist normalerweise Port 80. In [1] wird keine Seite angefordert. In diesem Fall wird die Seite [Default.aspx] angezeigt, daher auch ihr Name als Standardseite.
  • In [2] ist die Seite [Default.aspx] leer.
  • In Visual Web Developer kann die Seite [Default.aspx] [3] visuell (Registerkarte [Design]) oder mithilfe von Tags (Registerkarte [Quelle]) erstellt werden
  • In [4] ist die Seite [Default.aspx] im [Design]-Modus zu sehen. Sie wird durch Ziehen und Ablegen von Komponenten aus der Toolbox [5] erstellt.

Der [Quellcode]-Modus [6] bietet Zugriff auf den Quellcode der Seite:


<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="Intro._Default" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
  <title></title>
</head>
<body>
  <form id="form1" runat="server">
  <div>
  </div>
  </form>
</body>
</html>
  • Zeile 1 ist eine ASP.NET-Direktive, die bestimmte Eigenschaften der Seite auflistet
    • Die Page-Direktive gilt für eine Webseite. Es gibt weitere Direktiven wie Application, WebService usw., die für andere ASP.NET-Objekte gelten
    • Das CodeBehind-Attribut gibt die Datei an, die die Ereignisse der Seite verarbeitet
    • Das „Language“-Attribut gibt die von der CodeBehind-Datei verwendete .NET-Sprache an
    • Das Attribut „Inherits“ gibt den Namen der Klasse an, die in der CodeBehind-Datei definiert ist
    • Das Attribut „AutoEventWireUp="true"“ gibt an, dass die Verknüpfung zwischen einem Ereignis in [Default.aspx] und seinem Handler in [Default.aspx.cs] über den Ereignisnamen erfolgt. Somit wird das Load-Ereignis auf der Seite [Default.aspx] von der Methode „Page_Load“ der Klasse „Intro._Default“ verarbeitet, die durch das Attribut „Inherits“ definiert ist.
  • Die Zeilen 4–14 beschreiben die Seite [Default.aspx] mithilfe von Tags:
    • Klassische HTML-Tags wie die Tags <body> oder <div>
    • ASP.NET-Tags. Dies sind die Tags mit dem Attribut runat="server". ASP.NET-Tags werden vom Webserver verarbeitet, bevor die Seite an den Client gesendet wird. Sie werden in HTML-Tags umgewandelt. Der Client-Browser erhält daher eine Standard-HTML-Seite, in der keine ASP.NET-Tags mehr vorhanden sind.

Die Seite [Default.aspx] kann direkt über ihren Quellcode geändert werden. Dies ist manchmal einfacher als die Verwendung des [Design]-Modus. Wir ändern den Quellcode wie folgt:


<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="Intro._Default" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
  <title>Introduction ASP.NET</title>
</head>
<body>
  <h3>Introduction à ASP.NET</h3>
  <form id="form1" runat="server">
  <div>
  </div>
  </form>
</body>
</html>

In Zeile 6 geben wir der Seite mit dem HTML-Tag <title> einen Titel. In Zeile 9 fügen wir Text in den Hauptteil (<body>) der Seite ein. Wenn wir das Projekt ausführen (Strg-F5), erhalten wir im Browser folgendes Ergebnis:

 

2.1.3. Die Dateien [Default.aspx.designer.cs] und [Default.aspx.cs]

Die Datei [Default.aspx.designer.cs] deklariert die Komponenten der Seite [Default.aspx]:


//------------------------------------------------------------------------------
// <auto-generated>
//      This code was generated by a tool.
//      Runtime version :2.0.50727.3603
//
//      Changes made to this file may cause incorrect behavior and will be lost if
//      the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
 
namespace Intro {
    
 
    public partial class _Default {
 
        /// <summary>
        /// Control form1.
        /// </summary>
        /// <remarks>
        /// Automatically generated field.
        /// To modify, move the field declaration from the designer file to the code-behind file.
        /// </remarks>
        protected global::System.Web.UI.HtmlControls.HtmlForm form1;
    }
}

Diese Datei enthält die Liste der ASP.NET-Komponenten auf der Seite [Default.aspx], die über eine Kennung verfügen. Sie entsprechen den Tags in [Default.aspx], die das Attribut runat="server" und das Attribut id aufweisen. Somit entspricht die Komponente in Zeile 23 oben dem Tag


  <form id="form1" runat="server">

aus [Default.aspx].

Der Entwickler arbeitet selten mit der Datei [Default.aspx.designer.cs]. Diese Datei ist jedoch nützlich, um die Klasse einer bestimmten Komponente zu ermitteln. Wie unten gezeigt, ist die Komponente „form1“ vom Typ „HtmlForm“. Der Entwickler kann diese Klasse dann untersuchen, um mehr über ihre Eigenschaften und Methoden zu erfahren. Die Komponenten auf der Seite [Default.aspx] werden von der Klasse in der Datei [Default.aspx.cs] verwendet:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
 
namespace Intro
{
  public partial class _Default : System.Web.UI.Page
  {
    protected void Page_Load(object sender, EventArgs e)
    {
 
    }
  }
}

Beachten Sie, dass die in den Dateien [Default.aspx.cs] und [Default.aspx.designer.cs] definierte Klasse identisch ist (Zeile 10): Intro._Default. Es ist das Schlüsselwort „partial“, das es ermöglicht, eine Klassendeklaration über mehrere Dateien hinweg zu erweitern, in diesem Fall über zwei.

In Zeile 10 oben sehen wir, dass die Klasse [_Default] die Klasse [Page] erweitert und deren Ereignisse erbt. Eines davon ist das Load-Ereignis, das auftritt, wenn die Seite vom Webserver geladen wird. In Zeile 12 verarbeitet die Methode Page_Load das Load-Ereignis der Seite. Hier wird die Seite in der Regel initialisiert, bevor sie im Browser des Clients angezeigt wird. In diesem Fall führt die Methode Page_Load keine Aktion aus.

Die mit einer Webseite verknüpfte Klasse – in diesem Fall die Klasse „Intro._Default“ – wird zu Beginn der Client-Anfrage erstellt und gelöscht, sobald die Antwort an den Client gesendet wurde. Sie kann daher nicht dazu verwendet werden, Informationen zwischen den Anfragen zu speichern. Dazu müssen Sie das Konzept einer Benutzersitzung nutzen.

2.2. Ereignisse einer ASP.NET-Webseite

Wir erstellen die folgende Seite [Default.aspx]:


<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="Intro._Default" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
  <title>Introduction ASP.NET</title>
</head>
<body>
  <h3>Introduction à ASP.NET</h3>
  <form id="form1" runat="server">
  <div>
    <table>
      <tr>
        <td>
          Nom</td>
        <td>
          <asp:TextBox ID="TextBoxNom" runat="server"></asp:TextBox>
        </td>
        <td>
          &nbsp;</td>
      </tr>
      <tr>
        <td>
          Age</td>
        <td>
          <asp:TextBox ID="TextBoxAge" runat="server"></asp:TextBox>
        </td>
        <td>
          &nbsp;</td>
      </tr>
    </table>
  </div>
  <asp:Button ID="ButtonValider" runat="server" Text="Valider" />
  <hr />
  <p>
    Evénements traités par le serveur</p>
  <p>
    <asp:ListBox ID="ListBoxEvts" runat="server"></asp:ListBox>
  </p>
  </form>
</body>
</html>

Die [Entwurfsansicht] der Seite sieht wie folgt aus:

 

Die Datei [Default.aspx.designer.cs] sieht wie folgt aus:


namespace Intro {
    public partial class _Default {
        protected global::System.Web.UI.HtmlControls.HtmlForm form1;
        protected global::System.Web.UI.WebControls.TextBox TextBoxNom;
        protected global::System.Web.UI.WebControls.TextBox TextBoxAge;
        protected global::System.Web.UI.WebControls.Button ButtonValider;
        protected global::System.Web.UI.WebControls.ListBox ListBoxEvts;
    }
}

Dies enthält alle ASP.NET-Komponenten der Seite [Default.aspx], die über eine Kennung verfügen.

Wir ändern die Datei [Default.aspx.cs] wie folgt:


using System;
 
namespace Intro
{
  public partial class _Default : System.Web.UI.Page
  {
    protected void Page_Init(object sender, EventArgs e)
    {
      // the event
      ListBoxEvts.Items.Insert(0, string.Format("{0}: Page_Init", DateTime.Now.ToString("hh:mm:ss")));
    }
 
    protected void Page_Load(object sender, EventArgs e)
    {
      // the event
      ListBoxEvts.Items.Insert(0, string.Format("{0}: Page_Load", DateTime.Now.ToString("hh:mm:ss")));
    }
 
    protected void ButtonValider_Click(object sender, EventArgs e)
    {
      // the event
      ListBoxEvts.Items.Insert(0, string.Format("{0}: ButtonValider_Click", DateTime.Now.ToString("hh:mm:ss")));
    }
  }
}

Die Klasse [_Default] (Zeile 5) verarbeitet drei Ereignisse:

  • das Init-Ereignis (Zeile 7), das auftritt, wenn die Seite initialisiert wurde
  • das Load-Ereignis (Zeile 13), das auftritt, wenn die Seite vom Webserver geladen wurde. Das Init-Ereignis tritt vor dem Load-Ereignis auf.
  • das Click-Ereignis auf der Schaltfläche „ButtonValider“ (Zeile 19), das auftritt, wenn der Benutzer auf die Schaltfläche [Validate] klickt

Die Behandlung jedes dieser drei Ereignisse erfolgt durch Hinzufügen einer Meldung zur Listbox-Komponente mit dem Namen „ListBoxEvts“. Diese Meldung zeigt die Uhrzeit und den Namen des Ereignisses an. Jede Meldung wird an den Anfang der Liste gesetzt. Daher sind die Meldungen am Anfang der Liste die aktuellsten.

Wenn das Projekt ausgeführt wird, wird die folgende Seite angezeigt:

In [1] sehen wir, dass die Ereignisse „Page_Init“ und „Page_Load“ in dieser Reihenfolge aufgetreten sind. Denken Sie daran, dass das jüngste Ereignis ganz oben in der Liste steht. Wenn der Browser die Seite [Default.aspx] direkt über ihre URL [2] anfordert, geschieht dies mithilfe eines HTTP-Befehls (HyperText Transfer Protocol) namens GET. Sobald die Seite im Browser geladen ist, löst der Benutzer Ereignisse auf der Seite aus. Beispielsweise klickt er auf die Schaltfläche [Submit] [3]. Die vom Benutzer ausgelösten Ereignisse, sobald die Seite im Browser geladen ist, initiieren eine Anfrage an die Seite [Default.aspx], diesmal jedoch unter Verwendung eines HTTP-Befehls namens POST. Zusammenfassend lässt sich sagen:

  • Das anfängliche Laden einer Seite P in einem Browser erfolgt über einen HTTP-GET-Vorgang
  • die anschließend auf der Seite auftretenden Ereignisse generieren jedes Mal eine neue Anfrage an dieselbe Seite P, diesmal jedoch unter Verwendung eines HTTP-POST-Befehls. Eine Seite P kann feststellen, ob sie mit einem GET- oder einem POST-Befehl angefordert wurde, wodurch sie sich bei Bedarf anders verhalten kann – was in der Regel der Fall ist.

Erste Anfrage für eine ASPX-Seite: GET

  • In [1] fordert der Browser die ASPX-Seite über eine HTTP-GET-Anfrage ohne Parameter an.
  • In [2] sendet der Webserver die HTML-Ausgabe der angeforderten ASPX-Seite zurück.

Behandlung eines Ereignisses, das auf der vom Browser angezeigten Seite ausgelöst wird: POST

  • In [1] fordert der Browser, wenn ein Ereignis auf der HTML-Seite eintritt, die zuvor über einen GET-Vorgang abgerufene ASPX-Seite erneut an, diesmal jedoch mit einer HTTP-POST-Anfrage, der Parameter beigefügt sind. Diese Parameter sind die Werte der Komponenten, die sich innerhalb des <form>-Tags der vom Browser angezeigten HTML-Seite befinden. Diese Werte werden als vom Client übermittelte Werte bezeichnet. Sie werden von der ASPX-Seite zur Bearbeitung der Client-Anfrage verwendet.
  • In [2] sendet der Webserver die HTML-Ausgabe der ursprünglich per POST angeforderten ASPX-Seite zurück oder die einer anderen Seite, falls eine Seitenübertragung oder Weiterleitung stattgefunden hat.

Kehren wir zu unserer Beispielseite zurück:

  • In [2] wurde die Seite über eine GET-Anfrage abgerufen.
  • In [1] sehen wir die beiden Ereignisse, die während dieser GET-Anfrage auftraten

Wenn der Benutzer oben auf die Schaltfläche [Validate] [3] klickt, wird die Seite [Default.aspx] über eine POST-Anfrage angefordert. Dieser POST wird von Parametern begleitet, die die Werte aller Komponenten enthalten, die im <form>-Tag der Seite [Default.aspx] enthalten sind: die beiden TextBoxen [TextBoxName, TextBoxAge], die Schaltfläche [SubmitButton] und die Liste [EventListBox]. Die gesendeten Werte für die Komponenten lauten wie folgt:

  • TextBox: der eingegebene Wert
  • Button: der Button-Text, in diesem Fall „Validate“
  • ListBox: der Text der in der ListBox ausgewählten Meldung

Als Antwort auf den POST-Request erhalten wir Seite [4]. Dies ist wiederum die Seite [Default.aspx]. Dies ist normales Verhalten, sofern keine Seitenübergabe oder Umleitung durch die Ereignisbehandler der Seite stattfindet. Wir können sehen, dass zwei neue Ereignisse aufgetreten sind:

  • das Page_Load-Ereignis, das beim Laden der Seite ausgelöst wurde
  • das ButtonValider_Click-Ereignis, das auftrat, als die Schaltfläche [Validate] angeklickt wurde

Beachten Sie:

  • das Page_Init-Ereignis während des HTTP-POST-Vorgangs nicht auftrat, während es beim HTTP-GET-Vorgang auftrat
  • Das Page_Load-Ereignis tritt jedes Mal auf, egal ob es sich um einen GET- oder einen POST-Vorgang handelt. In dieser Methode müssen wir im Allgemeinen wissen, ob es sich um einen GET- oder einen POST-Vorgang handelt.
  • Nach dem POST wurde die Seite [Default.aspx] mit den von den Ereignishandlern vorgenommenen Änderungen an den Client zurückgesendet. Dies ist immer der Fall. Sobald die Ereignisse einer Seite P verarbeitet wurden, wird dieselbe Seite P an den Client zurückgesendet. Es gibt zwei Möglichkeiten, diese Regel zu durchbrechen. Der zuletzt ausgeführte Ereignishandler kann
    • den Ausführungsfluss auf eine andere Seite P2 übertragen.
    • den Browser des Clients auf eine andere Seite P2 umleiten.

In beiden Fällen ist es die Seite P2, die an den Browser zurückgesendet wird. Die beiden Methoden weisen Unterschiede auf, auf die wir später eingehen werden.

  • Das ButtonValider_Click-Ereignis trat nach dem Page_Load-Ereignis ein. Daher ist es dieser Handler, der entscheiden kann, ob an eine Seite P2 übergeben oder dorthin umgeleitet wird.
  • Die Ereignisliste [4] behielt die beiden Ereignisse bei, die beim anfänglichen GET-Laden der Seite [Default.aspx] angezeigt wurden. Dies ist überraschend, da die Seite [Default.aspx] während des POST-Vorgangs neu erstellt wurde. Wir sollten die Seite [Default.aspx] mit ihren Designwerten und somit eine leere ListBox sehen. Die Ausführung der Handler Page_Load und ButtonValider_Click sollte diese dann mit zwei Meldungen füllen. Es sind jedoch vier vorhanden. Dies lässt sich durch den VIEWSTATE-Mechanismus erklären. Während der anfänglichen GET-Anfrage sendet der Webserver die Seite [Default.aspx] mit einem HTML-Tag <input type="hidden" ...>, das als verstecktes Feld bezeichnet wird (Zeile 10 unten).
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><title>
        Introduction ASP.NET
</title></head>
<body>
  <h3>Introduction à ASP.NET</h3>
  <form name="form1" method="post" action="default.aspx" id="form1">
<div>
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKLTMzMTEyNDMxMg9kFgICAw9kFgICBw8QZBAVAhMwNjoxNjozNjogUGFnZV9Mb2FkEzA2OjE2OjM2OiBQYWdlX0luaXQVAhMwNjoxNjozNjogUGFnZV9Mb2FkEzA2OjE2OjM2OiBQYWdlX0luaXQUKwMCZ2dkZGRW1AnTL8f/q7h2MXBLxctKD1UKfg==" />
</div>
..............................

Im Feld „__VIEWSTATE“ codiert der Webserver die Werte aller Komponenten der Seite. Dies geschieht sowohl bei der anfänglichen GET-Anfrage als auch bei den nachfolgenden POST-Anfragen. Wenn eine POST-Anfrage an Seite P gesendet wird:

  • fordert der Browser die Seite P an, indem er die Werte aller Komponenten innerhalb des <form>-Tags in seiner Anfrage sendet. Oben sehen wir, dass sich die Komponente „__VIEWSTATE“ innerhalb des <form>-Tags befindet. Ihr Wert wird daher während einer POST-Anfrage an den Server gesendet.
  • Seite P wird instanziiert und mit ihren Konstruktorwerten initialisiert
  • Die Komponente „__VIEWSTATE“ wird verwendet, um die Werte wiederherzustellen, die die Komponenten hatten, als Seite P zuvor übermittelt wurde. Auf diese Weise ruft beispielsweise die Liste der Ereignisse [4] die ersten beiden Nachrichten ab, die sie hatte, als sie als Antwort auf die anfängliche GET-Anfrage des Browsers gesendet wurde.
  • Die Komponenten von Seite P nehmen dann die vom Browser gesendeten Werte an. Zu diesem Zeitpunkt befindet sich das Formular auf Seite P in dem Zustand, in dem der Benutzer es gesendet hat.
  • Das Page_Load-Ereignis wird verarbeitet. Hier wird eine Nachricht zur Liste der Ereignisse [4] hinzugefügt.
  • Das Ereignis, das die POST-Anfrage ausgelöst hat, wird verarbeitet. Hier fügt ButtonValider_Click eine Nachricht zur Ereignisliste [4] hinzu.
  • Seite P wird zurückgegeben. Die Komponenten haben die folgenden Werte:
    • entweder den gesendeten Wert, d. h. den Wert, den die Komponente im Formular hatte, als sie an den Server gesendet wurde
    • oder einen Wert, der von einem der Ereignisbehandler bereitgestellt wurde.

In unserem Beispiel

  • behalten die beiden TextBox-Komponenten ihre gesendeten Werte bei, da die Ereignisbehandler diese nicht ändern
  • die Liste der Ereignisse [4] erhält ihren gesendeten Wert zurück, d. h. alle bereits aufgeführten Ereignisse sowie zwei neue Ereignisse, die durch die Methoden Page_Load und ButtonValider_Click erstellt wurden.

Der VIEWSTATE-Mechanismus kann auf Komponentenebene aktiviert oder deaktiviert werden. Deaktivieren wir ihn für die [ListBoxEvts]-Komponente:

  • In [1] ist der VIEWSTATE der [ListBoxEvts]-Komponente deaktiviert. Der der TextBox [2] ist standardmäßig aktiviert.
  • In [3] werden die beiden Ereignisse nach dem anfänglichen GET zurückgegeben
  • In [4] haben wir das Formular ausgefüllt und auf die Schaltfläche [Validate] geklickt. Es wird eine POST-Anfrage an die Seite [Default.aspx] gesendet.
  • In [6] das Ergebnis, das nach dem Klicken auf die Schaltfläche [Validate] zurückgegeben wurde
  • Der Mechanismus des aktivierten VIEWSTATE erklärt, warum die TextBoxen [7] ihre in [4] gesendeten Werte beibehalten haben
  • Der deaktivierte VIEWSTATE-Mechanismus erklärt, warum die [ListBoxEvts]-Komponente [8] ihren Inhalt [5] nicht beibehalten hat.

2.3. Verarbeitung übermittelter Werte

Hier konzentrieren wir uns auf die Werte, die von den beiden TextBoxen gesendet werden, wenn der Benutzer auf die Schaltfläche [Validate] klickt. Die Seite [Default.aspx] im [Design]-Modus ändert sich wie folgt:

Der Quellcode für das unter [1] hinzugefügte Element lautet wie folgt:


  <p>
    Eléments postés au serveur :
    <asp:Label ID="LabelPost" runat="server"></asp:Label>
</p>

Wir verwenden die Komponente [LabelPost], um die in den beiden TextBoxen [2] eingegebenen Werte anzuzeigen. Der Code für den Ereignishandler [Default.aspx.cs] ändert sich wie folgt:


using System;
 
namespace Intro
{
  public partial class _Default : System.Web.UI.Page
  {
    protected void Page_Init(object sender, EventArgs e)
    {
      // the event
      ListBoxEvts.Items.Insert(0, string.Format("{0}: Page_Init", DateTime.Now.ToString("hh:mm:ss")));
    }
 
    protected void Page_Load(object sender, EventArgs e)
    {
      // the event
      ListBoxEvts.Items.Insert(0, string.Format("{0}: Page_Load", DateTime.Now.ToString("hh:mm:ss")));
    }

    protected void ButtonValider_Click(object sender, EventArgs e)
    {
      // the event
      ListBoxEvts.Items.Insert(0, string.Format("{0}: ButtonValider_Click", DateTime.Now.ToString("hh:mm:ss")));
      // display name and age
      LabelPost.Text = string.Format("nom={0}, age={1}", TextBoxNom.Text.Trim(), TextBoxAge.Text.Trim());
    }
  }
}

In Zeile 24 aktualisieren wir die LabelPost-Komponente:

  • LabelPost ist vom Typ [System.Web.UI.WebControls.Label] (siehe Default.aspx.designer.cs). Die Text-Eigenschaft stellt den von der Komponente angezeigten Text dar.
  • TextBoxName und TextBoxAge sind vom Typ [System.Web.UI.WebControls.TextBox]. Die Text-Eigenschaft einer TextBox-Komponente ist der Text, der im Eingabefeld angezeigt wird.
  • Die Methode Trim() entfernt alle Leerzeichen, die vor oder nach einer Zeichenfolge stehen

Wie bereits erläutert, haben die Seitenkomponenten bei Ausführung der ButtonValider_Click-Methode die Werte, die sie hatten, als die Seite vom Benutzer übermittelt wurde. Die Text-Eigenschaften der beiden TextBoxen enthalten daher den vom Benutzer im Browser eingegebenen Text.

Hier ein Beispiel:

  • in [1] die gesendeten Werte
  • in [2] die Antwort des Servers.
  • in [3] haben die TextBoxen ihre gesendeten Werte über den aktivierten VIEWSTATE-Mechanismus wiedererlangt
  • in [4] stammen die Meldungen der ListBoxEvts-Komponente aus den Methoden Page_Init, Page_Load und ButtonValider_Click sowie aus einem deaktivierten VIEWSTATE
  • in [5] hat die LabelPost-Komponente ihren Wert über die ButtonValider_Click-Methode erhalten. Wir haben die beiden vom Benutzer in die beiden TextBoxen [1] eingegebenen Werte erfolgreich abgerufen.

Wie oben gezeigt, ist der übermittelte Wert für das Alter die Zeichenfolge „yy“, ein ungültiger Wert. Wir werden der Seite Komponenten hinzufügen, die als Validatoren bezeichnet werden. Sie dienen dazu, die Gültigkeit der übermittelten Daten zu überprüfen. Diese Gültigkeit kann an zwei Stellen überprüft werden:

  • auf der Client-Seite. Eine Validator-Konfigurationsoption ermöglicht es Ihnen, zu wählen, ob die Prüfungen im Browser durchgeführt werden sollen oder nicht. Sie werden dann durch JavaScript-Code durchgeführt, der in die HTML-Seite eingebettet ist. Wenn der Benutzer die in das Formular eingegebenen Werte übermittelt, werden diese zunächst durch den JavaScript-Code geprüft. Wenn eine der Prüfungen fehlschlägt, wird die Übermittlung nicht durchgeführt. Dies vermeidet einen Roundtrip zum Server und macht die Seite reaktionsschneller.
  • auf dem Server. Während die clientseitige Validierung optional sein kann, ist die serverseitige Validierung obligatorisch, unabhängig davon, ob eine clientseitige Validierung durchgeführt wurde. Der Grund dafür ist, dass eine Seite, wenn sie übermittelte Werte empfängt, keine Möglichkeit hat zu wissen, ob diese vor dem Absenden vom Client validiert wurden. Auf der Serverseite muss der Entwickler daher immer die Gültigkeit der übermittelten Daten überprüfen.

Die Seite [Default.aspx] entwickelt sich wie folgt:


<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="Intro._Default" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
  <title>Introduction ASP.NET</title>
</head>
<body>
  <h3>Introduction à ASP.NET</h3>
  <form id="form1" runat="server">
  <div>
    <table>
      <tr>
        <td>
          Nom</td>
        <td>
          <asp:TextBox ID="TextBoxNom" runat="server"></asp:TextBox>
        </td>
        <td>
          <asp:RequiredFieldValidator ID="RequiredFieldValidatorNom" runat="server" 
            ControlToValidate="TextBoxNom" Display="Dynamic" 
            ErrorMessage="Donnée obligatoire !"></asp:RequiredFieldValidator>
        </td>
      </tr>
      <tr>
        <td>
          Age</td>
        <td>
          <asp:TextBox ID="TextBoxAge" runat="server"></asp:TextBox>
        </td>
        <td>
          <asp:RequiredFieldValidator ID="RequiredFieldValidatorAge" runat="server" 
            ControlToValidate="TextBoxAge" Display="Dynamic" 
            ErrorMessage="Donnée obligatoire !"></asp:RequiredFieldValidator>
          <asp:RangeValidator ID="RangeValidatorAge" runat="server" 
            ControlToValidate="TextBoxAge" Display="Dynamic" 
            ErrorMessage="Tapez un nombre entre 1 et 150 !" MaximumValue="150" 
            MinimumValue="1" Type="Integer"></asp:RangeValidator>
        </td>
      </tr>
    </table>
  </div>
  <asp:Button ID="ButtonValider" runat="server" onclick="ButtonValider_Click" 
    Text="Valider" CausesValidation="False"/>
  <hr />
  <p>
    Evénements traités par le serveur</p>
  <p>
    <asp:ListBox ID="ListBoxEvts" runat="server" EnableViewState="False">
    </asp:ListBox>
  </p>
  <p>
    Eléments postés au serveur :
    <asp:Label ID="LabelPost" runat="server"></asp:Label>
  </p>
  <p>
    Eléments validés par le serveur :
    <asp:Label ID="LabelValidation" runat="server"></asp:Label>
  </p>
  <asp:Label ID="LabelErreursSaisie" runat="server" ForeColor="Red"></asp:Label>
  </form>
</body>
</html>

In den Zeilen 20, 32 und 35 wurden Validatoren hinzugefügt. In Zeile 58 wird ein Label-Steuerelement verwendet, um die gültigen eingegebenen Werte anzuzeigen. In Zeile 60 wird ein Label-Steuerelement verwendet, um bei Eingabefehlern eine Fehlermeldung anzuzeigen.

Die Seite [Default.aspx] im [Design]-Modus sieht wie folgt aus:

  • Die Komponenten [1] und [2] sind vom Typ „RequiredFieldValidator“. Dieser Validator überprüft, ob ein Eingabefeld nicht leer ist.
  • Komponente [3] ist ein RangeValidator. Dieser Validator überprüft, ob ein Eingabefeld einen Wert zwischen zwei Grenzwerten enthält.
  • In [4] sind die Eigenschaften des Validators [1] aufgeführt.

Wir werden die beiden Validator-Typen anhand ihrer Tags im Code der Seite [Default.aspx] demonstrieren:


          <asp:RequiredFieldValidator ID="RequiredFieldValidatorNom" runat="server" 
            ControlToValidate="TextBoxNom" Display="Dynamic" 
ErrorMessage="Donnée obligatoire !"></asp:RequiredFieldValidator>
  • ID: die Kennung der Komponente
  • ControlToValidate: Der Name der Komponente, deren Wert validiert wird. Hier möchten wir sicherstellen, dass die TextBoxNom-Komponente keinen leeren Wert enthält (leere Zeichenfolge oder eine Folge von Leerzeichen)
  • ErrorMessage: Fehlermeldung, die im Validator angezeigt werden soll, wenn die Daten ungültig sind.
  • EnableClientScript: Ein boolescher Wert, der angibt, ob der Validator auch auf der Client-Seite ausgeführt werden soll. Dieses Attribut hat den Standardwert „True“, wenn es nicht wie oben gezeigt explizit gesetzt wird.
  • Display: Anzeigemodus des Validators. Es gibt zwei Modi:
    • static (Standard): Der Validator nimmt Platz auf der Seite ein, auch wenn er keine Fehlermeldung anzeigt
    • dynamic: Der Validator nimmt keinen Platz auf der Seite ein, wenn er keine Fehlermeldung anzeigt.

          <asp:RangeValidator ID="RangeValidatorAge" runat="server" 
            ControlToValidate="TextBoxAge" Display="Dynamic" 
            ErrorMessage="Tapez un nombre entre 1 et 150 !" MaximumValue="150" 
            MinimumValue="1" Type="Integer"></asp:RangeValidator>
  • Type: Der Typ der zu validierenden Daten. Hier ist das Alter eine ganze Zahl.
  • MinimumValue, MaximumValue: die Grenzen, innerhalb derer der validierte Wert liegen muss

Die Konfiguration der Komponente, die den POST-Aufruf auslöst, spielt eine Rolle für den Validierungsmodus. In diesem Fall ist diese Komponente die Schaltfläche [Validate]:


  <asp:Button ID="ButtonValider" runat="server" onclick="ButtonValider_Click"  Text="Valider" CausesValidation="True" />
  • CausesValidation: Legt den automatischen Modus oder den Namen der serverseitigen Validierungen fest. Dieses Attribut hat den Standardwert „True“, sofern nicht ausdrücklich anders angegeben. In diesem Fall
    • werden auf der Clientseite Validatoren ausgeführt, bei denen EnableClientScript auf „True“ gesetzt ist. Die POST-Anfrage wird nur gesendet, wenn alle clientseitigen Validatoren erfolgreich sind.
    • Auf der Serverseite werden alle Validatoren auf der Seite automatisch ausgeführt, bevor das Ereignis, das den POST-Aufruf ausgelöst hat, verarbeitet wird. In diesem Fall würden sie ausgeführt, bevor die Methode `ButtonValider_Click` aufgerufen wird. Innerhalb dieser Methode können Sie feststellen, ob alle Validierungen erfolgreich waren oder nicht. Page.IsValid ist „True“, wenn alle erfolgreich waren, andernfalls „False“. Im letzteren Fall können Sie die Verarbeitung des Ereignisses, das den POST ausgelöst hat, abbrechen. Die gesendete Seite wird genau so zurückgegeben, wie sie übermittelt wurde. Die Validatoren, die fehlgeschlagen sind, zeigen dann ihre Fehlermeldung an (Attribut ErrorMessage).

Wenn CausesValidation auf False gesetzt ist,

  • werden auf der Clientseite keine Validatoren ausgeführt
  • auf der Serverseite ist es Sache des Entwicklers, die Ausführung der Validatoren der Seite anzufordern. Dies geschieht mithilfe der Methode Page.Validate(). Abhängig von den Validierungsergebnissen setzt diese Methode die Eigenschaft Page.IsValid auf „True“ oder „False“.

In [Default.aspx.cs] sieht der Code für das ButtonValider_Click-Ereignis wie folgt aus:


protected void ButtonValider_Click(object sender, EventArgs e)
    {
      // the event
      ListBoxEvts.Items.Insert(0, string.Format("{0}: ButtonValider_Click", DateTime.Now.ToString("hh:mm:ss")));
      // display name and age
      LabelPost.Text = string.Format("nom={0}, age={1}", TextBoxNom.Text.Trim(), TextBoxAge.Text.Trim());
      // is the page valid?
      Page.Validate();
      if (!Page.IsValid)
      {
        // global error msg
        LabelErreursSaisie.Text = "Veuillez corriger les erreurs de saisie...";
        LabelErreursSaisie.Visible = true;
        return;
      }
      // hide error msg
      LabelErreursSaisie.Visible = false;
      // displays validated name and age
      LabelValidation.Text = string.Format("nom={0}, age={1}", TextBoxNom.Text.Trim(), TextBoxAge.Text.Trim());
}

Wenn für die Schaltfläche [Validate] das Attribut CausesValidation auf True gesetzt ist und für die Validatoren das Attribut EnableClientScript auf True gesetzt ist, wird die Methode ButtonValider_Click nur ausgeführt, wenn die übermittelten Werte gültig sind. Man könnte sich dann fragen, welchen Zweck der Code ab Zeile 8 hat. Es ist wichtig zu bedenken, dass es immer möglich ist, ein clientseitiges Skript zu schreiben, das unüberprüfte Werte an die Seite [Default.aspx] übermittelt. Daher muss diese Seite die Gültigkeitsprüfungen immer erneut durchführen.

  • Zeile 8: Löst die Ausführung aller Validatoren auf der Seite aus. Wenn das Attribut „CausesValidation“ der Schaltfläche [Validate] auf „True“ gesetzt ist, geschieht dies automatisch, und es besteht keine Notwendigkeit, dies zu wiederholen. Hier liegt eine Redundanz vor.
  • Zeilen 9–15: Fall, in dem einer der Validatoren fehlgeschlagen ist
  • Zeilen 16–19: Fall, in dem alle Validatoren erfolgreich waren

Hier sind zwei Beispiele für die Ausführung:

  • in [1] ein Ausführungsbeispiel für den Fall, dass:
    • die Eigenschaft CausesValidation der Schaltfläche [Validate] auf True gesetzt ist
    • die Eigenschaft „EnableClientScript“ der Validatoren auf „True“ gesetzt ist

Die Fehlermeldungen [2] wurden von den Validatoren angezeigt, die auf der Clientseite durch den JavaScript-Code der Seite ausgeführt wurden. Es wurde keine POST-Anfrage an den Server gesendet, wie die Beschriftung der geposteten Elemente [3] zeigt.

  • In [4] ein Beispiel für die Ausführung in dem Fall, in dem:
    • die Eigenschaft CausesValidation der Schaltfläche [Validate] auf False gesetzt ist
    • die Validatoren die Eigenschaft „EnableClientScript“ auf „False“ gesetzt haben

Die Fehlermeldungen [5] wurden von den Validatoren angezeigt, die auf der Serverseite ausgeführt wurden. Wie in [6] gezeigt, wurde tatsächlich eine POST-Anfrage an den Server gesendet. In [7] die Fehlermeldung, die von der Methode [ButtonValider_Click] im Falle von Eingabefehlern angezeigt wird.

  • In [8] ein Beispiel mit gültigen Daten. [9,10] zeigen, dass die gesendeten Elemente validiert wurden. Setzen Sie bei wiederholten Tests die Eigenschaft „EnableViewState“ des [LabelValidation]-Labels auf „False“, damit die Validierungsmeldung nicht über mehrere Durchläufe hinweg angezeigt bleibt.

2.4. Verwaltung von Daten im Anwendungsbereich

Werfen wir noch einmal einen Blick auf die Ausführungsarchitektur einer ASPX-Seite:

Die ASPX-Seitenklasse wird zu Beginn der Client-Anfrage instanziiert und am Ende derselben zerstört. Daher kann sie nicht zum Speichern von Daten zwischen Anfragen verwendet werden. Möglicherweise möchten Sie zwei Arten von Daten speichern:

  • Daten, die von allen Benutzern der Webanwendung gemeinsam genutzt werden. Dabei handelt es sich in der Regel um schreibgeschützte Daten. Zur Umsetzung dieser gemeinsamen Datennutzung werden drei Dateien verwendet:
    • [Web.Config]: die Anwendungskonfigurationsdatei
    • [Global.asax, Global.asax.cs]: Ermöglichen es Ihnen, eine Klasse zu definieren, die als globale Anwendungsklasse bezeichnet wird und deren Lebensdauer der der Anwendung entspricht, sowie Handler für bestimmte Ereignisse derselben Anwendung.

Mit der globalen Anwendungsklasse können Sie Daten definieren, die für alle Anfragen aller Benutzer verfügbar sind.

  • Daten, die über Anfragen desselben Clients hinweg gemeinsam genutzt werden. Diese Daten werden in einem Objekt namens „Session“ gespeichert. Wir bezeichnen dies als Client-Session, um den Speicher des Clients zu bezeichnen. Alle Anfragen eines Clients haben Zugriff auf diese Session. Sie können dort Informationen speichern und lesen

Oben zeigen wir die Speichertypen, auf die eine ASPX-Seite Zugriff hat:

  • den Anwendungsspeicher, der hauptsächlich schreibgeschützte Daten enthält und für alle Benutzer zugänglich ist.
  • den Speicher eines bestimmten Benutzers oder die Sitzung, die Lese-/Schreibdaten enthält und für aufeinanderfolgende Anfragen desselben Benutzers zugänglich ist.
  • Nicht oben dargestellt ist der Anforderungsspeicher oder Anforderungskontext. Die Anforderung eines Benutzers kann von mehreren aufeinanderfolgenden ASPX-Seiten verarbeitet werden. Der Anforderungskontext ermöglicht es Seite 1, Informationen an Seite 2 weiterzugeben.

Hier interessieren uns Daten im Anwendungsbereich, die von allen Benutzern gemeinsam genutzt werden. Die globale Klasse der Anwendung kann wie folgt erstellt werden:

  • Fügen Sie in [1] ein neues Element zum Projekt hinzu
  • Fügen Sie in [2] die globale Anwendungsklasse hinzu
  • Behalten Sie in [3] den Standardnamen [Global.asax] für das neue Element bei
  • in [4] wurden dem Projekt zwei neue Dateien hinzugefügt
  • in [5] wird der Markup-Code für [Global.asax] angezeigt

<%@ Application Codebehind="Global.asax.cs" Inherits="Intro.Global" Language="C#" %>
  • Das Application-Tag ersetzt das Page-Tag, das wir für [Default.aspx] hatten. Es identifiziert die globale Anwendungsklasse
  • Codebehind: definiert die Datei, in der die globale Anwendungsklasse definiert ist
  • Inherits: definiert den Namen dieser Klasse

Die generierte Klasse „Intro.Global“ sieht wie folgt aus:


using System;
 
namespace Intro
{
  public class Global : System.Web.HttpApplication
  {
 
    protected void Application_Start(object sender, EventArgs e)
    {
 
    }
 
    protected void Session_Start(object sender, EventArgs e)
    {
 
    }
 
    protected void Application_BeginRequest(object sender, EventArgs e)
    {
 
    }
 
    protected void Application_AuthenticateRequest(object sender, EventArgs e)
    {
 
    }
 
    protected void Application_Error(object sender, EventArgs e)
    {
 
    }
 
    protected void Session_End(object sender, EventArgs e)
    {
 
    }
 
    protected void Application_End(object sender, EventArgs e)
    {
 
    }
  }
}
  • Zeile 5: Die globale Anwendungsklasse leitet sich von der HttpApplication-Klasse ab

Die Klasse wird mit Vorlagen für Anwendungsereignisbehandler generiert:

  • Zeilen 8, 38: Behandlung der Ereignisse „Application_Start“ (Anwendungsstart) und „Application_End“ (Anwendungsbeendigung, wenn der Webserver gestoppt wird oder der Administrator die Anwendung entlädt)
  • Zeilen 13, 33: Behandeln Sie das Ereignis „Session_Start“ (Start einer neuen Client-Sitzung, wenn ein neuer Client eintrifft oder eine bestehende Sitzung abläuft) und das Ereignis „Session_End“ (Ende einer Client-Sitzung, entweder explizit durch Programmierung oder implizit durch Überschreiten der zulässigen Sitzungsdauer).
  • Zeile 28: Behandelt das Application_Error-Ereignis (Auftreten einer Ausnahme, die vom Anwendungscode nicht behandelt und an den Server weitergeleitet wird)
  • Zeile 18: Behandelt das Application_BeginRequest-Ereignis (Eingang einer neuen Anfrage).
  • Zeile 23: Behandelt das Application_AuthenticateRequest-Ereignis (tritt auf, wenn sich ein Benutzer authentifiziert hat).

Die [Application_Start]-Methode wird häufig verwendet, um die Anwendung auf der Grundlage der in [Web.Config] enthaltenen Informationen zu initialisieren. Die bei der ersten Projekterstellung generierte Methode sieht wie folgt aus:


<?xml version="1.0" encoding="utf-8"?>
 
<configuration>
    <configSections>
...
    </configSections>  
 
    <appSettings/>
    <connectionStrings/>
 
    <system.web>
...
    </system.web>
 
    <system.codedom>
....
    </system.codedom>
 
    <!-- 
        La section system.webServer est requise pour exécuter ASP.NET AJAX sur Internet
        Information Services 7.0.  Elle n'est pas nécessaire pour les versions précédentes d'IIS.
    -->
    <system.webServer>
...
    </system.webServer>
 
    <runtime>
....
    </runtime>
 
</configuration>

Für unsere aktuelle Anwendung ist diese Datei nicht erforderlich. Wenn wir sie löschen oder umbenennen, funktioniert die Anwendung weiterhin normal. Wir konzentrieren uns auf die Tags in den Zeilen 8 und 9:

  • Mit <appsettings> können Sie ein Informationswörterbuch definieren
  • <connectionStrings> ermöglicht es Ihnen, Verbindungszeichenfolgen zu Datenbanken zu definieren

Betrachten Sie die folgende [Web.config]-Datei:


<?xml version="1.0" encoding="utf-8"?>
 
<configuration>
    <configSections>
...
    </configSections>  
 
  <appSettings>
    <add key="cle1" value="valeur1"/>
    <add key="cle2" value="valeur2"/>
  </appSettings>
  <connectionStrings>
    <add connectionString="connectionString1" name="conn1"/>
  </connectionStrings>
 
    <system.web>
...
 

Diese Datei kann von der folgenden globalen Anwendungsklasse verwendet werden:


using System;
using System.Configuration;
 
namespace Intro
{
  public class Global : System.Web.HttpApplication
  {
    public static string Param1 { get; set; }
    public static string Param2 { get; set; }
    public static string ConnString1 { get; set; }
    public static string Erreur { get; set; }
 
    protected void Application_Start(object sender, EventArgs e)
    {
      try
      {
        Param1 = ConfigurationManager.AppSettings["cle1"];
        Param2 = ConfigurationManager.AppSettings["cle2"];
        ConnString1 = ConfigurationManager.ConnectionStrings["conn1"].ConnectionString;
      }
      catch (Exception ex)
      {
        Erreur = string.Format("Erreur de configuration : {0}", ex.Message);
      }
    }
 
    protected void Session_Start(object sender, EventArgs e)
    {
 
    }
 
  }
}
  • Zeilen 8–11: vier statische Eigenschaften P. Da die Klasse „Global“ dieselbe Lebensdauer wie die Anwendung hat, hat jede an die Anwendung gerichtete Anfrage über die Syntax „Global.P“ Zugriff auf diese P-Eigenschaften.
  • Zeilen 17–19: Auf die Datei [Web.config] kann über die Klasse [System.Configuration.ConfigurationManager] zugegriffen werden
  • Zeilen 17–18: Ruft die Elemente des <appSettings>-Tags aus der [Web.config]-Datei über das key-Attribut ab.
  • Zeile 19: Ruft die Elemente des <connectionStrings>-Tags aus der [Web.config]-Datei über das name-Attribut ab.

Auf die statischen Attribute in den Zeilen 8–11 kann von jedem Ereignishandler in geladenen ASPX-Seiten aus zugegriffen werden. Wir verwenden sie im [Page_Load]-Handler der Seite [Default.aspx]:


    protected void Page_Load(object sender, EventArgs e)
    {
      // the event
      ListBoxEvts.Items.Insert(0, string.Format("{0}: Page_Load", DateTime.Now.ToString("hh:mm:ss")));
      // retrieve information from the global application class
      LabelGlobal.Text = string.Format("Param1={0},Param2={1},ConnString1={2},Erreur={3}", Global.Param1, Global.Param2, Global.ConnString1, Global.Erreur);
}
  • Zeile 6: Die vier statischen Eigenschaften der globalen Anwendungsklasse werden verwendet, um ein neues Label auf der Seite [Default.aspx] zu füllen

Zur Laufzeit erhalten wir das folgende Ergebnis:

Oben sehen wir, dass die Parameter aus [web.config] korrekt abgerufen wurden. Die globale Anwendungsklasse ist der richtige Ort, um Informationen zu speichern, die von allen Benutzern gemeinsam genutzt werden.

2.5. Verwaltung von Daten im Sitzungsbereich

Hier interessiert uns, wie Informationen über mehrere Anfragen eines bestimmten Benutzers hinweg gespeichert werden können:

Jeder Benutzer verfügt über einen eigenen Speicher, der als seine Sitzung bezeichnet wird.

Wir haben gesehen, dass die globale Anwendungsklasse über zwei Handler zur Verwaltung von Ereignissen verfügt:

  • Session_Start: Beginn einer Sitzung
  • Session_end: Ende einer Sitzung

Der Sitzungsmechanismus funktioniert wie folgt:

  • Wenn ein Benutzer seine erste Anfrage stellt, erstellt der Webserver ein Sitzungstoken und weist es dem Benutzer zu. Dieses Token ist eine für jeden Benutzer eindeutige Zeichenfolge. Es wird vom Server in der Antwort auf die erste Anfrage des Benutzers gesendet.
  • Bei nachfolgenden Anfragen fügt der Benutzer (der Webbrowser) das zugewiesene Sitzungstoken in seine Anfrage ein. Dadurch kann der Webserver ihn wiedererkennen.
  • Eine Sitzung hat eine Zeitüberschreitungsdauer. Wenn der Webserver eine Anfrage von einem Benutzer erhält, berechnet er die Zeit, die seit der vorherigen Anfrage verstrichen ist. Wenn diese Zeit die Sitzungszeitüberschreitung überschreitet, wird eine neue Sitzung für den Benutzer erstellt. Die Daten aus der vorherigen Sitzung gehen verloren. Beim IIS-Webserver (Internet Information Server) von Microsoft haben Sitzungen eine Standardlaufzeit von 20 Minuten. Dieser Wert kann vom Webserver-Administrator geändert werden.
  • Der Webserver erkennt, dass es sich um die erste Anfrage eines Benutzers handelt, da diese Anfrage kein Sitzungstoken enthält. Es ist die einzige.

Jede ASP.NET-Seite hat über die Session-Eigenschaft der Seite vom Typ [System.Web.SessionState.HttpSessionState] Zugriff auf die Sitzung des Benutzers. Wir werden die folgenden P-Eigenschaften und M-Methoden der HttpSessionState-Klasse verwenden:

Name
Typ
Rolle
Item[String key]
P
Die Sitzung kann als Wörterbuch strukturiert sein. Item[key] ist das durch key identifizierte Sitzungselement. Anstelle von [HttpSessionState].Item[key] können Sie auch [HttpSessionState].[key] schreiben.
Löschen
M
löscht das Sitzungswörterbuch
Abbrechen
M
beendet die Sitzung. Die Sitzung ist danach nicht mehr gültig. Mit der nächsten Anfrage des Benutzers beginnt eine neue Sitzung.

Als Beispiel für den Benutzerstatus zählen wir die Anzahl der Klicks eines Benutzers auf die Schaltfläche [Absenden]. Dazu müssen wir einen Zähler in der Sitzung des Benutzers führen.

Die Seite [Default.aspx] ändert sich wie folgt:

Die globale Anwendungsklasse [Global.asax.cs] ändert sich wie folgt:


using System;
using System.Configuration;
 
namespace Intro
{
  public class Global : System.Web.HttpApplication
  {
    public static string Param1 { get; set; }
...
 
    protected void Application_Start(object sender, EventArgs e)
    {
...
    }
 
    protected void Session_Start(object sender, EventArgs e)
    {
      // query counter
      Session["nbRequêtes"] = 0;
    }
 
  }
}

In Zeile 19 verwenden wir die Sitzung des Benutzers, um einen Anforderungszähler zu speichern, der durch den Schlüssel „nbRequests“ identifiziert wird. Dieser Zähler wird vom [ButtonValider_Click]-Handler auf der Seite [Default.aspx] aktualisiert:


using System;
 
namespace Intro
{
  public partial class _Default : System.Web.UI.Page
  {
....
 
    protected void ButtonValider_Click(object sender, EventArgs e)
    {
      // the event
      ListBoxEvts.Items.Insert(0, string.Format("{0}: ButtonValider_Click", DateTime.Now.ToString("hh:mm:ss")));
      // post name and age are displayed
      LabelPost.Text = string.Format("nom={0}, age={1}", TextBoxNom.Text.Trim(), TextBoxAge.Text.Trim());
      // number of requests
      Session["nbRequêtes"] = (int)Session["nbRequêtes"] + 1;
      LabelNbRequetes.Text = Session["nbRequêtes"].ToString();
      // is the page valid?
      Page.Validate();
      if (!Page.IsValid)
      {
...
      }
...
    }
  }
}
  • Zeile 16: Den Anforderungszähler erhöhen
  • Zeile 17: Der Zähler wird auf der Seite angezeigt

Hier ist ein Ausführungsbeispiel:

2.6. Behandlung von GET- und POST-Anfragen beim Laden der Seite

Wir haben erwähnt, dass es zwei Arten von Anfragen an eine ASPX-Seite gibt:

  • die erste Anfrage vom Browser, die mit einem HTTP-GET-Befehl gestellt wird. Der Server antwortet, indem er die angeforderte Seite sendet. Wir gehen davon aus, dass es sich bei dieser Seite um ein Formular handelt, d. h., dass die gesendete ASPX-Seite ein <form runat="server">-Tag enthält.
  • Folgeanfragen, die vom Browser als Reaktion auf bestimmte Benutzeraktionen im Formular gestellt werden. Der Browser sendet dann eine HTTP-POST-Anfrage.

Unabhängig davon, ob es sich um eine GET- oder eine POST-Anfrage handelt, wird die [Page_Load]-Methode ausgeführt. Bei einer GET-Anfrage wird diese Methode in der Regel dazu verwendet, die an den Client-Browser gesendete Seite zu initialisieren. Anschließend bleibt die Seite durch den VIEWSTATE-Mechanismus initialisiert und wird nur durch die Ereignisbehandler geändert, die POST-Anfragen auslösen. Es ist nicht erforderlich, die Seite in Page_Load neu zu initialisieren. Daher muss diese Methode feststellen, ob es sich bei der Client-Anfrage um eine GET- oder eine POST-Anfrage handelt.

Betrachten wir das folgende Beispiel. Wir fügen der Seite [Default.aspx] eine Dropdown-Liste hinzu. Der Inhalt dieser Liste wird im Page_Load-Handler für die GET-Anfrage definiert:

Die Dropdown-Liste wird in [Default.aspx.designer.cs] wie folgt deklariert:


        protected global::System.Web.UI.WebControls.DropDownList DropDownListNoms;

Wir werden die folgenden M-Methoden und P-Eigenschaften der Klasse [DropDownList] verwenden:

Name
Typ
Rolle
Items
P
die ListItemCollection der ListItem-Elemente in der Dropdown-Liste
SelectedIndex
P
der Index (beginnend bei 0) des ausgewählten Elements in der Dropdown-Liste, wenn das Formular übermittelt wird
SelectedItem
P
das ListItem, das in der Dropdown-Liste ausgewählt ist, wenn das Formular übermittelt wird
SelectedValue
P
der Zeichenfolgenwert des ListItem, das bei der Übermittlung des Formulars in der Dropdown-Liste ausgewählt wurde. Wir werden dieses Konzept des Werts in Kürze definieren.

Die ListItem-Klasse für die Elemente in einer Dropdown-Liste wird verwendet, um die <option>-Tags innerhalb des HTML-Tags <select> zu generieren:

1
2
3
4
5
<select ....>
    <option value="val1">texte1</option>
    <option value="val2">texte2</option>
....
</select>

Im <option>-Tag

  • ist text1 der in der Dropdown-Liste angezeigte Text
  • vali ist der vom Browser übermittelte Wert, wenn texti der in der Dropdown-Liste ausgewählte Text ist

Jede Option kann durch ein ListItem-Objekt generiert werden, das mit dem Konstruktor ListItem(string text, string value) erstellt wird.

In [Default.aspx.cs] ändert sich der Code für den [Page_Load]-Handler wie folgt:


    protected void Page_Load(object sender, EventArgs e)
    {
      // the event
      ...
      // retrieve information from the global application class
      ...
      // initialization of name combo only during initial GET
      if (!IsPostBack)
      {
        for (int i = 0; i < 3; i++)
        {
          DropDownListNoms.Items.Add(new ListItem("nom"+i,i.ToString()));
        }
      }
}
  • Zeile 8: Die Page-Klasse verfügt über eine boolesche IsPostBack-Eigenschaft. Im Wesentlichen bedeutet dies, dass die Anfrage des Benutzers ein POST ist. Die Zeilen 10–13 werden daher nur bei der ersten GET-Anfrage des Clients ausgeführt.
  • Zeile 12: Wir fügen der Liste [DropDownListNames] ein Element vom Typ ListItem(string text, string value) hinzu. Der für das (i+1)-te Element angezeigte Text lautet „names“, und der für dieses Element gesendete Wert ist i, falls es ausgewählt wird.

Der [ButtonValider_Click]-Handler wird so geändert, dass er den von der Dropdown-Liste gesendeten Wert anzeigt:


    protected void ButtonValider_Click(object sender, EventArgs e)
    {
      // the event
...
      // display posted values
      LabelPost.Text = string.Format("nom={0}, age={1}, combo={2}", TextBoxNom.Text.Trim(), TextBoxAge.Text.Trim(), DropDownListNoms.SelectedValue);
      // number of requests
...
}

Zeile 6: Der übermittelte Wert für die Liste [DropDownListNames] wird mithilfe der SelectedValue-Eigenschaft der Liste abgerufen. Hier ein Ausführungsbeispiel:

  • in [1] der Inhalt der Dropdown-Liste nach dem ersten GET und unmittelbar vor dem ersten POST
  • in [2] die Seite nach dem ersten POST.
  • in [3] der für die Dropdown-Liste übermittelte Wert. Dies entspricht dem „value“-Attribut des ausgewählten ListItem in der Liste.
  • in [4], die Dropdown-Liste. Sie enthält dieselben Elemente wie nach der ursprünglichen GET-Anfrage. Dies ist auf den VIEWSTATE-Mechanismus zurückzuführen.

Um die Wechselwirkung zwischen dem VIEWSTATE der DropDownListNames-Liste und dem if (!IsPostBack)-Test im Page_Load-Handler von [Default.aspx] zu verstehen, wird der Leser gebeten, den vorherigen Test mit den folgenden Konfigurationen zu wiederholen:

Fall
DropDownListNames.EnableViewState
if(! IsPostBack)-Prüfung in Page_Load von [Default.aspx]
1
true
vorhanden
2
false
vorhanden
3
wahr
fehlt
4
false
nicht vorhanden

Die verschiedenen Tests liefern folgende Ergebnisse:

  1. Dies ist der oben beschriebene Fall
  2. Die Liste wird beim ersten GET-Aufruf gefüllt, nicht jedoch bei den nachfolgenden POST-Anfragen. Da „EnableViewState“ auf „false“ gesetzt ist, ist die Liste nach jedem POST leer
  3. Die Liste wird sowohl nach dem ersten GET als auch während der nachfolgenden POST-Anfragen gefüllt. Da „EnableViewState“ auf „true“ gesetzt ist, gibt es nach dem ersten GET 3 Namen, nach dem ersten POST 6 Namen, nach dem zweiten POST 9 Namen, ...
  4. Die Liste wird sowohl nach dem ersten GET als auch während der nachfolgenden POST-Anfragen gefüllt. Da „EnableViewState“ auf „false“ gesetzt ist, enthält die Liste bei jeder Anfrage nur 3 Namen, unabhängig davon, ob es sich um den ersten GET oder die nachfolgenden POST-Anfragen handelt. Wir beobachten dasselbe Verhalten wie in Fall 1. Es gibt also zwei Möglichkeiten, das gleiche Ergebnis zu erzielen.

2.7. Verwalten des VIEWSTATE von Elementen auf einer ASPX-Seite

Standardmäßig ist die Eigenschaft „EnableViewState“ aller Elemente auf einer ASPX-Seite auf „True“ gesetzt. Jedes Mal, wenn die ASPX-Seite an den Browser des Clients gesendet wird, enthält sie das versteckte Feld „__VIEWSTATE“, dessen Wert eine Zeichenfolge ist, die alle Werte der Komponenten mit der auf „True“ gesetzten Eigenschaft „EnableViewState“ kodiert. Um die Größe dieser Zeichenfolge zu minimieren, können wir versuchen, die Anzahl der Komponenten mit der auf „True“ gesetzten Eigenschaft „EnableViewState“ zu reduzieren.

Sehen wir uns an, wie Komponenten auf einer ASPX-Seite nach einer POST-Anfrage ihre Werte erhalten:

  1. Die ASPX-Seite wird instanziiert. Die Komponenten werden mit ihren Designwerten initialisiert.
  2. Der vom Browser gesendete __VIEWSTATE-Wert wird verwendet, um den Komponenten die Werte zuzuweisen, die sie hatten, als die ASPX-Seite das letzte Mal an den Browser gesendet wurde.
  3. Die vom Browser gesendeten Werte werden den Komponenten zugewiesen.
  4. Ereignisbehandler werden ausgeführt. Sie können die Werte bestimmter Komponenten ändern.

Aus dieser Abfolge lässt sich ableiten, dass Komponenten, die:

  • deren Werte übermittelt werden
  • deren Werte von einem Ereignisbehandler geändert werden

möglicherweise die Eigenschaft „EnableViewState“ auf „False“ gesetzt haben, da ihr VIEWSTATE-Wert (Schritt 2) entweder durch Schritt 3 oder Schritt 4 geändert wird.

Die Liste der Komponenten auf unserer Seite ist in [Default.aspx.designer.cs] verfügbar:


namespace Intro {
    public partial class _Default {
        protected global::System.Web.UI.HtmlControls.HtmlForm form1;
        protected global::System.Web.UI.WebControls.TextBox TextBoxNom;
        protected global::System.Web.UI.WebControls.RequiredFieldValidator RequiredFieldValidatorNom;
        protected global::System.Web.UI.WebControls.TextBox TextBoxAge;
        protected global::System.Web.UI.WebControls.RequiredFieldValidator RequiredFieldValidatorAge;
        protected global::System.Web.UI.WebControls.RangeValidator RangeValidatorAge;
        protected global::System.Web.UI.WebControls.DropDownList DropDownListNoms;
        protected global::System.Web.UI.WebControls.Button ButtonValider;
        protected global::System.Web.UI.WebControls.ListBox ListBoxEvts;
        protected global::System.Web.UI.WebControls.Label LabelPost;
        protected global::System.Web.UI.WebControls.Label LabelValidation;
        protected global::System.Web.UI.WebControls.Label LabelErreursSaisie;
        protected global::System.Web.UI.WebControls.Label LabelGlobal;
        protected global::System.Web.UI.WebControls.Label LabelNbRequetes;
    }
}

Der Wert der Eigenschaft „EnableViewState“ für diese Komponenten könnte wie folgt lauten:

Komponente
Gesendeter Wert
EnableViewState
Warum
TextBoxName
In das Textfeld eingegebener Wert
Falsch
Der Wert der Komponente wird übermittelt
TextBoxAge
gleich
  
RequiredFieldValidatorName
keine
Falsch
Kein Konzept für den Wert der Komponente
RequiredFieldValidatorAge
gleich
  
RangeValidatorAge
gleich
  
LabelPost
keine
Falsch
bezieht seinen Wert von einem Ereignis-Handler
LabelValidation
dasselbe
  
InputErrorLabel
gleich
  
GlobalLabel
gleich
  
Anzahl der Anfragen
gleich
  
DropDownListNames
„Wert“ des ausgewählten Elements
True
Wir möchten den Inhalt der Liste über mehrere Anfragen hinweg beibehalten, ohne ihn neu generieren zu müssen
ListBoxEvts
„Wert“ des ausgewählten Elements
Falsch
Der Inhalt der Liste wird von einem Ereignisbehandler generiert
ButtonValidate
Schaltflächenbeschriftung
Falsch
Die Komponente behält ihren Designwert bei

2.8. Weiterleitung von einer Seite zur anderen

Bisher haben GET- und POST-Anfragen immer dieselbe Seite [Default.aspx] zurückgegeben. Wir betrachten nun den Fall, in dem eine Anfrage von zwei aufeinanderfolgenden ASPX-Seiten, [Default.aspx] und [Page1.aspx], verarbeitet wird und wobei letztere an den Client zurückgegeben wird. Außerdem werden wir sehen, wie die Seite [Default.aspx] Informationen an die Seite [Page1.aspx] über einen Speicher weitergeben kann, den wir als Anfragespeicher bezeichnen werden.

Wir erstellen die Seite [Page1.aspx]:

  • In [1] fügen wir dem Projekt ein neues Element hinzu
  • In [2] fügen wir ein [Webformular]-Element mit dem Namen [Page1.aspx] hinzu [3]
  • in [4] die hinzugefügte Seite
  • in [5], die fertiggestellte Seite

Der Quellcode für [Page1.aspx] lautet wie folgt:


<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Page1.aspx.cs" Inherits="Intro.Page1" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
  <title>Page1</title>
</head>
<body>
  <form id="form1" runat="server">
  <div>
    <h1>
      Page 1</h1>
    <asp:Label ID="Label1" runat="server"></asp:Label>
    <br />
    <asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl="~/Default.aspx">Retour 
      vers page [Default]</asp:HyperLink>
  </div>
  </form>
</body>
</html>
  • Zeile 13: Ein Label, das zur Anzeige von Informationen verwendet wird, die von der Seite [Default.aspx] gesendet werden
  • Zeile 15: Ein HTML-Link zur Seite [Default.aspx]. Wenn der Benutzer auf diesen Link klickt, fordert der Browser die Seite [Default.aspx] mittels einer GET-Anfrage an. Die Seite [Default.aspx] wird dann so geladen, als hätte der Benutzer ihre URL direkt in den Browser eingegeben.

Die Seite [Default.aspx] wurde um eine neue LinkButton-Komponente erweitert:

Der Quellcode für diese neue Komponente lautet wie folgt:


  <asp:LinkButton ID="LinkButtonToPage1" runat="server" CausesValidation="False" 
    EnableViewState="False" onclick="LinkButtonToPage1_Click">Forward vers Page1</asp:LinkButton>
  • CausesValidation="False": Ein Klick auf den Link löst eine POST-Anfrage an [Default.aspx] aus. Die [LinkButton]-Komponente verhält sich wie die [Button]-Komponente. In diesem Fall soll ein Klick auf den Link nicht die Ausführung von Validatoren auslösen.
  • EnableViewState="False": Der Status des Links muss nicht über mehrere Anfragen hinweg beibehalten werden. Die Designwerte bleiben erhalten.
  • onclick="LinkButtonToPage1_Click": Name der Methode, die in [Defaul.aspx.cs] das Click-Ereignis der Komponente „LinkButtonToPage1“ verarbeitet.

Der Code für den LinkButtonToPage1_Click-Handler lautet wie folgt:


  // to Page1
  protected void LinkButtonToPage1_Click(object sender, EventArgs e)
  {
    // we put information in context
    Context.Items["msg1"] = "Message de Default.aspx pour Page1";
    // pass the request to Page1
    Server.Transfer("Page1.aspx",true);
}

Zeile 7: Die Anfrage wird mithilfe der Methode [Server.Transfer] an die Seite [Page1.aspx] weitergeleitet. Der zweite Parameter der Methode, der auf „true“ gesetzt ist, gibt an, dass alle Informationen, die während der POST-Anfrage an [Default.aspx] gesendet wurden, an [Page1.aspx] weitergeleitet werden müssen. Dadurch kann [Page1.aspx] beispielsweise über eine Sammlung namens Request.Form auf die gesendeten Werte zugreifen. Zeile 5 nutzt den sogenannten Anforderungskontext. Der Zugriff erfolgt über die Context-Eigenschaft der Page-Klasse. Dieser Kontext kann als gemeinsamer Speicher zwischen den verschiedenen Seiten dienen, die dieselbe Anforderung bearbeiten, in diesem Fall [Default.aspx] und [Page1.aspx]. Zu diesem Zweck wird das Items-Wörterbuch verwendet.

Wenn [Page1.aspx] durch den Befehl Server.Transfer("Page1.aspx", true) geladen wird, verläuft alles so, als wäre [Page1.aspx] durch eine GET-Anfrage eines Browsers aufgerufen worden. Der Page_Load-Handler von [Page1.aspx] wird normal ausgeführt. Wir werden ihn nutzen, um die von [Default.aspx] im Anforderungskontext hinterlegte Nachricht anzuzeigen:


using System;
 
namespace Intro
{
  public partial class Page1 : System.Web.UI.Page
  {
    protected void Page_Load(object sender, EventArgs e)
    {
      Label1.Text = Context.Items["msg1"] as string;
    }
  }
}

Zeile 9: Die von [Default.aspx] im Anforderungskontext festgelegte Meldung wird in Label1 angezeigt.

Hier ist ein Ausführungsbeispiel:

  • Klicken Sie auf der Seite [Default.aspx] [1] auf den Link [2], der Sie zur Seite Page1 führt
  • In [3] wird die Seite „Page1“ angezeigt
  • Unter [4] die in [Default.aspx] erstellte und von [Page1.aspx] angezeigte Meldung
  • Unter [5] ist die im Browser angezeigte URL die der Seite [Default.aspx]

2.9. Weiterleitung von einer Seite zu einer anderen

Hier stellen wir eine weitere Technik vor, die funktional der vorherigen ähnelt: Wenn der Benutzer die Seite [Default.aspx] über eine POST-Anfrage aufruft, erhält er als Antwort eine andere Seite [Page2.aspx]. Bei der vorherigen Methode wurde die Anfrage des Benutzers nacheinander von zwei Seiten verarbeitet: [Default.aspx] und [Page1.aspx]. Bei der nun vorgestellten Methode der Seitenumleitung gibt es zwei separate Anfragen vom Browser:

  • In [1] sendet der Browser eine POST-Anfrage an die Seite [Default.aspx]. Diese Seite verarbeitet die Anfrage und sendet eine sogenannte Redirect-Antwort an den Browser. Diese Antwort ist ein einfacher HTTP-Stream (Textzeilen), der den Browser anweist, zu einer anderen URL [Page2.aspx] umzuleiten. [Default.aspx] sendet in dieser ersten Antwort keinen HTML-Inhalt.
  • In [2] sendet der Browser eine GET-Anfrage an die Seite [Page2.aspx]. Diese Seite wird dann als Antwort an den Browser gesendet.
  • Wenn die Seite [Default.aspx] Informationen an die Seite [Page2.aspx] weitergeben möchte, kann sie dies über die Sitzung des Benutzers tun. Im Gegensatz zur vorherigen Methode kann der Anforderungskontext hier nicht verwendet werden, da es zwei separate Anfragen und somit zwei separate Kontexte gibt. Wir müssen daher die Sitzung des Benutzers nutzen, damit die Seiten miteinander kommunizieren können.

Wie bereits bei [Page1.aspx] fügen wir die Seite [Page2.aspx] zum Projekt hinzu:

  • In [1] wurde [Page2.aspx] zum Projekt hinzugefügt
  • in [2] das Erscheinungsbild von [Page2.aspx]
  • in [3] fügen wir der Seite [Default.aspx] eine LinkButton-Komponente [4] hinzu, die den Benutzer zu [Page2.aspx] weiterleitet.

Der Quellcode für [Page2.aspx] ähnelt dem von [Page1.aspx]:


<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Page2.aspx.cs" Inherits="Intro.Page2" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
  <title>Page2</title>
</head>
<body>
  <form id="form1" runat="server">
  <div>
    <h1>
      Page 2</h1>
    <asp:Label ID="Label1" runat="server"></asp:Label>
    <br />
    <asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl="~/Default.aspx">Retour 
      vers page [Default]</asp:HyperLink>
  </div>
  </form>
</body>
</html>

In [Default.aspx] wurde durch Hinzufügen der LinkButton-Komponente der folgende Quellcode generiert:


<asp:LinkButton ID="LinkButtonToPage2" runat="server" 
    onclick="LinkButtonToPage2_Click">Redirection vers Page2</asp:LinkButton>

Der Handler [LinkButtonToPage2_Click] übernimmt die Weiterleitung zu [Page2.aspx]. Sein Code in [Default.aspx.cs] lautet wie folgt:


    protected void LinkButtonToPage2_Click(object sender, EventArgs e)
    {
      // put a msg in the session
      Session["msg2"] = "Message de [Default.aspx] pour [Page2.aspx]";
      // the client is redirected to [Page2.aspx]
      Response.Redirect("Page2.aspx");
}
  • Zeile 4: Wir setzen eine Nachricht in der Sitzung des Benutzers
  • Zeile 5: Das Response-Objekt ist eine Eigenschaft jeder ASPX-Seite. Es repräsentiert die an den Client gesendete Antwort. Es verfügt über eine Redirect-Methode, die bewirkt, dass die an den Client gesendete Antwort eine HTTP-Weiterleitungsanfrage ist.

Wenn der Browser den Umleitungsbefehl zu [Page2.aspx] erhält, sendet er eine GET-Anfrage an diese Seite. Auf dieser Seite wird die [Page_Load]-Methode ausgeführt. Wir werden sie verwenden, um die von [Default.aspx] in der Sitzung gespeicherte Nachricht abzurufen und anzuzeigen. Der Code für [Page2.aspx.cs] lautet wie folgt:


using System;

namespace Intro
{
  public partial class Page2 : System.Web.UI.Page
  {
    protected void Page_Load(object sender, EventArgs e)
    {
      // displays the msg set in the session by [Default.aspx]
      Label1.Text = Session["msg2"] as string;
    }
  }
}

Bei der Ausführung werden die folgenden Ergebnisse erhalten:

  • In [1] klicken wir auf den Weiterleitungslink auf [Default.aspx]. Eine POST-Anfrage wird an die Seite [Default.aspx] gesendet
  • In [2] wurde der Browser zu [Page2.aspx] umgeleitet. Dies ist an der vom Browser angezeigten URL zu erkennen. Bei der vorherigen Methode war diese URL die von [Default.aspx], da die einzige vom Browser gesendete Anfrage an diese URL ging. Hier erfolgt zunächst eine POST-Anfrage an [Default.aspx], gefolgt von einer zweiten GET-Anfrage an [Page2.aspx], ohne dass der Benutzer davon Kenntnis hat.
  • In [3] sehen wir, dass [Page2.aspx] die von [Default.aspx] in der Sitzung hinterlegte Nachricht korrekt abgerufen hat.

2.10. Fazit

Wir haben anhand einiger Beispiele die ASP.NET-Konzepte vorgestellt, die uns im weiteren Verlauf dieses Dokuments nützlich sein werden. Diese Einführung behandelt nicht die Feinheiten der Client-Server-Kommunikation in einer Webanwendung. Dazu können Sie Folgendes lesen: