Freigeben über


Speichern von zusätzlichen Benutzerinformationen (C#)

von Scott Mitchell

Hinweis

Seit diesem Artikel wurden die ASP.NET-Mitgliedschaftsanbieter von ASP.NET Identity abgelöst. Es wird dringend empfohlen, Apps so zu aktualisieren, dass sie die ASP.NET Identity Platform anstelle der Mitgliedschaftsanbieter verwenden, die zum Zeitpunkt der Veröffentlichung dieses Artikels vorgestellt wurden. ASP.NET Identity hat eine Reihe von Vorteilen gegenüber dem ASP.NET Mitgliedschaftssystem, darunter :

  • Bessere Leistung
  • Verbesserte Erweiterbarkeit und Testbarkeit
  • Unterstützung für OAuth, OpenID Connect und zweistufige Authentifizierung
  • Unterstützung für anspruchsbasierte Identitäten
  • Bessere Interoperabilität mit ASP.Net Core

Code herunterladen oder PDF herunterladen

In diesem Tutorial beantworten wir diese Frage, indem wir eine sehr rudimentäre Gästebuchanwendung erstellen. Dabei sehen wir uns verschiedene Optionen zum Modellieren von Benutzerinformationen in einer Datenbank an und erfahren dann, wie diese Daten den benutzerkonten zugeordnet werden, die vom Mitgliedschaftsframework erstellt wurden.

Einführung

ASP. Das Mitgliedschaftsframework von NET bietet eine flexible Benutzeroberfläche zum Verwalten von Benutzern. Die Mitgliedschafts-API umfasst u. a. Methoden zum Überprüfen von Anmeldeinformationen, zum Abrufen von Informationen über den aktuell angemeldeten Benutzer, zum Erstellen eines neuen Benutzerkontos und zum Löschen eines Benutzerkontos. Jedes Benutzerkonto im Mitgliedschaftsframework enthält nur die Eigenschaften, die zum Überprüfen von Anmeldeinformationen und zum Ausführen wesentlicher Benutzerkontoaufgaben erforderlich sind. Dies wird durch die Methoden und Eigenschaften der MembershipUser -Klasse belegt, die ein Benutzerkonto im Membership-Framework modelliert. Diese Klasse verfügt über Eigenschaften wie UserName, Emailund IsLockedOut, und Methoden wie GetPassword und UnlockUser.

Häufig müssen Anwendungen zusätzliche Benutzerinformationen speichern, die nicht im Mitgliedschaftsframework enthalten sind. Ein Onlinehändler muss beispielsweise jedem Benutzer die Möglichkeit geben, seine Liefer- und Rechnungsadressen, Zahlungsinformationen, Lieferpräferenzen und Telefonnummern zu speichern. Darüber hinaus ist jede Bestellung im System einem bestimmten Benutzerkonto zugeordnet.

Die MembershipUser -Klasse enthält keine Eigenschaften wie PhoneNumber oder DeliveryPreferencesPastOrders. Wie verfolgen wir also die von der Anwendung benötigten Benutzerinformationen und lassen sie in das Mitgliedschaftsframework integrieren? In diesem Tutorial beantworten wir diese Frage, indem wir eine sehr rudimentäre Gästebuchanwendung erstellen. Dabei sehen wir uns verschiedene Optionen zum Modellieren von Benutzerinformationen in einer Datenbank an und erfahren dann, wie diese Daten den benutzerkonten zugeordnet werden, die vom Mitgliedschaftsframework erstellt wurden. Jetzt geht‘s los!

Schritt 1: Erstellen des Datenmodells der Gastbuchanwendung

Es gibt eine Vielzahl von Techniken, die verwendet werden können, um Benutzerinformationen in einer Datenbank zu erfassen und den benutzerkonten zuzuordnen, die vom Mitgliedschaftsframework erstellt wurden. Um diese Techniken zu veranschaulichen, müssen wir die Tutorialwebanwendung so erweitern, dass sie eine Art von benutzerbezogenen Daten erfasst. (Derzeit enthält das Datenmodell der Anwendung nur die Anwendungsdiensttabellen, die SqlMembershipProvidervon benötigt werden.)

Wir erstellen eine sehr einfache Gästebuchanwendung, in der ein authentifizierter Benutzer einen Kommentar hinterlassen kann. Zusätzlich zum Speichern von Gästebuchkommentaren können wir jedem Benutzer erlauben, seine Heimatstadt, Homepage und Signatur zu speichern. Falls angegeben, werden die Heimat, die Homepage und die Unterschrift des Benutzers auf jeder Nachricht angezeigt, die er im Gästebuch hinterlassen hat.

Hinzufügen derGuestbookCommentsTabelle

Um die Gästebuchkommentare zu erfassen, müssen wir eine Datenbanktabelle mit dem Namen GuestbookComments erstellen, die Spalten wie CommentId, Subject, Bodyund CommentDateenthält. Außerdem muss jeder Datensatz in der GuestbookComments Tabelle auf den Benutzer verweisen, der den Kommentar hinterlassen hat.

Um diese Tabelle zu unserer Datenbank hinzuzufügen, wechseln Sie in Visual Studio zum Explorer Datenbank, und führen Sie einen Drilldown in die SecurityTutorials Datenbank durch. Klicken Sie mit der rechten Maustaste auf den Ordner Tabellen, und wählen Sie Neue Tabelle hinzufügen aus. Dadurch wird eine Schnittstelle angezeigt, die es uns ermöglicht, die Spalten für die neue Tabelle zu definieren.

Hinzufügen einer neuen Tabelle zur SecurityTutorials-Datenbank

Abbildung 1: Hinzufügen einer neuen Tabelle zur SecurityTutorials Datenbank (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Definieren Sie als Nächstes die GuestbookCommentsSpalten des . Fügen Sie zunächst eine Spalte mit dem Namen CommentId des Typs uniqueidentifierhinzu. In dieser Spalte wird jeder Kommentar im Gästebuch eindeutig identifiziert. Daher lassen Sie s nicht zu NULL , und markieren Sie ihn als Primärschlüssel der Tabelle. Anstatt einen Wert für das CommentId Feld in jedem INSERTanzugeben, können wir angeben, dass automatisch ein neuer uniqueidentifier Wert für dieses Feld INSERT für generiert werden soll, indem wir den Standardwert der Spalte auf NEWID()festlegen. Nachdem Sie dieses erste Feld hinzugefügt, es als Primärschlüssel markiert und dessen Standardwert festgelegt haben, sollte ihr Bildschirm ähnlich wie in Abbildung 2 dargestellt aussehen.

Hinzufügen einer primären Spalte mit dem Namen CommentId

Abbildung 2: Hinzufügen einer primären Spalte mit dem Namen CommentId (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Fügen Sie als Nächstes eine Spalte mit dem Namen Subject vom Typ nvarchar(50) und eine Spalte mit dem Body Namen vom Typ nvarchar(MAX)hinzu, und heben Sie die Streuung NULL von s in beiden Spalten auf. Fügen Sie anschließend eine Spalte mit dem Namen CommentDate vom Typ datetimehinzu. Lassen Sie s nicht zu NULL , und legen Sie den Standardwert der CommentDate Spalte auf fest getdate().

Es bleibt nur noch, eine Spalte hinzuzufügen, die jedem Gastbuchkommentar ein Benutzerkonto zuordnet. Eine Möglichkeit wäre das Hinzufügen einer Spalte mit dem Namen UserName vom Typ nvarchar(256). Dies ist eine geeignete Wahl, wenn Sie einen anderen Mitgliedschaftsanbieter als den SqlMembershipProviderverwenden. Wenn Sie jedoch verwenden SqlMembershipProvider, wie in dieser Tutorialreihe, ist die UserName Spalte in der aspnet_Users Tabelle nicht garantiert eindeutig. Der aspnet_Users Primärschlüssel der Tabelle ist UserId und vom Typ uniqueidentifier. Aus diesem Grund benötigt die GuestbookComments Tabelle eine Spalte mit dem Namen UserId des Typs uniqueidentifier (nicht zulässige NULL Werte). Fügen Sie diese Spalte hinzu.

Hinweis

Wie im Tutorial Erstellen des Mitgliedschaftsschemas in SQL Server erläutert, ist das Mitgliedschaftsframework so konzipiert, dass mehrere Webanwendungen mit unterschiedlichen Benutzerkonten denselben Benutzerspeicher gemeinsam nutzen können. Dazu werden Benutzerkonten in verschiedene Anwendungen partitioniert. Und obwohl jeder Benutzername innerhalb einer Anwendung garantiert eindeutig ist, kann derselbe Benutzername in verschiedenen Anwendungen verwendet werden, die denselben Benutzerspeicher verwenden. Es gibt eine zusammengesetzte UNIQUE Einschränkung in der aspnet_Users Tabelle für die UserName Felder und ApplicationId , aber nicht nur für das UserName Feld. Folglich ist es möglich, dass die aspnet_Users Tabelle über zwei (oder mehr) Datensätze mit demselben UserName Wert verfügt. Es gibt jedoch eine UNIQUE Einschränkung für das Feld der aspnet_Users Tabelle UserId (da es sich um den Primärschlüssel handelt). Eine UNIQUE Einschränkung ist wichtig, da ohne sie keine Fremdschlüsseleinschränkung zwischen den GuestbookComments Tabellen und aspnet_Users festgelegt werden kann.

Nachdem Sie die UserId Spalte hinzugefügt haben, speichern Sie die Tabelle, indem Sie in der Symbolleiste auf das Symbol Speichern klicken. Geben Sie der neuen Tabelle GuestbookCommentsden Namen .

Wir haben ein letztes Problem mit der GuestbookComments Tabelle: Wir müssen eine Fremdschlüsseleinschränkung zwischen der GuestbookComments.UserId Spalte und der aspnet_Users.UserId Spalte erstellen. Klicken Sie dazu auf der Symbolleiste auf das Symbol Beziehung, um das Dialogfeld Fremdschlüsselbeziehungen zu starten. (Alternativ können Sie dieses Dialogfeld starten, indem Sie zum Menü Tabelle Designer wechseln und Beziehungen auswählen.)

Klicken Sie in der unteren linken Ecke des Dialogfelds Fremdschlüsselbeziehungen auf die Schaltfläche Hinzufügen. Dadurch wird eine neue Fremdschlüsseleinschränkung hinzugefügt, obwohl wir weiterhin die Tabellen definieren müssen, die an der Beziehung beteiligt sind.

Verwenden des Dialogfelds Fremdschlüsselbeziehungen zum Verwalten der Fremdschlüsseleinschränkungen einer Tabelle

Abbildung 3: Verwenden des Dialogfelds Fremdschlüsselbeziehungen zum Verwalten der Fremdschlüsseleinschränkungen einer Tabelle (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Klicken Sie als Nächstes auf das Symbol mit den Auslassungspunkten in der Zeile "Tabellen- und Spaltenspezifikationen" auf der rechten Seite. Dadurch wird das Dialogfeld Tabellen und Spalten gestartet, in dem wir die Primärschlüsseltabelle und -spalte sowie die Fremdschlüsselspalte aus der GuestbookComments Tabelle angeben können. Wählen Sie aspnet_Users insbesondere und UserId als Primärschlüsseltabelle und -spalte und UserId aus der GuestbookComments Tabelle als Fremdschlüsselspalte aus (siehe Abbildung 4). Klicken Sie nach dem Definieren der Primär- und Fremdschlüsseltabellen und -spalten auf OK, um zum Dialogfeld Fremdschlüsselbeziehungen zurückzukehren.

Einrichten einer Fremdschlüsseleinschränkung zwischen den Tabellen aspnet_Users und GuesbookComments

Abbildung 4: Einrichten einer Fremdschlüsseleinschränkung zwischen den aspnet_Users Tabellen und GuesbookComments (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

An diesem Punkt wurde die Fremdschlüsseleinschränkung eingerichtet. Das Vorhandensein dieser Einschränkung gewährleistet die relationale Integrität zwischen den beiden Tabellen, indem sichergestellt wird, dass nie ein Gastbucheintrag vorhanden ist, der sich auf ein nicht vorhandenes Benutzerkonto bezieht. Standardmäßig lässt eine Fremdschlüsseleinschränkung das Löschen eines übergeordneten Datensatzes nicht zu, wenn entsprechende untergeordnete Datensätze vorhanden sind. Das heißt, wenn ein Benutzer einen oder mehrere Gästebuchkommentare abgibt und wir dann versuchen, dieses Benutzerkonto zu löschen, schlägt die Löschung fehl, es sei denn, seine Gästebuchkommentare werden zuerst gelöscht.

Fremdschlüsseleinschränkungen können so konfiguriert werden, dass die zugeordneten untergeordneten Datensätze automatisch gelöscht werden, wenn ein übergeordneter Datensatz gelöscht wird. Anders ausgedrückt: Wir können diese Fremdschlüsseleinschränkung so einrichten, dass die Gastbucheinträge eines Benutzers automatisch gelöscht werden, wenn ihr Benutzerkonto gelöscht wird. Erweitern Sie hierzu den Abschnitt "INSERT And UPDATE Specification", und legen Sie die Eigenschaft "Delete Rule" auf Cascade fest.

Konfigurieren der Fremdschlüsseleinschränkung für kaskadierende Löschvorgänge

Abbildung 5: Konfigurieren der Fremdschlüsseleinschränkung für kaskadierende Löschvorgänge (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Um die Fremdschlüsseleinschränkung zu speichern, klicken Sie auf die Schaltfläche Schließen, um die Fremdschlüsselbeziehungen zu beenden. Klicken Sie dann in der Symbolleiste auf das Symbol Speichern, um die Tabelle und diese Beziehung zu speichern.

Speichern von Heimatort, Homepage und Signatur des Benutzers

Die GuestbookComments Tabelle veranschaulicht, wie Informationen gespeichert werden, die eine 1:n-Beziehung mit Benutzerkonten gemeinsam verwenden. Da jedes Benutzerkonto über eine beliebige Anzahl von zugeordneten Kommentaren verfügen kann, wird diese Beziehung modelliert, indem eine Tabelle erstellt wird, die den Satz von Kommentaren enthält, die eine Spalte enthält, die jeden Kommentar zu einem bestimmten Benutzer zurückgibt. Wenn Sie verwenden SqlMembershipProvider, wird dieser Link am besten hergestellt, indem Sie eine Spalte mit dem Namen des UserId Typs uniqueidentifier und eine Fremdschlüsseleinschränkung zwischen dieser Spalte und aspnet_Users.UserIderstellen.

Nun müssen wir jedem Benutzerkonto drei Spalten zuordnen, um die Heimat des Benutzers, die Homepage und die Signatur des Benutzers zu speichern, die in seinen Gästebuchkommentaren angezeigt werden. Es gibt verschiedene Möglichkeiten, dies zu erreichen:

  • Hinzufügen neuer Spalten zumaspnet_UsersOderaspnet_MembershipTabellen. Ich würde diesen Ansatz nicht empfehlen, da er das schema ändert, das SqlMembershipProvidervon verwendet wird. Diese Entscheidung kann Sie auf der Straße heimgesucht haben. Was geschieht beispielsweise, wenn eine zukünftige Version von ASP.NET ein anderes SqlMembershipProvider Schema verwendet. Microsoft kann ein Tool zum Migrieren der ASP.NET 2.0-Daten SqlMembershipProvider in das neue Schema einschließen, aber wenn Sie das ASP.NET 2.0-Schema SqlMembershipProvider geändert haben, ist eine solche Konvertierung möglicherweise nicht möglich.

  • Verwenden Sie ASP. NET's Profile Framework, das eine Profileigenschaft für den Heimatort, die Homepage und die Signatur definiert. ASP.NET enthält ein Profilframework, das zum Speichern zusätzlicher benutzerspezifischer Daten konzipiert ist. Wie das Mitgliedschaftsframework wird das Profilframework auf dem Anbietermodell erstellt. Die .NET Framework mit einem SqlProfileProvider Sthat geliefert wird, speichert Profildaten in einer SQL Server-Datenbank. Tatsächlich verfügt unsere Datenbank bereits über die von SqlProfileProvider (aspnet_Profile) verwendete Tabelle, da sie hinzugefügt wurde, als wir die Anwendungsdienste im Tutorial Erstellen des Mitgliedschaftsschemas in SQL Server hinzugefügt haben.
    Der Standard Vorteil des Profile-Frameworks besteht darin, dass Entwickler die Profileigenschaften in Web.config definieren können– es muss kein Code geschrieben werden, um die Profildaten in und aus dem zugrunde liegenden Datenspeicher zu serialisieren. Kurz gesagt, es ist unglaublich einfach, eine Reihe von Profileigenschaften zu definieren und mit ihnen im Code zu arbeiten. Das Profilsystem lässt jedoch bei der Versionsverwaltung zu wünschen übrig. Wenn Sie also über eine Anwendung verfügen, bei der Sie erwarten, dass zu einem späteren Zeitpunkt neue benutzerspezifische Eigenschaften hinzugefügt oder vorhandene Eigenschaften entfernt oder geändert werden, ist das Profilframework möglicherweise nicht die beste Option. Darüber hinaus speichert der die SqlProfileProvider Profileigenschaften in einer stark denormalisierten Weise, sodass es so gut wie unmöglich ist, Abfragen direkt gegen die Profildaten auszuführen (z. B. wie viele Benutzer eine Heimatstadt New York haben).
    Weitere Informationen zum Profilframework finden Sie im Abschnitt "Weitere Lesungen" am Ende dieses Tutorials.

  • Fügen Sie diese drei Spalten einer neuen Tabelle in der Datenbank hinzu, und stellen Sie eine 1:1-Beziehung zwischen dieser Tabelle undaspnet_Users. Dieser Ansatz erfordert etwas mehr Arbeit als mit dem Profilframework, bietet jedoch maximale Flexibilität bei der Modellierung der zusätzlichen Benutzereigenschaften in der Datenbank. Dies ist die Option, die wir in diesem Tutorial verwenden werden.

Wir erstellen eine neue Tabelle namens, UserProfiles um die Heimatstadt, die Homepage und die Signatur für jeden Benutzer zu speichern. Klicken Sie im Fenster Datenbank Explorer mit der rechten Maustaste auf den Ordner Tabellen, und wählen Sie aus, um eine neue Tabelle zu erstellen. Benennen Sie die erste Spalte, UserId und legen Sie ihren Typ auf fest uniqueidentifier. Zulassen von NULL Werten, und markieren Sie die Spalte als Primärschlüssel. Fügen Sie als Nächstes Spalten mit dem Namen : HomeTown vom Typ nvarchar(50); HomepageUrl vom Typ nvarchar(100); und Signatur des Typs hinzu nvarchar(500). Jede dieser drei Spalten kann einen NULL Wert akzeptieren.

Erstellen der Tabelle

Abbildung 6: Erstellen der UserProfiles Tabelle (Klicken Sie hier, um das bild in voller Größe anzuzeigen)

Speichern Sie die Tabelle, und nennen Sie sie UserProfiles. Richten Sie schließlich eine Fremdschlüsseleinschränkung zwischen dem Feld der UserProfiles Tabelle UserId und dem aspnet_Users.UserId Feld ein. Wie bei der Fremdschlüsseleinschränkung zwischen den GuestbookComments Tabellen und aspnet_Users lassen Sie diese Einschränkung kaskadieren. Da das UserId Feld in UserProfiles der Primärschlüssel ist, wird dadurch sichergestellt, dass nicht mehr als ein Datensatz in der UserProfiles Tabelle für jedes Benutzerkonto vorhanden ist. Diese Art von Beziehung wird als 1:1 bezeichnet.

Nachdem wir nun das Datenmodell erstellt haben, können wir es verwenden. In Den Schritten 2 und 3 wird erläutert, wie der aktuell angemeldete Benutzer seine Heimatort-, Homepage- und Signaturinformationen anzeigen und bearbeiten kann. In Schritt 4 erstellen wir die Schnittstelle für authentifizierte Benutzer, um neue Kommentare an das Gästebuch zu übermitteln und die vorhandenen anzuzeigen.

Schritt 2: Anzeigen von Heimatort, Homepage und Signatur des Benutzers

Es gibt eine Vielzahl von Möglichkeiten, um dem aktuell angemeldeten Benutzer das Anzeigen und Bearbeiten seiner Heimatort-, Homepage- und Signaturinformationen zu ermöglichen. Wir können die Benutzeroberfläche manuell mit TextBox- und Label-Steuerelementen erstellen oder eines der Datenwebsteuerelemente verwenden, z. B. das DetailsView-Steuerelement. Um die Datenbank SELECT und UPDATE die Anweisungen auszuführen, können wir ADO.NET Code in der CodeBehind-Klasse unserer Seite schreiben oder alternativ einen deklarativen Ansatz mit der SqlDataSource verwenden. Im Idealfall enthält unsere Anwendung eine mehrstufige Architektur, die entweder programmgesteuert von der CodeBehind-Klasse der Seite oder deklarativ über das ObjectDataSource-Steuerelement aufgerufen werden könnte.

Da sich diese Tutorialreihe auf Formularauthentifizierung, Autorisierung, Benutzerkonten und Rollen konzentriert, wird es keine ausführliche Erläuterung dieser verschiedenen Datenzugriffsoptionen geben oder warum eine mehrstufige Architektur gegenüber der Ausführung von SQL-Anweisungen direkt auf der ASP.NET-Seite bevorzugt wird. Ich werde die Verwendung von DetailsView und SqlDataSource – die schnellste und einfachste Option – durchgehen, aber die besprochenen Konzepte können sicherlich auf alternative Websteuerelemente und Datenzugriffslogik angewendet werden. Weitere Informationen zum Arbeiten mit Daten in ASP.NET finden Sie in der Tutorialreihe Arbeiten mit Daten in ASP.NET 2.0 .

Öffnen Sie die AdditionalUserInfo.aspx Seite im Membership Ordner, und fügen Sie der Seite ein DetailsView-Steuerelement hinzu, legen Sie dessen ID Eigenschaft auf UserProfile fest, und löschen Sie die Width Eigenschaften und Height aus. Erweitern Sie das Smarttag von DetailsView, und binden Sie es an ein neues Datenquellensteuerelement. Dadurch wird der DataSource-Konfigurations-Assistent gestartet (siehe Abbildung 7). Im ersten Schritt werden Sie aufgefordert, den Datenquellentyp anzugeben. Da wir eine direkte Verbindung mit der SecurityTutorials Datenbank herstellen möchten, wählen Sie das Datenbanksymbol aus, und geben Sie als an IDUserProfileDataSource.

Hinzufügen eines neuen SqlDataSource-Steuerelements namens UserProfileDataSource

Abbildung 7: Hinzufügen eines neuen SqlDataSource-Steuerelements namens UserProfileDataSource (Klicken Sie hier, um das bild in voller Größe anzuzeigen)

Auf dem nächsten Bildschirm wird zur Verwendung der Datenbank aufgefordert. Wir haben bereits eine Verbindungszeichenfolge für Web.config die SecurityTutorials Datenbank definiert. Dieser Verbindungszeichenfolgenname – SecurityTutorialsConnectionString sollte sich in der Dropdownliste befinden. Wählen Sie diese Option aus, und klicken Sie auf Weiter.

Wählen Sie SecurityTutorialsConnectionString aus der Drop-Down-Liste aus.

Abbildung 8: Auswählen SecurityTutorialsConnectionString aus der Drop-Down-Liste (Klicken Sie, um das Bild in voller Größe anzuzeigen)

Auf dem folgenden Bildschirm werden wir aufgefordert, die abzufragende Tabelle und die zu abfragenden Spalten anzugeben. Wählen Sie die UserProfiles Tabelle aus der Dropdownliste aus, und überprüfen Sie alle Spalten.

Wiederherstellen aller Spalten aus der Tabelle

Abbildung 9: Wiederherstellen aller Spalten aus der UserProfiles Tabelle (Klicken Sie hier, um das bild in voller Größe anzuzeigen)

Die aktuelle Abfrage in Abbildung 9 gibt alle Datensätze in UserProfileszurück, aber wir interessieren uns nur für den aktuell angemeldeten Benutzerdatensatz. Um eine WHERE Klausel hinzuzufügen, klicken Sie auf die WHERE Schaltfläche, um das Dialogfeld Klausel hinzufügen zu WHERE öffnen (siehe Abbildung 10). Hier können Sie die Spalte zum Filtern, den Operator und die Quelle des Filterparameters auswählen. Wählen Sie als Spalte und "=" als Operator aus UserId .

Leider gibt es keine integrierte Parameterquelle, die den Wert des UserId aktuell angemeldeten Benutzers zurückgibt. Wir müssen diesen Wert programmgesteuert abrufen. Legen Sie daher die Dropdownliste Quelle auf "Keine" fest, klicken Sie auf die Schaltfläche Hinzufügen, um den Parameter hinzuzufügen, und klicken Sie dann auf OK.

Hinzufügen eines Filterparameters für die UserId-Spalte

Abbildung 10: Hinzufügen eines Filterparameters für die UserId Spalte (Klicken Sie hier, um das bild in voller Größe anzuzeigen)

Nachdem Sie auf OK geklickt haben, kehren Sie zu dem in Abbildung 9 gezeigten Bildschirm zurück. Dieses Mal sollte die SQL-Abfrage am unteren Bildschirmrand jedoch eine WHERE Klausel enthalten. Klicken Sie auf Weiter, um zum Bildschirm "Abfrage testen" zu wechseln. Hier können Sie die Abfrage ausführen und die Ergebnisse anzeigen. Klicken Sie auf Fertig stellen, um den Assistenten abzuschließen.

Nach Abschluss des DataSource-Konfigurations-Assistenten erstellt Visual Studio das SqlDataSource-Steuerelement basierend auf den im Assistenten angegebenen Einstellungen. Darüber hinaus fügt es BoundFields manuell zur DetailsView für jede Spalte hinzu, die von sqlDataSource SelectCommandzurückgegeben wird. Es ist nicht erforderlich, das UserId Feld in der DetailsView anzuzeigen, da der Benutzer diesen Wert nicht kennen muss. Sie können dieses Feld direkt aus dem deklarativen Markup des DetailsView-Steuerelements entfernen oder indem Sie im Smarttag auf den Link "Felder bearbeiten" klicken.

An diesem Punkt sollte das deklarative Markup Ihrer Seite wie folgt aussehen:

<asp:DetailsView ID="UserProfile" runat="server"
     AutoGenerateRows="False" DataKeyNames="UserId"
     DataSourceID="UserProfileDataSource">
     <Fields>
          <asp:BoundField DataField="HomeTown" HeaderText="HomeTown"
               SortExpression="HomeTown" />
          <asp:BoundField DataField="HomepageUrl" HeaderText="HomepageUrl"
               SortExpression="HomepageUrl" />
          <asp:BoundField DataField="Signature" HeaderText="Signature"
               SortExpression="Signature" />
     </Fields>
</asp:DetailsView>
<asp:SqlDataSource ID="UserProfileDataSource" runat="server"
          ConnectionString="<%$ ConnectionStrings:SecurityTutorialsConnectionString %>"
          SelectCommand="SELECT [UserId], [HomeTown], [HomepageUrl], [Signature] FROM
          [UserProfiles] WHERE ([UserId] = @UserId)">
     <SelectParameters>
          <asp:Parameter Name="UserId" Type="Object" />
     </SelectParameters>
</asp:SqlDataSource>

Wir müssen den Parameter des SqlDataSource-Steuerelements UserId programmgesteuert auf den des aktuell angemeldeten Benutzers UserId festlegen, bevor die Daten ausgewählt werden. Dies kann erreicht werden, indem Sie einen Ereignishandler für das SqlDataSource-Ereignis Selecting erstellen und dort den folgenden Code hinzufügen:

protected void UserProfileDataSource_Selecting(object sender, 
          SqlDataSourceSelectingEventArgs e)
{
     // Get a reference to the currently logged on user
     MembershipUser currentUser = Membership.GetUser();
 
     // Determine the currently logged on user's UserId value
     Guid currentUserId = (Guid)currentUser.ProviderUserKey;
 
     // Assign the currently logged on user's UserId to the @UserId parameter
     e.Command.Parameters["@UserId"].Value = currentUserId;
}

Der obige Code ruft zunächst einen Verweis auf den aktuell angemeldeten Benutzer ab, indem die -Methode der Membership -Klasse GetUser aufgerufen wird. Dadurch wird ein MembershipUser -Objekt zurückgegeben, dessen ProviderUserKey -Eigenschaft das UserIdenthält. Der UserId Wert wird dann dem SqlDataSource-Parameter @UserId zugewiesen.

Hinweis

Die Membership.GetUser() -Methode gibt Informationen zum aktuell angemeldeten Benutzer zurück. Wenn ein anonymer Benutzer die Seite besucht, wird der Wert zurückgegeben null. In einem solchen Fall führt dies zu einem NullReferenceException in der folgenden Codezeile, wenn versucht wird, die ProviderUserKey Eigenschaft zu lesen. Natürlich müssen wir uns nicht um Membership.GetUser() die Rückgabe eines null Werts auf der AdditionalUserInfo.aspx Seite kümmern, da wir die URL-Autorisierung in einem vorherigen Tutorial so konfiguriert haben, dass nur authentifizierte Benutzer auf die ASP.NET Ressourcen in diesem Ordner zugreifen konnten. Wenn Sie auf Informationen über den aktuell angemeldeten Benutzer auf einer Seite zugreifen müssen, auf der anonymer Zugriff zulässig ist, vergewissern Sie sich, dass ein Nichtobjektnull MembershipUser von der GetUser() -Methode zurückgegeben wird, bevor Sie auf ihre Eigenschaften verweisen.

Wenn Sie die AdditionalUserInfo.aspx Seite über einen Browser besuchen, wird eine leere Seite angezeigt, da der Tabelle noch keine Zeilen UserProfiles hinzugefügt wurden. In Schritt 6 wird erläutert, wie Sie das CreateUserWizard-Steuerelement anpassen, um der UserProfiles Tabelle automatisch eine neue Zeile hinzuzufügen, wenn ein neues Benutzerkonto erstellt wird. Vorerst müssen wir jedoch manuell einen Datensatz in der Tabelle erstellen.

Navigieren Sie in Visual Studio zum Explorer Datenbank, und erweitern Sie den Ordner Tabellen. Klicken Sie mit der rechten Maustaste auf die aspnet_Users Tabelle, und wählen Sie "Tabellendaten anzeigen", um die Datensätze in der Tabelle anzuzeigen. Führen Sie dasselbe für die Tabelle aus UserProfiles . Abbildung 11 zeigt diese Ergebnisse, wenn sie vertikal gekachelt werden. In meiner Datenbank gibt es derzeit aspnet_Users Datensätze für Bruce, Fred und Tito, aber keine Datensätze in der UserProfiles Tabelle.

Der Inhalt der Aspnet_Users- und UserProfiles-Tabellen wird angezeigt.

Abbildung 11: Der Inhalt der aspnet_Users Tabellen und UserProfiles der Tabellen werden angezeigt (Klicken Sie hier, um das bild in voller Größe anzuzeigen)

Fügen Sie der UserProfiles Tabelle einen neuen Datensatz hinzu, indem Sie manuell Werte für die HomeTownFelder , HomepageUrlund Signature eingeben. Die einfachste Möglichkeit, einen gültigen UserId Wert im neuen UserProfiles Datensatz abzurufen, besteht darin, das UserId Feld aus einem bestimmten Benutzerkonto in der aspnet_Users Tabelle auszuwählen und es zu kopieren und in das UserId Feld in UserProfileseinzufügen. Abbildung 12 zeigt die UserProfiles Tabelle, nachdem ein neuer Datensatz für Bruce hinzugefügt wurde.

Ein Datensatz wurde zu UserProfiles für Bruce hinzugefügt.

Abbildung 12: Ein Datensatz wurde für Bruce hinzugefügt UserProfiles (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Kehren Sie zur Seite zurück, die AdditionalUserInfo.aspx als Bruce angemeldet ist. Wie Abbildung 13 zeigt, werden Bruces Einstellungen angezeigt.

Dem aktuell besuchten Benutzer werden seine Einstellungen angezeigt.

Abbildung 13: Dem derzeit besuchenden Benutzer werden seine Einstellungen angezeigt (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Hinweis

Fügen Sie in der UserProfiles Tabelle für jeden Mitgliedschaftsbenutzer manuell Datensätze hinzu. In Schritt 6 erfahren Sie, wie Sie das CreateUserWizard-Steuerelement so anpassen, dass der UserProfiles Tabelle automatisch eine neue Zeile hinzugefügt wird, wenn ein neues Benutzerkonto erstellt wird.

Schritt 3: Zulassen, dass der Benutzer seine Heimatstadt, Homepage und Signatur bearbeiten kann

Zu diesem Zeitpunkt kann der aktuell angemeldete Benutzer seine Heimat, Homepage und Signatureinstellung einsehen, aber noch nicht ändern. Aktualisieren Wir nun das DetailsView-Steuerelement, damit die Daten bearbeitet werden können.

Zunächst müssen wir eine UpdateCommand für sqlDataSource hinzufügen und dabei die auszuführende Anweisung und die UPDATE entsprechenden Parameter angeben. Wählen Sie sqlDataSource aus, und klicken Sie im Eigenschaftenfenster auf die Auslassungspunkte neben der UpdateQuery-Eigenschaft, um das Dialogfeld Befehls- und Parameter-Editor anzuzeigen. Geben Sie die folgende UPDATE Anweisung in das Textfeld ein:

UPDATE UserProfiles SET
     HomeTown = @HomeTown,
     HomepageUrl = @HomepageUrl,
     Signature = @Signature
WHERE UserId = @UserId

Klicken Sie als Nächstes auf die Schaltfläche "Parameter aktualisieren", um einen Parameter in der Auflistung des SqlDataSource-Steuerelements UpdateParameters für jeden parameter in der UPDATE -Anweisung zu erstellen. Lassen Sie die Quelle für alle Parameter auf Keine festgelegt, und klicken Sie auf die Schaltfläche OK, um das Dialogfeld abzuschließen.

Geben Sie updateCommand und UpdateParameters von SqlDataSource an.

Abbildung 14: Angeben der SqlDataSource und UpdateCommandUpdateParameters (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Aufgrund der Ergänzungen, die wir am SqlDataSource-Steuerelement vorgenommen haben, kann das DetailsView-Steuerelement jetzt die Bearbeitung unterstützen. Aktivieren Sie im Smarttag von DetailsView das Kontrollkästchen "Bearbeitung aktivieren". Dadurch wird der Auflistung des Steuerelements Fields ein CommandField hinzugefügt, dessen ShowEditButton -Eigenschaft auf True festgelegt ist. Dadurch wird eine Schaltfläche Bearbeiten gerendert, wenn detailsView im schreibgeschützten Modus und die Schaltflächen Aktualisieren und Abbrechen angezeigt wird, wenn sie im Bearbeitungsmodus angezeigt wird. Anstatt jedoch zu verlangen, dass der Benutzer auf Bearbeiten klicken muss, können wir detailsView in einem "immer bearbeitbaren" Zustand rendern lassen, indem wir die -Eigenschaft desDefaultMode DetailsView-Steuerelements auf Editfestlegen.

Mit diesen Änderungen sollte das deklarative Markup Ihres DetailsView-Steuerelements in etwa wie folgt aussehen:

<asp:DetailsView ID="UserProfile" runat="server"
          AutoGenerateRows="False" DataKeyNames="UserId"
          DataSourceID="UserProfileDataSource" DefaultMode="Edit">
     <Fields>
          <asp:BoundField DataField="HomeTown" HeaderText="HomeTown"
               SortExpression="HomeTown" />
          <asp:BoundField DataField="HomepageUrl" HeaderText="HomepageUrl"
               SortExpression="HomepageUrl" />
          <asp:BoundField DataField="Signature" HeaderText="Signature"
               SortExpression="Signature" />
          <asp:CommandField ShowEditButton="True" />
     </Fields>
</asp:DetailsView>

Beachten Sie das Hinzufügen von CommandField und der DefaultMode -Eigenschaft.

Testen Sie diese Seite über einen Browser. Beim Besuch mit einem Benutzer, der über einen entsprechenden Datensatz in UserProfilesverfügt, werden die Einstellungen des Benutzers in einer bearbeitbaren Benutzeroberfläche angezeigt.

DetailsView rendert eine bearbeitbare Schnittstelle

Abbildung 15: DetailsView rendert eine bearbeitbare Schnittstelle (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Versuchen Sie, die Werte zu ändern, und klicken Sie auf die Schaltfläche Aktualisieren. Es scheint, als ob nichts geschieht. Es gibt ein Postback, und die Werte werden in der Datenbank gespeichert, aber es gibt kein visuelles Feedback, dass die Speicherung erfolgt ist.

Um dies zu beheben, kehren Sie zu Visual Studio zurück, und fügen Sie ein Label-Steuerelement über der DetailsView hinzu. Legen Sie auf SettingsUpdatedMessageID , die Text -Eigenschaft auf "Ihre Einstellungen wurden aktualisiert" und die Visible Eigenschaften und EnableViewState auf festfalse.

<asp:Label ID="SettingsUpdatedMessage" runat="server"
     Text="Your settings have been updated."
     EnableViewState="false"
     Visible="false"></asp:Label>

Wir müssen die SettingsUpdatedMessage Bezeichnung anzeigen, wenn die DetailsView aktualisiert wird. Erstellen Sie hierzu einen Ereignishandler für das Ereignis von ItemUpdated DetailsView, und fügen Sie den folgenden Code hinzu:

protected void UserProfile_ItemUpdated(object sender, DetailsViewUpdatedEventArgs e)
{
     SettingsUpdatedMessage.Visible = true;
}

Kehren Sie über einen Browser zur AdditionalUserInfo.aspx Seite zurück, und aktualisieren Sie die Daten. Dieses Mal wird eine hilfreiche status Meldung angezeigt.

Eine kurze Meldung wird angezeigt, wenn die Einstellungen aktualisiert werden.

Abbildung 16: Eine kurze Meldung wird angezeigt, wenn die Einstellungen aktualisiert werden (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Hinweis

Die Bearbeitungsoberfläche des DetailsView-Steuerelements lässt viel zu wünschen übrig. Es werden Textfelder in Standardgröße verwendet, aber das Feld Signatur sollte wahrscheinlich ein mehrzeiliges Textfeld sein. Ein RegularExpressionValidator sollte verwendet werden, um sicherzustellen, dass die Homepage-URL bei Eingabe mit "http://" oder "https://" beginnt. Da die Eigenschaft des DetailsView-Steuerelements auf Editfestgelegt istDefaultMode, führt die Schaltfläche Abbrechen keine Aktionen aus. Sie sollte entweder entfernt oder beim Klicken auf eine andere Seite umgeleitet werden (z ~/Default.aspx. B. ). Ich belasse diese Verbesserungen als Übung für den Leser.

Derzeit stellt die Website keine Links zu der AdditionalUserInfo.aspx Seite bereit. Die einzige Möglichkeit, sie zu erreichen, besteht darin, die URL der Seite direkt in die Adressleiste des Browsers einzugeben. Fügen Sie auf der Site.master Seite master einen Link zu dieser Seite hinzu.

Denken Sie daran, dass die Seite master ein LoginView-Websteuerelement in ihrem LoginContent ContentPlaceHolder enthält, das unterschiedliche Markups für authentifizierte und anonyme Besucher anzeigt. Aktualisieren Sie die LoginView-Steuerelemente LoggedInTemplate , um einen Link zur AdditionalUserInfo.aspx Seite einzuschließen. Nachdem Sie diese Änderungen vorgenommen haben, sollte das deklarative Markup des LoginView-Steuerelements in etwa wie folgt aussehen:

<asp:LoginView ID="LoginView1" runat="server">
     <LoggedInTemplate>
          Welcome back,
          <asp:LoginName ID="LoginName1" runat="server" />.
          <br />
          <asp:HyperLink ID="lnkUpdateSettings" runat="server" 
               NavigateUrl="~/Membership/AdditionalUserInfo.aspx">
               Update Your Settings</asp:HyperLink>
     </LoggedInTemplate>
     <AnonymousTemplate>
          Hello, stranger.
     </AnonymousTemplate>
</asp:LoginView>

Beachten Sie das Hinzufügen des lnkUpdateSettings HyperLink-Steuerelements zu .LoggedInTemplate Wenn dieser Link vorhanden ist, können authentifizierte Benutzer schnell zur Seite springen, um ihre Heimat, Homepage und Signatureinstellungen anzuzeigen und zu ändern.

Schritt 4: Hinzufügen neuer Gästebuchkommentare

Auf Guestbook.aspx der Seite können authentifizierte Benutzer das Gästebuch anzeigen und einen Kommentar hinterlassen. Beginnen wir mit dem Erstellen der Benutzeroberfläche, um neue Gästebuchkommentare hinzuzufügen.

Öffnen Sie die Guestbook.aspx Seite in Visual Studio, und erstellen Sie eine Benutzeroberfläche, die aus zwei TextBox-Steuerelementen besteht: eines für den Betreff des neuen Kommentars und eines für den Textkörper. Legen Sie die Eigenschaft des ersten TextBox-Steuerelements ID auf Subject und seine Columns -Eigenschaft auf 40 fest. Legen Sie die zweite ID auf Bodyfest, WidthTextMode und MultiLinelegen Sie die Eigenschaften und Rows auf "95%" bzw. 8 fest. Fügen Sie zum Abschließen der Benutzeroberfläche ein Button-Websteuerelement mit dem Namen PostCommentButton hinzu, und legen Sie dessen Text Eigenschaft auf "Kommentar posten" fest.

Da jeder Gastbuchkommentar einen Betreff und einen Text erfordert, fügen Sie für jedes Der TextBoxes einen RequiredFieldValidator hinzu. Legen Sie die ValidationGroup -Eigenschaft dieser Steuerelemente auf "EnterComment" fest. Legen Sie ebenfalls die PostCommentButton -Eigenschaft des Steuerelements ValidationGroup auf "EnterComment" fest. Weitere Informationen zu ASP. Die Validierungssteuerelemente von NET finden Sie unter Formularüberprüfung in ASP.NET.

Nach dem Erstellen der Benutzeroberfläche sollte das deklarative Markup Ihrer Seite in etwa wie folgt aussehen:

<h3>Leave a Comment</h3>
<p>
     <b>Subject:</b>
     <asp:RequiredFieldValidator ID="SubjectReqValidator" runat="server"
          ErrorMessage="You must provide a value for Subject"
          ControlToValidate="Subject" ValidationGroup="EnterComment">
     </asp:RequiredFieldValidator><br/>
     <asp:TextBox ID="Subject" Columns="40" runat="server"></asp:TextBox>
</p>
<p>
     <b>Body:</b>
     <asp:RequiredFieldValidator ID="BodyReqValidator" runat="server"
          ControlToValidate="Body"
          ErrorMessage="You must provide a value for Body" ValidationGroup="EnterComment">
     </asp:RequiredFieldValidator><br/>
     <asp:TextBox ID="Body" TextMode="MultiLine" Width="95%"
          Rows="8" runat="server"></asp:TextBox>
</p>
<p>
     <asp:Button ID="PostCommentButton" runat="server" 
          Text="Post Your Comment"
          ValidationGroup="EnterComment" />
</p>

Wenn die Benutzeroberfläche abgeschlossen ist, besteht die nächste Aufgabe darin, einen neuen Datensatz in die GuestbookComments Tabelle einzufügen, wenn auf geklickt PostCommentButton wird. Dies kann auf verschiedene Arten erreicht werden: Wir können ADO.NET Code in den Ereignishandler der Schaltfläche Click schreiben. Wir können der Seite ein SqlDataSource-Steuerelement hinzufügen, dessen InsertCommandkonfigurieren und dann die - Insert Methode aus dem Click Ereignishandler aufrufen; oder wir könnten eine mittlere Ebene erstellen, die für das Einfügen neuer Gastbuchkommentare verantwortlich war, und diese Funktionalität über den Click Ereignishandler aufrufen. Da wir uns in Schritt 3 mit der Verwendung einer SqlDataSource befasst haben, verwenden wir hier ADO.NET Code.

Hinweis

Die ADO.NET Klassen, die für den programmgesteuerten Zugriff auf Daten aus einer Microsoft SQL Server-Datenbank verwendet werden, befinden sich im System.Data.SqlClient Namespace. Möglicherweise müssen Sie diesen Namespace in die CodeBehind-Klasse Ihrer Seite importieren (d. h. using System.Data.SqlClient;).

Erstellen Sie einen Ereignishandler für das PostCommentButton-Ereignis, Click und fügen Sie den folgenden Code hinzu:

protected void PostCommentButton_Click(object sender, EventArgs e)
{
     if (!Page.IsValid)
          return;
 
     // Determine the currently logged on user's UserId
     MembershipUser currentUser = Membership.GetUser();
     Guid currentUserId = (Guid)currentUser.ProviderUserKey;
 
     // Insert a new record into GuestbookComments
     string connectionString = 
          ConfigurationManager.ConnectionStrings["SecurityTutorialsConnectionString"].ConnectionString;
     string insertSql = "INSERT INTO GuestbookComments(Subject, Body, UserId) VALUES(@Subject,
               @Body, @UserId)";
 
     using (SqlConnection myConnection = new SqlConnection(connectionString))
     {
          myConnection.Open();
          SqlCommand myCommand = new SqlCommand(insertSql, myConnection);
          myCommand.Parameters.AddWithValue("@Subject", Subject.Text.Trim());
          myCommand.Parameters.AddWithValue("@Body", Body.Text.Trim());
          myCommand.Parameters.AddWithValue("@UserId", currentUserId);
          myCommand.ExecuteNonQuery();
          myConnection.Close();
     }
 
     // "Reset" the Subject and Body TextBoxes
     Subject.Text = string.Empty;
     Body.Text = string.Empty;
}

Der Click Ereignishandler überprüft zunächst, ob die vom Benutzer bereitgestellten Daten gültig sind. Wenn dies nicht der Fall ist, wird der Ereignishandler vor dem Einfügen eines Datensatzes beendet. Wenn die angegebenen Daten gültig sind, wird der Wert des UserId aktuell angemeldeten Benutzers abgerufen und in der currentUserId lokalen Variablen gespeichert. Dieser Wert wird benötigt, da beim Einfügen eines UserId Datensatzes in GuestbookCommentseinen -Wert verwendet werden muss.

Anschließend wird die Verbindungszeichenfolge für die SecurityTutorials Datenbank aus Web.config abgerufen, und die INSERT SQL-Anweisung wird angegeben. Anschließend SqlConnection wird ein -Objekt erstellt und geöffnet. Als Nächstes wird ein SqlCommand -Objekt erstellt, und die Werte für die in der INSERT Abfrage verwendeten Parameter werden zugewiesen. Anschließend INSERT wird die Anweisung ausgeführt, und die Verbindung wird geschlossen. Am Ende des Ereignishandlers werden die Eigenschaften und Body die Subject TextBoxes-Eigenschaften Text gelöscht, sodass die Werte des Benutzers nicht über das Postback gespeichert werden.

Testen Sie diese Seite in einem Browser. Da sich diese Seite im Membership Ordner befindet, ist sie für anonyme Besucher nicht zugänglich. Daher müssen Sie sich zuerst anmelden (sofern noch nicht geschehen). Geben Sie einen Wert in die Subject Textfelder und Body ein, und klicken Sie auf die PostCommentButton Schaltfläche. Dies führt dazu, dass ein neuer Datensatz zu GuestbookCommentshinzugefügt wird. Beim Postback werden betreff und text, den Sie angegeben haben, aus den TextBoxen zurückgesetzt.

Nach dem Klicken auf die PostCommentButton Schaltfläche gibt es kein visuelles Feedback, dass der Kommentar dem Gästebuch hinzugefügt wurde. Wir müssen diese Seite noch aktualisieren, um die vorhandenen Gästebuchkommentare anzuzeigen, was wir in Schritt 5 tun werden. Sobald wir dies erreicht haben, wird der gerade hinzugefügte Kommentar in der Liste der Kommentare angezeigt und liefert ein angemessenes visuelles Feedback. Vergewissern Sie sich vorerst, dass Ihr Gastbuchkommentar gespeichert wurde, indem Sie den Inhalt der GuestbookComments Tabelle untersuchen.

Abbildung 17 zeigt den Inhalt der GuestbookComments Tabelle, nachdem zwei Kommentare verlassen wurden.

Sie können die Gästebuchkommentare in der Tabelle GästebuchKommentare anzeigen.

Abbildung 17: Sie können die Gästebuchkommentare in der GuestbookComments Tabelle sehen (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Hinweis

Wenn ein Benutzer versucht, einen Gastbuchkommentar einzufügen, der potenziell gefährliches Markup (z. B. HTML) enthält, löst ASP.NET einen aus HttpRequestValidationException. Weitere Informationen zu dieser Ausnahme, warum sie ausgelöst wird und wie Benutzer potenziell gefährliche Werte übermitteln können, finden Sie im Whitepaper Zur Anforderungsüberprüfung.

Schritt 5: Auflisten der vorhandenen Gästebuchkommentare

Zusätzlich zum Hinterlassen von Kommentaren sollte ein Benutzer, der die Guestbook.aspx Seite besucht, auch in der Lage sein, die vorhandenen Kommentare des Gästebuchs anzuzeigen. Fügen Sie dazu am unteren Rand der Seite ein ListView-Steuerelement mit dem Namen CommentList hinzu.

Hinweis

Das ListView-Steuerelement ist neu in ASP.NET Version 3.5. Es wurde entwickelt, um eine Liste von Elementen in einem sehr anpassbaren und flexiblen Layout anzuzeigen, bietet aber dennoch integrierte Bearbeitungs-, Einfüge-, Lösch-, Paging- und Sortierfunktionen wie gridView. Wenn Sie ASP.NET 2.0 verwenden, müssen Sie stattdessen das DataList- oder Repeater-Steuerelement verwenden. Weitere Informationen zur Verwendung der ListView finden Sie unter Scott Guthries Blogeintrag Das asp:ListView-Steuerelement und in meinem Artikel Anzeigen von Daten mit dem ListView-Steuerelement.

Öffnen Sie das Smarttag von ListView, und binden Sie das Steuerelement in der Dropdownliste Datenquelle auswählen an eine neue Datenquelle. Wie in Schritt 2 gezeigt, wird der Datenquellenkonfigurations-Assistent gestartet. Wählen Sie das Symbol Datenbank aus, benennen Sie die resultierende SqlDataSource CommentsDataSource, und klicken Sie auf OK. Wählen Sie als Nächstes die SecurityTutorialsConnectionString Verbindungszeichenfolge aus der Dropdownliste aus, und klicken Sie auf Weiter.

An diesem Punkt in Schritt 2 haben wir die abzufragenden Daten angegeben, indem wir die UserProfiles Tabelle aus der Dropdownliste auswählen und die zurückzugebenden Spalten auswählen (siehe Abbildung 9). Dieses Mal möchten wir jedoch eine SQL-Anweisung erstellen, die nicht nur die Datensätze aus GuestbookComments, sondern auch die Heimatstadt, die Homepage, die Signatur und den Benutzernamen des Kommentators zurückzieht. Wählen Sie daher das Optionsfeld "Benutzerdefinierte SQL-Anweisung oder gespeicherte Prozedur angeben" aus, und klicken Sie auf Weiter.

Dadurch wird der Bildschirm "Benutzerdefinierte Anweisungen oder gespeicherte Prozeduren definieren" geöffnet. Klicken Sie auf die Schaltfläche Abfrage-Generator, um die Abfrage grafisch zu erstellen. Der Abfrage-Generator fordert uns zunächst auf, die Tabellen anzugeben, die wir abfragen möchten. Wählen Sie die GuestbookCommentsTabellen , UserProfilesund aus, und aspnet_Users klicken Sie auf OK. Dadurch werden alle drei Tabellen der Entwurfsoberfläche hinzugefügt. Da es Fremdschlüsseleinschränkungen zwischen den GuestbookCommentsTabellen , UserProfilesund aspnet_Users gibt der Abfrage-Generator diese Tabellen automatisch JOIN aus.

Es bleibt nur noch, die zurückzugebenden Spalten anzugeben. Wählen Sie in der Tabelle die Spalten , Bodyund CommentDate aus. Geben Sie die HomeTownSpalten , HomepageUrlund Signature aus der UserProfiles Tabelle zurück, und geben Sie von zurück UserNameaspnet_Users.SubjectGuestbookComments Fügen Sie außerdem "ORDER BY CommentDate DESC" am Ende der SELECT Abfrage hinzu, sodass die neuesten Beiträge zuerst zurückgegeben werden. Nachdem Sie diese Auswahl getroffen haben, sollte Ihre Abfrage-Generator-Schnittstelle ähnlich dem Screenshot in Abbildung 18 aussehen.

Die konstruierte Abfrage-JOINs die Gastbuch-, Benutzerprofile- und aspnet_Users-Tabellen

Abbildung 18: Die konstruierte Abfrage JOIN enthält die GuestbookCommentsTabellen , UserProfilesund aspnet_Users (Klicken Sie hier, um das bild in voller Größe anzuzeigen)

Klicken Sie auf OK, um das Fenster Abfrage-Generator zu schließen und zum Bildschirm "Benutzerdefinierte Anweisungen oder gespeicherte Prozeduren definieren" zurückzukehren. Klicken Sie auf Weiter, um zum Bildschirm "Abfrage testen" zu gelangen. Dort können Sie die Abfrageergebnisse anzeigen, indem Sie auf die Schaltfläche Abfrage testen klicken. Wenn Sie bereit sind, klicken Sie auf Fertig stellen, um den Assistenten Datenquellen konfigurieren abzuschließen.

Als wir den Assistenten zum Konfigurieren von Datenquellen in Schritt 2 abgeschlossen haben, wurde die Auflistung des Fields zugehörigen DetailsView-Steuerelements aktualisiert, um ein BoundField für jede spalte zu enthalten, die SelectCommandvon zurückgegeben wird. Die ListView bleibt jedoch unverändert; Das Layout muss noch definiert werden. Das Layout der ListView kann manuell über das deklarative Markup oder über die Option "ListView konfigurieren" im smarten Tag erstellt werden. Normalerweise ziehe ich es vor, das Markup von Hand zu definieren, aber verwenden Sie eine beliebige Methode, die für Sie am natürlichsten ist.

Ich habe die folgenden LayoutTemplate, ItemTemplateund ItemSeparatorTemplate für mein ListView-Steuerelement verwendet:

<asp:ListView ID="CommentList" runat="server" DataSourceID="CommentsDataSource">
     <LayoutTemplate>
          <span ID="itemPlaceholder" runat="server" />
          <p>
               <asp:DataPager ID="DataPager1" runat="server">
                    <Fields>
                         <asp:NextPreviousPagerField ButtonType="Button" 
                              ShowFirstPageButton="True"
                              ShowLastPageButton="True" />
                    </Fields>
               </asp:DataPager>
          </p>
     </LayoutTemplate>
     <ItemTemplate>
          <h4><asp:Label ID="SubjectLabel" runat="server" 
               Text='<%# Eval("Subject") %>' /></h4>
          <asp:Label ID="BodyLabel" runat="server" 
               Text='<%# Eval("Body").ToString().Replace(Environment.NewLine, "<br />") %>' />
          <p>
               ---<br />
               <asp:Label ID="SignatureLabel" Font-Italic="true" runat="server"
                    Text='<%# Eval("Signature") %>' />
               <br />
               <br />
               My Home Town:
               <asp:Label ID="HomeTownLabel" runat="server" 
                    Text='<%# Eval("HomeTown") %>' />
               <br />
               My Homepage:
               <asp:HyperLink ID="HomepageUrlLink" runat="server" 
                    NavigateUrl='<%# Eval("HomepageUrl") %>' 
                    Text='<%# Eval("HomepageUrl") %>' />
          </p>
          <p align="center">
               Posted by
               <asp:Label ID="UserNameLabel" runat="server" 
                    Text='<%# Eval("UserName") %>' /> on
               <asp:Label ID="CommentDateLabel" runat="server" 
                    Text='<%# Eval("CommentDate") %>' />
          </p>
     </ItemTemplate>
     <ItemSeparatorTemplate>
          <hr />
     </ItemSeparatorTemplate>
</asp:ListView>

Definiert LayoutTemplate das vom -Steuerelement ausgegebene Markup, während die ItemTemplate jedes von SqlDataSource zurückgegebene Element rendert. Das ItemTemplateresultierende Markup wird im LayoutTemplate-Steuerelement des -Steuerelements itemPlaceholder platziert. Zusätzlich zu itemPlaceholderenthält das LayoutTemplate ein DataPager-Steuerelement, das die ListView auf die Anzeige von nur 10 Gastbuchkommentaren pro Seite (standard) beschränkt und eine Pagingschnittstelle rendert.

My ItemTemplate zeigt den Betreff jedes Gästebuchkommentars in einem <h4> Element an, dessen Text sich unterhalb des Betreffs befindet. Beachten Sie, dass die syntax für die Anzeige des Textkörpers die von der Eval("Body") Datenbindungsanweisung zurückgegebenen Daten übernimmt, sie in eine Zeichenfolge konvertiert und Zeilenumbrüche durch das <br /> -Element ersetzt. Diese Konvertierung ist erforderlich, um die Zeilenumbrüche anzuzeigen, die beim Übermitteln des Kommentars eingegeben wurden, da Leerzeichen von HTML ignoriert werden. Die Signatur des Benutzers wird kursiv unter dem Text angezeigt, gefolgt von der Heimatstadt des Benutzers, einem Link zu seiner Homepage, dem Datum und der Uhrzeit des Kommentars und dem Benutzernamen der Person, die den Kommentar verlassen hat.

Nehmen Sie sich einen Moment Zeit, um die Seite über einen Browser anzuzeigen. Die Kommentare, die Sie dem Gästebuch in Schritt 5 hinzugefügt haben, sollten hier angezeigt werden.

Guestbook.aspx zeigt jetzt die Kommentare des Gästebuchs an.

Abbildung 19: Guestbook.aspx Zeigt jetzt die Kommentare des Gästebuchs an (Klicken, um das bild in voller Größe anzuzeigen)

Versuchen Sie, dem Gästebuch einen neuen Kommentar hinzuzufügen. Wenn Sie auf die PostCommentButton Schaltfläche klicken, wird die Seite zurückgeschrieben, und der Kommentar wird der Datenbank hinzugefügt, aber das ListView-Steuerelement wird nicht aktualisiert, um den neuen Kommentar anzuzeigen. Dies kann durch folgendes behoben werden:

  • Aktualisieren des Ereignishandlers Click der PostCommentButton Schaltfläche so, dass die Methode des DataBind() ListView-Steuerelements aufgerufen wird, nachdem der neue Kommentar in die Datenbank eingefügt wurde, oder
  • Festlegen der Eigenschaft des EnableViewState ListView-Steuerelements auf false. Dieser Ansatz funktioniert, da es durch Deaktivieren des Ansichtszustands des Steuerelements bei jedem Postback erneut an die zugrunde liegenden Daten gebunden werden muss.

Die Tutorialwebsite, die aus diesem Tutorial heruntergeladen werden kann, veranschaulicht beide Techniken. Die Eigenschaft des ListView-Steuerelements EnableViewState an false und der Code, der zum programmgesteuerten Erneuten Binden der Daten an die ListView erforderlich ist, ist im Click Ereignishandler vorhanden, wird jedoch auskommentiert.

Hinweis

Derzeit ermöglicht die AdditionalUserInfo.aspx Seite dem Benutzer das Anzeigen und Bearbeiten seiner Heimat-, Homepage- und Signatureinstellungen. Es kann schön sein, zu aktualisieren AdditionalUserInfo.aspx , um die Gästebuchkommentare des angemeldeten Benutzers anzuzeigen. Das heißt, neben der Überprüfung und Änderung ihrer Informationen kann ein Benutzer die AdditionalUserInfo.aspx Seite besuchen, um zu sehen, welche Gästebuchkommentare er in der Vergangenheit gemacht hat. Ich belasse dies als Übung für den interessierten Leser.

Schritt 6: Anpassen des CreateUserWizard-Steuerelements, um eine Schnittstelle für den Heimatort, die Homepage und die Signatur einzuschließen

Die SELECT von der Guestbook.aspx Seite verwendete Abfrage verwendet ein INNER JOIN , um die zugehörigen Datensätze zwischen den GuestbookCommentsTabellen , UserProfilesund aspnet_Users zu kombinieren. Wenn ein Benutzer, der keinen Datensatz enthält UserProfiles , einen Gastbuchkommentar erstellt, wird der Kommentar nicht in der ListView angezeigt, da nur INNER JOIN Datensätze zurückgegeben GuestbookComments werden, wenn übereinstimmende Datensätze in UserProfiles und aspnet_Usersvorhanden sind. Und wie wir in Schritt 3 gesehen haben, kann ein Benutzer, der keinen Datensatz enthält UserProfiles , seine Einstellungen auf der AdditionalUserInfo.aspx Seite nicht anzeigen oder bearbeiten.

Unnötig zu sagen, dass es aufgrund unserer Entwurfsentscheidungen wichtig ist, dass jedes Benutzerkonto im Mitgliedschaftssystem über einen übereinstimmenden Datensatz in der UserProfiles Tabelle verfügt. Wir möchten, dass ein entsprechender Datensatz hinzugefügt UserProfiles wird, wenn ein neues Mitgliedschaftsbenutzerkonto über createUserWizard erstellt wird.

Wie im Tutorial Erstellen von Benutzerkonten erläutert, löst das CreateUserWizard-Steuerelement nach dem Erstellen des neuen Mitgliedsbenutzerkontos sein -Ereignis ausCreatedUser. Wir können einen Ereignishandler für dieses Ereignis erstellen, die UserId für den gerade erstellten Benutzer abrufen und dann einen Datensatz mit Standardwerten für die Spalten , HomepageUrlund Signature in die UserProfilesHomeTownTabelle einfügen. Darüber hinaus ist es möglich, den Benutzer zur Eingabe dieser Werte aufzufordern, indem die Schnittstelle des CreateUserWizard-Steuerelements so angepasst wird, dass sie zusätzliche TextBoxes enthält.

Zunächst sehen wir uns an, wie Sie der UserProfiles Tabelle im CreatedUser Ereignishandler eine neue Zeile mit Standardwerten hinzufügen. Anschließend erfahren Sie, wie Sie die Benutzeroberfläche des CreateUserWizard-Steuerelements so anpassen, dass sie zusätzliche Formularfelder einschließt, um den Heimatort, die Homepage und die Signatur des neuen Benutzers zu erfassen.

Hinzufügen einer Standardzeile zuUserProfiles

Im Tutorial Erstellen von Benutzerkonten haben wir der CreatingUserAccounts.aspx Seite im Membership Ordner ein CreateUserWizard-Steuerelement hinzugefügt. Damit das CreateUserWizard-Steuerelement bei der Erstellung eines Benutzerkontos einen Datensatz zur UserProfiles Tabelle hinzugibt, müssen wir die Funktionalität des CreateUserWizard-Steuerelements aktualisieren. Anstatt diese Änderungen an der CreatingUserAccounts.aspx Seite vorzunehmen, fügen wir stattdessen ein neues CreateUserWizard-Steuerelement zur Seite hinzu EnhancedCreateUserWizard.aspx und nehmen die Änderungen für dieses Tutorial dort vor.

Öffnen Sie die EnhancedCreateUserWizard.aspx Seite in Visual Studio, und ziehen Sie ein CreateUserWizard-Steuerelement aus der Toolbox auf die Seite. Legen Sie die Eigenschaft des ID CreateUserWizard-Steuerelements auf fest NewUserWizard. Wie im Tutorial Erstellen von Benutzerkonten erläutert, fordert die Standardbenutzeroberfläche von CreateUserWizard den Besucher zur Eingabe der erforderlichen Informationen auf. Sobald diese Informationen bereitgestellt wurden, erstellt das Steuerelement intern ein neues Benutzerkonto im Membership-Framework, ohne dass wir eine einzelne Codezeile schreiben müssen.

Das CreateUserWizard-Steuerelement löst während des Workflows eine Reihe von Ereignissen aus. Nachdem ein Besucher die Anforderungsinformationen bereitgestellt und das Formular übermittelt hat, löst das CreateUserWizard-Steuerelement zunächst sein CreatingUser Ereignis aus. Wenn während des Erstellungsprozesses ein Problem auftritt, wird das CreateUserError Ereignis ausgelöst. Wenn der Benutzer jedoch erfolgreich erstellt wurde, wird das CreatedUser Ereignis ausgelöst. Im Tutorial Erstellen von Benutzerkonten haben wir einen Ereignishandler für das CreatingUser Ereignis erstellt, um sicherzustellen, dass der angegebene Benutzername keine führenden oder nachgestellten Leerzeichen enthält und dass der Benutzername an keiner Stelle im Kennwort angezeigt wurde.

Um eine Zeile in der Tabelle für den UserProfiles gerade erstellten Benutzer hinzuzufügen, müssen wir einen Ereignishandler für das CreatedUser Ereignis erstellen. Zu dem Zeitpunkt, zu dem das CreatedUser Ereignis ausgelöst wurde, wurde das Benutzerkonto bereits im Mitgliedschaftsframework erstellt, sodass wir den UserId-Wert des Kontos abrufen können.

Erstellen Sie einen Ereignishandler für das NewUserWizardEreignis des -Ereignisses, CreatedUser und fügen Sie den folgenden Code hinzu:

protected void NewUserWizard_CreatedUser(object sender, EventArgs e)
{
     // Get the UserId of the just-added user
     MembershipUser newUser = Membership.GetUser(NewUserWizard.UserName);
     Guid newUserId = (Guid)newUser.ProviderUserKey;
 
     // Insert a new record into UserProfiles
     string connectionString = 
          ConfigurationManager.ConnectionStrings["SecurityTutorialsConnectionString"].ConnectionString;
     string insertSql = "INSERT INTO UserProfiles(UserId, HomeTown, HomepageUrl,
          Signature) VALUES(@UserId, @HomeTown, @HomepageUrl, @Signature)";
 
     using (SqlConnection myConnection = new SqlConnection(connectionString))
     {
          myConnection.Open();
          SqlCommand myCommand = new SqlCommand(insertSql, myConnection);
          myCommand.Parameters.AddWithValue("@UserId", newUserId);
          myCommand.Parameters.AddWithValue("@HomeTown", DBNull.Value);
          myCommand.Parameters.AddWithValue("@HomepageUrl", DBNull.Value);
          myCommand.Parameters.AddWithValue("@Signature", DBNull.Value);
          myCommand.ExecuteNonQuery();
          myConnection.Close();
     }
}

Die oben genannten Codewesen, indem sie die UserId des gerade hinzugefügten Benutzerkontos abrufen. Dies wird erreicht, indem Sie die Membership.GetUser(username) -Methode verwenden, um Informationen zu einem bestimmten Benutzer zurückzugeben, und dann die -Eigenschaft zum Abrufen der ProviderUserKey UserId verwenden. Der vom Benutzer in das CreateUserWizard-Steuerelement eingegebene Benutzername ist über seine UserName -Eigenschaft verfügbar.

Als Nächstes wird die Verbindungszeichenfolge von Web.config abgerufen, und die INSERT -Anweisung wird angegeben. Die erforderlichen ADO.NET Objekte werden instanziiert und der Befehl ausgeführt. Der Code weist den @HomeTownParametern , @HomepageUrl, und @Signature eine DBNull instance zu, wodurch Datenbankwerte NULL für die HomeTownFelder , HomepageUrlund Signature eingefügt werden.

Besuchen Sie die EnhancedCreateUserWizard.aspx Seite über einen Browser, und erstellen Sie ein neues Benutzerkonto. Kehren Sie anschließend zu Visual Studio zurück, und untersuchen Sie den Inhalt der aspnet_Users Tabellen und UserProfiles (wie in Abbildung 12 dargestellt). Das neue Benutzerkonto sollte in aspnet_Users und eine entsprechende UserProfiles Zeile (mit NULL Werten für HomeTown, HomepageUrlund Signature) angezeigt werden.

Ein neues Benutzerkonto und ein neuer UserProfiles-Datensatz wurden hinzugefügt.

Abbildung 20: Ein neues Benutzerkonto und UserProfiles datensatz wurden hinzugefügt (Klicken Sie hier, um das bild in voller Größe anzuzeigen)

Nachdem der Besucher seine neuen Kontoinformationen angegeben und auf die Schaltfläche "Benutzer erstellen" geklickt hat, wird das Benutzerkonto erstellt und eine Zeile zur UserProfiles Tabelle hinzugefügt. Der CreateUserWizard zeigt CompleteWizardStepdann seine an, die eine Erfolgsmeldung und eine Schaltfläche Weiter anzeigt. Wenn Sie auf die Schaltfläche Weiter klicken, wird ein Postback verursacht, aber es wird keine Aktion ausgeführt, sodass der Benutzer auf der EnhancedCreateUserWizard.aspx Seite hängen bleibt.

Wir können eine URL angeben, an die der Benutzer gesendet werden soll, wenn über die Eigenschaft des CreateUserWizard-Steuerelements ContinueDestinationPageUrlauf die Schaltfläche Weiter geklickt wird. Legen Sie die ContinueDestinationPageUrl -Eigenschaft auf "~/Membership/AdditionalUserInfo.aspx" fest. Dadurch wird der neue Benutzer zu gelangen, AdditionalUserInfo.aspxwo er seine Einstellungen anzeigen und aktualisieren kann.

Anpassen der CreateUserWizard-Benutzeroberfläche zur Aufforderung zur Eingabe von Heimatort, Homepage und Signatur des neuen Benutzers

Die Standardschnittstelle des CreateUserWizard-Steuerelements reicht für einfache Kontoerstellungsszenarien aus, in denen nur wichtige Benutzerkontoinformationen wie Benutzername, Kennwort und E-Mail erfasst werden müssen. Aber was wäre, wenn wir den Besucher auffordern wollten, seine Heimat, Homepage und Unterschrift einzugeben, während er sein Konto erstellt? Es ist möglich, die Schnittstelle des CreateUserWizard-Steuerelements anzupassen, um zusätzliche Informationen bei der CreatedUser Registrierung zu sammeln. Diese Informationen können im Ereignishandler verwendet werden, um zusätzliche Datensätze in die zugrunde liegende Datenbank einzufügen.

Das CreateUserWizard-Steuerelement erweitert das ASP.NET-Assistent-Steuerelement, bei dem es sich um ein Steuerelement handelt, das es einem Seitenentwickler ermöglicht, eine Reihe von geordneten WizardStepszu definieren. Das Assistent-Steuerelement rendert den aktiven Schritt und stellt eine Navigationsoberfläche bereit, die es dem Besucher ermöglicht, diese Schritte zu durchlaufen. Das Assistentensteuerelement eignet sich ideal, um eine lange Aufgabe in mehrere kurze Schritte zu unterteilen. Weitere Informationen zum Assistenten-Steuerelement finden Sie unter Erstellen einer schrittweisen Benutzeroberfläche mit dem ASP.NET 2.0-Assistentensteuerelement.

Das Standardmarkup des CreateUserWizard-Steuerelements definiert zwei WizardSteps: CreateUserWizardStep und CompleteWizardStep.

<asp:CreateUserWizard ID="NewUserWizard" runat="server"
     ContinueDestinationPageUrl="~/Membership/AdditionalUserInfo.aspx">
     <WizardSteps>
          <asp:CreateUserWizardStep ID="CreateUserWizardStep1" runat="server">
          </asp:CreateUserWizardStep>
          <asp:CompleteWizardStep ID="CompleteWizardStep1" runat="server">
          </asp:CompleteWizardStep>
     </WizardSteps>
</asp:CreateUserWizard>

Der erste WizardStep, CreateUserWizardSteprendert die Schnittstelle, die zur Eingabe von Benutzername, Kennwort, E-Mail usw. auffordert. Nachdem der Besucher diese Informationen bereitgestellt hat und auf "Benutzer erstellen" klickt, wird ihr der CompleteWizardStepangezeigt, der die Erfolgsmeldung und die Schaltfläche "Weiter" anzeigt.

Um die Schnittstelle des CreateUserWizard-Steuerelements so anzupassen, dass sie zusätzliche Formularfelder enthält, können wir:

  • Erstellen einer oder mehrerer neuerWizardSteps, um die zusätzlichen Benutzeroberflächenelemente zu enthalten. Um dem CreateUserWizard ein neues WizardStep hinzuzufügen, klicken Sie im zugehörigen Smarttag auf den Link "Hinzufügen/Entfernen WizardSteps", um den WizardStep Sammlungs-Editor zu starten. Von dort aus können Sie die Schritte im Assistenten hinzufügen, entfernen oder neu anordnen. Dies ist der Ansatz, den wir für dieses Tutorial verwenden werden.

  • Konvertieren vonCreateUserWizardStepin eine bearbeitbareWizardStep. Dadurch wird durch CreateUserWizardStep ein Äquivalent WizardStep ersetzt, dessen Markup eine Benutzeroberfläche definiert, die mit den CreateUserWizardStep-Elementen übereinstimmt. Durch Konvertieren von CreateUserWizardStep in können WizardStep wir die Steuerelemente neu positionieren oder diesem Schritt zusätzliche Benutzeroberflächenelemente hinzufügen. Klicken Sie im Smarttag des CreateUserWizardStepCompleteWizardStep Steuerelements auf den Link "Benutzerschritt erstellen anpassen" oder "Vollständigen Schritt anpassen", um oder in eine bearbeitbare WizardStepDatei zu konvertieren.

  • Verwenden Sie eine Kombination der beiden oben genannten Optionen.

Eine wichtige Sache zu beachten ist, dass das CreateUserWizard-Steuerelement seinen Benutzerkontoerstellungsprozess ausführt, wenn in seiner CreateUserWizardStepauf die Schaltfläche "Benutzer erstellen" geklickt wird. Es spielt keine Rolle, ob es zusätzliche WizardStep s nach dem CreateUserWizardStep gibt oder nicht.

Wenn Sie dem CreateUserWizard-Steuerelement eine benutzerdefinierte WizardStep hinzufügen, um zusätzliche Benutzereingaben zu sammeln, kann die benutzerdefinierte WizardStep vor oder nach dem CreateUserWizardStepplatziert werden. Wenn es vor dem CreateUserWizardStep kommt, ist die zusätzliche Benutzereingabe, die von der benutzerdefinierten WizardStep gesammelt wurde, für den CreatedUser Ereignishandler verfügbar. Wenn die benutzerdefinierte WizardStep jedoch nach CreateUserWizardStep dem Angezeigten WizardStep kommt, wurde das neue Benutzerkonto bereits erstellt, und das CreatedUser Ereignis wurde bereits ausgelöst.

Abbildung 21 zeigt den Workflow, wenn der hinzugefügte WizardStep vor dem CreateUserWizardStep-Objekt steht. Da die zusätzlichen Benutzerinformationen zum Zeitpunkt des Auslösens des CreatedUser Ereignisses gesammelt wurden, müssen wir nur den CreatedUser Ereignishandler aktualisieren, um diese Eingaben abzurufen und diese für die Parameterwerte der INSERT Anweisung (anstelle DBNull.Valuevon ) zu verwenden.

Der CreateUserWizard-Workflow, wenn ein zusätzlicher AssistentSchritt dem CreateUserWizardStep vorangestellt ist

Abbildung 21: Der CreateUserWizard-Workflow, wenn ein Zusätzliches WizardStep vorangestellt ist CreateUserWizardStep (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Wenn der benutzerdefiniert WizardStepnachCreateUserWizardStepdem platziert wird, erfolgt der Prozess zum Erstellen eines Benutzerkontos jedoch, bevor der Benutzer die Möglichkeit hatte, seine Heimatstadt, Homepage oder Signatur einzugeben. In diesem Fall müssen diese zusätzlichen Informationen in die Datenbank eingefügt werden, nachdem das Benutzerkonto erstellt wurde, wie Abbildung 22 veranschaulicht.

Der CreateUserWizard-Workflow, wenn ein zusätzlicher AssistentSchritt nach dem CreateUserWizardStep kommt

Abbildung 22: Der CreateUserWizard-Workflow, wenn ein Zusätzliches WizardStep nach dem CreateUserWizardStep kommt (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Der in Abbildung 22 gezeigte Workflow wartet auf das Einfügen eines Datensatzes in die UserProfiles Tabelle, bis Schritt 2 abgeschlossen ist. Wenn der Besucher jedoch nach Schritt 1 den Browser schließt, haben wir einen Zustand erreicht, in dem ein Benutzerkonto erstellt wurde, aber kein Datensatz hinzugefügt UserProfileswurde. Eine Problemumgehung besteht darin, einen Datensatz mit NULL oder Standardwerten UserProfiles im CreatedUser Ereignishandler einzufügen (der nach Schritt 1 ausgelöst wird) und diesen Datensatz dann nach Abschluss von Schritt 2 zu aktualisieren. Dadurch wird sichergestellt, dass ein UserProfiles Datensatz für das Benutzerkonto hinzugefügt wird, auch wenn der Benutzer den Registrierungsprozess in der Mitte beendet.

In diesem Tutorial erstellen wir eine neue WizardStep , die nach dem CreateUserWizardStep , aber vor dem CompleteWizardStepauftritt. Lassen Sie uns zunächst den Assistentenschritt festlegen und konfigurieren, und dann sehen wir uns den Code an.

Wählen Sie im Smarttag des CreateUserWizard-Steuerelements die Option "Hinzufügen/Entfernen WizardStep " aus, wodurch das WizardStep Dialogfeld Sammlungs-Editor geöffnet wird. Fügen Sie ein neues WizardStephinzu, und legen Sie auf UserSettingsID fest, auf , auf Title "Ihre Einstellungen" und auf StepTypeStep. Positionieren Sie sie dann so, dass sie nach dem CreateUserWizardStep ("Für Ihr neues Konto registrieren") und vor dem CompleteWizardStep ("Abschließen") kommt, wie in Abbildung 23 dargestellt.

Hinzufügen eines neuen AssistentenSchritt zum CreateUserWizard-Steuerelement

Abbildung 23: Hinzufügen eines Neuen WizardStep zum CreateUserWizard-Steuerelement (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Klicken Sie auf OK, um das WizardStep Dialogfeld Sammlungs-Editor zu schließen. Das neue WizardStep wird durch das aktualisierte deklarative Markup des CreateUserWizard-Steuerelements belegt:

<asp:CreateUserWizard ID="NewUserWizard" runat="server"
     ContinueDestinationPageUrl="~/Membership/AdditionalUserInfo.aspx">
     <WizardSteps>
          <asp:CreateUserWizardStep ID="CreateUserWizardStep1" runat="server">
          </asp:CreateUserWizardStep>
          <asp:WizardStep runat="server" ID="UserSettings" StepType="Step"
               Title="Your Settings">
          </asp:WizardStep>
          <asp:CompleteWizardStep ID="CompleteWizardStep1" runat="server">
          </asp:CompleteWizardStep>
     </WizardSteps>
</asp:CreateUserWizard>

Beachten Sie das neue <asp:WizardStep> Element. Wir müssen die Benutzeroberfläche hinzufügen, um die Heimat, die Homepage und die Signatur des neuen Benutzers hier zu erfassen. Sie können diesen Inhalt in der deklarativen Syntax oder über die Designer eingeben. Um die Designer zu verwenden, wählen Sie in der Dropdownliste im Smarttag den Schritt "Ihre Einstellungen" aus, um den Schritt im Designer anzuzeigen.

Hinweis

Wenn Sie einen Schritt in der Dropdownliste des Smarttags auswählen, wird die Eigenschaft des CreateUserWizard-Steuerelements ActiveStepIndexaktualisiert, die den Index des Startschritts angibt. Wenn Sie diese Dropdownliste verwenden, um den Schritt "Ihre Einstellungen" im Designer zu bearbeiten, stellen Sie daher sicher, dass Sie ihn wieder auf "Registrieren für Ihr neues Konto" festlegen, damit dieser Schritt angezeigt wird, wenn Benutzer die EnhancedCreateUserWizard.aspx Seite zum ersten Mal besuchen.

Erstellen Sie im Schritt "Ihre Einstellungen" eine Benutzeroberfläche, die drei TextBox-Steuerelemente mit den Namen HomeTown, HomepageUrlund Signatureenthält. Nach dem Erstellen dieser Schnittstelle sollte das deklarative Markup des CreateUserWizard wie folgt aussehen:

<asp:CreateUserWizard ID="NewUserWizard" runat="server"
     ContinueDestinationPageUrl="~/Membership/AdditionalUserInfo.aspx">
     <WizardSteps>
          <asp:CreateUserWizardStep ID="CreateUserWizardStep1" runat="server">
          </asp:CreateUserWizardStep>
          <asp:WizardStep runat="server" ID="UserSettings" StepType="Step"
               Title="Your Settings">
               <p>
                    <b>Home Town:</b><br />
                    <asp:TextBox ID="HomeTown" runat="server"></asp:TextBox>
               </p>
               <p>
                    <b>Homepage URL:</b><br />
                    <asp:TextBox ID="HomepageUrl" Columns="40" runat="server"></asp:TextBox>
               </p>
               <p>
                    <b>Signature:</b><br />
                    <asp:TextBox ID="Signature" TextMode="MultiLine" Width="95%"
                         Rows="5" runat="server"></asp:TextBox>
               </p>
          </asp:WizardStep>
          <asp:CompleteWizardStep ID="CompleteWizardStep1" runat="server">
          </asp:CompleteWizardStep>
     </WizardSteps>
</asp:CreateUserWizard>

Besuchen Sie diese Seite über einen Browser, und erstellen Sie ein neues Benutzerkonto, in dem Werte für die Heimatstadt, die Homepage und die Signatur angegeben werden. Nach Abschluss des Abschlusses wird das CreateUserWizardStep Benutzerkonto im Membership-Framework erstellt, und der CreatedUser Ereignishandler wird ausgeführt, wodurch eine neue Zeile hinzugefügt UserProfileswird, jedoch mit einem Datenbankwert NULL für HomeTown, HomepageUrlund Signature. Die für Heimatort, Homepage und Signatur eingegebenen Werte werden nie verwendet. Das Nettoergebnis ist ein neues Benutzerkonto mit einem UserProfiles Datensatz, dessen HomeTownFelder , HomepageUrlund Signature noch angegeben werden müssen.

Wir müssen Code nach dem Schritt "Ihre Einstellungen" ausführen, der die vom Benutzer eingegebenen Werte für Heimat, Honepage und Signatur übernimmt und den entsprechenden UserProfiles Datensatz aktualisiert. Jedes Mal, wenn der Benutzer zwischen den Schritten in einem Assistenten-Steuerelement wechselt, wird das Ereignis des ActiveStepChanged Assistenten ausgelöst. Wir können einen Ereignishandler für dieses Ereignis erstellen und die UserProfiles Tabelle aktualisieren, wenn der Schritt "Ihre Einstellungen" abgeschlossen ist.

Fügen Sie einen Ereignishandler für das Ereignis von ActiveStepChanged CreateUserWizard hinzu, und fügen Sie den folgenden Code hinzu:

protected void NewUserWizard_ActiveStepChanged(object sender, EventArgs e)
{
     // Have we JUST reached the Complete step?
     if (NewUserWizard.ActiveStep.Title == "Complete")
     {
          WizardStep UserSettings = NewUserWizard.FindControl("UserSettings") as
          WizardStep;
 
          // Programmatically reference the TextBox controls
          TextBox HomeTown = UserSettings.FindControl("HomeTown") as TextBox;
          TextBox HomepageUrl = UserSettings.FindControl("HomepageUrl") as TextBox;
          TextBox Signature = UserSettings.FindControl("Signature") as TextBox;
 
          // Update the UserProfiles record for this user
          // Get the UserId of the just-added user
          MembershipUser newUser = Membership.GetUser(NewUserWizard.UserName);
          Guid newUserId = (Guid)newUser.ProviderUserKey;
 
          // Insert a new record into UserProfiles
          string connectionString = 
               ConfigurationManager.ConnectionStrings["SecurityTutorialsConnectionString"].ConnectionString;
          string updateSql = "UPDATE UserProfiles SET HomeTown = @HomeTown, HomepageUrl
               = @HomepageUrl, Signature = @Signature WHERE UserId = @UserId";
 
          using (SqlConnection myConnection = new SqlConnection(connectionString))
          {
               myConnection.Open();
               SqlCommand myCommand = new SqlCommand(updateSql, myConnection);
               myCommand.Parameters.AddWithValue("@HomeTown", HomeTown.Text.Trim());
               myCommand.Parameters.AddWithValue("@HomepageUrl", HomepageUrl.Text.Trim());
               myCommand.Parameters.AddWithValue("@Signature", Signature.Text.Trim());
               myCommand.Parameters.AddWithValue("@UserId", newUserId);
               myCommand.ExecuteNonQuery();
               myConnection.Close();
          }
     }
}

Der obige Code beginnt mit der Bestimmung, ob wir gerade den Schritt "Complete" erreicht haben. Da der Schritt "Abschließen" unmittelbar nach dem Schritt "Ihre Einstellungen" erfolgt, bedeutet dies, dass der Besucher den Schritt "Ihre Einstellungen" gerade abgeschlossen hat, wenn der Besucher den Schritt "Abgeschlossen" erreicht.

In einem solchen Fall müssen wir programmgesteuert auf die TextBox-Steuerelemente in der UserSettings WizardStepverweisen. Dies wird erreicht, indem zuerst die FindControl -Methode verwendet wird, um programmgesteuert auf zu UserSettings WizardStepverweisen, und dann erneut, um von innerhalb der WizardStepauf die TextBoxes zu verweisen. Nachdem auf die TextBoxes verwiesen wurde, können wir die UPDATE Anweisung ausführen. Die UPDATE -Anweisung verfügt über die gleiche Anzahl von Parametern wie die INSERT -Anweisung im CreatedUser Ereignishandler, aber hier verwenden wir die vom Benutzer bereitgestellten Werte für den Heimatort, die Homepage und die Signatur.

Wenn dieser Ereignishandler eingerichtet ist, besuchen Sie die EnhancedCreateUserWizard.aspx Seite über einen Browser, und erstellen Sie ein neues Benutzerkonto, das Werte für den Heimatort, die Homepage und die Signatur angibt. Nach dem Erstellen des neuen Kontos sollten Sie zu der AdditionalUserInfo.aspx Seite weitergeleitet werden, auf der die gerade eingegebene Heimat, Homepage und Signaturinformationen angezeigt werden.

Hinweis

Unsere Website verfügt derzeit über zwei Seiten, von denen ein Besucher ein neues Konto erstellen kann: CreatingUserAccounts.aspx und EnhancedCreateUserWizard.aspx. Die Sitemap und Anmeldeseite der Website verweisen auf die CreatingUserAccounts.aspx Seite, aber die CreatingUserAccounts.aspx Seite fordert den Benutzer nicht auf, seine Heimat, Homepage und Signaturinformationen anzugeben, und fügt keine entsprechende Zeile zu UserProfileshinzu. Aktualisieren Sie daher entweder die CreatingUserAccounts.aspx Seite so, dass sie diese Funktionalität bietet, oder aktualisieren Sie die Sitemap und die Anmeldeseite so, dass sie anstelle von referenzieren EnhancedCreateUserWizard.aspxCreatingUserAccounts.aspx. Wenn Sie die letztere Option auswählen, müssen Sie die Membership Datei des Ordners Web.config aktualisieren, damit anonyme Benutzer auf die EnhancedCreateUserWizard.aspx Seite zugreifen können.

Zusammenfassung

In diesem Tutorial haben wir uns mit Techniken zum Modellieren von Daten im Zusammenhang mit Benutzerkonten innerhalb des Mitgliedschaftsframeworks befasst. Insbesondere haben wir uns mit der Modellierung von Entitäten befasst, die eine 1:n-Beziehung mit Benutzerkonten gemeinsam nutzen, sowie daten, die eine 1:1-Beziehung gemeinsam nutzen. Darüber hinaus haben wir gesehen, wie diese zugehörigen Informationen angezeigt, eingefügt und aktualisiert werden können. Einige Beispiele verwenden das SqlDataSource-Steuerelement und andere verwenden ADO.NET Code.

In diesem Tutorial wird der Blick auf Benutzerkonten abgeschlossen. Ab dem nächsten Tutorial richten wir unsere Aufmerksamkeit auf Rollen. In den nächsten Tutorials sehen wir uns das Rollenframework an, erfahren Sie, wie Sie neue Rollen erstellen, Benutzern Rollen zuweisen, wie Sie bestimmen, zu welchen Rollen ein Benutzer gehört, und wie Sie die rollenbasierte Autorisierung anwenden.

Viel Spaß beim Programmieren!

Weitere Informationen

Weitere Informationen zu den in diesem Tutorial behandelten Themen finden Sie in den folgenden Ressourcen:

Zum Autor

Scott Mitchell, Autor mehrerer ASP/ASP.NET-Bücher und Gründer von 4GuysFromRolla.com, arbeitet seit 1998 mit Microsoft-Webtechnologien. Scott arbeitet als unabhängiger Berater, Trainer und Autor. Sein neuestes Buch ist Sams Teach Yourself ASP.NET 2.0 in 24 Hours. Scott kann unter mitchell@4guysfromrolla.com oder über seinen Blog unter http://ScottOnWriting.NETerreicht werden.

Besonderer Dank an...

Diese Tutorialreihe wurde von vielen hilfreichen Prüfern überprüft. Möchten Sie meine bevorstehenden MSDN-Artikel lesen? Wenn dies der Fall ist, legen Sie eine Zeile unter ab mitchell@4GuysFromRolla.com.