Procédure pas à pas : Utilisation du service d'authentification avec une application de navigation Silverlight
Dans cette procédure pas à pas, vous allez apprendre à configurer vos projets client et serveur dans une solution Services RIA WCF, afin qu'ils fonctionnent avec un service d'authentification. Lorsque vous créez une solution avec le modèle Application de navigation Silverlight et que vous activez les Services RIA , vous pouvez accéder à l'infrastructure de l'appartenance ASP.NET en ajoutant un service d'authentification. Le service d'authentification expose l'authentification, les rôles et les profils du projet serveur au projet client. Le service d'authentification sert à valider les informations d'identification de l'utilisateur, à limiter l'accès aux ressources en fonction des rôles et à stocker des propriétés de profil.
Remarque : |
---|
L'application métier Silverlight implémente automatiquement le service d'authentification. Pour plus d'informations, consultez Procédure pas à pas : Utilisation du service d'authentification avec une application métier Silverlight. |
Configuration requise
Cette procédure pas à pas, ainsi que les autres procédures du même type présentées dans la documentation des Services RIA , nécessite au préalable l'installation et la configuration correctes de plusieurs programmes, tels que Visual Studio 2010 et le Developer Runtime et SDK Silverlight, en plus des Services RIA WCF et du kit de ressources des Services RIA WCF. Ces procédures nécessitent également l'installation et la configuration de SQL Server 2008 R2 Express with Advanced Services et l'installation de la base de données AdventureWorks OLTP et LT.
Vous trouverez des instructions détaillées pour satisfaire chacune de ces conditions préalables dans les rubriques du nœud Conditions préalables pour les Services RIA WCF. Suivez ces instructions avant de poursuivre, pour être sûr de rencontrer le moins de problèmes possibles en effectuant ces procédures pas à pas des Services RIA .
Configuration du serveur projet pour l'authentification, les rôles et les profils
Pour utiliser le service d'authentification d'une application Silverlight, vous devez configurer l'authentification sur le projet serveur. L'authentification se configure dans le fichier Web.config. Après avoir configuré l'authentification, vous pouvez aussi configurer les rôles et les profils sur le projet serveur, si vous souhaitez utiliser ces fonctionnalités de l'application Silverlight. Dans cette procédure pas à pas, vous configurerez ces trois fonctionnalités. Pour terminer, vous ajouterez un service d'authentification qui expose les fonctionnalités actives au client.
Pour configurer le projet serveur
Dans Visual Studio 2010, sélectionnez Fichier, Nouveau, puis Projet.
La boîte de dialogue Nouveau projet s'affiche.
Sélectionnez le type de projet Silverlight.
Sélectionnez le modèle Application de navigation Silverlight et nommez l'application ExampleNavigationApplication.
Cliquez sur OK.
La boîte de dialogue Nouvelle application Silverlight s'ouvre.
Vérifiez que la case à cocher Héberger l'application Silverlight sur un nouveau site Web est activée et que le Nouveau type de projet Web est Projet d'application Web ASP.NET.
Activez la case à cocher Activer les services RIA WCF.
Cliquez sur OK pour créer la solution.
Dans le projet serveur (ExampleBusinessApplication.Web), ouvrez le fichier Web.config.
Dans l'élément
<system.web>
, ajoutez un élément<authentication>
et paramétrez la propriétémode
sur Formulaires.<authentication mode="Forms"></authentication>
Dans l'élément
<system.web>
, ajoutez un élément<roleManager>
et donnez à la propriétéenabled
la valeur true.<roleManager enabled="true"></roleManager>
Dans l'élément
<system.web>
, ajoutez un élément<profile>
, donnez à la propriétéenabled
la valeur trueet incluez une propriétéprofile
nommée DefaultRows.<profile enabled="true"> <properties> <add type="System.Int32" defaultValue="10" name="DefaultRows"/> </properties> </profile>
L'élément
<system.web>
terminé doit inclure les éléments suivants.<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>
Enregistrez le fichier Web.config.
Dans l'Explorateur de solutions, cliquez avec le bouton droit sur le projet serveur, sélectionnez Ajouter, puis Nouvel élément.
La boîte de dialogue Ajouter un nouvel élément s'affiche.
Sélectionnez le modèle DomainService d'authentification et nommez-le AuthenticationDomainService.
Cliquez sur Ajouter.
Ouvrez le fichier de code du service d'authentification (AuthenticationDomainService.cs ou AuthenticationDomainService.vb) et ajoutez la propriété DefaultRows que vous avez définie dans le fichier Web.config à la classe User.
<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; } }
Générez la solution.
Dans cette section, vous utiliserez l'outil Administration de site Web ASP.NET pour créer un utilisateur et un rôle. Vous vous connecterez sous l'identité de cet utilisateur dans une section ultérieure.
Pour ajouter des utilisateurs avec l'outil d'administration de site Web ASP.NET
Pour ouvrir l'outil d'administration de site Web ASP.NET, sélectionnez tout d'abord le projet serveur dans l'Explorateur de solutions.
Dans le menu Projet, sélectionnez Configuration ASP.NET.
Si vous ne voyez pas l'option Configuration ASP.NET dans le menu Projet, c'est peut être parce que vous avez sélectionné le projet client.
Sélectionnez l'onglet Sécurité dans l'outil Administration de site Web ASP.NET.
Dans la section Rôles, cliquez sur le lien Créer ou gérer des rôles.
Ajoutez un nouveau rôle nommé Managers et cliquez sur le bouton Ajouter le rôle.
Dans l'angle inférieur droit, cliquez sur le bouton Retour.
Dans la section Utilisateurs, cliquez sur le lien Créer un utilisateur.
Créez un utilisateur avec les valeurs suivantes et activez la case à cocher du rôle Managers.
Nom d'utilisateur : CustomerManager
Mot de passe : P@ssword
Adresse de messagerie : someone@example.com
Question de sécurité : couleur préférée ?
Réponse de sécurité : bleu
Rôle Managers : sélectionné
Cliquez sur le bouton Créer un utilisateur.
Fermez l'outil Administration de site Web ASP.NET.
Configuration du client pour l'authentification
Vous devez configurer le projet client de façon à ce qu'il utilise le mode d'authentification correspondant à celui que vous avez configuré dans le projet serveur.
Pour configurer le projet client
Dans le projet client, ouvrez le fichier code-behind du fichier App.xaml (App.xaml.cs ou App.xaml.vb).
Dans le constructeur, créez une nouvelle instance de la classe WebContext.
Paramétrez la propriété Authentication sur une nouvelle instance de la classe FormsAuthentication et ajoutez l'instance WebContext aux ApplicationLifetimeObjects.
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); }
Ajout d'une fonctionnalité de connexion au client
Dans cette section, vous ajouterez des contrôles Silverlight qui permettent à l'utilisateur de fournir un nom d'utilisateur et un mot de passe pour se connecter. Vous ajouterez un code qui appelle la méthode Login avec les informations d'identification de l'utilisateur. Vous définirez aussi les contrôles qui seront visibles selon que l'utilisateur est connecté ou non.
Pour simplifier les choses, l'interface utilisateur de connexion est ajoutée à la page d'accueil dans cette procédure pas à pas. Dans votre application, vous souhaiterez peut-être créer une page de connexion distincte.
Pour connecter et déconnecter un utilisateur
Dans l'Explorateur de solutions, développez le dossier Views dans le projet client.
Ouvrez le fichier Home.xaml.
Après le
ContentText
nommé TextBlock, ajoutez le XAML suivant.Le XAML comprend une TextBox permettant de fournir un nom d'utilisateur, une PasswordBox permettant de fournir un mot de passe et un Button permettant de soumettre la demande de connexion, ainsi qu'un TextBlock et un HyperlinkButton permettant de se déconnecter. Ces deux derniers éléments ne s'affichent qu'une fois l'utilisateur connecté.
<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>
Ouvrez le fichier code-behind de la page d'accueil (Home.xaml.cs ou Home.xaml.vb).
Ajoutez une instruction using ou Imports pour l'espace de noms System.ServiceModel.DomainServices.Client.ApplicationServices.
Ajoutez le code suivant à la classe Home.
Le code comprend des gestionnaires d'événements pour la connexion et la déconnexion, des méthodes de rappel pour les opérations de connexion et de déconnexion terminées, et une méthode qui détermine la visibilité des contrôles selon que l'utilisateur est authentifié ou non.
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(); } }
Exécutez la solution.
Connectez-vous sous l'identité CustomerManager avec le mot de passe P@ssword.
Remarquez que la zone de connexion ne s'affiche plus, mais que le texte de bienvenue et le lien de déconnexion sont maintenant affichés.
Cliquez sur le lien Déconnexion et fermez le navigateur Web.
Ajout d'utilisateurs depuis le client
Le service d'authentification ne contient pas d'opération permettant de créer des utilisateurs. Pour inscrire un nouvel utilisateur, vous devez créer un service de domaine vide et ajouter une opération permettant d'ajouter un utilisateur à l'infrastructure de l'appartenance ASP.NET.
Pour configurer le projet serveur de manière à ajouter un nouvel utilisateur
Dans le projet serveur, ajoutez un fichier de classe nommé NewUser.
Définissez les propriétés d'inscription d'un nouvel utilisateur en ajoutant le code suivant à la classe NewUser.
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; } } }
La propriété ConfirmPassword de l'étape précédente est définie à l'aide d'un attribut CustomValidationAttribute. Dans l'attribut, elle spécifie une classe RegistrationValidator et une méthode nommée IsPasswordConfirmed. Vous devez maintenant définir cette classe de validation personnalisée.
Ajoutez une nouvelle classe nommée RegistrationValidator.shared.cs ou RegistrationValidator.shared.vb.
Ajoutez le code suivant au fichier RegistrationValidator.shared.
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."); } } } }
Ajoutez un nouvel élément au projet serveur et sélectionnez le modèle Classe DomainService.
Nommez le fichier RegistrationDomainService.cs ou RegistrationDomainService.vb, puis cliquez sur le bouton Ajouter.
Dans la boîte de dialogue Ajouter une nouvelle classe de service de domaine, sélectionnez <classe de service de domaine vide> dans la liste DataContexts/ObjectContexts disponibles.
Cliquez sur OK.
Pour créer une opération de domaine qui ajoute un utilisateur via l'infrastructure Membership et enregistre une propriété de profil, ajoutez le code suivant à la classe RegistrationDomainService.
La méthode GetUsers doit être incluse pour que la classe d'entité NewUser puisse être générée pour le projet client. Seules les classes exposées via une opération de requête publique sont générées dans le projet client.
Une fois l'utilisateur créé, la propriété de profil nommée DefaultRows est définie. Dans ce cas précis, la propriété de profil est définie dans le cadre de l'opération de domaine pour la création d'un utilisateur. Dans une section ultérieure, vous ajouterez le code permettant de définir la propriété de profil depuis le projet client.
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(); } } }
Pour configurer le projet client de manière à pouvoir ajouter des utilisateurs
Ouvrez le fichier Home.xaml.
Après la balise de fin du contrôle
LoginBorder
Border, ajoutez le XAML suivant pour créer un deuxième contrôle Border avec des contrôles d'entrée afin de recueillir des informations permettant de créer des utilisateurs.Les contrôles acceptent des valeurs pour le nom d'utilisateur, le mot de passe, la confirmation du mot de passe, l'adresse de messagerie, la question de sécurité, la réponse de sécurité et le nombre d'enregistrements à afficher sur les rapports. Le nombre d'enregistrements à afficher sera enregistré comme une propriété de profil. Toutes les autres valeurs sont utilisées pour créer l'utilisateur via l'infrastructure de l'appartenance ASP.NET.
<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>
Ouvrez le fichier code-behind Home.xaml.cs (ou Home.xaml.vb).
Ajoutez une instruction using ou Imports pour les espaces de noms System.ServiceModel.DomainServices.Client, System.ComponentModel.DataAnnotations et ExampleNavigationApplication.Web.
Ajoutez un gestionnaire d'événements pour l'événement de clic sur le bouton d'enregistrement et ajoutez aussi une méthode de rappel pour l'opération de domaine. La méthode de rappel comprend le code permettant de connecter l'utilisateur après avoir créé son compte.
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; }
Modifiez la méthode SetControlVisibility de façon à paramétrer la visibilité de RegisterBorder, comme le montre le code suivant.
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; } }
Voici le fichier de code-behind complet.
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; } } }
Exécutez la solution.
Fournissez des valeurs pour inscrire un nouvel utilisateur.
Fermez le navigateur Web.
Restriction de l'accès aux opérations de domaine
Vous pouvez limiter l'accès à une opération de domaine en appliquant l'attribut RequiresAuthenticationAttribute ou RequiresRoleAttribute à l'opération de domaine. Les opérations de domaine sans attribut sont disponibles pour tous les utilisateurs. L'application d'un attribut à l'opération de domaine n'empêche pas l'utilisateur d'appeler cette opération ; néanmoins, les utilisateurs ne possédant pas les informations d'identification requises recevront une exception.
Pour limiter les données affichées selon le rôle
Dans l'Explorateur de solutions, sélectionnez le projet serveur et cliquez sur le bouton Afficher tous les fichiers.
Cliquez avec le bouton droit sur le dossier App_Data et sélectionnez Inclure dans le projet.
Cliquez avec le bouton droit sur le dossier App_Data, sélectionnez Ajouter, puis Élément existant.
Dans la boîte de dialogue Ajouter un élément existant, ajoutez l'exemple de base de données AdventureWorksLT.
Dans le projet serveur, ajoutez un nouvel élément et sélectionnez le modèle ADO.NET Entity Data Model.
Donnez au modèle le nom AdventureWorksModel.edmx, puis cliquez sur Ajouter.
L'Assistant EDM s'affiche.
Sélectionnez l'option Générer à partir de la base de données, puis cliquez sur Suivant.
Sélectionnez la base de données AdventureWorksLT, puis cliquez sur Suivant.
Dans la liste des objets de base de données, sélectionnez les tables Customer, Product et SalesOrderHeader, puis cliquez sur Terminer.
L'Entity Data Model s'affiche dans le concepteur.
Générez la solution.
Dans le projet serveur, ajoutez un nouvel élément et sélectionnez le modèle Classe DomainService.
Nommez le service de domaine AdventureWorksDomainService, puis cliquez sur Ajouter.
Dans la boîte de dialogue Ajouter une nouvelle classe de service de domaine, sélectionnez les entités Customer, Product et SalesOrderHeader.
Cliquez sur OK pour terminer la création du service de domaine.
Dans le fichier de classe AdventureWorksDomainService, ajoutez l'attribut RequiresAuthenticationAttribute à la méthode
GetSalesOrderHeader
.<RequiresAuthentication()> _ Public Function GetSalesOrderHeaders() As IQueryable(Of SalesOrderHeader) Return Me.ObjectContext.SalesOrderHeaders End Function
[RequiresAuthentication()] public IQueryable<SalesOrderHeader> GetSalesOrderHeaders() { return this.ObjectContext.SalesOrderHeaders; }
Ajoutez l'attribut RequiresRoleAttribute à la méthode
GetCustomers
et nommez le rôle requis « Managers ».<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; }
L'opération de domaine
GetProducts
est disponible pour tous les utilisateurs ;GetSalesOrderHeaders
est disponible pour les utilisateurs authentifiés ; etGetCustomers
n'est disponible que pour les utilisateurs du rôle Managers.Voici le service de domaine complet.
<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; } }
Utilisation du service d'authentification à partir du client
Avant d'appeler une opération de domaine avec des autorisations limitées, vous devez vérifier que l'utilisateur possède les informations d'identification requises ; sinon, une exception est levée. Dans cette section, vous vérifierez les informations d'identification de l'utilisateur et remplirez entre un et trois contrôles DataGrid en fonction des informations d'identification de l'utilisateur. Vous récupérerez également le nombre d'enregistrements en fonction d'une propriété dans le profil utilisateur. Une valeur par défaut de 10 est utilisée pour les utilisateurs non authentifiés. Cette section n'indique pas le moyen pour les utilisateurs de définir la propriété de profil DefaultRows, mais vous ajouterez cette propriété dans une section ultérieure.
Pour ajouter une page Silverlight permettant d'afficher les données
Dans le projet client, ajoutez un nouvel élément au dossier Views.
Sélectionnez le modèle Page Silverlight et nommez la nouvelle page Reports.xaml.
Ouvrez le fichier MainPage.xaml et ajoutez un lien pour la page Reports en ajoutant le XAML suivant après le HyperlinkButton nommé
Link2
qui renvoie à la page À propos de.<Rectangle x:Name="Divider2" Style="{StaticResource DividerStyle}"/> <HyperlinkButton x:Name="Link3" Style="{StaticResource LinkStyle}" NavigateUri="/Reports" TargetName="ContentFrame" Content="reports"/>
Ouvrez le fichier Reports.xaml et ajoutez le XAML suivant entre les balises
Grid
de façon à ce que son formatage corresponde à celui des autres pages du site, de façon aussi à inclure un contrôle HyperlinkButton qui déclenchera l'ouverture d'une fenêtre pour l'édition d'une propriété de profil.<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>
Faites glisser trois contrôles DataGrid depuis la Boîte à outils, juste avant la balise de fin du panneau d'empilement nommé
ContentStackPanel
.Lorsque vous faites glisser les contrôles DataGrid depuis la Boîte à outils, une référence à l'assembly System.Windows.Controls.Data est ajoutée au projet et un préfixe pour l'espace de noms System.Windows.Controls est ajouté à la page.
Donnez aux contrôles DataGrid les noms
ProductsGrid
,SalesOrdersGrid
etCustomersGrid
et donnez àMargin
la valeur 5.L'exemple suivant montre le fichier Reports.xaml terminé.
<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>
Ouvrez le fichier Reports.xaml.cs ou Reports.xaml.vb et ajoutez les instructions using ou Imports pour les espaces de noms System.ServiceModel.DomainServices.Client et ExampleNavigationApplication.Web.
Créez une instance du contexte nommé AdventureWorksDomainContext et créez une variable nommée numberOfRows qui contient le nombre de lignes à récupérer.
Private context As New AdventureWorksDomainContext Private numberOfRows As Integer = 10
private AdventureWorksDomainContext context = new AdventureWorksDomainContext(); int numberOfRows = 10;
Ajoutez une méthode nommée
LoadRestrictedReports
qui appelle la méthodeGetSalesOrderHeaderQuery
et la méthodeGetCustomersQuery
, si l'utilisateur appartient au rôle Managers, et qui remplit les grilles de données correspondantes avec les résultats.Si vous appelez une opération de domaine alors que l'utilisateur ne possède pas les informations d'identification requises, l'opération de domaine retourne une exception. Vous pouvez éviter cette situation en vérifiant les informations d'identification avant d'appeler l'opération de domaine.
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; } }
Ajoutez une méthode nommée
LoadReports
qui vérifie si l'utilisateur est authentifié et, si c'est le cas, appelle la méthodeLoadRestrictedReports
. Elle récupère également la propriété de profil nomméeDefaultRows
et ajoute un gestionnaire d'événements pour l'événement PropertyChanged sur l'objet User. Enfin, elle appelle la méthodeGetProductsQuery
pour tous les utilisateurs.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; }
Ajoutez un gestionnaire d'événements pour l'événement PropertyChanged qui appelle
LoadReports
si la propriétéDefaultRows
a été modifiée.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(); } }
Ajoutez le code suivant au constructeur. Ce code charge les rapports et rend visible le lien des paramètres pour les utilisateurs authentifiés.
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; } }
Ajoutez un gestionnaire d'événements pour l'événement de clic sur le lien des paramètres.
La
ProfileWindow
sera ajoutée lors d'une étape ultérieure.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(); }
Voici le fichier de code terminé.
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(); } } }
Vous pouvez permettre aux utilisateurs de modifier la propriété de profil DefaultRows en ajoutant une fenêtre enfant. Lorsque la valeur est modifiée, vous appelez la méthode SaveUser pour enregistrer la valeur dans la source de données. Vous récupérez la valeur actuelle via les propriétés de l'objet user de l'instance WebContext actuelle.
Pour ajouter une fenêtre permettant de définir la propriété de profil
Dans le projet client, ajoutez un nouvel élément au dossier Views.
Sélectionnez le modèle Fenêtre enfant Silverlight et nommez-le ProfileWindow.xaml.
Cliquez sur le bouton Ajouter.
Dans le fichier ProfileWindow.xaml, ajoutez le XAML suivant pour inclure un ComboBox afin de pouvoir sélectionner le nombre de lignes à afficher dans les rapports.
<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>
Dans le fichier code-behind ProfileWindow.xaml.cs ou ProfileWindow.xaml.vb, ajoutez le code suivant pour récupérer et définir la propriété de profil.
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; } }
Exécutez la solution.
Cliquez sur le lien Rapports.
Remarquez que lorsque le site démarre sans que vous soyez connecté, seule la table des produits s'affiche sur la page Rapports.
Sur la page d'accueil, enregistrez-vous et ouvrez une session sous l'identité d'un nouvel utilisateur.
Cliquez sur le lien Rapports.
Remarquez que les tables des produits et des commandes client sont affichées.
Déconnectez-vous et connectez-vous en tant que CustomerManager.
Remarquez que les tables des produits, des commandes client et des clients sont affichées.
Cliquez sur le lien Ajuster les paramètres et définissez le nombre de lignes à afficher par défaut dans les rapports.
Remarquez que le DataGrid contient maintenant le nombre de lignes que vous avez sélectionné.
Fermez le navigateur Web.