Udostępnij za pośrednictwem


Przechowywanie dodatkowych informacji dotyczących użytkowników (C#)

Autor : Scott Mitchell

Uwaga

Od czasu napisania tego artykułu dostawcy członkostwa ASP.NET zostali zastąpioni przez ASP.NET Identity. Zdecydowanie zalecamy aktualizowanie aplikacji w celu korzystania z platformy ASP.NET Identity , a nie dostawców członkostwa w momencie pisania tego artykułu. ASP.NET Identity ma wiele zalet w porównaniu z systemem członkostwa ASP.NET, w tym :

  • Lepsza wydajność
  • Ulepszona rozszerzalność i możliwość testowania
  • Obsługa uwierzytelniania OAuth, OpenID Connect i uwierzytelniania dwuskładnikowego
  • Obsługa tożsamości opartej na oświadczeniach
  • Lepsze współdziałanie z platformą ASP.Net Core

Pobierz kod lub pobierz plik PDF

W tym samouczku odpowiemy na to pytanie, tworząc bardzo podstawową aplikację elementu-gościa. W ten sposób przyjrzymy się różnym opcjom modelowania informacji o użytkownikach w bazie danych, a następnie zobaczymy, jak skojarzyć te dane z kontami użytkowników utworzonymi przez strukturę członkostwa.

Wprowadzenie

ASP. Platforma członkostwa platformy NET oferuje elastyczny interfejs do zarządzania użytkownikami. Interfejs API członkostwa zawiera metody sprawdzania poprawności poświadczeń, pobieranie informacji o aktualnie zalogowanym użytkowniku, tworzenie nowego konta użytkownika i usuwanie konta użytkownika, między innymi. Każde konto użytkownika w strukturze członkostwa zawiera tylko właściwości wymagane do weryfikacji poświadczeń i wykonywania podstawowych zadań związanych z kontem użytkownika. Jest to dowodem metod i właściwości MembershipUser klasy, która modeluje konto użytkownika w strukturze członkostwa. Ta klasa ma właściwości, takie jak UserName, Emaili , oraz IsLockedOut, GetPassword oraz UnlockUser.

Często aplikacje muszą przechowywać dodatkowe informacje o użytkownikach nieuwzględnione w strukturze członkostwa. Na przykład sprzedawca internetowy może wymagać, aby każdy użytkownik przechowywał adresy wysyłkowe i rozliczeniowe, informacje o płatności, preferencje dostawy i numer telefonu kontaktowego. Ponadto każda kolejność w systemie jest skojarzona z określonym kontem użytkownika.

Klasa MembershipUser nie zawiera właściwości takich jak PhoneNumber lub DeliveryPreferences lub PastOrders. Jak więc śledzić informacje o użytkowniku wymagane przez aplikację i zintegrować ją z platformą członkostwa? W tym samouczku odpowiemy na to pytanie, tworząc bardzo podstawową aplikację elementu-gościa. W ten sposób przyjrzymy się różnym opcjom modelowania informacji o użytkownikach w bazie danych, a następnie zobaczymy, jak skojarzyć te dane z kontami użytkowników utworzonymi przez strukturę członkostwa. Zaczynamy!

Krok 1. Tworzenie modelu danych aplikacji elementu guestbook

Istnieje wiele technik, które można zastosować do przechwytywania informacji o użytkowniku w bazie danych i kojarzenia ich z kontami użytkowników utworzonymi przez platformę członkostwa. Aby zilustrować te techniki, musimy rozszerzyć aplikację internetową samouczka, aby przechwycić jakieś dane związane z użytkownikiem. (Obecnie model danych aplikacji zawiera tylko tabele usług aplikacji wymagane przez klasę SqlMembershipProvider.

Utwórzmy bardzo prostą aplikację z podręcznikiem gościa, w której uwierzytelniony użytkownik może pozostawić komentarz. Oprócz przechowywania komentarzy do książek gości, pozwólmy każdemu użytkownikowi na przechowywanie swojego rodzinnego miasta, strony głównej i podpisu. Jeśli zostanie podana, miasto główne użytkownika, strona główna i podpis będą wyświetlane w każdej wiadomości pozostawionej w podręczniku gościa.

GuestbookCommentsDodawanie tabeli

Aby przechwycić komentarze do elementu guestbook, musimy utworzyć tabelę bazy danych o nazwie GuestbookComments zawierającą kolumny, takie jak CommentId, Subject, Bodyi CommentDate. Musimy również mieć każdy rekord w GuestbookComments tabeli odwołujący się do użytkownika, który opuścił komentarz.

Aby dodać tę tabelę do bazy danych, przejdź do Eksploratora baz danych w programie Visual Studio i przejdź do SecurityTutorials szczegółów bazy danych. Kliknij prawym przyciskiem myszy folder Tables i wybierz polecenie Dodaj nową tabelę. Spowoduje to wyświetlenie interfejsu, który umożliwia zdefiniowanie kolumn dla nowej tabeli.

Dodawanie nowej tabeli do bazy danych SecurityTutorials

Rysunek 1. Dodawanie nowej tabeli do SecurityTutorials bazy danych (kliknij, aby wyświetlić obraz pełnowymiarowy)

Następnie zdefiniuj GuestbookCommentskolumny . Zacznij od dodania kolumny o nazwie CommentId typu uniqueidentifier. Ta kolumna będzie unikatowo identyfikować każdy komentarz w podręczniku gościa, więc nie zezwalaj NULL na nie i oznacza go jako klucz podstawowy tabeli. Zamiast podawać wartość pola dla CommentId każdego elementu , możemy wskazać, że dla tego pola INSERT powinna być generowana automatycznie nowa uniqueidentifier wartość, ustawiając wartość domyślną kolumny na NEWID()INSERT. Po dodaniu tego pierwszego pola, oznaczeniu go jako klucza podstawowego i ustawieniu jego wartości domyślnej ekran powinien wyglądać podobnie do zrzutu ekranu pokazanego na rysunku 2.

Dodawanie kolumny podstawowej o nazwie CommentId

Rysunek 2. Dodawanie kolumny podstawowej o nazwie CommentId (kliknij, aby wyświetlić obraz pełnowymiarowy)

Następnie dodaj kolumnę o nazwie Subject type (typ nvarchar(50) ) i kolumnę o nazwie Body typu nvarchar(MAX)( disallowing NULL s w obu kolumnach). Następnie dodaj kolumnę o nazwie CommentDate typu datetime. Nie zezwalaj NULL i ustaw wartość domyślną CommentDate kolumny na getdate().

Pozostaje tylko dodać kolumnę, która kojarzy konto użytkownika z każdym komentarzem do książki gościa. Jedną z opcji jest dodanie kolumny o nazwie UserName typu nvarchar(256). Jest to odpowiedni wybór w przypadku korzystania z dostawcy członkostwa innego niż SqlMembershipProvider. Jednak w przypadku korzystania z elementu SqlMembershipProvider, ponieważ w tej serii samouczków kolumna UserName w aspnet_Users tabeli nie jest unikatowa. Klucz aspnet_Users podstawowy tabeli to UserId i jest typu uniqueidentifier. W związku z tym GuestbookComments tabela wymaga kolumny o nazwie UserId typu uniqueidentifier (brak zezwalania na NULL wartości). Przejdź dalej i dodaj tę kolumnę.

Uwaga

Jak omówiono w samouczku Tworzenie schematu członkostwa w SQL Server, struktura członkostwa została zaprojektowana tak, aby umożliwić wielu aplikacjom internetowym z różnymi kontami użytkowników współużytkowania tego samego magazynu użytkowników. Robi to przez partycjonowanie kont użytkowników w różnych aplikacjach. Mimo że każda nazwa użytkownika jest unikatowa w aplikacji, ta sama nazwa użytkownika może być używana w różnych aplikacjach przy użyciu tego samego magazynu użytkowników. W tabeli w polach UserName i ApplicationId występuje ograniczenie aspnet_Users złożoneUNIQUE, ale nie jedno w UserName polu. W związku z tym istnieje możliwość, aby tabela aspnet_Users miała dwa (lub więcej) rekordy o tej samej UserName wartości. Istnieje jednak UNIQUE ograniczenie w aspnet_Users polu tabeli UserId (ponieważ jest to klucz podstawowy). Ograniczenie UNIQUE jest ważne, ponieważ bez niego nie możemy ustanowić ograniczenia klucza obcego między tabelami GuestbookComments i aspnet_Users .

Po dodaniu kolumny UserId zapisz tabelę, klikając ikonę Zapisz na pasku narzędzi. Nadaj nowej tabeli GuestbookCommentsnazwę .

Mamy ostatni problem, aby uczestniczyć GuestbookComments w tabeli: musimy utworzyć ograniczenie klucza obcego między GuestbookComments.UserId kolumną a kolumną aspnet_Users.UserId . Aby to osiągnąć, kliknij ikonę Relacja na pasku narzędzi, aby uruchomić okno dialogowe Relacje kluczy obcych. (Alternatywnie możesz uruchomić to okno dialogowe, przechodząc do menu Tabela Projektant i wybierając pozycję Relacje).

Kliknij przycisk Dodaj w lewym dolnym rogu okna dialogowego Relacje kluczy obcych. Spowoduje to dodanie nowego ograniczenia klucza obcego, chociaż nadal musimy zdefiniować tabele, które uczestniczą w relacji.

Okno dialogowe Relacje kluczy obcych umożliwia zarządzanie ograniczeniami klucza obcego tabeli

Rysunek 3. Okno dialogowe Relacje kluczy obcych umożliwia zarządzanie ograniczeniami klucza obcego tabeli (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Następnie kliknij ikonę wielokropka w wierszu "Tabela i specyfikacje kolumn" po prawej stronie. Spowoduje to uruchomienie okna dialogowego Tabele i kolumny, z którego można określić tabelę i kolumnę klucza podstawowego oraz kolumnę klucza obcego GuestbookComments z tabeli. W szczególności wybierz aspnet_UsersUserId tabelę i kolumnę klucza podstawowego oraz UserId z GuestbookComments tabeli jako kolumnę klucza obcego (zobacz Rysunek 4). Po zdefiniowaniu tabel i kolumn klucza podstawowego i obcego kliknij przycisk OK, aby powrócić do okna dialogowego Relacje kluczy obcych.

Ustanawianie ograniczenia klucza obcego między tabelami aspnet_Users i GuesbookComments

Rysunek 4. Ustanowienie ograniczenia klucza obcego między aspnet_Users tabelami i GuesbookComments (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

W tym momencie ustalono ograniczenie klucza obcego. Obecność tego ograniczenia zapewnia integralność relacyjną między dwiema tabelami, gwarantując, że nigdy nie będzie wpisu elementu gościa odwołującego się do nieistniejącego konta użytkownika. Domyślnie ograniczenie klucza obcego nie zezwala na usunięcie rekordu nadrzędnego, jeśli istnieją odpowiednie rekordy podrzędne. Oznacza to, że jeśli użytkownik tworzy co najmniej jeden komentarz do książki gościa, a następnie próbujemy usunąć to konto użytkownika, usunięcie zakończy się niepowodzeniem, chyba że jego komentarze do książki gościa zostaną najpierw usunięte.

Ograniczenia klucza obcego można skonfigurować do automatycznego usuwania skojarzonych rekordów podrzędnych po usunięciu rekordu nadrzędnego. Innymi słowy, możemy skonfigurować to ograniczenie klucza obcego, aby wpisy elementu guestbook użytkownika były automatycznie usuwane po usunięciu konta użytkownika. Aby to osiągnąć, rozwiń sekcję "INSERT And UPDATE Specification" (Wstaw i aktualizuj specyfikację) i ustaw właściwość "Delete Rule" na Cascade.

Konfigurowanie ograniczenia klucza obcego do usuwania kaskadowego

Rysunek 5. Konfigurowanie ograniczenia klucza obcego do usuwania kaskadowego (kliknij, aby wyświetlić obraz w pełnym rozmiarze)

Aby zapisać ograniczenie klucza obcego, kliknij przycisk Zamknij, aby wyjść z relacji klucza obcego. Następnie kliknij ikonę Zapisz na pasku narzędzi, aby zapisać tabelę i tę relację.

Przechowywanie głównego miasta użytkownika, strony głównej i podpisu

W GuestbookComments tabeli przedstawiono sposób przechowywania informacji, które współudzielą relację jeden do wielu z kontami użytkowników. Ponieważ każde konto użytkownika może mieć dowolną liczbę skojarzonych komentarzy, ta relacja jest modelowana przez utworzenie tabeli do przechowywania zestawu komentarzy zawierających kolumnę, która łączy każdy komentarz z powrotem do określonego użytkownika. W przypadku korzystania z SqlMembershipProviderelementu ten link najlepiej ustanowić, tworząc kolumnę o nazwie UserId typu uniqueidentifier i ograniczenie klucza obcego między tą kolumną a aspnet_Users.UserId.

Teraz musimy skojarzyć trzy kolumny z każdym kontem użytkownika, aby przechowywać miasto główne, stronę główną i podpis użytkownika, które będą wyświetlane w komentarzach do jego książki gościa. Istnieje wiele różnych sposobów, aby to osiągnąć:

  • Dodawanie nowych kolumn do elementuaspnet_UsersLubaspnet_MembershipTabel. Nie polecam tego podejścia, ponieważ modyfikuje schemat używany przez program SqlMembershipProvider. Ta decyzja może wrócić do nawiedzić cię w dół drogi. Na przykład co zrobić, jeśli przyszła wersja ASP.NET używa innego SqlMembershipProvider schematu. Firma Microsoft może zawierać narzędzie do migrowania danych ASP.NET 2.0 SqlMembershipProvider do nowego schematu, ale jeśli zmodyfikowano schemat ASP.NET 2.0 SqlMembershipProvider , taka konwersja może nie być możliwa.

  • Użyj platformy ASP. Struktura profilu platformy NET, definiująca właściwość profilu dla rodzinnego miasta, strony głównej i podpisu. ASP.NET zawiera strukturę profilów przeznaczoną do przechowywania dodatkowych danych specyficznych dla użytkownika. Podobnie jak w przypadku struktury członkostwa, platforma Profilu jest zbudowana na szczycie modelu dostawcy. .NET Framework jest dostarczany ze SqlProfileProvider sthat przechowuje dane profilów w bazie danych SQL Server. W rzeczywistości nasza baza danych zawiera już tabelę używaną przez SqlProfileProvider element (aspnet_Profile), ponieważ została dodana podczas dodawania usług aplikacji z powrotem w samouczku Tworzenie schematu członkostwa w SQL Server.
    Główną zaletą struktury profilów jest umożliwienie deweloperom definiowania właściwości profilu w Web.config programie — nie trzeba zapisywać kodu w celu serializacji danych profilu do i z bazowego magazynu danych. Krótko mówiąc, bardzo łatwo jest zdefiniować zestaw właściwości profilu i pracować z nimi w kodzie. Jednak system profilów pozostawia wiele do życzenia, jeśli chodzi o przechowywanie wersji, więc jeśli masz aplikację, w której oczekujesz, że nowe właściwości specyficzne dla użytkownika zostaną dodane w późniejszym czasie lub istniejące do usunięcia lub zmodyfikowania, wówczas struktura profilu może nie być najlepszą opcją. Ponadto SqlProfileProvider obiekt przechowuje właściwości profilu w sposób wysoce zdenormalizowany, dzięki czemu nie można uruchamiać zapytań bezpośrednio względem danych profilu (takich jak liczba użytkowników, którzy mają miasto domowe w Nowym Jorku).
    Aby uzyskać więcej informacji na temat struktury profilów, zapoznaj się z sekcją "Dalsze informacje" na końcu tego samouczka.

  • Dodaj te trzy kolumny do nowej tabeli w bazie danych i ustanów relację jeden do jednego między tą tabelą aaspnet_Users. Takie podejście wymaga nieco większej pracy niż w przypadku struktury profilów, ale zapewnia maksymalną elastyczność w sposobie modelowania dodatkowych właściwości użytkownika w bazie danych. Jest to opcja, która zostanie użyta w tym samouczku.

Utworzymy nową tabelę o nazwie UserProfiles , aby zapisać miasto domowe, stronę główną i podpis dla każdego użytkownika. Kliknij prawym przyciskiem myszy folder Tables w oknie Eksplorator bazy danych i wybierz opcję utworzenia nowej tabeli. Nazwij pierwszą kolumnę UserId i ustaw jej typ na uniqueidentifier. Nie zezwalaj NULL na wartości i oznaczaj kolumnę jako klucz podstawowy. Następnie dodaj kolumny o nazwie: HomeTown typu ; HomepageUrl typu nvarchar(50)nvarchar(100); i Podpis typu nvarchar(500). Każda z tych trzech kolumn może akceptować NULL wartość.

Tworzenie tabeli UserProfiles

Rysunek 6. Tworzenie UserProfiles tabeli (kliknij, aby wyświetlić obraz pełnowymiarowy)

Zapisz tabelę i nadaj jej UserProfilesnazwę . Na koniec ustanów ograniczenie klucza obcego między UserProfiles polem tabeli UserId a polem aspnet_Users.UserId . Podobnie jak w przypadku ograniczenia klucza obcego między GuestbookComments tabelami i aspnet_Users , należy usunąć to ograniczenie kaskadowe. UserId Ponieważ pole w UserProfiles pliku jest kluczem podstawowym, gwarantuje to, że w tabeli nie będzie więcej niż jeden rekord UserProfiles dla każdego konta użytkownika. Ten typ relacji jest określany jako jeden do jednego.

Teraz, gdy mamy utworzony model danych, możemy go używać. W krokach 2 i 3 przyjrzymy się, jak aktualnie zalogowany użytkownik może wyświetlać i edytować swoje miasto domowe, stronę główną i informacje o podpisie. W kroku 4 utworzymy interfejs dla uwierzytelnionych użytkowników w celu przesyłania nowych komentarzy do elementu guestbook i wyświetlania istniejących.

Krok 2. Wyświetlanie głównego miasta użytkownika, strony głównej i podpisu

Istnieje wiele sposobów, aby umożliwić aktualnie zalogowanym użytkownikowi wyświetlanie i edytowanie jego rodzinnego miasta, strony głównej i informacji o podpisie. Możemy ręcznie utworzyć interfejs użytkownika za pomocą kontrolek TextBox i Label lub użyć jednej z kontrolek sieci Web danych, takich jak kontrolka DetailsView. Aby wykonać bazę danych SELECT i UPDATE instrukcje, możemy napisać ADO.NET kod w klasie za pomocą kodu naszej strony lub, alternatywnie, zastosować podejście deklaratywne w usłudze SqlDataSource. Najlepiej, aby nasza aplikacja zawierała architekturę warstwową, którą można wywołać programowo z klasy za pomocą kodu strony lub deklaratywnie za pośrednictwem kontrolki ObjectDataSource.

Ponieważ ta seria samouczków koncentruje się na uwierzytelnianiu formularzy, autoryzacji, kontach użytkowników i rolach, nie będzie szczegółowej dyskusji na temat tych różnych opcji dostępu do danych ani dlaczego architektura warstwowa jest preferowana w przypadku wykonywania instrukcji SQL bezpośrednio ze strony ASP.NET. Przejdę przez proces korzystania z elementów DetailsView i SqlDataSource — najszybszej i najłatwiejszej opcji — ale omówione koncepcje z pewnością można zastosować do alternatywnych mechanizmów kontroli sieci Web i logiki dostępu do danych. Aby uzyskać więcej informacji na temat pracy z danymi w ASP.NET, zapoznaj się z serią samouczków Praca z danymi w ASP.NET 2.0 .

AdditionalUserInfo.aspx Otwórz stronę w folderze Membership i dodaj kontrolkę DetailsView do strony, ustawiając jej właściwość na UserProfile i usuwając jej ID właściwości i Height usuwając jej Width właściwości. Rozwiń tag inteligentny kontrolki DetailsView i wybierz powiązanie go z nową kontrolką źródła danych. Spowoduje to uruchomienie Kreatora konfiguracji źródła danych (zobacz Rysunek 7). Pierwszy krok wymaga określenia typu źródła danych. Ponieważ połączymy się bezpośrednio z bazą SecurityTutorials danych, wybierz ikonę Baza danych, określając parametr ID jako UserProfileDataSource.

Dodawanie nowej kontrolki SqlDataSource o nazwie UserProfileDataSource

Rysunek 7. Dodawanie nowej kontrolki SqlDataSource o nazwie UserProfileDataSource (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Następny ekran wyświetla monit o użycie bazy danych. Zdefiniowaliśmy już parametry połączenia dla Web.configSecurityTutorials bazy danych. Ta nazwa parametrów połączenia — SecurityTutorialsConnectionString powinna znajdować się na liście rozwijanej. Wybierz tę opcję i kliknij przycisk Dalej.

Wybierz pozycję SecurityTutorialsConnectionString z listy Drop-Down

Rysunek 8. Wybieranie SecurityTutorialsConnectionString z listy Drop-Down (kliknij, aby wyświetlić obraz pełnowymiarowy)

Na kolejnym ekranie zostanie wyświetlony monit o określenie tabeli i kolumn do zapytania. Wybierz tabelę UserProfiles z listy rozwijanej i sprawdź wszystkie kolumny.

Przywrócenie wszystkich kolumn z tabeli UserProfiles

Rysunek 9. Przywrócenie wszystkich kolumn z UserProfiles tabeli (kliknij, aby wyświetlić obraz pełnowymiarowy)

Bieżące zapytanie na rysunku 9 zwraca wszystkie rekordy w UserProfileselemencie , ale interesuje nas tylko rekord aktualnie zalogowanego użytkownika. Aby dodać klauzulę WHERE , kliknij WHERE przycisk, aby wyświetlić okno dialogowe Dodawanie WHERE klauzuli (zobacz Rysunek 10). W tym miejscu możesz wybrać kolumnę do filtrowania, operator i źródło parametru filtru. Wybierz UserId jako kolumnę i "=" jako operator.

Niestety nie ma wbudowanego źródła parametrów, aby zwrócić wartość aktualnie zalogowanego użytkownika UserId . Będziemy musieli chwycić tę wartość programowo. W związku z tym ustaw listę rozwijaną Źródło na wartość "Brak", kliknij przycisk Dodaj, aby dodać parametr, a następnie kliknij przycisk OK.

Dodawanie parametru filtru w kolumnie UserId

Rysunek 10. Dodawanie parametru filtru w kolumnie UserId (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Po kliknięciu przycisku OK nastąpi powrót do ekranu pokazanego na rysunku 9. Tym razem jednak zapytanie SQL w dolnej części ekranu powinno zawierać klauzulę WHERE . Kliknij przycisk Dalej, aby przejść do ekranu "Zapytanie testowe". W tym miejscu możesz uruchomić zapytanie i wyświetlić wyniki. Kliknij przycisk Zakończ, aby zakończyć kreatora.

Po ukończeniu pracy Kreatora konfiguracji źródła danych program Visual Studio tworzy kontrolkę SqlDataSource na podstawie ustawień określonych w kreatorze. Ponadto ręcznie dodaje element BoundFields do kontrolki DetailsView dla każdej kolumny zwróconej SelectCommandprzez element SqlDataSource. Nie ma potrzeby wyświetlania UserId pola w widoku DetailsView, ponieważ użytkownik nie musi znać tej wartości. To pole można usunąć bezpośrednio z tagu deklaratywnego kontrolki DetailsView lub klikając link "Edytuj pola" z tagu inteligentnego.

Na tym etapie znaczniki deklaratywne strony powinny wyglądać podobnie do następujących:

<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>

Przed wybraniem danych należy programowo ustawić parametr kontrolki UserId SqlDataSource na aktualnie zalogowanego użytkownika UserId . Można to zrobić, tworząc procedurę obsługi zdarzeń dla zdarzenia sqlDataSource Selecting i dodając w nim następujący kod:

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;
}

Powyższy kod rozpoczyna się od uzyskania odwołania do aktualnie zalogowanego użytkownika przez wywołanie Membership metody klasy GetUser . Spowoduje to zwrócenie MembershipUser obiektu, którego ProviderUserKey właściwość zawiera UserIdobiekt . Wartość UserId jest następnie przypisywana do parametru @UserId sqlDataSource.

Uwaga

Metoda Membership.GetUser() zwraca informacje o aktualnie zalogowanym użytkowniku. Jeśli anonimowy użytkownik odwiedza stronę, zwróci wartość null. W takim przypadku spowoduje to wywołanie NullReferenceException obiektu w następującym wierszu kodu podczas próby odczytania ProviderUserKey właściwości. Oczywiście nie musimy martwić się o Membership.GetUser() zwrócenie wartości na AdditionalUserInfo.aspx stronie, ponieważ skonfigurowaliśmy autoryzację null adresu URL w poprzednim samouczku, aby tylko uwierzytelnieni użytkownicy mogli uzyskiwać dostęp do zasobów ASP.NET w tym folderze. Jeśli musisz uzyskać dostęp do informacji o aktualnie zalogowanym użytkowniku na stronie, na której jest dozwolony dostęp anonimowy, przed odwoływaniem się do jego właściwości upewnij się, że obiekt inny niż-null MembershipUser jest zwracany z GetUser() metody .

Jeśli odwiedzisz AdditionalUserInfo.aspx stronę za pośrednictwem przeglądarki, zobaczysz pustą stronę, ponieważ nie dodaliśmy jeszcze żadnych wierszy do UserProfiles tabeli. W kroku 6 przyjrzymy się, jak dostosować kontrolkę CreateUserWizard, aby automatycznie dodać nowy wiersz do tabeli po utworzeniu UserProfiles nowego konta użytkownika. Na razie jednak musimy ręcznie utworzyć rekord w tabeli.

Przejdź do Eksploratora baz danych w programie Visual Studio i rozwiń folder Tables. Kliknij prawym przyciskiem myszy tabelę aspnet_Users i wybierz polecenie "Pokaż dane tabeli", aby wyświetlić rekordy w tabeli. Wykonaj te same czynności dla UserProfiles tabeli. Rysunek 11 przedstawia te wyniki w przypadku kafelków w pionie. W mojej bazie danych istnieją obecnie aspnet_Users rekordy dla Bruce'a, Freda i Tito, ale w tabeli nie ma żadnych rekordów UserProfiles .

Zawartość tabel aspnet_Users i UserProfiles jest wyświetlana

Rysunek 11. Zawartość aspnet_Users tabel i UserProfiles tabel jest wyświetlana (kliknij, aby wyświetlić obraz w pełnym rozmiarze)

Dodaj nowy rekord do UserProfiles tabeli, wpisując ręcznie wartości dla HomeTownpól , HomepageUrli Signature . Najprostszym sposobem uzyskania prawidłowej UserId wartości w nowym UserProfiles rekordzie jest wybranie UserId pola z określonego konta użytkownika w tabeli i skopiowanie i wklejenie jej do UserId pola w aspnet_UsersUserProfilespliku . Rysunek 12 przedstawia tabelę UserProfiles po dodaniu nowego rekordu dla Bruce'a.

Rekord został dodany do pliku UserProfile dla Bruce'a

Rysunek 12. Dodano rekord dla UserProfiles Bruce'a (Kliknij, aby wyświetlić obraz pełnowymiarowy)

Wróć do AdditionalUserInfo.aspx strony, zaloguj się jako Bruce. Jak pokazano na rysunku 13, ustawienia Bruce'a są wyświetlane.

Aktualnie odwiedzający użytkownik jest wyświetlany jego ustawienia

Rysunek 13. Aktualnie odwiedzający użytkownik jest wyświetlany jego ustawienia (kliknij, aby wyświetlić obraz pełnowymiarowy)

Uwaga

Przejdź do przodu i ręcznie dodaj rekordy w UserProfiles tabeli dla każdego użytkownika członkostwa. W kroku 6 przyjrzymy się, jak dostosować kontrolkę CreateUserWizard, aby automatycznie dodać nowy wiersz do tabeli po utworzeniu UserProfiles nowego konta użytkownika.

Krok 3. Zezwolenie użytkownikowi na edytowanie swojego rodzinnego miasta, strony głównej i podpisu

W tym momencie zalogowany użytkownik może wyświetlać swoje miasto, stronę główną i ustawienie podpisu, ale nie może jeszcze ich modyfikować. Zaktualizujmy kontrolkę DetailsView, aby można było edytować dane.

Pierwszą rzeczą, którą musimy zrobić, jest dodanie elementu UpdateCommand dla elementu SqlDataSource, określając instrukcję UPDATE do wykonania i odpowiadających mu parametrów. Wybierz pozycję SqlDataSource i w okno Właściwości kliknij wielokropek obok właściwości UpdateQuery, aby wyświetlić okno dialogowe Edytor poleceń i parametrów. Wprowadź następującą UPDATE instrukcję w polu tekstowym:

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

Następnie kliknij przycisk "Odśwież parametry", który utworzy parametr w kolekcji kontrolki UpdateParameters SqlDataSource dla każdego z parametrów w UPDATE instrukcji . Pozostaw źródło dla wszystkich parametrów ustawionych na Wartość Brak, a następnie kliknij przycisk OK, aby ukończyć okno dialogowe.

Określanie parametrów UpdateCommand i UpdateParameters usługi SqlDataSource

Rysunek 14. Określanie wartości SqlDataSource UpdateCommand i UpdateParameters (kliknij, aby wyświetlić obraz pełnowymiarowy)

Ze względu na dodatki wprowadzone do kontrolki SqlDataSource kontrolka DetailsView może teraz obsługiwać edytowanie. Z tagu inteligentnego elementu DetailsView zaznacz pole wyboru "Włącz edytowanie". Spowoduje to dodanie pola polecenia do kolekcji kontrolki Fields z jej ShowEditButton właściwością ustawioną na wartość True. Spowoduje to renderowanie przycisku Edytuj, gdy widok DetailsView jest wyświetlany w trybie tylko do odczytu, a przyciski Aktualizuj i Anuluj po wyświetleniu w trybie edycji. Zamiast wymagać od użytkownika kliknięcia przycisku Edytuj, możemy mieć renderowany element DetailsView w stanie "zawsze edytowalny", ustawiając właściwość kontrolki DefaultMode DetailsView na Edit.

Dzięki tym zmianom znacznik deklaratywny kontrolki DetailsView powinien wyglądać podobnie do następującego:

<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>

Zanotuj dodanie pola commandfield i DefaultMode właściwości .

Przejdź do przodu i przetestuj tę stronę za pośrednictwem przeglądarki. Podczas odwiedzania użytkownika, który ma odpowiedni rekord w programie UserProfiles, ustawienia użytkownika są wyświetlane w edytowalnym interfejsie.

Element DetailsView renderuje interfejs edytowalny

Rysunek 15. Widok DetailsView renderuje interfejs edytowalny (kliknij, aby wyświetlić obraz pełnowymiarowy)

Spróbuj zmienić wartości i kliknąć przycisk Aktualizuj. Wygląda na to, że nic się nie dzieje. Istnieje postback i wartości są zapisywane w bazie danych, ale nie ma żadnych wizualnych opinii, że zapisanie wystąpiło.

Aby rozwiązać ten problem, wróć do programu Visual Studio i dodaj kontrolkę Etykieta nad kontrolką DetailsView. Ustaw dla właściwości SettingsUpdatedMessageID wartość , na Text wartość "Ustawienia zostały zaktualizowane", a jej Visible właściwości i EnableViewState na falsewartość .

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

Musimy wyświetlić etykietę SettingsUpdatedMessage za każdym razem, gdy element DetailsView zostanie zaktualizowany. Aby to zrobić, utwórz procedurę obsługi zdarzeń dla zdarzenia DetailsView ItemUpdated i dodaj następujący kod:

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

Wróć do AdditionalUserInfo.aspx strony za pośrednictwem przeglądarki i zaktualizuj dane. Tym razem zostanie wyświetlony przydatny komunikat o stanie.

Krótki komunikat jest wyświetlany po zaktualizowaniu ustawień

Rysunek 16. Krótki komunikat jest wyświetlany po zaktualizowaniu ustawień (kliknij, aby wyświetlić obraz pełnowymiarowy)

Uwaga

Interfejs edycji kontrolki DetailsView pozostawia wiele do życzenia. Używa ona standardowych pól tekstowych, ale pole Podpis powinno prawdopodobnie być polem tekstowym wielowierszowym. Należy użyć modułu RegularExpressionValidator, aby upewnić się, że adres URL strony głównej, jeśli zostanie wprowadzony, zaczyna się od "http://" lub "https://". Ponadto, ponieważ kontrolka DetailsView ma właściwość DefaultMode ustawioną na Edit, przycisk Anuluj nie wykonuje żadnych czynności. Powinien zostać usunięty lub po kliknięciu przekierowuje użytkownika do innej strony (na przykład ~/Default.aspx). Pozostawiam te ulepszenia jako ćwiczenie dla czytelnika.

Obecnie witryna internetowa nie udostępnia żadnych linków do AdditionalUserInfo.aspx strony. Jedynym sposobem dotarcia do niego jest wprowadzenie adresu URL strony bezpośrednio na pasku adresu przeglądarki. Dodajmy link do tej strony na stronie wzorcowej Site.master .

Pamiętaj, że strona wzorcowa zawiera kontrolkę internetową LoginView w swoim LoginContent elemecie ContentPlaceHolder, która wyświetla różne znaczniki dla uwierzytelnionych i anonimowych odwiedzających. Zaktualizuj kontrolkę LoggedInTemplate LoginView, aby dołączyć link do AdditionalUserInfo.aspx strony. Po wprowadzeniu tych zmian znacznik deklaratywne kontrolki LoginView powinien wyglądać podobnie do następującego:

<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>

Zwróć uwagę na dodanie kontrolki lnkUpdateSettings HyperLink do .LoggedInTemplate Dzięki temu linkowi uwierzytelnieni użytkownicy mogą szybko przejść do strony, aby wyświetlić i zmodyfikować ustawienia swojego rodzinnego miasta, strony głównej i podpisu.

Krok 4. Dodawanie nowych komentarzy do elementu guestbook

Strona to miejsce, na Guestbook.aspx którym uwierzytelnieni użytkownicy mogą wyświetlać element gościa i pozostawiać komentarz. Zacznijmy od utworzenia interfejsu w celu dodania nowych komentarzy do elementu guestbook.

Guestbook.aspx Otwórz stronę w programie Visual Studio i skonstruuj interfejs użytkownika składający się z dwóch kontrolek TextBox, jeden dla tematu nowego komentarza i jeden dla jego treści. Ustaw właściwość pierwszej kontrolki TextBox na Subject i jej Columns właściwość na 40; ustaw wartość sekundy BodyID na , na wartość , MultiLineTextMode a jej WidthRows właściwości na wartość "95%" i 8.ID Aby ukończyć interfejs użytkownika, dodaj kontrolkę Sieć Web przycisku o nazwie PostCommentButton i ustaw jej Text właściwość na "Opublikuj komentarz".

Ponieważ każdy komentarz elementu gościa wymaga tematu i treści, dodaj element RequiredFieldValidator dla każdego pola tekstowego. ValidationGroup Ustaw właściwość tych kontrolek na "EnterComment", podobnie ustaw PostCommentButton właściwość kontrolki ValidationGroup na "EnterComment". Aby uzyskać więcej informacji na temat platformy ASP. Kontrolki sprawdzania poprawności platformy NET można sprawdzić w ASP.NET weryfikacji formularzy.

Po zakończeniu tworzenia interfejsu użytkownika znaczniki deklaratywne strony powinny wyglądać mniej więcej tak:

<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>

Po zakończeniu pracy interfejsu użytkownika następnym zadaniem jest wstawienie nowego rekordu do tabeli po kliknięciu GuestbookCommentsPostCommentButton . Można to osiągnąć na wiele sposobów: możemy napisać kod ADO.NET w procedurze obsługi zdarzeń przycisku Click . Możemy dodać kontrolkę SqlDataSource do strony, skonfigurować jej InsertCommandmetodę , a następnie wywołać metodę Insert z Click programu obsługi zdarzeń. Możemy też utworzyć warstwę środkową, która była odpowiedzialna za wstawianie nowych komentarzy do podręcznika gościa i wywołać tę funkcję z Click programu obsługi zdarzeń. Ponieważ przyjrzeliśmy się użyciu usługi SqlDataSource w kroku 3, użyjmy tutaj kodu ADO.NET.

Uwaga

Klasy ADO.NET używane do programowego uzyskiwania dostępu do danych z bazy danych microsoft SQL Server znajdują się w System.Data.SqlClient przestrzeni nazw. Może być konieczne zaimportowanie tej przestrzeni nazw do klasy za pomocą kodu strony (tj. using System.Data.SqlClient;).

Utwórz procedurę obsługi zdarzeń dla PostCommentButtonClick zdarzenia i dodaj następujący kod:

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;
}

Procedura Click obsługi zdarzeń rozpoczyna się od sprawdzenia, czy podane przez użytkownika dane są prawidłowe. Jeśli tak nie jest, program obsługi zdarzeń kończy działanie przed wstawieniem rekordu. Zakładając, że podane dane są prawidłowe, wartość aktualnie zalogowanego użytkownika UserId jest pobierana i przechowywana w zmiennej currentUserId lokalnej. Ta wartość jest potrzebna, ponieważ musimy podać UserId wartość podczas wstawiania rekordu do GuestbookCommentselementu .

Następnie parametry połączenia dla SecurityTutorials bazy danych są pobierane z Web.config , a instrukcja SQL jest określona INSERT . Następnie SqlConnection zostanie utworzony i otwarty obiekt. SqlCommand Następnie obiekt jest konstruowany, a wartości parametrów używanych w INSERT zapytaniu są przypisywane. Instrukcja INSERT jest następnie wykonywana, a połączenie zostało zamknięte. Na końcu procedury obsługi Subject zdarzeń właściwości i Body TextBoxes Text są wyczyszczone, aby wartości użytkownika nie zostały utrwalone po powrocie zwrotne.

Przejdź do przodu i przetestuj tę stronę w przeglądarce. Ponieważ ta strona znajduje się w folderze Membership , nie jest dostępna dla anonimowych odwiedzających. W związku z tym należy najpierw zalogować się (jeśli jeszcze tego nie zrobiono). Wprowadź wartość w polach Subject TextBoxes i Body kliknij PostCommentButton przycisk . Spowoduje to dodanie nowego rekordu do GuestbookCommentselementu . Po wycofaniu temat i podana treść zostaną wyczyszczone z pola TextBoxes.

Po kliknięciu PostCommentButton przycisku nie ma żadnych wizualnych opinii, że komentarz został dodany do elementu gościa. Nadal musimy zaktualizować tę stronę, aby wyświetlić istniejące komentarze dotyczące elementów gościa, które wykonamy w kroku 5. Po osiągnięciu tego celu komentarz dodany po prostu pojawi się na liście komentarzy, zapewniając odpowiednią opinię wizualną. Na razie upewnij się, że komentarz do książki gościa został zapisany, sprawdzając zawartość GuestbookComments tabeli.

Rysunek 17 przedstawia zawartość tabeli po pozostawieniu GuestbookComments dwóch komentarzy.

Komentarze do elementów guestbook można zobaczyć w tabeli GuestbookComments

Rysunek 17. Komentarze do książki gościa można wyświetlić w GuestbookComments tabeli (kliknij, aby wyświetlić obraz pełnowymiarowy)

Uwaga

Jeśli użytkownik spróbuje wstawić komentarz do elementu guestbook, który zawiera potencjalnie niebezpieczne znaczniki — takie jak HTML — ASP.NET zgłosi błąd HttpRequestValidationException. Aby dowiedzieć się więcej na temat tego wyjątku, dlaczego jest on zgłaszany i jak zezwolić użytkownikom na przesyłanie potencjalnie niebezpiecznych wartości, zapoznaj się z oficjalnym dokumentem dotyczącym weryfikacji żądań.

Krok 5. Wyświetlanie listy istniejących komentarzy do podręcznika gościa

Oprócz pozostawiania komentarzy użytkownik odwiedzający Guestbook.aspx stronę powinien również mieć możliwość wyświetlania istniejących komentarzy elementu gościa. Aby to osiągnąć, dodaj kontrolkę ListView o nazwie CommentList na dole strony.

Uwaga

Kontrolka ListView jest nowym elementem ASP.NET w wersji 3.5. Jest ona przeznaczona do wyświetlania listy elementów w bardzo dostosowywalnym i elastycznym układzie, ale nadal oferuje wbudowane funkcje edytowania, wstawiania, usuwania, stronicowania i sortowania, takich jak GridView. Jeśli używasz ASP.NET 2.0, musisz zamiast tego użyć kontrolki DataList lub Repeater. Aby uzyskać więcej informacji na temat korzystania z kontrolki ListView, zobacz wpis w blogu Scotta Guthrie, kontrolka asp:ListView i artykuł Wyświetlanie danych za pomocą kontrolki ListView.

Otwórz tag inteligentny elementu ListView i z listy rozwijanej Wybierz źródło danych powiąż kontrolkę z nowym źródłem danych. Jak pokazano w kroku 2, spowoduje to uruchomienie Kreatora konfiguracji źródła danych. Wybierz ikonę Baza danych, nadaj wynikowej nazwie sqlDataSource CommentsDataSource, a następnie kliknij przycisk OK. Następnie wybierz SecurityTutorialsConnectionString parametry połączenia z listy rozwijanej, a następnie kliknij przycisk Dalej.

W tym momencie w kroku 2 określiliśmy dane do zapytania, wybierając UserProfiles tabelę z listy rozwijanej i wybierając kolumny do zwrócenia (wróć do rysunku 9). Tym razem jednak chcemy utworzyć instrukcję SQL, która ściąga nie tylko rekordy z GuestbookComments, ale także do rodzinnego miasta komentatora, strony głównej, podpisu i nazwy użytkownika. W związku z tym wybierz przycisk radiowy "Określ niestandardową instrukcję SQL lub procedurę składowaną", a następnie kliknij przycisk Dalej.

Spowoduje to wyświetlenie ekranu "Definiowanie instrukcji niestandardowych lub procedur składowanych". Kliknij przycisk Konstruktor zapytań, aby graficznie skompilować zapytanie. Konstruktor zapytań rozpoczyna się od monitowania o określenie tabel, z których chcemy wykonać zapytanie. Wybierz tabele GuestbookComments, UserProfilesi aspnet_Users i kliknij przycisk OK. Spowoduje to dodanie wszystkich trzech tabel do powierzchni projektowej. Ponieważ istnieją ograniczenia klucza obcego GuestbookCommentsmiędzy tabelami , UserProfilesi aspnet_Users , konstruktor zapytań automatycznie JOIN podsyła te tabele.

Pozostaje tylko określić kolumny, które mają być zwracane. GuestbookComments W tabeli wybierz Subjectkolumny , Bodyi , a CommentDate następnie zwróć HomeTownkolumny , HomepageUrli Signature z UserProfilesaspnet_Userstabeli .UserName Dodaj również element "ORDER BY CommentDate DESC" na końcu SELECT zapytania, tak aby najnowsze wpisy zostały zwrócone jako pierwsze. Po wybraniu tych opcji interfejs konstruktora zapytań powinien wyglądać podobnie do zrzutu ekranu na rysunku 18.

Skonstruowane elementy JOIN zapytania są tworzone przez elementy guestbookComments, UserProfiles i tabele aspnet_Users

Rysunek 18. Skonstruowane zapytanie JOIN zawiera GuestbookCommentstabele , UserProfilesi aspnet_Users (kliknij, aby wyświetlić obraz pełnowymiarowy)

Kliknij przycisk OK, aby zamknąć okno Konstruktora zapytań i wrócić do ekranu "Definiowanie instrukcji niestandardowych lub procedur składowanych". Kliknij przycisk Dalej, aby przejść do ekranu "Zapytanie testowe", na którym można wyświetlić wyniki zapytania, klikając przycisk Testuj zapytanie. Gdy wszystko będzie gotowe, kliknij przycisk Zakończ, aby ukończyć pracę kreatora Konfigurowanie źródła danych.

Po zakończeniu pracy Kreatora konfigurowania źródła danych w kroku 2 skojarzona kolekcja kontrolki Fields DetailsView została zaktualizowana w celu uwzględnienia pola BoundField dla każdej kolumny zwróconej przez SelectCommandelement . Jednak widok ListView pozostaje niezmieniony; Nadal musimy zdefiniować jego układ. Układ obiektu ListView można utworzyć ręcznie za pomocą narzutu deklaratywnego lub z opcji "Konfiguruj widok ListView" w tagu inteligentnym. Zwykle preferuję definiowanie znaczników ręcznie, ale używaj dowolnej metody, która jest dla Ciebie najbardziej naturalna.

Skończyło się na użyciu następujących LayoutTemplateelementów , ItemTemplatei ItemSeparatorTemplate dla mojej kontrolki ListView:

<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>

Element LayoutTemplate definiuje znaczniki emitowane przez kontrolkę, podczas gdy ItemTemplate renderuje każdy element zwrócony przez element SqlDataSource. Wynikowy ItemTemplateadiustacja jest umieszczana w kontrolce LayoutTemplate. itemPlaceholder . Oprócz elementu itemPlaceholderLayoutTemplate element zawiera kontrolkę DataPager, która ogranicza widok ListView do wyświetlania tylko 10 komentarzy elementów gości na stronę (ustawienie domyślne) i renderuje interfejs stronicowania.

Mój ItemTemplate wyświetla temat każdego komentarza elementu gościa w elemecie <h4> z treścią znajdującą się poniżej tematu. Zwróć uwagę, że składnia używana do wyświetlania treści pobiera dane zwracane przez Eval("Body") instrukcję powiązania danych, konwertuje je na ciąg i zastępuje podziały wierszy elementem <br /> . Ta konwersja jest wymagana w celu pokazania podziałów wierszy wprowadzonych podczas przesyłania komentarza, ponieważ biały znak jest ignorowany przez kod HTML. Podpis użytkownika jest wyświetlany pod treścią kursywy, a następnie miasto domowe użytkownika, link do jego strony głównej, data i godzina komentarza oraz nazwa użytkownika osoby, która opuściła komentarz.

Poświęć chwilę, aby wyświetlić stronę za pośrednictwem przeglądarki. Komentarze dodane do elementu guestbook powinny zostać wyświetlone w kroku 5.

Guestbook.aspx wyświetla teraz komentarze elementu gościa

Rysunek 19. Guestbook.aspx Teraz wyświetla komentarze elementu gościa (kliknij, aby wyświetlić obraz pełnowymiarowy)

Spróbuj dodać nowy komentarz do elementu guestbook. Po kliknięciu PostCommentButton przycisku strona publikuje z powrotem i komentarz jest dodawany do bazy danych, ale kontrolka ListView nie jest aktualizowana w celu wyświetlenia nowego komentarza. Można to naprawić za pomocą jednego z następujących:

  • PostCommentButton Aktualizowanie programu obsługi zdarzeń przycisku Click w celu wywołania metody kontrolki DataBind() ListView po wstawieniu nowego komentarza do bazy danych lub
  • Ustawienie właściwości kontrolki EnableViewState ListView na false. Takie podejście działa, ponieważ wyłączenie stanu widoku kontrolki wymaga ponownego powiązania danych bazowych na każdym ogłaszaniu zwrotnym.

Witryna internetowa samouczka, która można pobrać z tego samouczka, ilustruje obie techniki. Właściwość kontrolki EnableViewState ListView do false i kod potrzebny do programowego powiązania danych z listview jest obecny w procedurze Click obsługi zdarzeń, ale jest komentowany.

Uwaga

Obecnie strona umożliwia użytkownikowi AdditionalUserInfo.aspx wyświetlanie i edytowanie ustawień swojego rodzinnego miasta, strony głównej i podpisu. Może być miło zaktualizować AdditionalUserInfo.aspx w celu wyświetlenia zalogowanych komentarzy do podręcznika użytkownika. Oznacza to, że oprócz badania i modyfikowania jej informacji użytkownik może odwiedzić AdditionalUserInfo.aspx stronę, aby zobaczyć, jakie komentarze książki gościa zrobiła w przeszłości. Zostawię to jako ćwiczenie dla zainteresowanego czytelnika.

Krok 6. Dostosowywanie kontrolki CreateUserWizard w celu uwzględnienia interfejsu dla miasta głównego, strony głównej i podpisu

Zapytanie SELECT używane przez Guestbook.aspx stronę używa elementu , INNER JOIN aby połączyć powiązane rekordy między GuestbookCommentstabelami , UserProfilesi aspnet_Users . Jeśli użytkownik bez rekordu w elemecie UserProfiles tworzy komentarz do elementu guestbook, komentarz nie będzie wyświetlany w widoku ListView, ponieważ INNER JOIN zwraca tylko GuestbookComments rekordy, gdy w elementach i aspnet_Userssą zgodne rekordy.UserProfiles Jak pokazano w kroku 3, jeśli użytkownik nie ma w UserProfiles niej rekordu, nie może wyświetlić ani edytować jej ustawień na AdditionalUserInfo.aspx stronie.

Nie trzeba powiedzieć, ze względu na nasze decyzje projektowe ważne jest, aby każde konto użytkownika w systemie członkostwa miało pasujący rekord w UserProfiles tabeli. Chcemy, aby odpowiedni rekord był dodawany do UserProfiles każdego utworzenia nowego konta użytkownika członkostwa za pomocą polecenia CreateUserWizard.

Zgodnie z opisem w samouczku Tworzenie kont użytkowników po utworzeniu nowego konta użytkownika członkostwo kontrolka CreateUserWizard zgłasza zdarzenieCreatedUser. Możemy utworzyć procedurę obsługi zdarzeń dla tego zdarzenia, pobrać identyfikator UserId dla właśnie utworzonego użytkownika, a następnie wstawić rekord do UserProfiles tabeli z wartościami domyślnymi dla HomeTownkolumn , HomepageUrli Signature . Co więcej, można monitować użytkownika o te wartości, dostosowując interfejs kontrolki CreateUserWizard w celu uwzględnienia dodatkowych pól TextBoxes.

Najpierw przyjrzyjmy się, jak dodać nowy wiersz do UserProfiles tabeli w CreatedUser procedurze obsługi zdarzeń z wartościami domyślnymi. W tym celu zobaczymy, jak dostosować interfejs użytkownika kontrolki CreateUserWizard w celu uwzględnienia dodatkowych pól formularza w celu zbierania nowego miasta, strony głównej i podpisu nowego użytkownika.

Dodawanie domyślnego wiersza doUserProfiles

W samouczku Tworzenie kont użytkowników dodaliśmy kontrolkę CreateUserWizard do CreatingUserAccounts.aspx strony w folderze Membership . Aby kontrolka CreateUserWizard dodała rekord do UserProfiles tabeli podczas tworzenia konta użytkownika, musimy zaktualizować funkcjonalność kontrolki CreateUserWizard. Zamiast wprowadzać te zmiany na CreatingUserAccounts.aspx stronie, zamiast tego dodajmy nową kontrolkę CreateUserWizard do EnhancedCreateUserWizard.aspx strony i wprowadźmy tam modyfikacje tego samouczka.

EnhancedCreateUserWizard.aspx Otwórz stronę w programie Visual Studio i przeciągnij kontrolkę CreateUserWizard z przybornika na stronę. Ustaw właściwość kontrolki ID CreateUserWizard na NewUserWizardwartość . Jak omówiono w samouczku Tworzenie kont użytkowników , domyślny interfejs użytkownika createUserWizard monituje użytkownika o podanie niezbędnych informacji. Po podaniu tych informacji kontrolka wewnętrznie tworzy nowe konto użytkownika w strukturze członkostwa bez konieczności pisania pojedynczego wiersza kodu.

Kontrolka CreateUserWizard zgłasza wiele zdarzeń podczas przepływu pracy. Gdy gość dostarczy informacje o żądaniu i prześle formularz, kontrolka CreateUserWizard początkowo uruchamia zdarzenieCreatingUser. Jeśli podczas procesu tworzenia wystąpi problem, CreateUserError zdarzenie zostanie wyzwolone. Jeśli jednak użytkownik zostanie pomyślnie utworzony, CreatedUser zdarzenie zostanie zgłoszone . W samouczku Tworzenie kont użytkowników utworzyliśmy procedurę obsługi zdarzeń dla CreatingUser zdarzenia, aby upewnić się, że podana nazwa użytkownika nie zawiera żadnych spacji wiodących ani końcowych oraz że nazwa użytkownika nie pojawiła się nigdzie w haśle.

Aby dodać wiersz w UserProfiles tabeli dla właśnie utworzonego użytkownika, musimy utworzyć procedurę obsługi zdarzeń dla CreatedUser zdarzenia. CreatedUser Gdy zdarzenie zostało wyzwolone, konto użytkownika zostało już utworzone w strukturze członkostwa, co umożliwi nam pobranie wartości UserId konta.

Utwórz procedurę obsługi zdarzeń dla NewUserWizardzdarzenia i CreatedUser dodaj następujący kod:

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();
     }
}

Powyższe istoty kodu przez pobranie identyfikatora UserId właśnie dodanego konta użytkownika. Jest to realizowane przy użyciu Membership.GetUser(username) metody w celu zwrócenia informacji o określonym użytkowniku, a następnie przy użyciu ProviderUserKey właściwości w celu pobrania identyfikatora UserId. Nazwa użytkownika wprowadzona przez użytkownika w kontrolce CreateUserWizard jest dostępna za pośrednictwem jego UserName właściwości.

Następnie parametry połączenia są pobierane z Web.config instrukcji , a instrukcja jest określona INSERT . Niezbędne obiekty ADO.NET są tworzone i wykonywane polecenie. Kod przypisuje DBNull wystąpienie do @HomeTownparametrów , @HomepageUrli @Signature , które mają wpływ na wstawianie wartości bazy danych NULL dla HomeTownpól , HomepageUrli Signature .

EnhancedCreateUserWizard.aspx Odwiedź stronę za pośrednictwem przeglądarki i utwórz nowe konto użytkownika. Po wykonaniu tej czynności wróć do programu Visual Studio i sprawdź zawartość aspnet_Users tabel i UserProfiles (tak jak na rysunku 12). Powinno zostać wyświetlone nowe konto użytkownika w aspnet_Users i odpowiadający mu UserProfiles wiersz (z wartościami NULL , HomeTownHomepageUrli Signature).

Dodano nowe konto użytkownika i rekord UserProfiles

Rysunek 20. Dodano nowe konto użytkownika i UserProfiles rekord (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Po podaniu przez użytkownika informacji o nowym koncie i kliknięciu przycisku "Utwórz użytkownika" konto użytkownika zostanie utworzone i zostanie dodany wiersz do UserProfiles tabeli. Następnie w obszarze CreateUserWizard zostanie wyświetlony komunikat CompleteWizardStepo powodzeniu i przycisk Kontynuuj. Kliknięcie przycisku Kontynuuj powoduje powrót, ale nie podjęto żadnej akcji, pozostawiając użytkownika zablokowanego EnhancedCreateUserWizard.aspx na stronie.

Możemy określić adres URL, który ma zostać wysłany do użytkownika po kliknięciu przycisku Kontynuuj za pośrednictwem właściwości kontrolki ContinueDestinationPageUrlCreateUserWizard. ContinueDestinationPageUrl Ustaw właściwość na "~/Membership/AdditionalUserInfo.aspx". Spowoduje to przejście nowego użytkownika do AdditionalUserInfo.aspxlokalizacji , w której może wyświetlać i aktualizować ustawienia.

Dostosowywanie interfejsu CreateUserWizard w celu monitowania o podanie głównego miasta, strony głównej i podpisu nowego użytkownika

Domyślny interfejs kontrolki CreateUserWizard jest wystarczający dla prostych scenariuszy tworzenia konta, w których zbierane są tylko podstawowe informacje o koncie użytkownika, takie jak nazwa użytkownika, hasło i wiadomość e-mail. Ale co zrobić, jeśli chcemy skłonić gościa do wejścia do swojego rodzinnego miasta, strony głównej i podpisu podczas tworzenia konta? Istnieje możliwość dostosowania interfejsu kontrolki CreateUserWizard w celu zbierania dodatkowych informacji podczas rejestracji, a te informacje mogą być używane w CreatedUser procedurze obsługi zdarzeń w celu wstawiania dodatkowych rekordów do bazowej bazy danych.

Kontrolka CreateUserWizard rozszerza kontrolkę Kreatora ASP.NET, która umożliwia deweloperowi strony zdefiniowanie serii uporządkowanych WizardStepselementów . Kontrolka Kreator renderuje aktywny krok i udostępnia interfejs nawigacyjny, który umożliwia odwiedzającym przejście przez te kroki. Kontrolka Kreator jest idealna do podziału długiego zadania na kilka krótkich kroków. Aby uzyskać więcej informacji na temat kontrolki Kreatora, zobacz Tworzenie interfejsu użytkownika krok po kroku za pomocą kontrolki kreatora ASP.NET 2.0.

Domyślny znacznik kontrolki CreateUserWizard definiuje dwa WizardStepselementy : CreateUserWizardStep i 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>

Pierwszy WizardStepelement , CreateUserWizardSteprenderuje interfejs, który wyświetla monit o podanie nazwy użytkownika, hasła, poczty e-mail itd. Gdy odwiedzający dostarczy te informacje i kliknie pozycję "Utwórz użytkownika", zostanie wyświetlona wartość , która pokazuje komunikat o powodzeniu CompleteWizardStepi przycisk Kontynuuj.

Aby dostosować interfejs kontrolki CreateUserWizard w celu uwzględnienia dodatkowych pól formularza, możemy:

  • Utwórz co najmniej jeden nowyWizardSteps, aby zawierać dodatkowe elementy interfejsu użytkownika. Aby dodać nowy WizardStep element do elementu CreateUserWizard, kliknij link "Dodaj/Usuń WizardSteps" z tagu inteligentnego WizardStep , aby uruchomić edytor kolekcji. W tym miejscu możesz dodawać, usuwać lub zmieniać kolejność kroków w kreatorze. Jest to podejście, które będziemy używać w tym samouczku.

  • KonwertowanieCreateUserWizardStepdo edycjiWizardStep. Spowoduje to zamianę CreateUserWizardStep elementu na odpowiednik WizardStep , którego znacznik definiuje interfejs użytkownika zgodny z parametrami CreateUserWizardStep.s. Konwertując CreateUserWizardStep element na WizardStep element , możemy zmienić położenie kontrolek lub dodać dodatkowe elementy interfejsu użytkownika do tego kroku. Aby przekonwertować element CreateUserWizardStep lub CompleteWizardStep na edytowalny WizardStep, kliknij link "Dostosuj krok użytkownika" lub "Dostosuj pełny krok" z tagu inteligentnego kontrolki.

  • Użyj kombinacji powyższych dwóch opcji.

Należy pamiętać, że kontrolka CreateUserWizard wykonuje proces tworzenia konta użytkownika po kliknięciu przycisku "Utwórz użytkownika" z poziomu elementu CreateUserWizardStep. Nie ma znaczenia, czy są dodatkowe WizardStep po CreateUserWizardStep lub nie.

Podczas dodawania niestandardowego WizardStep do kontrolki CreateUserWizard w celu zbierania dodatkowych danych wejściowych użytkownika można umieścić niestandardowe WizardStep przed lub po CreateUserWizardStep. Jeśli nastąpi to przed CreateUserWizardStep wprowadzeniem dodatkowych danych wejściowych użytkownika zebranych z niestandardowego CreatedUser obiektu WizardStep obsługi zdarzeń. Jeśli jednak niestandardowe WizardStep nastąpi po CreateUserWizardStep upływie tego czasu, po wyświetleniu niestandardowego WizardStep zostanie już utworzone nowe konto użytkownika i CreatedUser zdarzenie zostało już wyzwolone.

Rysunek 21 przedstawia przepływ pracy po dodaniu WizardStep poprzedzającym CreateUserWizardStepelement . Ponieważ dodatkowe informacje o użytkowniku zostały zebrane przez czas CreatedUser uruchomienia zdarzenia, wystarczy zaktualizować CreatedUser procedurę obsługi zdarzeń, aby pobrać te dane wejściowe i użyć tych wartości INSERT parametrów instrukcji (a DBNull.Valuenie ).

Przepływ pracy CreateUserWizard, gdy dodatkowy kreatorKrok poprzedza element CreateUserWizardStep

Rysunek 21. Przepływ pracy CreateUserWizard po WizardStep dodatkowym poprzedza CreateUserWizardStep (kliknij, aby wyświetlić obraz pełnowymiarowy)

Jeśli jednak po ustawieniu parametruCreateUserWizardStepzostanie umieszczony niestandardowy WizardStep proces tworzenia konta użytkownika, zanim użytkownik miał szansę wejść do swojego rodzinnego miasta, strony głównej lub podpisu. W takim przypadku te dodatkowe informacje należy wstawić do bazy danych po utworzeniu konta użytkownika, jak pokazano na rysunku 22.

Przepływ pracy CreateUserWizard, gdy dodatkowy kreatorKrok pojawia się po kroku CreateUserWizardStep

Rysunek 22. Przepływ pracy CreateUserWizard po wprowadzeniu dodatkowych WizardStepCreateUserWizardStep informacji (kliknij, aby wyświetlić obraz pełnowymiarowy)

Przepływ pracy przedstawiony na rysunku 22 czeka na wstawienie rekordu UserProfiles do tabeli do momentu ukończenia kroku 2. Jeśli odwiedzający zamknie przeglądarkę po kroku 1, jednak osiągniemy stan, w którym zostało utworzone konto użytkownika, ale nie dodano rekordu do UserProfilesusługi . Jednym z obejść jest posiadanie rekordu z wartościami domyślnymi NULL wstawionym do UserProfilesCreatedUser programu obsługi zdarzeń (który jest uruchamiany po kroku 1), a następnie zaktualizować ten rekord po ukończeniu kroku 2. Dzięki UserProfiles temu rekord zostanie dodany dla konta użytkownika, nawet jeśli użytkownik zakończy proces rejestracji w połowie.

W tym samouczku utworzymy nową, WizardStep która występuje po CreateUserWizardStep obiekcie , ale przed .CompleteWizardStep Najpierw pobierzemy polecenie WizardStep i skonfigurujemy go, a następnie przyjrzymy się kodowi.

Na karcie Smart Tag kontrolki CreateUserWizard wybierz pozycję "Dodaj/Usuń WizardStep ", która powoduje wyświetlenie okna dialogowego WizardStep Edytor kolekcji. Dodaj nowy WizardStepelement , ustawiając element ID na UserSettings, Title na "Ustawienia" i na StepTypeStep. Następnie umieść go tak, aby był dostępny po CreateUserWizardStep ("Zarejestruj się na nowe konto") i przed ("Complete"), jak pokazano na rysunku CompleteWizardStep 23.

Dodawanie nowego kreatoraKrok do kontrolki CreateUserWizard

Rysunek 23. Dodawanie nowego WizardStep do kontrolki CreateUserWizard (kliknij, aby wyświetlić obraz pełnowymiarowy)

Kliknij przycisk OK, WizardStep aby zamknąć okno dialogowe Edytor kolekcji. Nowy WizardStep jest dowodem na zaktualizowane znaczniki deklaratywne kontrolki CreateUserWizard:

<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>

Zanotuj nowy <asp:WizardStep> element. Musimy dodać interfejs użytkownika, aby zebrać miasto macierzyste nowego użytkownika, stronę główną i podpis tutaj. Tę zawartość można wprowadzić w składni deklaratywnej lub za pomocą Projektant. Aby użyć Projektant, wybierz krok "Ustawienia" z listy rozwijanej w tagu inteligentnym, aby wyświetlić krok w Projektant.

Uwaga

Wybranie kroku na liście rozwijanej tagu inteligentnego spowoduje zaktualizowanie właściwości kontrolki ActiveStepIndexCreateUserWizard, która określa indeks kroku początkowego. W związku z tym, jeśli używasz tej listy rozwijanej do edytowania kroku "Ustawienia" w Projektant, pamiętaj, aby ustawić go z powrotem na "Zarejestruj się na nowe konto", aby ten krok był wyświetlany podczas pierwszej wizyty użytkowników na EnhancedCreateUserWizard.aspx stronie.

Utwórz interfejs użytkownika w kroku "Ustawienia", który zawiera trzy kontrolki TextBox o nazwie HomeTown, HomepageUrli Signature. Po utworzeniu tego interfejsu znacznik deklaratywny CreateUserWizard powinien wyglądać podobnie do następującego:

<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>

Przejdź dalej i odwiedź tę stronę za pośrednictwem przeglądarki i utwórz nowe konto użytkownika, określając wartości dla rodzinnego miasta, strony głównej i podpisu. Po ukończeniu CreateUserWizardStep konta użytkownika zostanie utworzone w strukturze członkostwa i CreatedUser zostanie uruchomiona procedura obsługi zdarzeń, która dodaje nowy wiersz do UserProfileselementu , ale z wartością bazy danych NULL dla HomeTown, HomepageUrli Signature. Wartości wprowadzone dla rodzinnego miasta, strony głównej i podpisu nigdy nie są używane. Wynik netto to nowe konto użytkownika z rekordem UserProfiles , którego HomeTownpola , HomepageUrli Signature nie zostały jeszcze określone.

Musimy wykonać kod po kroku "Twoje ustawienia", który przyjmuje miasto macierzyste, honepage i wartości podpisu wprowadzone przez użytkownika i aktualizuje odpowiedni UserProfiles rekord. Za każdym razem, gdy użytkownik przechodzi między krokami w kontrolce Kreatora, zdarzenie Kreatora ActiveStepChanged jest uruchamiane. Możemy utworzyć procedurę obsługi zdarzeń dla tego zdarzenia i zaktualizować UserProfiles tabelę po zakończeniu kroku "Ustawienia".

Dodaj procedurę obsługi zdarzeń dla zdarzenia CreateUserWizard ActiveStepChanged i dodaj następujący kod:

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();
          }
     }
}

Powyższy kod rozpoczyna się od określenia, czy właśnie osiągnięto krok "Ukończono". Ponieważ krok "Ukończ" występuje natychmiast po kroku "Ustawienia", gdy gość osiągnie krok "Ukończono", oznacza to, że właśnie zakończyła krok "Twoje ustawienia".

W takim przypadku musimy programowo odwołać się do kontrolek TextBox w obiekcie UserSettings WizardStep. Jest to realizowane przy użyciu FindControl metody , aby programowo odwoływać UserSettings WizardStepsię do elementu , a następnie ponownie odwołać się do pola TextBoxes z poziomu elementu WizardStep. Po odwołaniu się do pola TextBoxes możemy wykonać instrukcję UPDATE . Instrukcja UPDATE ma taką samą liczbę parametrów jak INSERT instrukcja w CreatedUser procedurze obsługi zdarzeń, ale w tym miejscu używamy wartości miasta macierzystego, strony głównej i podpisu dostarczone przez użytkownika.

Korzystając z tej procedury obsługi zdarzeń, odwiedź EnhancedCreateUserWizard.aspx stronę za pośrednictwem przeglądarki i utwórz nowe konto użytkownika określające wartości dla rodzinnego miasta, strony głównej i podpisu. Po utworzeniu nowego konta należy przekierować na AdditionalUserInfo.aspx stronę, na której są wyświetlane informacje o właśnie wprowadzonej miejscowości głównej, stronie głównej i podpisie.

Uwaga

Nasza witryna internetowa ma obecnie dwie strony, na których odwiedzający może utworzyć nowe konto: CreatingUserAccounts.aspx i EnhancedCreateUserWizard.aspx. Mapa witryny i strona logowania witryny internetowej wskazują CreatingUserAccounts.aspx stronę, ale CreatingUserAccounts.aspx strona nie monituje użytkownika o podanie informacji o swoim rodzinnym mieście, stronie głównej i podpisie i nie dodaje odpowiedniego wiersza do UserProfiles. W związku z tym zaktualizuj CreatingUserAccounts.aspx stronę tak, aby oferuje ona tę funkcję lub zaktualizowała mapę witryny i stronę logowania, aby odwoływać EnhancedCreateUserWizard.aspx się zamiast CreatingUserAccounts.aspx. Jeśli wybierzesz tę drugą opcję, pamiętaj, aby zaktualizować Membership plik folderu Web.config tak, aby zezwolić anonimowym użytkownikom na dostęp do EnhancedCreateUserWizard.aspx strony.

Podsumowanie

W tym samouczku przyjrzeliśmy się technikom modelowania danych związanych z kontami użytkowników w ramach struktury członkostwa. W szczególności przyjrzeliśmy się modelowaniu jednostek, które współdzielą relację jeden do wielu z kontami użytkowników, a także dane, które współużytkuje relację jeden do jednego. Ponadto zobaczyliśmy, jak te powiązane informacje można wyświetlać, wstawiać i aktualizować, przy użyciu niektórych przykładów przy użyciu kontrolki SqlDataSource i innych przy użyciu kodu ADO.NET.

W tym samouczku przedstawiono konta użytkowników. Począwszy od następnego samouczka zwrócimy uwagę na role. W kolejnych kilku samouczkach przyjrzymy się strukturze Role, zobaczymy, jak tworzyć nowe role, jak przypisywać role do użytkowników, jak określić, do jakich ról należy użytkownik, oraz jak zastosować autoryzację opartą na rolach.

Szczęśliwe programowanie!

Dalsze informacje

Aby uzyskać więcej informacji na temat tematów omówionych w tym samouczku, zapoznaj się z następującymi zasobami:

Informacje o autorze

Scott Mitchell, autor wielu książek ASP/ASP.NET i założyciel 4GuysFromRolla.com, współpracuje z technologiami internetowymi firmy Microsoft od 1998 roku. Scott pracuje jako niezależny konsultant, trener i pisarz. Jego najnowsza książka to Sams Teach Yourself ASP.NET 2.0 w ciągu 24 godzin. Scott można dotrzeć na mitchell@4guysfromrolla.com lub za pośrednictwem swojego bloga pod adresem http://ScottOnWriting.NET.

Specjalne podziękowania...

Ta seria samouczków została sprawdzona przez wielu pomocnych recenzentów. Chcesz przejrzeć nadchodzące artykuły MSDN? Jeśli tak, upuść mi wiersz pod adresem mitchell@4GuysFromRolla.com.