Exemplarische Vorgehensweise: Verwenden des Authentifizierungsdiensts mit der Silverlight-Navigationsanwendung
In dieser exemplarischen Vorgehensweise erfahren Sie, wie die Server- und Clientprojekte in einer WCF RIA Services-Projektmappe für die Arbeit mit einem Authentifizierungsdienst eingerichtet werden. Wenn Sie eine Projektmappe mit der Vorlage "Silverlight-Navigationsanwendung" erstellen und RIA Services aktivieren, können Sie auf das ASP.NET-Mitgliedschaftsframework zugreifen, indem Sie einen Authentifizierungsdienst hinzufügen. Der Authentifizierungsdienst macht Authentifizierung, Rollen und Profile vom Serverprojekt für das Clientprojekt verfügbar. Mit dem Authentifizierungsdienst werden Benutzeranmeldeinformationen überprüft, der Zugriff auf Ressourcen auf Grundlage von Rollen eingeschränkt und Profileigenschaften gespeichert.
Hinweis: |
---|
In der Silverlight-Geschäftsanwendung wird der Authentifizierungsdienst automatisch implementiert. Weitere Informationen finden Sie unter Exemplarische Vorgehensweise: Verwenden des Authentifizierungsdiensts mit der Silverlight-Geschäftsanwendung. |
Erforderliche Komponenten
Für diese und die anderen exemplarischen Vorgehensweisen in der RIA Services -Dokumentation müssen zusätzlich zu WCF RIA Services und dem WCF RIA Services-Toolkit mehrere erforderliche Programme installiert und korrekt konfiguriert werden, z. B. Visual Studio 2010, die Silverlight Developer-Laufzeit und das Silverlight-SDK. Zudem müssen Sie SQL Server 2008 R2 Express with Advanced Services installieren und konfigurieren und die AdventureWorks OLTP- und LT-Datenbanken installieren.
Ausführliche Anweisungen für jede dieser erforderlichen Komponenten finden Sie in den Themen unter Erforderliche Komponenten für WCF RIA Services. Folgen Sie den Anweisungen in diesen Themen, bevor Sie mit dieser exemplarischen Vorgehensweise fortfahren, um sicherzustellen, dass beim Ausführen der exemplarischen Vorgehensweisen für RIA Services so wenig Probleme wie möglich auftreten.
Konfigurieren des Serverprojekts für Authentifizierung, Rollen und Profile
Um den Authentifizierungsdienst in einer Silverlight-Anwendung verwenden zu können, müssen Sie die Authentifizierung für das Serverprojekt konfigurieren. Sie konfigurieren die Authentifizierung in der Datei "Web.config". Nach der Konfiguration der Authentifizierung können Sie auch Rollen und Profile für das Serverprojekt konfigurieren, wenn Sie diese Funktionen in der Silverlight-Anwendung verwenden möchten. In dieser exemplarischen Vorgehensweise konfigurieren Sie alle drei Funktionen. Schließlich fügen Sie einen Authentifizierungsdienst hinzu, der die aktivierten Funktionen für den Client verfügbar macht.
So konfigurieren Sie das Serverprojekt
Wählen Sie in Visual Studio 2010 Datei, Neu und dann Projekt aus.
Das Dialogfeld Neues Projekt wird angezeigt.
Wählen Sie den Projekttyp Silverlight aus.
Wählen Sie die Vorlage Silverlight-Navigationsanwendung aus, und nennen Sie die Anwendung ExampleNavigationApplication.
Klicken Sie auf OK.
Das Dialogfeld Neue Silverlight-Anwendung wird angezeigt.
Stellen Sie sicher, dass das Kontrollkästchen Die Silverlight-Anwendung in einer neuen Website hosten aktiviert wurde, und dass der neue Webprojekttyp auf ASP.NET-Webanwendungsprojekt festgelegt wurde.
Aktivieren Sie das Kontrollkästchen WCF RIA Services aktivieren.
Klicken Sie auf OK, um die Projektmappe zu erstellen.
Öffnen Sie im Serverprojekt (ExampleBusinessApplication.Web) die Datei "Web.config".
Fügen Sie im
<system.web>
-Element ein<authentication>
-Element hinzu, und legen Sie diemode
-Eigenschaft auf "Formulare" fest.<authentication mode="Forms"></authentication>
Fügen Sie im
<system.web>
-Element ein<roleManager>
-Element hinzu, und legen Sie dieenabled
-Eigenschaft auf "true" fest.<roleManager enabled="true"></roleManager>
Fügen Sie im
<system.web>
-Element ein<profile>
-Element hinzu, legen Sie dieenabled
-Eigenschaft auf true fest, und schließen Sie eineprofile
-Eigenschaft mit dem Namen "DefaultRows" ein.<profile enabled="true"> <properties> <add type="System.Int32" defaultValue="10" name="DefaultRows"/> </properties> </profile>
Das abgeschlossene
<system.web>
-Element sollte die folgenden Elemente einschließen:<system.web> <compilation debug="true" targetFramework="4.0" /> <authentication mode="Forms"></authentication> <roleManager enabled="true"></roleManager> <profile enabled="true"> <properties> <add type="System.Int32" defaultValue="10" name="DefaultRows"/> </properties> </profile> </system.web>
Speichern Sie die Datei "Web.config".
Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Serverprojekt, wählen Sie Hinzufügen und dann Neues Element aus.
Das Dialogfeld Neues Element hinzufügen wird angezeigt.
Wählen Sie die Vorlage Domänendienst zur Authentifizierung aus, und nennen Sie sie AuthenticationDomainService.
Klicken Sie auf Hinzufügen.
Öffnen Sie die Authentifizierungsdienst-Codedatei (AuthenticationDomainService.cs oder AuthenticationDomainService.vb), und fügen Sie die DefaultRows-Eigenschaft, die Sie in der Datei "Web.config" definiert haben, der User-Klasse hinzu.
<EnableClientAccess()> _ Public Class AuthenticationDomainService Inherits AuthenticationBase(Of User) End Class Public Class User Inherits UserBase Public Property DefaultRows As Integer End Class
[EnableClientAccess] public class AuthenticationDomainService : AuthenticationBase<User> { } public class User : UserBase { public int DefaultRows { get; set; } }
Erstellen Sie die Projektmappe.
In diesem Abschnitt erstellen Sie mithilfe des ASP.NET-Websiteverwaltungstools einen Benutzer und eine Rolle. Sie melden sich in einem späteren Abschnitt als Benutzer an.
So fügen Sie Benutzer mit dem ASP.NET-Websiteverwaltungs-Tool hinzu
Um das ASP.NET-Websiteverwaltungs-Tool zu öffnen, wählen Sie zuerst das Serverprojekt im Projektmappen-Explorer aus.
Wählen Sie im Menü Projekt die Option ASP.NET-Konfiguration aus.
Wenn die Option "ASP.NET-Konfiguration" nicht im Menü "Projekt" angezeigt wird, haben Sie möglicherweise das Clientprojekt ausgewählt.
Klicken Sie im ASP.NET-Websiteverwaltungs-Tool auf die Registerkarte Sicherheit.
Klicken Sie im Abschnitt Rollen auf den Link Rollen erstellen oder verwalten.
Fügen Sie eine neue Rolle mit dem Namen Managers hinzu, und klicken Sie auf die Schaltfläche Rolle hinzufügen.
Klicken Sie rechts unten auf die Schaltfläche Zurück.
Klicken Sie im Abschnitt Benutzer auf den Link Benutzer erstellen.
Erstellen Sie einen neuen Benutzer mit den folgenden Werten, und aktivieren Sie das Kontrollkästchen für die Rolle "Managers".
Benutzername: CustomerManager
Kennwort: P@ssword
E-Mail: someone@example.com
Sicherheitsfrage: Lieblingsfarbe?
Sicherheitsantwort: Blau
Rolle "Managers": aktiviert
Klicken Sie auf die Schaltfläche Benutzer erstellen.
Schließen Sie das ASP.NET-Websiteverwaltungs-Tool.
Konfigurieren des Clients zur Authentifizierung
Sie müssen das Clientprojekt für die Verwendung des Authentifizierungsmodus konfigurieren, der dem im Serverprojekt konfigurierten Authentifizierungsmodus entspricht.
So konfigurieren Sie das Clientprojekt
Öffnen Sie im Clientprojekt die CodeBehind-Datei für die Datei "App.xaml" ("App.xaml.cs" bzw. "App.xaml.vb").
Erstellen Sie im Konstruktor eine neue Instanz der WebContext-Klasse.
Legen Sie die Authentication-Eigenschaft auf eine neue Instanz der FormsAuthentication-Klasse fest, und fügen Sie die WebContext-Instanz ApplicationLifetimeObjects hinzu.
Public Sub New() InitializeComponent() Dim webcontext As New WebContext webcontext.Authentication = New System.ServiceModel.DomainServices.Client.ApplicationServices.FormsAuthentication Me.ApplicationLifetimeObjects.Add(webcontext) End Sub
public App() { this.Startup += this.Application_Startup; this.UnhandledException += this.Application_UnhandledException; InitializeComponent(); WebContext webcontext = new WebContext(); webcontext.Authentication = new System.ServiceModel.DomainServices.Client.ApplicationServices.FormsAuthentication(); this.ApplicationLifetimeObjects.Add(webcontext); }
Hinzufügen der Anmeldefunktionalität zum Client
In diesem Abschnitt fügen Sie Silverlight-Steuerelemente hinzu, mit denen der Benutzer Benutzername und Kennwort für die Anmeldung angeben kann. Sie fügen Code hinzu, durch den die Login-Methode mit den Anmeldeinformationen des Benutzers aufgerufen wird. Sie legen auch fest, welche Steuerelemente sichtbar sind, und zwar abhängig davon, ob der Benutzer angemeldet ist.
Zur Vereinfachung wird die Anmeldebenutzeroberfläche der Startseite in dieser exemplarischen Vorgehensweise hinzugefügt. In Ihrer Anwendung möchten Sie ggf. eine separate Anmeldeseite erstellen.
So melden Sie einen Benutzer an und ab
Erweitern Sie im Projektmappen-Explorer im Clientprojekt den Ordner "Views".
Öffnen Sie die Datei "Home.xaml".
Fügen Sie nach dem TextBlock mit dem Namen
ContentText
das folgende XAML hinzu.Das XAML schließt eine TextBox zur Angabe eines Benutzernamens, eine PasswordBox zur Angabe eines Kennworts, eine Button zur Übermittlung der Anmeldeanforderung und einen TextBlock sowie eine HyperlinkButton für die Abmeldung ein. Diese Elemente werden erst nach der Anmeldung des Benutzers angezeigt.
<TextBlock x:Name="WelcomeText" Style="{StaticResource ContentTextStyle}" Visibility="Collapsed"></TextBlock> <HyperlinkButton x:Name="LogoutButton" Content="Logout" Click="LogoutButton_Click" Visibility="Collapsed"> </HyperlinkButton> <Border x:Name="LoginBorder" Margin="10,10,0,0" BorderThickness="2" BorderBrush="Black" HorizontalAlignment="Left" CornerRadius="15" Padding="10" Background="BlanchedAlmond" Width="300"> <Grid HorizontalAlignment="Left"> <Grid.RowDefinitions> <RowDefinition></RowDefinition> <RowDefinition Height="30" ></RowDefinition> <RowDefinition Height="30"></RowDefinition> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition></ColumnDefinition> <ColumnDefinition></ColumnDefinition> </Grid.ColumnDefinitions> <TextBlock Grid.Row="0" Grid.ColumnSpan="2" Grid.Column="0" FontWeight="Bold" HorizontalAlignment="Left" VerticalAlignment="Center" Text="Log In Existing User"> </TextBlock> <TextBlock Grid.Row="1" Grid.Column="0" HorizontalAlignment="Right" VerticalAlignment="Center" Text="User Name: "> </TextBlock> <TextBox x:Name="UserName" VerticalAlignment="Center" Grid.Row="1" Grid.Column="1" Width="100"> </TextBox> <TextBlock Grid.Row="2" HorizontalAlignment="Right" Grid.Column="0" VerticalAlignment="Center" Text="Password: "> </TextBlock> <PasswordBox x:Name="Password" VerticalAlignment="Center" Grid.Row="2" Grid.Column="1" Width="100"> </PasswordBox> <TextBlock x:Name="LoginResult" TextWrapping="Wrap" Visibility="Collapsed" Grid.Row="3" Grid.ColumnSpan="2" Foreground="Red"> </TextBlock> <Button x:Name="LoginButton" Margin="0,5,0,0" Grid.Row="4" Grid.Column="1" Content="Log In" Click="LoginButton_Click"> </Button> </Grid> </Border>
Öffnen Sie die CodeBehind-Datei für die Startseite (Home.xaml.cs oder Home.xaml.vb).
Fügen Sie dem System.ServiceModel.DomainServices.Client.ApplicationServices-Namespace eine using- oder eine Imports-Anweisung hinzu.
Fügen Sie der Home-Klasse den folgenden Code hinzu.
Der Code schließt Ereignishandler zur An- und Abmeldung, Rückrufmethoden für abgeschlossene Anmelde- und Abmeldevorgänge sowie eine Methode ein, mit denen die Sichtbarkeit von Steuerelementen festgelegt wird. Dies beruht darauf, ob der Benutzer authentifiziert ist.
Protected Overrides Sub OnNavigatedTo(ByVal e As System.Windows.Navigation.NavigationEventArgs) SetControlVisibility(WebContext.Current.User.IsAuthenticated) End Sub Private Sub LoginButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) Dim lp As LoginParameters = New LoginParameters(UserName.Text, Password.Password) WebContext.Current.Authentication.Login(lp, AddressOf Me.LoginOperation_Completed, Nothing) LoginButton.IsEnabled = False LoginResult.Text = "" End Sub Private Sub LoginOperation_Completed(ByVal lo As LoginOperation) If (lo.HasError) Then LoginResult.Text = lo.Error.Message LoginResult.Visibility = System.Windows.Visibility.Visible lo.MarkErrorAsHandled() ElseIf (lo.LoginSuccess = False) Then LoginResult.Text = "Login failed. Please check user name and password." LoginResult.Visibility = System.Windows.Visibility.Visible ElseIf (lo.LoginSuccess = True) Then SetControlVisibility(True) End If LoginButton.IsEnabled = True End Sub Private Sub SetControlVisibility(ByVal isAuthenticated As Boolean) If (isAuthenticated) Then LoginBorder.Visibility = System.Windows.Visibility.Collapsed WelcomeText.Text = "Welcome " + WebContext.Current.User.Name WelcomeText.Visibility = System.Windows.Visibility.Visible LogoutButton.Visibility = System.Windows.Visibility.Visible Else LoginBorder.Visibility = System.Windows.Visibility.Visible WelcomeText.Visibility = System.Windows.Visibility.Collapsed LogoutButton.Visibility = System.Windows.Visibility.Collapsed End If End Sub Private Sub LogoutButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) WebContext.Current.Authentication.Logout(AddressOf Me.LogoutOperation_Completed, Nothing) End Sub Private Sub LogoutOperation_Completed(ByVal lo As LogoutOperation) If (Not (lo.HasError)) Then SetControlVisibility(False) Else Dim ew As ErrorWindow = New ErrorWindow("Logout failed.", "Please try logging out again.") ew.Show() lo.MarkErrorAsHandled() End If End Sub
protected override void OnNavigatedTo(NavigationEventArgs e) { SetControlVisibility(WebContext.Current.User.IsAuthenticated); } private void LoginButton_Click(object sender, RoutedEventArgs e) { LoginParameters lp = new LoginParameters(UserName.Text, Password.Password); WebContext.Current.Authentication.Login(lp, this.LoginOperation_Completed, null); LoginButton.IsEnabled = false; LoginResult.Text = ""; } private void LoginOperation_Completed(LoginOperation lo) { if (lo.HasError) { LoginResult.Text = lo.Error.Message; LoginResult.Visibility = System.Windows.Visibility.Visible; lo.MarkErrorAsHandled(); } else if (lo.LoginSuccess == false) { LoginResult.Text = "Login failed. Please check user name and password."; LoginResult.Visibility = System.Windows.Visibility.Visible; } else if (lo.LoginSuccess == true) { SetControlVisibility(true); } LoginButton.IsEnabled = true; } private void SetControlVisibility(bool isAuthenticated) { if (isAuthenticated) { LoginBorder.Visibility = System.Windows.Visibility.Collapsed; WelcomeText.Text = "Welcome " + WebContext.Current.User.Name; WelcomeText.Visibility = System.Windows.Visibility.Visible; LogoutButton.Visibility = System.Windows.Visibility.Visible; } else { LoginBorder.Visibility = System.Windows.Visibility.Visible; WelcomeText.Visibility = System.Windows.Visibility.Collapsed; LogoutButton.Visibility = System.Windows.Visibility.Collapsed; } } private void LogoutButton_Click(object sender, RoutedEventArgs e) { WebContext.Current.Authentication.Logout(this.LogoutOperation_Completed, null); } private void LogoutOperation_Completed(LogoutOperation lo) { if (!lo.HasError) { SetControlVisibility(false); } else { ErrorWindow ew = new ErrorWindow("Logout failed.", "Please try logging out again."); ew.Show(); lo.MarkErrorAsHandled(); } }
Führen Sie die Projektmappe aus.
Melden Sie sich als CustomerManager mit P@ssword für das Kennwort an.
Der Anmeldebereich wird nicht mehr angezeigt, doch der Begrüßungstext und der Abmeldelink werden jetzt eingeblendet.
Klicken Sie auf Link Abmelden, und schließen Sie den Webbrowser.
Hinzufügen von neuen Benutzern aus dem Client
Der Authentifizierungsdienst enthält keinen Vorgang für die Erstellung neuer Benutzer. Um einen neuen Benutzer zu registrieren, erstellen Sie einen leeren Domänendienst und fügen zum Hinzufügen eines Benutzers zum ASP.NET-Mitgliedschaftsframework einen Vorgang hinzu.
So konfigurieren Sie das Serverprojekt zum Hinzufügen eines neuen Benutzers
Fügen Sie im Serverprojekt eine neue Klassendatei mit dem Namen NewUser hinzu.
Definieren Sie die Eigenschaften zum Registrieren eines neuen Benutzers durch das Hinzufügen des folgenden Codes zur NewUser-Klasse.
Imports System.ComponentModel.DataAnnotations Public Class NewUser <Key()> _ <Required()> _ <RegularExpression("^[a-zA-Z0-9_]*$", ErrorMessage:="Invalid user name. It must contain only alphanumeric characters")> _ Public Property UserName As String <Key()> _ <Required()> _ <RegularExpression("^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$", ErrorMessage:="Invalid email. An email must use the format username@mycompany.com")> _ Public Property Email As String <Required()> _ <RegularExpression("^.*[^a-zA-Z0-9].*$", ErrorMessage:="A password needs to contain at least one special character e.g. @ or #")> _ <StringLength(50, MinimumLength:=7, ErrorMessage:="Invalid password. It must be contain at least 7 characters and no more than 50 characters.")> _ Public Property Password As String <Required()> _ <CustomValidation(GetType(RegistrationValidator), "IsPasswordConfirmed")> _ Public Property ConfirmPassword As String <Range(1, 20)> _ Public Property RecordsToShow As Integer <Required()> _ Public Property SecurityQuestion As String <Required()> _ Public Property SecurityAnswer As String End Class
using System; using System.ComponentModel.DataAnnotations; namespace ExampleNavigationApplication.Web { public class NewUser { [Key] [Required()] [RegularExpression("^[a-zA-Z0-9_]*$", ErrorMessage="Invalid user name. It must contain only alphanumeric characters")] public string UserName { get; set; } [Key] [Required()] [RegularExpression(@"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$", ErrorMessage="Invalid email. An email must use the format username@mycompany.com")] public string Email { get; set; } [Required()] [RegularExpression("^.*[^a-zA-Z0-9].*$", ErrorMessage="A password needs to contain at least one special character e.g. @ or #")] [StringLength(50, MinimumLength = 7, ErrorMessage="Invalid password. It must be contain at least 7 characters and no more than 50 characters.")] public string Password { get; set; } [Required()] [CustomValidation(typeof(RegistrationValidator), "IsPasswordConfirmed")] public string ConfirmPassword { get; set; } [Range(1, 20)] public int RecordsToShow { get; set; } [Required()] public string SecurityQuestion { get; set; } [Required()] public string SecurityAnswer { get; set; } } }
Die ConfirmPassword-Eigenschaft im vorherigen Schritt wird mit einem CustomValidationAttribute-Attribut definiert. Im Attribut wird eine RegistrationValidator-Klasse und eine Methode mit dem Namen "IsPasswordConfirmed" angegeben. Sie müssen nun diese benutzerdefinierte Validierungsklasse definieren.
Fügen Sie eine neue Klasse mit dem Namen "RegistrationValidator.shared.cs" oder "RegistrationValidator.shared.vb" hinzu.
Fügen Sie den folgenden Code der Datei RegistrationValidator.shared hinzu.
Imports System.ComponentModel.DataAnnotations Public Class RegistrationValidator Public Shared Function IsPasswordConfirmed(ByVal confirmPassword As String, ByVal context As ValidationContext) As ValidationResult Dim data As Web.NewUser = CType(context.ObjectInstance, Web.NewUser) If (data.Password = confirmPassword) Then Return ValidationResult.Success Else Return New ValidationResult("Please confirm your password by providing it again.") End If End Function End Class
using System.ComponentModel.DataAnnotations; namespace ExampleNavigationApplication.Web { public class RegistrationValidator { public static ValidationResult IsPasswordConfirmed(string confirmPassword, ValidationContext context) { NewUser data = (NewUser)context.ObjectInstance; if (data.Password == confirmPassword) { return ValidationResult.Success; } else { return new ValidationResult("Please confirm your password by providing it again."); } } } }
Fügen Sie dem Serverprojekt ein neues Element hinzu, und wählen Sie die Vorlage "Domänendienstklasse" aus.
Nennen Sie die Datei "RegistrationDomainService.cs" oder "RegistrationDomainService.vb", und klicken Sie dann auf die Schaltfläche Hinzufügen.
Wählen Sie im Dialogfeld "Neue Domänendienstklasse hinzufügen" <leere Domänendienstklasse> aus der Liste Verfügbare DataContext-/ObjectContext-Klassen aus.
Klicken Sie auf OK.
Um einen Domänenvorgang zu erstellen, bei dem durch das Mitgliedschaftsframework ein neuer Benutzer hinzugefügt und eine Profileigenschaft gespeichert wird, fügen Sie der RegistrationDomainService-Klasse den folgenden Code hinzu.
Die GetUsers-Methode muss eingeschlossen werden, um sicherzustellen, dass die NewUser-Entitätsklasse für das Clientprojekt generiert wird. Nur Klassen, die durch einen öffentlichen Abfragevorgang verfügbar gemacht werden, werden im Clientprojekt generiert.
Nach dem Erstellen des Benutzers wird die Profileigenschaft mit der Bezeichnung "DefaultRows" festgelegt. In diesem Fall wird die Profileigenschaft als Teil des Domänenvorgangs zum Erstellen eines Benutzers festgelegt. In einem späteren Abschnitt fügen Sie Code hinzu, um die Profileigenschaft vom Clientprojekt aus festzulegen.
Option Compare Binary Option Infer On Option Strict On Option Explicit On Imports System Imports System.Collections.Generic Imports System.ComponentModel Imports System.ComponentModel.DataAnnotations Imports System.Linq Imports System.ServiceModel.DomainServices.Hosting Imports System.ServiceModel.DomainServices.Server Imports System.Web.Profile <EnableClientAccess()> _ Public Class RegistrationDomainService Inherits DomainService Public Sub AddUser(ByVal user As NewUser) Dim createStatus As MembershipCreateStatus Membership.CreateUser(user.UserName, user.Password, user.Email, user.SecurityQuestion, user.SecurityAnswer, True, Nothing, createStatus) If (createStatus <> MembershipCreateStatus.Success) Then Throw New DomainException(createStatus.ToString()) End If Dim profile = ProfileBase.Create(user.UserName, True) profile.SetPropertyValue("DefaultRows", user.RecordsToShow) profile.Save() End Sub Public Function GetUsers() As IEnumerable(Of NewUser) Throw New NotSupportedException() End Function End Class
namespace ExampleNavigationApplication.Web { using System; using System.Collections.Generic; using System.ServiceModel.DomainServices.Hosting; using System.ServiceModel.DomainServices.Server; using System.Web.Security; using System.Web.Profile; [EnableClientAccess()] public class RegistrationDomainService : DomainService { public void AddUser(NewUser user) { MembershipCreateStatus createStatus; Membership.CreateUser(user.UserName, user.Password, user.Email, user.SecurityQuestion, user.SecurityAnswer, true, null, out createStatus); if (createStatus != MembershipCreateStatus.Success) { throw new DomainException(createStatus.ToString()); } ProfileBase profile = ProfileBase.Create(user.UserName, true); profile.SetPropertyValue("DefaultRows", user.RecordsToShow); profile.Save(); } public IEnumerable<NewUser> GetUsers() { throw new NotSupportedException(); } } }
So konfigurieren Sie das Clientprojekt für das Hinzufügen von neuen Benutzern
Öffnen Sie die Datei "Home.xaml".
Nach dem Endtag für das
LoginBorder
Border-Steuerelement fügen Sie das folgende XAML hinzu, um ein zweites Border-Steuerelement mit Eingabesteuerelementen zu erstellen, mit denen Informationen für die Erstellung von neuen Benutzern gesammelt werden.Die Steuerelemente akzeptieren Werte für Benutzername, Kennwort, Kennwortbestätigung, E-Mail-Adresse, Sicherheitsfrage, Sicherheitsantwort und die Anzahl von Datensätzen, die in Berichten angezeigt werden soll. Die Anzahl von Datensätzen, die angezeigt werden soll, wird als Profileigenschaft gespeichert. Alle anderen Werte dienen zur Erstellung des Benutzers über das ASP.NET-Mitgliedschaftsframework.
<Border x:Name="RegisterBorder" Margin="10,10,0,0" BorderThickness="2" BorderBrush="Black" HorizontalAlignment="Left" CornerRadius="15" Padding="10" Background="BurlyWood" Width="400"> <Grid HorizontalAlignment="Left"> <Grid.RowDefinitions> <RowDefinition></RowDefinition> <RowDefinition Height="30" ></RowDefinition> <RowDefinition Height="30"></RowDefinition> <RowDefinition Height="30"></RowDefinition> <RowDefinition Height="30"></RowDefinition> <RowDefinition Height="30"></RowDefinition> <RowDefinition Height="30"></RowDefinition> <RowDefinition Height="30"></RowDefinition> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition></ColumnDefinition> <ColumnDefinition></ColumnDefinition> </Grid.ColumnDefinitions> <TextBlock Grid.Row="0" Grid.ColumnSpan="2" Grid.Column="0" FontWeight="Bold" HorizontalAlignment="Left" VerticalAlignment="Center" Text="Register New User"> </TextBlock> <TextBlock Grid.Row="1" Grid.Column="0" HorizontalAlignment="Right" VerticalAlignment="Center" Text="User Name: "> </TextBlock> <TextBox x:Name="NewUsername" VerticalAlignment="Center" HorizontalAlignment="Left" Grid.Row="1" Grid.Column="1" Width="100"> </TextBox> <TextBlock Grid.Row="2" HorizontalAlignment="Right" Grid.Column="0" VerticalAlignment="Center" Text="Password: "> </TextBlock> <PasswordBox x:Name="NewPassword" VerticalAlignment="Center" HorizontalAlignment="Left" Grid.Row="2" Grid.Column="1" Width="100"> </PasswordBox> <TextBlock Grid.Row="3" HorizontalAlignment="Right" Grid.Column="0" VerticalAlignment="Center" Text="Confirm Password: "> </TextBlock> <PasswordBox x:Name="NewConfirmPassword" HorizontalAlignment="Left" VerticalAlignment="Center" Grid.Row="3" Grid.Column="1" Width="100"> </PasswordBox> <TextBlock Grid.Row="4" HorizontalAlignment="Right" Grid.Column="0" VerticalAlignment="Center" Text="Email: "> </TextBlock> <TextBox x:Name="NewEmail" VerticalAlignment="Center" Grid.Row="4" Grid.Column="1" Width="200"> </TextBox> <TextBlock Grid.Row="5" HorizontalAlignment="Right" Grid.Column="0" VerticalAlignment="Center" Text="Records to show: "> </TextBlock> <ComboBox Grid.Row="5" Grid.Column="1" x:Name="DefaultRows" HorizontalAlignment="Left" Width="50" Height="20" VerticalAlignment="Center"> <ComboBoxItem Content="1"></ComboBoxItem> <ComboBoxItem Content="3"></ComboBoxItem> <ComboBoxItem Content="5"></ComboBoxItem> <ComboBoxItem Content="10" IsSelected="True"></ComboBoxItem> <ComboBoxItem Content="15"></ComboBoxItem> <ComboBoxItem Content="20"></ComboBoxItem> </ComboBox> <TextBlock Grid.Row="6" HorizontalAlignment="Right" Grid.Column="0" VerticalAlignment="Center" Text="Security Question: "> </TextBlock> <TextBox x:Name="SecurityQuestion" VerticalAlignment="Center" Grid.Row="6" Grid.Column="1" Width="200"> </TextBox> <TextBlock Grid.Row="7" HorizontalAlignment="Right" Grid.Column="0" VerticalAlignment="Center" Text="Security Answer: "> </TextBlock> <TextBox x:Name="SecurityAnswer" VerticalAlignment="Center" Grid.Row="7" Grid.Column="1" Width="200"> </TextBox> <TextBlock x:Name="registerResult" TextWrapping="Wrap" Visibility="Collapsed" Grid.Row="8" Grid.ColumnSpan="2" Foreground="Red"> </TextBlock> <Button x:Name="RegisterButton" Click="RegisterButton_Click" Margin="0,5,0,0" Grid.Row="9" Grid.Column="1" Content="Register" > </Button> </Grid> </Border>
Öffnen Sie die CodeBehind-Datei "Home.xaml.cs" (oder "Home.xaml.vb").
Fügen Sie dem System.ServiceModel.DomainServices.Client-, System.ComponentModel.DataAnnotations- und dem ExampleNavigationApplication.Web-Namespace eine using- oder eine Imports-Anweisung hinzu.
Fügen Sie einen Ereignishandler für das Registerschaltflächen-Klickereignis hinzu, und fügen Sie eine Rückrufmethode für den Domänenvorgang hinzu. Die Rückrufmethode beinhaltet Code für die Anmeldung des Benutzers nach erfolgreicher Erstellung des Benutzerkontos.
Private Sub RegisterButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) RegisterButton.IsEnabled = False Dim context = New RegistrationDomainContext() Dim nu = New NewUser() Try nu.UserName = NewUsername.Text nu.Password = NewPassword.Password nu.Email = NewEmail.Text nu.ConfirmPassword = NewConfirmPassword.Password nu.RecordsToShow = Integer.Parse(DefaultRows.SelectionBoxItem.ToString()) nu.SecurityQuestion = SecurityQuestion.Text nu.SecurityAnswer = SecurityAnswer.Text context.NewUsers.Add(nu) context.SubmitChanges(AddressOf RegisterUser_Completed, Nothing) Catch ve As ValidationException registerResult.Visibility = System.Windows.Visibility.Visible registerResult.Text = ve.Message RegisterButton.IsEnabled = True End Try End Sub Private Sub RegisterUser_Completed(ByVal so As SubmitOperation) If (so.HasError) Then Dim ew = New ErrorWindow("Registration failed.", "Please try registering again.") ew.Show() so.MarkErrorAsHandled() Else Dim lp = New LoginParameters(NewUsername.Text, NewPassword.Password) WebContext.Current.Authentication.Login(lp, AddressOf Me.LoginOperation_Completed, Nothing) NewUsername.Text = "" NewPassword.Password = "" NewConfirmPassword.Password = "" NewEmail.Text = "" DefaultRows.SelectedIndex = 0 SecurityQuestion.Text = "" SecurityAnswer.Text = "" End If RegisterButton.IsEnabled = True End Sub
private void RegisterButton_Click(object sender, RoutedEventArgs e) { RegisterButton.IsEnabled = false; RegistrationDomainContext context = new RegistrationDomainContext(); NewUser nu = new NewUser(); try { nu.UserName = NewUsername.Text; nu.Password = NewPassword.Password; nu.Email = NewEmail.Text; nu.ConfirmPassword = NewConfirmPassword.Password; nu.RecordsToShow = int.Parse(DefaultRows.SelectionBoxItem.ToString()); nu.SecurityQuestion = SecurityQuestion.Text; nu.SecurityAnswer = SecurityAnswer.Text; context.NewUsers.Add(nu); context.SubmitChanges(RegisterUser_Completed, null); } catch (ValidationException ve) { registerResult.Visibility = System.Windows.Visibility.Visible; registerResult.Text = ve.Message; RegisterButton.IsEnabled = true; } } private void RegisterUser_Completed(SubmitOperation so) { if (so.HasError) { ErrorWindow ew = new ErrorWindow("Registration failed.", "Please try registering again."); ew.Show(); so.MarkErrorAsHandled(); } else { LoginParameters lp = new LoginParameters(NewUsername.Text, NewPassword.Password); WebContext.Current.Authentication.Login(lp, this.LoginOperation_Completed, null); NewUsername.Text = ""; NewPassword.Password = ""; NewConfirmPassword.Password = ""; NewEmail.Text = ""; DefaultRows.SelectedIndex = 0; SecurityQuestion.Text = ""; SecurityAnswer.Text = ""; } RegisterButton.IsEnabled = true; }
Ändern Sie die SetControlVisibility-Methode, um die Sichtbarkeit von RegisterBorder festzulegen, wie im folgenden Code gezeigt.
Private Sub SetControlVisibility(ByVal isAuthenticated As Boolean) If (isAuthenticated) Then LoginBorder.Visibility = System.Windows.Visibility.Collapsed RegisterBorder.Visibility = Windows.Visibility.Collapsed WelcomeText.Text = "Welcome " + WebContext.Current.User.Name WelcomeText.Visibility = System.Windows.Visibility.Visible LogoutButton.Visibility = System.Windows.Visibility.Visible Else LoginBorder.Visibility = System.Windows.Visibility.Visible RegisterBorder.Visibility = Windows.Visibility.Visible WelcomeText.Visibility = System.Windows.Visibility.Collapsed LogoutButton.Visibility = System.Windows.Visibility.Collapsed End If End Sub
private void SetControlVisibility(bool isAuthenticated) { if (isAuthenticated) { LoginBorder.Visibility = System.Windows.Visibility.Collapsed; RegisterBorder.Visibility = System.Windows.Visibility.Collapsed; WelcomeText.Text = "Welcome " + WebContext.Current.User.Name; WelcomeText.Visibility = System.Windows.Visibility.Visible; LogoutButton.Visibility = System.Windows.Visibility.Visible; } else { LoginBorder.Visibility = System.Windows.Visibility.Visible; RegisterBorder.Visibility = System.Windows.Visibility.Visible; WelcomeText.Visibility = System.Windows.Visibility.Collapsed; LogoutButton.Visibility = System.Windows.Visibility.Collapsed; } }
Das folgende Beispiel zeigt die vollständige CodeBehind-Datei.
Imports System.ServiceModel.DomainServices.Client.ApplicationServices Imports System.ServiceModel.DomainServices.Client Imports System.ComponentModel.DataAnnotations Partial Public Class Home Inherits Page Public Sub New() InitializeComponent() End Sub Protected Overrides Sub OnNavigatedTo(ByVal e As System.Windows.Navigation.NavigationEventArgs) SetControlVisibility(WebContext.Current.User.IsAuthenticated) End Sub Private Sub LoginButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) Dim lp As LoginParameters = New LoginParameters(UserName.Text, Password.Password) WebContext.Current.Authentication.Login(lp, AddressOf Me.LoginOperation_Completed, Nothing) LoginButton.IsEnabled = False LoginResult.Text = "" End Sub Private Sub LoginOperation_Completed(ByVal lo As LoginOperation) If (lo.HasError) Then LoginResult.Text = lo.Error.Message LoginResult.Visibility = System.Windows.Visibility.Visible lo.MarkErrorAsHandled() ElseIf (lo.LoginSuccess = False) Then LoginResult.Text = "Login failed. Please check user name and password." LoginResult.Visibility = System.Windows.Visibility.Visible ElseIf (lo.LoginSuccess = True) Then SetControlVisibility(True) End If LoginButton.IsEnabled = True End Sub Private Sub SetControlVisibility(ByVal isAuthenticated As Boolean) If (isAuthenticated) Then LoginBorder.Visibility = System.Windows.Visibility.Collapsed RegisterBorder.Visibility = Windows.Visibility.Collapsed WelcomeText.Text = "Welcome " + WebContext.Current.User.Name WelcomeText.Visibility = System.Windows.Visibility.Visible LogoutButton.Visibility = System.Windows.Visibility.Visible Else LoginBorder.Visibility = System.Windows.Visibility.Visible RegisterBorder.Visibility = Windows.Visibility.Visible WelcomeText.Visibility = System.Windows.Visibility.Collapsed LogoutButton.Visibility = System.Windows.Visibility.Collapsed End If End Sub Private Sub LogoutButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) WebContext.Current.Authentication.Logout(AddressOf Me.LogoutOperation_Completed, Nothing) End Sub Private Sub LogoutOperation_Completed(ByVal lo As LogoutOperation) If (Not (lo.HasError)) Then SetControlVisibility(False) Else Dim ew As ErrorWindow = New ErrorWindow("Logout failed.", "Please try logging out again.") ew.Show() lo.MarkErrorAsHandled() End If End Sub Private Sub RegisterButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) RegisterButton.IsEnabled = False Dim context = New RegistrationDomainContext() Dim nu = New NewUser() Try nu.UserName = NewUsername.Text nu.Password = NewPassword.Password nu.Email = NewEmail.Text nu.ConfirmPassword = NewConfirmPassword.Password nu.RecordsToShow = Integer.Parse(DefaultRows.SelectionBoxItem.ToString()) nu.SecurityQuestion = SecurityQuestion.Text nu.SecurityAnswer = SecurityAnswer.Text context.NewUsers.Add(nu) context.SubmitChanges(AddressOf RegisterUser_Completed, Nothing) Catch ve As ValidationException registerResult.Visibility = System.Windows.Visibility.Visible registerResult.Text = ve.Message RegisterButton.IsEnabled = True End Try End Sub Private Sub RegisterUser_Completed(ByVal so As SubmitOperation) If (so.HasError) Then Dim ew = New ErrorWindow("Registration failed.", "Please try registering again.") ew.Show() so.MarkErrorAsHandled() Else Dim lp = New LoginParameters(NewUsername.Text, NewPassword.Password) WebContext.Current.Authentication.Login(lp, AddressOf Me.LoginOperation_Completed, Nothing) NewUsername.Text = "" NewPassword.Password = "" NewConfirmPassword.Password = "" NewEmail.Text = "" DefaultRows.SelectedIndex = 0 SecurityQuestion.Text = "" SecurityAnswer.Text = "" End If RegisterButton.IsEnabled = True End Sub End Class
using System; using System.Windows; using System.Windows.Controls; using System.Windows.Navigation; using System.ServiceModel.DomainServices.Client.ApplicationServices; using System.ServiceModel.DomainServices.Client; using System.ComponentModel.DataAnnotations; using ExampleNavigationApplication.Web; namespace ExampleNavigationApplication { public partial class Home : Page { public Home() { InitializeComponent(); } // Executes when the user navigates to this page. protected override void OnNavigatedTo(NavigationEventArgs e) { SetControlVisibility(WebContext.Current.User.IsAuthenticated); } private void LoginButton_Click(object sender, RoutedEventArgs e) { LoginParameters lp = new LoginParameters(UserName.Text, Password.Password); WebContext.Current.Authentication.Login(lp, this.LoginOperation_Completed, null); LoginButton.IsEnabled = false; LoginResult.Text = ""; } private void LoginOperation_Completed(LoginOperation lo) { if (lo.HasError) { LoginResult.Text = lo.Error.Message; LoginResult.Visibility = System.Windows.Visibility.Visible; lo.MarkErrorAsHandled(); } else if (lo.LoginSuccess == false) { LoginResult.Text = "Login failed. Please check user name and password."; LoginResult.Visibility = System.Windows.Visibility.Visible; } else if (lo.LoginSuccess == true) { SetControlVisibility(true); } LoginButton.IsEnabled = true; } private void SetControlVisibility(bool isAuthenticated) { if (isAuthenticated) { LoginBorder.Visibility = System.Windows.Visibility.Collapsed; RegisterBorder.Visibility = System.Windows.Visibility.Collapsed; WelcomeText.Text = "Welcome " + WebContext.Current.User.Name; WelcomeText.Visibility = System.Windows.Visibility.Visible; LogoutButton.Visibility = System.Windows.Visibility.Visible; } else { LoginBorder.Visibility = System.Windows.Visibility.Visible; RegisterBorder.Visibility = System.Windows.Visibility.Visible; WelcomeText.Visibility = System.Windows.Visibility.Collapsed; LogoutButton.Visibility = System.Windows.Visibility.Collapsed; } } private void LogoutButton_Click(object sender, RoutedEventArgs e) { WebContext.Current.Authentication.Logout(this.LogoutOperation_Completed, null); } private void LogoutOperation_Completed(LogoutOperation lo) { if (!lo.HasError) { SetControlVisibility(false); } else { ErrorWindow ew = new ErrorWindow("Logout failed.", "Please try logging out again."); ew.Show(); lo.MarkErrorAsHandled(); } } private void RegisterButton_Click(object sender, RoutedEventArgs e) { RegisterButton.IsEnabled = false; RegistrationDomainContext context = new RegistrationDomainContext(); NewUser nu = new NewUser(); try { nu.UserName = NewUsername.Text; nu.Password = NewPassword.Password; nu.Email = NewEmail.Text; nu.ConfirmPassword = NewConfirmPassword.Password; nu.RecordsToShow = int.Parse(DefaultRows.SelectionBoxItem.ToString()); nu.SecurityQuestion = SecurityQuestion.Text; nu.SecurityAnswer = SecurityAnswer.Text; context.NewUsers.Add(nu); context.SubmitChanges(RegisterUser_Completed, null); } catch (ValidationException ve) { registerResult.Visibility = System.Windows.Visibility.Visible; registerResult.Text = ve.Message; RegisterButton.IsEnabled = true; } } private void RegisterUser_Completed(SubmitOperation so) { if (so.HasError) { ErrorWindow ew = new ErrorWindow("Registration failed.", "Please try registering again."); ew.Show(); so.MarkErrorAsHandled(); } else { LoginParameters lp = new LoginParameters(NewUsername.Text, NewPassword.Password); WebContext.Current.Authentication.Login(lp, this.LoginOperation_Completed, null); NewUsername.Text = ""; NewPassword.Password = ""; NewConfirmPassword.Password = ""; NewEmail.Text = ""; DefaultRows.SelectedIndex = 0; SecurityQuestion.Text = ""; SecurityAnswer.Text = ""; } RegisterButton.IsEnabled = true; } } }
Führen Sie die Projektmappe aus.
Geben Sie Werte an, um einen neuen Benutzer zu registrieren.
Schließen Sie den Webbrowser.
Einschränken des Zugriffs auf Domänenvorgänge
Zum Einschränken des Zugriffs auf einen Domänenvorgang wird das RequiresAuthenticationAttribute-Attribut oder das RequiresRoleAttribute-Attribut auf den Domänenvorgang angewendet. Domänenvorgänge ohne Attribut sind für alle Benutzer verfügbar. Durch das Anwenden eines Attributs auf einen Domänenvorgang wird nicht verhindert, dass der Benutzer den Domänenvorgang aufruft. Bei Benutzern ohne die erforderlichen Anmeldeinformationen führt der Aufruf jedoch zu einem Ausnahmefehler.
So schränken Sie die angezeigten Daten nach Rollen ein
Wählen Sie im Projektmappen-Explorer das Serverprojekt aus, und klicken Sie auf die Schaltfläche Alle Dateien anzeigen.
Klicken Sie mit der rechten Maustaste auf den Ordner "App_Data", und wählen Sie Zu Projekt hinzufügen aus.
Klicken Sie mit der rechten Maustaste auf den Ordner "App_Data", wählen Sie Hinzufügen und dann Vorhandenes Element aus.
Fügen Sie im Dialogfeld Vorhandenes Element hinzufügen die AdventureWorksLT-Beispieldatenbank hinzu.
Fügen Sie im Serverprojekt ein neues Element hinzu, und wählen Sie die Vorlage ADO.NET Entity Data Model aus.
Geben Sie für das Modell den Namen "AdventureWorksModel.edmx" ein, und klicken Sie auf Hinzufügen.
Der Assistent für Entity Data Model wird angezeigt.
Wählen Sie die Option Aus Datenbank generieren aus, und klicken Sie dann auf Weiter.
Wählen Sie die AdventureWorksLT-Datenbank aus, und klicken Sie anschließend auf Weiter.
Wählen Sie in der Liste der Datenbankobjekte die Tabellen "Customer", "Product" und "SalesOrderHeader" aus, und klicken Sie dann auf Fertig stellen.
Das Entity Data Model wird im Designer angezeigt.
Erstellen Sie die Projektmappe.
Fügen Sie im Serverprojekt ein neues Element hinzu, und wählen Sie die Vorlage Domänendienstklasse aus.
Geben Sie für den Domänendienst den Namen "AdventureWorksDomainService" ein, und klicken Sie dann auf Hinzufügen.
Wählen Sie im Dialogfeld Neue Domänendienstklasse hinzufügen die Entitäten "Customer", "Product" und "SalesOrderHeader" aus.
Klicken Sie auf OK, um den Domänendienst zu erstellen.
Fügen Sie in der AdventureWorksDomainService-Klassendatei der
GetSalesOrderHeader
-Methode das RequiresAuthenticationAttribute-Attribut hinzu.<RequiresAuthentication()> _ Public Function GetSalesOrderHeaders() As IQueryable(Of SalesOrderHeader) Return Me.ObjectContext.SalesOrderHeaders End Function
[RequiresAuthentication()] public IQueryable<SalesOrderHeader> GetSalesOrderHeaders() { return this.ObjectContext.SalesOrderHeaders; }
Fügen Sie der
GetCustomers
-Methode das RequiresRoleAttribute-Attribut hinzu, und legen Sie den Namen der erforderlichen Rolle auf "Managers" fest.<RequiresRole("Managers")> _ Public Function GetCustomers() As IQueryable(Of Customer) Return Me.ObjectContext.Customers End Function
[RequiresRole("Managers")] public IQueryable<Customer> GetCustomers() { return this.ObjectContext.Customers; }
Der
GetProducts
-Domänenvorgang steht allen Benutzern zur Verfügung,GetSalesOrderHeaders
ist für authentifizierte Benutzer verfügbar undGetCustomers
nur für Benutzer in der Rolle "Managers".Das folgende Beispiel zeigt den vollständigen Domänendienst.
<EnableClientAccess()> _ Public Class AdventureWorksDomainService Inherits LinqToEntitiesDomainService(Of AdventureWorksLT_DataEntities) <RequiresRole("Managers")> _ Public Function GetCustomers() As IQueryable(Of Customer) Return Me.ObjectContext.Customers End Function Public Function GetProducts() As IQueryable(Of Product) Return Me.ObjectContext.Products End Function <RequiresAuthentication()> _ Public Function GetSalesOrderHeaders() As IQueryable(Of SalesOrderHeader) Return Me.ObjectContext.SalesOrderHeaders End Function End Class
[EnableClientAccess()] public class AdventureWorksDomainService : LinqToEntitiesDomainService<AdventureWorksLT_DataEntities> { [RequiresRole("Managers")] public IQueryable<Customer> GetCustomers() { return this.ObjectContext.Customers; } public IQueryable<Product> GetProducts() { return this.ObjectContext.Products; } [RequiresAuthentication()] public IQueryable<SalesOrderHeader> GetSalesOrderHeaders() { return this.ObjectContext.SalesOrderHeaders; } }
Verwenden des Authentifizierungsdiensts im Client
Bevor Sie einen Domänenvorgang mit eingeschränkten Berechtigungen aufrufen, sollten Sie sicherstellen, dass der Benutzer über die erforderlichen Anmeldeinformationen verfügt. Andernfalls wird ein Ausnahmefehler ausgelöst. In diesem Abschnitt überprüfen Sie die Anmeldeinformationen des Benutzers, und Sie füllen drei DataGrid-Steuerelemente anhand der Anmeldeinformationen des Benutzers auf. Zudem rufen Sie die Anzahl von Datensätzen basierend auf einer Eigenschaft im Benutzerprofil ab. Für nicht authentifizierte Benutzer wird der Standardwert 10 verwendet. Dieser Abschnitt enthält keine Methode, mit der Benutzer die DefaultRows-Profileigenschaft festlegen können. Eine solche Eigenschaft wird jedoch in einem späteren Abschnitt hinzugefügt.
So fügen Sie eine Silverlight-Seite zum Anzeigen von Daten hinzu
Fügen Sie im Clientprojekt dem Ordner "Views" ein neues Element hinzu.
Wählen Sie die Vorlage Silverlight-Seite aus, und geben Sie für die neue Seite den Namen "Reports.xaml" ein.
Öffnen Sie die Datei "MainPage.xaml", und fügen Sie einen Link für die Seite "Reports" hinzu, indem Sie nach dem HyperlinkButton mit dem Namen
Link2
für die Infoseite (About) den folgenden XAML-Code hinzufügen.<Rectangle x:Name="Divider2" Style="{StaticResource DividerStyle}"/> <HyperlinkButton x:Name="Link3" Style="{StaticResource LinkStyle}" NavigateUri="/Reports" TargetName="ContentFrame" Content="reports"/>
Öffnen Sie die Datei "Reports.xaml", und fügen Sie das folgende XAML in den
Grid
-Tags hinzu, damit dieselbe Formatierung wie auf den anderen Seiten der Website verwendet wird. Außerdem wird ein HyperlinkButton-Steuerelement eingeschlossen, das ein Fenster zum Bearbeiten einer Profileigenschaft startet.<ScrollViewer x:Name="PageScrollViewer" Style="{StaticResource PageScrollViewerStyle}"> <StackPanel x:Name="ContentStackPanel"> <TextBlock x:Name="HeaderText" Style="{StaticResource HeaderTextStyle}" Text="Reports"/> <TextBlock x:Name="ContentText" Style="{StaticResource ContentTextStyle}" Text="Display reports based on user permissions"/> <HyperlinkButton x:Name="SettingsButton" Content="Adjust Settings" Click="SettingsButton_Click" Visibility="Collapsed"> </HyperlinkButton> </StackPanel> </ScrollViewer>
Ziehen Sie drei DataGrid-Steuerelemente aus der Toolbox direkt vor das Endtag des Stapelbereichs mit dem Namen
ContentStackPanel
.Wenn Sie die DataGrid-Steuerelemente aus der Toolbox ziehen, wird dem Projekt ein Verweis auf die System.Windows.Controls.Data-Assembly hinzugefügt, und der Seite wird ein Präfix für den System.Windows.Controls-Namespace hinzugefügt.
Nennen Sie die DataGrid-Steuerelemente
ProductsGrid
,SalesOrdersGrid
undCustomersGrid
, und legen SieMargin
auf 5 fest.Das folgende Beispiel zeigt die vollständige Datei "Reports.xaml".
<navigation:Page x:Class="ExampleNavigationApplication.Views.Reports" xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="https://schemas.microsoft.com/expression/blend/2008" xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data" xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation" d:DesignWidth="640" d:DesignHeight="480" Title="Reports Page"> <Grid x:Name="LayoutRoot"> <ScrollViewer x:Name="PageScrollViewer" Style="{StaticResource PageScrollViewerStyle}"> <StackPanel x:Name="ContentStackPanel"> <TextBlock x:Name="HeaderText" Style="{StaticResource HeaderTextStyle}" Text="Reports"/> <TextBlock x:Name="ContentText" Style="{StaticResource ContentTextStyle}" Text="Display reports based on user permissions"/> <HyperlinkButton x:Name="SettingsButton" Content="Adjust Settings" Click="SettingsButton_Click" Visibility="Collapsed"> </HyperlinkButton> <data:DataGrid Name="ProductsGrid" Margin="5" /> <data:DataGrid Name="SalesOrdersGrid" Margin="5" /> <data:DataGrid Name="CustomersGrid" Margin="5" /> </StackPanel> </ScrollViewer> </Grid> </navigation:Page>
Öffnen Sie die Datei "Reports.xaml.cs" oder "Reports.xaml.vb", und fügen Sie die using-Anweisung oder die Imports-Anweisung für den System.ServiceModel.DomainServices.Client-Namespace und den ExampleNavigationApplication.Web-Namespace hinzu.
Erstellen Sie eine Instanz des AdventureWorksDomainContext-Kontexts und eine Variable mit dem Namen "numberOfRows", die die Anzahl abzurufender Zeilen enthält.
Private context As New AdventureWorksDomainContext Private numberOfRows As Integer = 10
private AdventureWorksDomainContext context = new AdventureWorksDomainContext(); int numberOfRows = 10;
Fügen Sie eine Methode mit dem Namen
LoadRestrictedReports
hinzu, durch die dieGetSalesOrderHeaderQuery
- und dieGetCustomersQuery
-Methode aufgerufen und die entsprechenden Datenraster mit den Ergebnissen aufgefüllt werden, wenn der Benutzer der Rolle "Managers" angehört.Wenn Sie einen Domänenvorgang aufrufen und der Benutzer nicht über die erforderlichen Anmeldeinformationen verfügt, gibt der Domänenvorgang eine Ausnahme zurück. Sie können diese Situation vermeiden, indem Sie die Anmeldeinformationen vor dem Aufrufen des Domänenvorgangs überprüfen.
Private Sub LoadRestrictedReports() Dim loadSales = context.Load(context.GetSalesOrderHeadersQuery().Take(numberOfRows)) SalesOrdersGrid.ItemsSource = loadSales.Entities SalesOrdersGrid.Visibility = System.Windows.Visibility.Visible If (WebContext.Current.User.IsInRole("Managers")) Then Dim loadCustomers = context.Load(context.GetCustomersQuery().Take(numberOfRows)) CustomersGrid.ItemsSource = loadCustomers.Entities CustomersGrid.Visibility = System.Windows.Visibility.Visible Else CustomersGrid.Visibility = System.Windows.Visibility.Collapsed End If End Sub
private void LoadRestrictedReports() { LoadOperation<SalesOrderHeader> loadSales = context.Load(context.GetSalesOrderHeadersQuery().Take(numberOfRows)); SalesOrdersGrid.ItemsSource = loadSales.Entities; SalesOrdersGrid.Visibility = System.Windows.Visibility.Visible; if (WebContext.Current.User.IsInRole("Managers")) { LoadOperation<Customer> loadCustomers = context.Load(context.GetCustomersQuery().Take(numberOfRows)); CustomersGrid.ItemsSource = loadCustomers.Entities; CustomersGrid.Visibility = System.Windows.Visibility.Visible; } else { CustomersGrid.Visibility = System.Windows.Visibility.Collapsed; } }
Fügen Sie eine Methode mit dem Namen
LoadReports
hinzu, durch die überprüft wird, ob der Benutzer authentifiziert ist, und ob dieLoadRestrictedReports
-Methode aufgerufen wird, wenn dies der Fall ist. Diese Methode ruft auch dieDefaultRows
-Profileigenschaft ab und fügt dem User-Objekt einen Ereignishandler für das PropertyChanged-Ereignis hinzu. Zum Schluss ruft sie dieGetProductsQuery
-Methode für alle Benutzer auf.Private Sub LoadReports() If (WebContext.Current.User.IsAuthenticated) Then numberOfRows = WebContext.Current.User.DefaultRows AddHandler WebContext.Current.User.PropertyChanged, AddressOf User_PropertyChanged LoadRestrictedReports() Else CustomersGrid.Visibility = System.Windows.Visibility.Collapsed SalesOrdersGrid.Visibility = System.Windows.Visibility.Collapsed End If Dim loadProducts = context.Load(context.GetProductsQuery().Take(numberOfRows)) ProductsGrid.ItemsSource = loadProducts.Entities End Sub
private void LoadReports() { if (WebContext.Current.User.IsAuthenticated) { numberOfRows = WebContext.Current.User.DefaultRows; WebContext.Current.User.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(User_PropertyChanged); LoadRestrictedReports(); } else { CustomersGrid.Visibility = System.Windows.Visibility.Collapsed; SalesOrdersGrid.Visibility = System.Windows.Visibility.Collapsed; } LoadOperation<Product> loadProducts = context.Load(context.GetProductsQuery().Take(numberOfRows)); ProductsGrid.ItemsSource = loadProducts.Entities; }
Fügen Sie einen Ereignishandler für das PropertyChanged-Ereignis hinzu, durch den
LoadReports
aufgerufen wird, wenn sich dieDefaultRows
-Eigenschaft geändert hat.Private Sub User_PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) If (e.PropertyName = "DefaultRows") Then LoadReports() End If End Sub
void User_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { if (e.PropertyName == "DefaultRows") { LoadReports(); } }
Fügen Sie dem Konstruktor den folgenden Code hinzu. Von diesem Code werden die Berichte geladen, und der Link "Einstellungen" wird für authentifizierte Benutzer sichtbar gemacht.
Public Sub New() InitializeComponent() LoadReports() If (WebContext.Current.User.IsAuthenticated) Then SettingsButton.Visibility = System.Windows.Visibility.Visible End If End Sub
public Reports() { InitializeComponent(); LoadReports(); if (WebContext.Current.User.IsAuthenticated) { SettingsButton.Visibility = System.Windows.Visibility.Visible; } }
Fügen Sie für das Klickereignis auf dem Einstellungslink einen Ereignishandler hinzu.
ProfileWindow
wird in einem späteren Schritt hinzugefügt.Private Sub SettingsButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) Dim settingsWindow = New ProfileWindow() settingsWindow.Show() End Sub
private void SettingsButton_Click(object sender, RoutedEventArgs e) { Views.ProfileWindow settingsWindow = new Views.ProfileWindow(); settingsWindow.Show(); }
Das folgende Beispiel zeigt die vollständige Codedatei.
Imports System.ServiceModel.DomainServices.Client Imports ExampleNavigationApplication.Web Partial Public Class Reports Inherits Page Private context As New AdventureWorksDomainContext Private numberOfRows As Integer = 10 Public Sub New() InitializeComponent() LoadReports() If (WebContext.Current.User.IsAuthenticated) Then SettingsButton.Visibility = System.Windows.Visibility.Visible End If End Sub Private Sub LoadReports() If (WebContext.Current.User.IsAuthenticated) Then numberOfRows = WebContext.Current.User.DefaultRows AddHandler WebContext.Current.User.PropertyChanged, AddressOf User_PropertyChanged LoadRestrictedReports() Else CustomersGrid.Visibility = System.Windows.Visibility.Collapsed SalesOrdersGrid.Visibility = System.Windows.Visibility.Collapsed End If Dim loadProducts = context.Load(context.GetProductsQuery().Take(numberOfRows)) ProductsGrid.ItemsSource = loadProducts.Entities End Sub Private Sub LoadRestrictedReports() Dim loadSales = context.Load(context.GetSalesOrderHeadersQuery().Take(numberOfRows)) SalesOrdersGrid.ItemsSource = loadSales.Entities SalesOrdersGrid.Visibility = System.Windows.Visibility.Visible If (WebContext.Current.User.IsInRole("Managers")) Then Dim loadCustomers = context.Load(context.GetCustomersQuery().Take(numberOfRows)) CustomersGrid.ItemsSource = loadCustomers.Entities CustomersGrid.Visibility = System.Windows.Visibility.Visible Else CustomersGrid.Visibility = System.Windows.Visibility.Collapsed End If End Sub Private Sub User_PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) If (e.PropertyName = "DefaultRows") Then LoadReports() End If End Sub Private Sub SettingsButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) Dim settingsWindow = New ProfileWindow() settingsWindow.Show() End Sub End Class
using System; using System.Windows; using System.Windows.Controls; using System.Windows.Navigation; using System.ServiceModel.DomainServices.Client; using ExampleNavigationApplication.Web; namespace ExampleNavigationApplication.Views { public partial class Reports : Page { private AdventureWorksDomainContext context = new AdventureWorksDomainContext(); int numberOfRows = 10; public Reports() { InitializeComponent(); LoadReports(); if (WebContext.Current.User.IsAuthenticated) { SettingsButton.Visibility = System.Windows.Visibility.Visible; } } private void LoadReports() { if (WebContext.Current.User.IsAuthenticated) { numberOfRows = WebContext.Current.User.DefaultRows; WebContext.Current.User.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(User_PropertyChanged); LoadRestrictedReports(); } else { CustomersGrid.Visibility = System.Windows.Visibility.Collapsed; SalesOrdersGrid.Visibility = System.Windows.Visibility.Collapsed; } LoadOperation<Product> loadProducts = context.Load(context.GetProductsQuery().Take(numberOfRows)); ProductsGrid.ItemsSource = loadProducts.Entities; } private void LoadRestrictedReports() { LoadOperation<SalesOrderHeader> loadSales = context.Load(context.GetSalesOrderHeadersQuery().Take(numberOfRows)); SalesOrdersGrid.ItemsSource = loadSales.Entities; SalesOrdersGrid.Visibility = System.Windows.Visibility.Visible; if (WebContext.Current.User.IsInRole("Managers")) { LoadOperation<Customer> loadCustomers = context.Load(context.GetCustomersQuery().Take(numberOfRows)); CustomersGrid.ItemsSource = loadCustomers.Entities; CustomersGrid.Visibility = System.Windows.Visibility.Visible; } else { CustomersGrid.Visibility = System.Windows.Visibility.Collapsed; } } void User_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { if (e.PropertyName == "DefaultRows") { LoadReports(); } } private void SettingsButton_Click(object sender, RoutedEventArgs e) { Views.ProfileWindow settingsWindow = new Views.ProfileWindow(); settingsWindow.Show(); } } }
Sie können ein untergeordnetes Fenster hinzufügen, um Benutzern das Bearbeiten der DefaultRows-Profileigenschaft zu ermöglichen. Wenn der Wert geändert wird, rufen Sie die SaveUser-Methode auf, um den Wert in der Datenquelle zu speichern. Der aktuelle Wert wird über die Eigenschaften des User-Objekts der aktuellen WebContext-Instanz abgerufen.
So fügen Sie ein Fenster zum Festlegen der Profileigenschaft hinzu
Fügen Sie im Clientprojekt dem Ordner "Views" ein neues Element hinzu.
Wählen Sie die Vorlage Untergeordnetes Silverlight-Fenster aus, und geben Sie dafür den Namen "ProfileWindow.xaml" ein.
Klicken Sie auf die Schaltfläche Hinzufügen.
Fügen Sie in der Datei "ProfileWindow.xaml" das folgende XAML hinzu, um eine ComboBox für die Auswahl der Anzahl von Zeilen einzuschließen, die in den Berichten angezeigt werden soll.
<controls:ChildWindow x:Class="ExampleNavigationApplication.Views.ProfileWindow" xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls" Width="300" Height="200" Title="ProfileWindow"> <Grid x:Name="LayoutRoot" Margin="2"> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <StackPanel Orientation="Horizontal" Grid.Row="0"> <TextBlock Text="Number of rows to display for reports: "></TextBlock> <ComboBox x:Name="defaultRows" Height="20" VerticalAlignment="Top"> <ComboBoxItem Content="1"></ComboBoxItem> <ComboBoxItem Content="3"></ComboBoxItem> <ComboBoxItem Content="5"></ComboBoxItem> <ComboBoxItem Content="10"></ComboBoxItem> <ComboBoxItem Content="15"></ComboBoxItem> <ComboBoxItem Content="20"></ComboBoxItem> </ComboBox> </StackPanel> <Button x:Name="CancelButton" Content="Cancel" Click="CancelButton_Click" Width="75" Height="23" HorizontalAlignment="Right" Margin="0,12,0,0" Grid.Row="1" /> <Button x:Name="OKButton" Content="OK" Click="OKButton_Click" Width="75" Height="23" HorizontalAlignment="Right" Margin="0,12,79,0" Grid.Row="1" /> </Grid> </controls:ChildWindow>
Fügen Sie in der CodeBehind-Datei "ProfileWindow.xaml.cs" bzw. "ProfileWindow.xaml.vb" den folgenden Code hinzu, um die Profileigenschaft abzurufen und festzulegen.
Partial Public Class ProfileWindow Inherits ChildWindow Public Sub New() InitializeComponent() Dim userDefaultRows = WebContext.Current.User.DefaultRows.ToString() For Each cbi As ComboBoxItem In defaultRows.Items If (cbi.Content.ToString() = userDefaultRows) Then defaultRows.SelectedItem = cbi Exit For End If Next End Sub Private Sub OKButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) Handles OKButton.Click Dim newSelection = Integer.Parse(defaultRows.SelectionBoxItem.ToString()) If (newSelection <> WebContext.Current.User.DefaultRows) Then WebContext.Current.User.DefaultRows = newSelection WebContext.Current.Authentication.SaveUser(True) End If Me.DialogResult = True End Sub Private Sub CancelButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) Handles CancelButton.Click Me.DialogResult = False End Sub End Class
public partial class ProfileWindow : ChildWindow { public ProfileWindow() { InitializeComponent(); string userDefaultRows = WebContext.Current.User.DefaultRows.ToString(); foreach (ComboBoxItem cbi in defaultRows.Items) { if (cbi.Content.ToString() == userDefaultRows) { defaultRows.SelectedItem = cbi; break; } } } private void OKButton_Click(object sender, RoutedEventArgs e) { int newSelection = int.Parse(defaultRows.SelectionBoxItem.ToString()); if (newSelection != WebContext.Current.User.DefaultRows) { WebContext.Current.User.DefaultRows = newSelection; WebContext.Current.Authentication.SaveUser(true); } this.DialogResult = true; } private void CancelButton_Click(object sender, RoutedEventArgs e) { this.DialogResult = false; } }
Führen Sie die Projektmappe aus.
Klicken Sie auf den Link Reports.
Wenn die Website gestartet wird und Sie nicht angemeldet sind, wird nur die Tabelle "Products" auf der Seite "Reports" angezeigt.
Auf der Startseite erfolgt die Registrierung und Anmeldung als neuer Benutzer.
Klicken Sie auf den Link Reports.
Die Tabellen für Produkte und Verkaufsaufträge werden angezeigt.
Melden Sie sich ab, und melden Sie sich als CustomerManager an.
Die Tabellen für Produkte, Verkaufsaufträge und Kunden werden angezeigt.
Klicken Sie auf den Link Einstellungen anpassen, und legen Sie die Standardanzahl von Zeilen fest, die für die Berichte angezeigt werden soll.
Beachten Sie, dass das DataGrid nun die Anzahl der ausgewählten Zeilen enthält.
Schließen Sie den Webbrowser.