ASP.NET

Vorstellung des Navigation for ASP.NET Web Forms-Frameworks

Graham Mendick

Das Navigation for ASP.NET Web Forms-Framework, ein unter navigation.codeplex.com gehostetes Open-Source-Projekt, ermöglicht Ihnen, Web Forms-Code mit Komponententestabdeckung und Einhaltung der „Wiederhole dich nicht“-Prinzipien zu schreiben, der eine ASP.NET MVC-Anwendung vor Neid erblassen lassen würde.

Auch wenn es in letzter Zeit zu einer Abkehr von Web Forms zugunsten von MVC gekommen ist, da einige Entwickler große, für Komponententests unerreichbare CodeBehinds satt hatten, ist dieses neue Framework in Verbindung mit Datenbindung ein überzeugendes Argument dafür, Web Forms im neuen Licht zu betrachten.

Datenbindung mit ObjectDataSource-Steuerelementen existiert schon seit Visual Studio 2005 und ermöglicht aufgeräumtere CodeBehinds sowie Komponententests für Datenabrufcode. Es gab jedoch auch einige Probleme, die die Einführung behinderten. So war das Auslösen einer Ausnahme z. B. die einzige Möglichkeit, einen Geschäftsvalidierungsfehler an die Benutzeroberfläche zurückzugeben.

Ein Großteil des Web Forms-Entwicklungsaufwands für die neue Version von Visual Studio wurde in die Datenbindung investiert. Dabei wurden Modellbindungskonzepte von MVC zur Lösung der Probleme berücksichtigt, z. B. wird durch Einführung des Modellstatus das Kommunikationsproblem des Geschäftsvalidierungsfehlers gelöst. Bei der Datenbindung gibt jedoch noch zwei Schwachstellen in Bezug auf die Navigation und Datenübergabe. Mithilfe des Navigation for ASP.NET Web Forms-Frameworks (das ich im Folgenden der Kürze halber das „Navigationsframework“ nennen werde) können diese aber auf unkomplizierte Weise ausgeräumt werden.

Die erste Schwachstelle besteht darin, dass es keine Abstraktion für die Navigationslogik gibt, anders als in MVC, wo sie in den Rückgabetypen der Controllermethode eingekapselt ist. Dies führt zur Umleitung von Aufrufen in datengebundenen Methoden, sodass sie nicht mehr für Komponententests verfügbar sind. Die zweite Schwachstelle besteht darin, dass der Typ eines Parameters einer „ObjectDataSource“ bestimmt, woher der Wert stammt. Ein „QueryStringParameter“ erhält seine Daten beispielsweise immer von der Abfragezeichenfolge. Dadurch wird verhindert, dass ein und dieselbe Datenquelle in verschiedenen Navigationskontexten wie Postback und Non-Postback ohne eine grundlegende Logik in der gefürchteten CodeBehind verwendet wird.

Durch einen ganzheitlichen Ansatz für die Navigation und Datenübergabe beseitigt das Navigationsframework diese Schwachstellen. Unabhängig vom Typ der durchgeführten Navigation, sei es Hyperlink, Postback, AJAX-Verlauf oder Komponententest, werden die übergebenen Daten immer auf die gleiche Weise gespeichert. In zukünftigen Artikeln werde ich aufzeigen, warum dies zu leeren CodeBehinds mit vollständig komponentengetestetem Datenabruf und Navigationslogik und auch zu für die Suchmaschinenoptimierung geeigneten, progressiv verbesserten Single Page Applications mit Codeduplizierung für Szenarios mit und ohne JavaScript-Aktivierung führt. In diesem Artikel wird das Navigationsframework vorgestellt. Darüber hinaus werden anhand der Erstellung einer Beispielwebanwendung einige der grundlegenden, aber wichtigen Konzepte demonstriert.

Beispielanwendung

Die Beispielwebanwendung ist eine Onlineumfrage. Diese Umfrage umfasst nur zwei Fragen und zeigt beim Abschluss eine Dankesmeldung an. Jede Frage wird durch eine separate ASPX-Seite mit dem Namen „Question1.aspx“ bzw. „Question2.aspx“ repräsentiert, und die Dankesmeldung hat eine eigene Seite namens „Thanks.aspx“.

Die erste Frage lautet: „Welche ASP.NET-Technologie verwenden Sie zurzeit?“, und die möglichen Antworten sind entweder „Web Forms“ oder „MVC“. Daher füge ich „Question1.aspx“ die Frage und die hartcodierten Optionsfeldantworten hinzu:

    <h1>Question 1</h1>
    <h2>Which ASP.NET technology are you currently using?</h2>
    <asp:RadioButtonList ID="Answer" runat="server">
      <asp:ListItem Text="Web Forms" Selected="True" />
      <asp:ListItem Text="MVC" />
    </asp:RadioButtonList>

Die zweite Frage, „Verwenden Sie das Navigation for ASP.NET Web Forms-Framework?“, hat die Antworten „Ja“ und „Nein“ und wird auf ähnliche Weise markiert.

Erste Schritte

Die einfachste Möglichkeit zur Einrichtung des Umfragewebprojekts zur Verwendung des Navigationsframeworks besteht darin, es mithilfe des NuGet-Paket-Managers zu installieren. Durch Ausführen des Befehls „Install-Package Navigation“ in der Paket-Manager-Konsole werden der erforderliche Verweis und die Konfiguration hinzugefügt. Wenn Sie nicht mit Visual Studio 2010 arbeiten, finden Sie Anweisungen für die manuelle Einrichtung unter navigation.codeplex.com/documentation.

Konfigurationskonfiguration

Das Navigationsframework kann als Zustandsautomat betrachtet werden, bei dem jeder einzelne Zustand eine Seite repräsentiert und der Wechsel von einem Zustand zum anderen als Übergang bezeichnet wird. Dieser vordefinierte Satz von Zuständen und Übergängen ist in der Datei „StateInfo.config“ konfiguriert, die durch die NuGet-Installation erstellt wird. Ohne diese zugrunde liegende Konfiguration wird durch das Ausführen der Umfrageanwendung eine Ausnahme ausgelöst.

Da Zustände im Grunde nur Seiten sind, erfordert die Umfrageanwendung drei Zustände, einen für jede ihrer drei Seiten:

    <state key="Question1" page="~/Question1.aspx">
    </state>
    <state key="Question2" page="~/Question2.aspx">
    </state>
    <state key="Thanks" page="~/Thanks.aspx">
    </state>

Ab jetzt werde ich die unterschiedlichen Zustände mit ihren Schlüsselnamen „Question1“, „Question2“ und „Thanks“ bezeichnen, statt mit den Seiten, die sie repräsentieren.

Da Übergänge die möglichen Navigationen zwischen Zuständen beschreiben, erfordert die Umfrageanwendung zwei Übergänge, einen für die Navigation von „Question1“ zu „Question2“ und einen für die Navigation von „Question2“ zu „Thanks“. Ein Übergang wird als untergeordnetes Elemente des beendeten Zustands angezeigt und verweist über sein To-Attribut auf den Zustand, in den gewechselt wird:

    <state key="Question1" page="~/Question1.aspx">
      <transition key="Next" to="Question2"/>
    </state>
    <state key="Question2" page="~/Question2.aspx">
      <transition key="Next" to="Thanks"/>
    </state>
    <state key="Thanks" page="~/Thanks.aspx">
    </state>

Dialoge sind das abschließende Element der Konfiguration und repräsentieren eine logische Gruppierung von Zuständen. Die Umfrageanwendung erfordert nur einen Dialog, da es sich bei „Question1“, „Question2“ und „Thanks“ im Prinzip nur um einen einzigen Navigationspfad handelt. Das Initial-Attribut des Dialogs muss auf den Startzustand verweisen, nämlich „Question1“:

    <dialog key="Survey" initial="Question1" path="~/Question1.aspx">
      <state key="Question1" page="~/Question1.aspx">
        <transition key="Next" to="Question2"/>
      </state>
      <state key="Question2" page="~/Question2.aspx">
        <transition key="Next" to="Thanks"/>
      </state>
      <state key="Thanks" page="~/Thanks.aspx">
      </state>
    </dialog>

Wie Sie sehen, hat jeder Dialog, Zustand und Übergang ein Schlüsselattribut. Ich habe mich dafür entschiedenen, die Zustandsschlüssel nach den Seitennamen zu benennen, dies ist jedoch kein Muss. Beachten Sie jedoch, dass alle Schlüssel innerhalb ihres übergeordneten Elements eindeutig sein müssen. Es können beispielsweise keine gleichgeordneten Zustände mit dem gleichen Schlüssel vorhanden sein.

Mit „Question1.aspx“ als Startseite startet die Umfrageanwendung nun erfolgreich in den Question1-Zustand. Die Umfrage verharrt jedoch in diesem Zustand, da keine Möglichkeit besteht, zu „Question2“ überzugehen.

Es empfiehlt sich, die verschiedenen Arten der Web Forms-Navigation in zwei Gruppen aufzuteilen. In der Non-Postback-Gruppe in Form von Hyperlinks, Umleitungen oder Übertragungen wird das Steuerelement von einer ASPX-Seite zur nächsten weitergegeben. In der Postback-Gruppe in Form von Postbacks, Teilseitenanforderungen oder AJAX-Verlauf verbleibt das Steuerelement auf der entsprechenden Seite. Die zweite Gruppe wird in einem zukünftigen Artikel über die Single Page Interface-Muster näher erläutert. In diesem Artikel konzentriere ich mich auf die erste Navigationsart.

Für den Wechsel zwischen Seiten muss eine URL erstellt werden. Vor Visual Studio 2008 konnten URLs nur manuell aus hartcodierten ASPX-Seitennamen erstellt werden, was zu einer engen Verknüpfung zwischen Seiten führte, sodass Anwendungen fehleranfällig und schwer zu verwalten waren. Durch die Einführung von Routing wurde dieses Problem gelöst, hier werden konfigurierbare Routennamen anstelle von Seitennamen verwendet. Die Tatsache, dass Routing jedoch bei Verwendung außerhalb einer Webumgebung eine Ausnahme auslöst, macht es in Kombination mit seiner Resistenz gegenüber „Mocking“ zum Feind von Komponententests.

Das Navigationsframework behält die lose Verknüpfung durch das Routing bei und eignet sich gut für Komponententests. Analog zur Verwendung von Routennamen statt hartcodierten ASPX-Seitennamen sind es die im vorherigen Abschnitt konfigurierten Dialog- und Übergangsschlüssel, auf die im Code verwiesen wird. Der Zustand, zu dem navigiert wird, wird durch die jeweiligen Initial- und To-Attribute bestimmt.

Um zur Umfrage zurückzukommen: Der Übergangsschüssel „Next“ kann für den Wechsel von „Question1“ zu „Question2“ verwendet werden. Ich füge „Question1.aspx“ eine Schaltfläche „Next“ und den folgenden Code zum zugehörigen Click-Ereignishandler hinzu:

protected void Next_Click(object sender, EventArgs e)
{
  StateController.Navigate("Next");
}

Der an die Navigate-Methode übergebene Schlüssel wird mit den konfigurierten untergeordneten Übergängen des Zustands „Question1“ abgeglichen. Anschließend wird der anhand des To-Attributs identifizierte Zustand, nämlich„Question2“, angezeigt. Ich füge „Question2.aspx“ die gleiche Schaltfläche und den gleichen Handler hinzu. Beim Ausführen der Umfrage werden Sie feststellen, dass Sie durch Klicken auf die Next-Schaltflächen durch die drei Zustände navigieren können.

Wie Sie sicherlich bemerkt haben, ist die zweite Frage eine Web Forms-spezifische Frage und daher irrelevant, wenn als erste Antwort „MVC“ ausgewählt wird. Für dieses Szenario muss der Code geändert werden, sodass direkt von „Question1“ zu „Thanks“ navigiert und„Question2“ komplett umgangen wird.

Die aktuelle Konfiguration lässt die Navigation von „Question1“ zu „Thanks“ nicht zu, da der einzige aufgeführte Übergang der zu „Question2“ ist. Deshalb ändere ich die Konfiguration, indem ich unter dem Zustand „Question1“ einen zweiten Übergang hinzufüge:

    <state key="Question1" page="~/Question1.aspx">
      <transition key="Next" to="Question2"/>
      <transition key="Next_MVC" to="Thanks"/>
    </state>

Ist dieser neue Übergang eingerichtet, kann der Click-Ereignishandler der Next-Schaltfläche auf einfache Weise angepasst werden, um je nach ausgewählter Antwort einen anderen Übergangsschlüssel zu übergeben:

if (Answer.SelectedValue != "MVC")
{
  StateController.Navigate("Next");
}
else
{
  StateController.Navigate("Next_MVC");
}

Eine Umfrage würde wenig taugen, wenn der Benutzer nicht die Möglichkeit hätte, seine Antworten noch einmal zu ändern. Zurzeit besteht keine Möglichkeit, zu einer vorherigen Frage zurückzukehren (abgesehen von der Zurück-Schaltfläche des Browsers). Man könnte nun meinen, Sie müssten für die Rückwärtsnavigation zwei Übergänge unter „Thanks“ hinzufügen, die auf „Question1“ und „Question2“ verweisen, und einen weiteren unter „Question2“, der auf „Question1“ verweist. Dies würde zwar funktionieren, ist jedoch unnötig, da die Rückwärtsnavigation beim Navigationsframework umsonst enthalten ist.

Bei der Breadcrumb-Navigation handelt es sich um einen Satz von Links, die Zugriff auf alle vorherigen Seiten bieten, die der Benutzer bis zum Erreichen der aktuellen Seite besucht hat. In Web Forms ist die Breadcrumb-Navigation in der Sitemap-Funktionalität integriert. Da Sitemaps jedoch durch eine feste Navigationsstruktur gekennzeichnet sind, sind diese Breadcrumbs für eine bestimmte Seite unabhängig von der Route immer gleich. Sie sind für Situationen wie in der Umfrage, bei denen „Question2“ auf der Route zu „Thanks“ manchmal ausgeschlossen ist, nicht geeignet. Das Navigationsframework erstellt durch Nachverfolgung der während der Navigation besuchten Zustände einen Breadcrumb-Pfad der tatsächlichen Route.

Zur Demonstration füge ich „Question2.aspx“ einen Hyperlink hinzu und lege in der CodeBehind mithilfe der Rückwärtsnavigation die Eigenschaft „NavigateUrl“ programmgesteuert fest. Es muss ein Distanzparameter übergeben werden, der angibt, bis zu welchem Zustand zurückgegangen werden soll. Der Wert 1 steht hier für den unmittelbar vorhergehenden Zustand:

protected void Page_Load(object sender, EventArgs e)
{
  Question1.NavigateUrl = StateController.GetNavigationBackLink(1);
}

Wenn Sie bei Ausführung der Anwendung auf Frage 1 „Web Forms“ antworten, werden Sie feststellen, dass der Hyperlink auf „Question2.aspx“ Sie zurück zur ersten Frage bringt.

Genauso verfahre ich mit „Thanks.aspx“, wobei es hier etwas komplizierter ist, da zwei Hyperlinks benötigt werden (einer für jede Frage) und der Benutzer möglicherweise nicht beide Fragen gesehen hat, wenn seine Antwort auf die erste Frage „MVC“ lautete. Die Anzahl der vorhergehenden Zustände kann überprüft werden, bevor entschieden wird, wie die Hyperlinks eingerichtet werden (siehe Abbildung 1).

Abbildung 1 Dynamische Rückwärtsnavigation

protected void Page_Load(object sender, EventArgs e)
{
  if (StateController.CanNavigateBack(2))
  {
    Question1.NavigateUrl = StateController.GetNavigationBackLink(2);
    Question2.NavigateUrl = StateController.GetNavigationBackLink(1);
  }
  else
  {
    Question1.NavigateUrl = StateController.GetNavigationBackLink(1);
    Question2.Visible = false;
  }
}

Die Umfrage funktioniert nun und ermöglicht Ihnen, Fragen auszufüllen und vorherige Antworten zu ändern. Eine Umfrage hat jedoch wenig Sinn, wenn die Antworten nicht genutzt werden. Ich werde Ihnen zeigen, wie die Antworten von „Question1“ und „Question2“ an „Thanks“ übergeben werden können, wo sie in zusammengefasster Form angezeigt werden.

Datenübergabe

Es gibt genauso viele verschiedene Möglichkeiten zur Datenübergabe in Web Forms wie Möglichkeiten zur Navigation. Bei der Non-Postback-Navigation, bei der das Steuerelement von einer Seite zur nächsten weitergegeben wird (über Hyperlink, Umleitung oder Übertragung), können Abfragezeichenfolge- oder Routendaten verwendet werden. Bei der Postback-Navigation, bei der das Steuerelement auf der entsprechenden Seite verbleibt (über Postbacks, Teilseitenanforderung oder AJAX-Verlauf) sind Steuerelementwerte, Anzeigezustand oder Ereignisargumente infrage kommende Kandidaten.

Vor Visual Studio 2005 waren CodeBehinds durch die Verarbeitung dieser übergebenen Daten belastet und quollen über vor Wertextraktions- und Typkonvertierungslogik. Diese Last wurde durch die Einführung von Datenquellen-Steuerelementen und select-Parameter erheblich reduziert („Wertanbieter“ in der nächsten Version von Visual Studio). Diese select-Parameter sind jedoch an eine bestimmte Datenquelle gebunden, und ein dynamischer Wechsel der Quelle abhängig vom Navigationskontext ist nicht möglich. So können sie ihre Werte beispielsweise nicht alternativ von einem Steuerelement oder von der Abfragezeichenfolge abrufen, je nachdem, ob es sich um ein Postback handelt oder nicht. Eine Umgehung dieser Beschränkungen führt dazu, dass Code zurück in die CodeBehind fließt, sodass wir wieder bei den aufgeblähten und nicht testbaren CodeBehinds sind.

Beim Navigationsframework werden solche Probleme durch die Bereitstellung einer einzigen Datenquelle unabhängig von der jeweiligen Navigation, den so genannten Statusdaten, vermieden. Wenn eine Seite zum ersten Mal geladen wird, werden die Statusdaten mit allen während der Navigation übergebenen Daten gefüllt, und zwar auf ähnliche Weise wie Abfragezeichenfolge- oder Routendaten. Ein wesentlicher Unterschied besteht jedoch darin, dass die Statusdaten nicht schreibgeschützt sind. Bei nachfolgenden Postback-Navigationen können Sie also mit der aktuellen Version der Seite aktualisiert werden. Ich werde am Ende dieses Abschnitts erneut auf die Rückwärtsnavigation eingehen und Ihnen aufzeigen, warum dies sinnvoll ist.

Ich ändere die Umfrage so, dass die Antwort auf die erste Frage an den Thanks-Zustand übergeben wird, wo sie dem Benutzer erneut angezeigt wird. Während der Navigation werden die Daten über eine Sammlung von Schlüssel-Wert-Paaren übergeben, die als „NavigationData“ bezeichnet werden. Ich ändere den Click-Ereignishandler der Next-Schaltfläche von „Question1.aspx“ so, dass die Antwort auf die erste Frage an den nächsten Zustand übergeben wird:

NavigationData data = new NavigationData();
data["technology"] = Answer.SelectedValue;
if (Answer.SelectedValue != "MVC")
{
  StateController.Navigate("Next", data);
}
else
{
  StateController.Navigate("Next_MVC", data);
}

Mithilfe der während der Navigation übergebenen „NavigationData“ werden die Statusdaten initialisiert, die über die Eigenschaft „Data“ des Objekts „StateContext“ für den nächsten Zustand zur Verfügung gestellt werden. Ich füge „Thanks.aspx“ ein Label hinzu und lege die Eigenschaft „Text“ so fest, dass die übergebene Antwort angezeigt wird:

Summary.Text = (string) StateContext.Data["technology"];

Bei Ausführung der Umfrage werden Sie feststellen, dass diese zusammenfassende Information nur angezeigt wird, wenn die Antwort auf die erste Frage „MVC“ lautet. Die Antwort „Web Forms“ wird nie angezeigt. Dies liegt daran, dass „NavigationData“ nur für den nächsten Zustand verfügbar ist, nicht für alle Zustände, die durch nachfolgende Navigation erreicht werden. Daher ist die Antwort „Web Forms“ in den Question2-Statusdaten vorhanden, jedoch nicht verfügbar, wenn „Thanks“ erreicht wird. Eine Möglichkeit zur Lösung dieses Problems besteht darin, „Question2.aspx“ so zu ändern, dass die Antwort auf die erste Frage weitergeleitet wird, d. h. bei der Navigation wird die Antwort den Statusdaten entnommen und an „Thanks“ übergeben:

NavigationData data = new NavigationData();
data["technology"] = StateContext.Data["technology"];
StateController.Navigate("Next", data);

Dieser Ansatz ist nicht ideal, da er „Question1“ und „Question2“ miteinander verknüpft, sodass der letzte Zustand die vom vorherigen Zustand übergebenen Daten berücksichtigen muss. Eine neue Frage kann beispielsweise nicht zwischen der ersten und der zweiten Frage eingefügt werden, ohne „Question2.aspx“ entsprechend zu ändern. Zu einer zukunftssicheren Implementierung gehört das Erstellen einer neuen „NavigationData“, die alle Question2-Statusdaten enthält. Dazu wird „true“ an den NavigationData-Konstruktor übergeben:

NavigationData data = new NavigationData(true);
StateController.Navigate("Next", data);

Ein weiterer wichtiger Unterschied zwischen Statusdaten und Abfragezeichenfolge- bzw. Routendaten besteht darin, dass Sie bei Statusdaten nicht auf die Übergabe von Zeichenfolgen beschränkt sind. Statt die Antwort wie für „Question1“ als Zeichenfolge zu übergeben, übergebe ich für „Question2“ einen bool-Wert an „Thanks“, wobei der Wert „true“ „Ja“ entspricht:

NavigationData data = new NavigationData(true);
data["navigation"] = Answer.SelectedValue == "Yes" ? true : false;
StateController.Navigate("Next", data);

Wie Sie sehen, wird der Datentyp beibehalten, wenn er von den Thanks-Statusdaten abgerufen wird:

Summary.Text = (string) StateContext.Data["technology"];
if (StateContext.Data["navigation"] != null)
{
  Summary.Text += ", " + (bool) StateContext.Data["navigation"];
}

Die Umfrage ist fertig, bis auf ein Problem: Antworten auf Fragen werden nicht gespeichert, wenn die Rückwärtsnavigations-Hyperlinks verwendet werden. Wenn Sie beispielsweise von „Thanks“ zu „Question1“ zurückkehren, geht der Kontext verloren, daher wird unabhängig von der gegebenen Antwort immer das Web Forms-Standardoptionsfeld ausgewählt.

Im vorigen Abschnitt wurde der Vorteil der Rückwärtsnavigation gegenüber den statischen Sitemap-Breadcrumbs erläutert. Eine weitere Einschränkung der von der Sitemap generierten Breadcrumbs besteht darin, dass sie keine Daten transportieren, d. h., wenn man ihnen folgt, können Kontextinformationen verloren gehen. Sie können z. B. die zuvor ausgewählte Antwort „MVC“ nicht übergeben, wenn sie von „Thanks“ zu „Question1“ zurückkehren. Das Navigationsframework erstellt durch Nachverfolgung der Statusdaten, die mit den während der Navigationen besuchten Zuständen verbunden sind, einen kontextbezogenen Breadcrumb-Pfad. Bei Rückwärtsnavigation werden diese Statusdaten wiederhergestellt, sodass die Seite genauso wie zuvor neu erstellt werden kann.

Dank der kontextbezogenen Rückwärtsnavigation kann ich die Umfrage so ändern, dass die Antworten gespeichert werden, wenn Zustände erneut besucht werden. Die erste Phase besteht darin, die Antworten in den Statusdaten in den Click-Ereignishandlern der Next-Schaltfläche festzulegen, bevor wegnavigiert wird:

StateContext.Data["answer"] = Answer.SelectedValue;

Wenn „Question1“ bzw. „Question2“ nun erneut besucht werden, enthalten die Statusdaten die zuvor ausgewählte Antwort. Nun ist es einfach, diese Antwort in der Methode „Page_Load“ abzurufen und das entsprechende Optionsfeld vorzugeben:

protected void Page_Load(object sender, EventArgs e)
{
  if (!Page.IsPostBack)
  {
    if (StateContext.Data["answer"] != null)
    {
      Answer.SelectedValue = 
        (string)StateContext.Data["answer"];
    }
  }
}

Die nun abgeschlossene Umfrage ist nicht anfällig für die Fehler, die in Webanwendungen häufig auftreten, wenn Benutzer auf die Zurück-Schaltfläche des Browsers klicken (oder mehrere Browserfenster geöffnet haben). Solche Probleme entstehen in der Regel dadurch, dass seitenspezifische Daten in einer serverseitigen Sitzung gespeichert werden. Obwohl es nur ein Sitzungsobjekt gibt, können mehrere „aktuelle“ Versionen einer einzelnen Seite vorhanden sein. Wird beispielsweise die Zurück-Schaltfläche zum Abrufen einer „veralteten“ Version einer Seite vom Browsercache verwendet, kann dies dazu führen, dass Client und Server nicht mehr synchron sind. Beim Navigationsframework treten solche Probleme nicht auf, da kein serverseitiger Cache vorhanden ist. Stattdessen sind sowohl der Zustand, die Statusdaten als auch der Breadcrumb-Pfad in der URL enthalten. Das bedeutet jedoch auch, dass ein Benutzer diese Werte durch Bearbeiten der URL ändern kann.

Vorteile gegenüber MVC

Wie bereits erwähnt, können Sie mit dem Navigationsframework Web Forms-Code erstellen, der eindeutige Vorteile gegenüber MVC aufweist. Nach dieser kühnen Behauptung sind Sie von der Umfrage-Beispielanwendung vielleicht ein wenig enttäuscht, da sie wahrscheinlich aufgrund des dabei involvierten CodeBehind immer noch hinter MVC zurückbleibt. Aber keine Sorge, dies war nur eine Einführung in die grundlegenden Konzepte. In zukünftigen Artikeln wird die architektonische Integrität behandelt, wobei besonderes Augenmerk auf die Komponententests und die „Wiederhole dich nicht“-Prinzipien gelegt wird.

Im zweiten Teil werde ich ein datengebundenes Beispiel mit leeren CodeBehinds und vollständiger Codeabdeckung für Komponententests erstellen. Diese Abdeckung beinhaltet auch den Navigationscode, der in einer MVC-Anwendung bekanntermaßen schwierig zu testen ist.

Im dritten Teil werde ich eine für die Suchmaschinenoptimierung geeignete Single Page Application erstellen. Diese nutzt die progressive Verbesserung bei Einsatz von ASP.NET AJAX, wenn JavaScript aktiviert ist, und bei sinnvoller Herabstufung, wenn JavaScript deaktiviert ist. Dabei werden in beiden Szenarios die gleichen datengebundenen Methoden verwendet. Auch dies ist in einer MVC-Anwendung nicht leicht umzusetzen.

Wenn ich Sie neugierig gemacht habe und Sie schon einmal einige der erweiterten Funktionen testen möchten, laden Sie unter navigation.codeplex.com die umfassende Featuredokumentation und den Beispielcode herunter.

Graham Mendick ist einer der größten Fans von Web Forms und möchte zeigen, dass die Architektur von Web Forms genauso solide ist wie die von ASP.NET MVC. Er hat das Navigation for ASP.NET Web Forms-Framework erstellt und ist überzeugt, dass es Web Forms bei Verwendung mit Datenbindung neues Leben einhauchen kann.

Unser Dank gilt dem folgenden technischen Experten für die Durchsicht dieses Artikels: Damian Edwards