Procedura dettagliata: utilizzo del servizio di autenticazione con Applicazione di navigazione Silverlight
In questa procedura dettagliata verrà illustrato come impostare progetti server e client in una soluzione WCF RIA Services per l'utilizzo di un servizio di autenticazione. Quando si crea una soluzione con il modello Applicazione di navigazione Silverlight e si abilita RIA Services , è possibile accedere al framework di appartenenza ASP.NET aggiungendo un servizio di autenticazione. Il servizio di autenticazione espone l'autenticazione, i ruoli e i profili dal progetto server al progetto client. Viene utilizzato il servizio di autenticazione per convalidare le credenziali utente, limitare l'accesso a risorse in base ai ruoli e memorizzare le proprietà del profilo.
[!NOTA] L'applicazione aziendale di Silverlight implementa automaticamente il servizio di autenticazione. Per ulteriori informazioni, vedere Procedura dettagliata: utilizzo del servizio di autenticazione con l'applicazione aziendale di Silverlight.
Prerequisiti
Per l'esecuzione di questa e di altre procedure dettagliate descritte nella documentazione di RIA Services è necessario che siano installati e configurati correttamente alcuni programmi prerequisiti quali Visual Studio 2010 e Silverlight Developer Runtime e SDK, oltre a WCF RIA Services e a WCF RIA Services Toolkit. È inoltre richiesta l'installazione e la configurazione di SQL Server 2008 R2 Express with Advanced Services e l'installazione del database AdventureWorks OLTP e LT.
Le istruzioni dettagliate per soddisfare tali prerequisiti vengono fornite negli argomenti all'interno del nodo Prerequisiti per WCF RIA Services. Seguire tali istruzioni prima di continuare con questa procedura dettagliata in modo da assicurarsi che si verifichi il minor numero possibile di problemi durante l'esecuzione della procedura dettagliata di RIA Services .
Configurazione del progetto server per autenticazione, ruoli e profili
Per utilizzare il servizio di autenticazione da un'applicazione Silverlight, è necessario configurare l'autenticazione sul progetto server. È possibile configurare l'autenticazione nel file Web.config. Dopo avere configurato l'autenticazione, è possibile configurare anche ruoli e profili nel progetto server, se si desidera utilizzarne le funzionalità dall'applicazione Silverlight. In questa procedura dettagliata, verranno configurate tutte e tre le funzionalità. Infine, verrà aggiunto un servizio di autenticazione che consente di esporre le funzionalità abilitate al client.
Per configurare il progetto server
In Visual Studio 2010, selezionare File, Nuovo, quindi Progetto.
Verrà visualizzata la finestra di dialogo Nuovo progetto.
Selezionare il tipo di progetto Silverlight.
Selezionare il modello Applicazione di navigazione Silverlight e denominare l'applicazione ExampleNavigationApplication.
Fare clic su OK.
Verrà visualizzata la finestra di dialogo Nuova applicazione Silverlight.
Assicurarsi che sia selezionata la casella di controllo Ospita l'applicazione Silverlight in un nuovo sito Web e che il tipo di nuovo progetto Web sia impostato su Progetto Applicazione Web ASP.NET.
Selezionare la casella di controllo Abilita WCF RIA Services.
Fare clic su OK per creare la soluzione.
Nel progetto server (ExampleBusinessApplication.Web) aprire il file Web.config.
Nell'elemento
<system.web>
aggiungere un elemento<authentication>
e impostare la proprietàmode
su Form.<authentication mode="Forms"></authentication>
Nell'elemento
<system.web>
aggiungere un elemento<roleManager>
e impostare la proprietàenabled
su true.<roleManager enabled="true"></roleManager>
Nell'elemento
<system.web>
aggiungere un elemento<profile>
, impostare la proprietàenabled
su true e includere una proprietàprofile
denominata DefaultRows.<profile enabled="true"> <properties> <add type="System.Int32" defaultValue="10" name="DefaultRows"/> </properties> </profile>
L'elemento
<system.web>
completato deve includere gli elementi seguenti.<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>
Salvare il file Web.config.
In Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto server, scegliere Aggiungi, quindi fare clic su Nuovo elemento.
Verrà visualizzata la finestra di dialogo Aggiungi nuovo elemento.
Selezionare il modello DomainService di autenticazione e denominarlo AuthenticationDomainService.
Fare clic su Aggiungi.
Aprire il file di codice del servizio di autenticazione (AuthenticationDomainService.cs o AuthenticationDomainService.vb) e aggiungere la proprietà DefaultRows definita nel file Web.config alla 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; } }
Compilare la soluzione.
In questa sezione si utilizzerà lo strumento Amministrazione sito Web di ASP.NET per la creazione di un utente e del relativo ruolo. In un'altra sezione, più avanti in questa procedura, si effettuerà l'accesso con le credenziali dell'utente creato.
Per aggiungere utenti con lo strumento Amministrazione sito Web di ASP.NET
Per aprire lo strumento Amministrazione sito Web di ASP.NET, selezionare innanzitutto il progetto server in Esplora soluzioni.
Scegliere Configurazione di ASP.NET dal menu Progetto.
Se l'opzione Configurazione di ASP.NET non è presente nel menu Progetto, è possibile che sia stato selezionato il progetto client.
Selezionare la scheda Sicurezza nello strumento Amministrazione sito Web di ASP.NET.
Nella sezione Ruoli, fare clic sul collegamento Crea o gestisci ruoli.
Aggiungere un nuovo ruolo denominato Managers e fare clic sul pulsante Aggiungi ruolo.
Nell'angolo inferiore destro, fare clic sul pulsante Indietro.
Nella sezione Utenti, fare clic sul collegamento Crea utente.
Creare un nuovo utente con i valori seguenti e selezionare la casella di controllo del ruolo Managers.
Nome utente: CustomerManager
Password: P@ssword
Posta elettronica: prova@example.com
Domanda di sicurezza: Colore preferito?
Risposta di sicurezza: blu
Ruolo Managers: selezionato
Fare clic sul pulsante Crea utente.
Chiudere lo strumento Amministrazione sito Web di ASP.NET.
Configurazione del client per l'autenticazione
È necessario configurare il progetto client per utilizzare la modalità di autenticazione che corrisponde alla modalità di autenticazione configurata nel progetto server.
Per configurare il progetto client
Nel progetto client aprire il file code-behind per il file App.xaml (App.xaml.cs o App.xaml.vb).
Nel costruttore creare una nuova istanza della classe WebContext.
Impostare la proprietà Authentication su una nuova istanza della classe FormsAuthentication, quindi aggiungere l'istanza WebContext agli oggetti 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); }
Aggiunta della funzionalità di accesso al client
In questa sezione verranno aggiunti controlli Silverlight che consentono all'utente di fornire il nome utente e la password per l'accesso. Verrà aggiunto del codice che chiama il metodo Login con le credenziali dell'utente. Verrà anche stabilito quali controlli saranno visibili agli utenti che hanno effettuato l'accesso.
Per semplicità, in questa procedura dettagliata l'interfaccia utente di accesso viene aggiunta alla home page. Nell'applicazione potrebbe essere opportuno creare una pagina di accesso separata.
Accesso e disconnessione di un utente
In Esplora soluzioni espandere la cartella Views nel progetto client.
Aprire il file Home.xaml.
Dopo l'elemento TextBlock denominato
ContentText
, aggiungere il seguente codice XAML.Il codice XAML include un oggetto TextBox per fornire un nome utente, un oggetto PasswordBox per fornire una password, un oggetto Button per l'invio della richiesta di accesso e un oggetto TextBlock e HyperlinkButton per la disconnessione, visualizzati solo dopo che l'utente ha effettuato l'accesso.
<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>
Aprire il file code-behind per la home page (Home.xaml.cs or Home.xaml.vb).
Aggiungere un'istruzione using o Imports per lo spazio dei nomi System.ServiceModel.DomainServices.Client.ApplicationServices.
Aggiungere il codice seguente alla classe Home.
Il codice include gestori eventi per l'accesso e la disconnessione, metodi di callback per il completamento delle operazioni di accesso e disconnessione e un metodo che imposta la visibilità dei controlli in base allo stato di autenticazione dell'utente.
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(); } }
Eseguire la soluzione.
Accedere come CustomerManager utilizzando P@ssword come password.
Si noti che l'area di accesso non è più visualizzata, ma sono ora visualizzati il testo di benvenuto e il collegamento di disconnessione.
Fare clic sul collegamento Logout e chiudere il browser.
Aggiunta di nuovi utenti dal client
Il servizio di autenticazione non contiene un'operazione per creare i nuovi utenti. Per registrare un nuovo utente, è necessario creare un servizio di dominio vuoto e aggiungere un'operazione per l'aggiunta di un utente al framework di appartenenza ASP.NET.
Per configurare il progetto server per l'aggiunta di un nuovo utente
Nel progetto server, aggiungere un nuovo file di classe denominato NewUser.
Definire le proprietà per la registrazione di un nuovo utente aggiungendo il codice seguente alla 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 proprietà ConfirmPassword nel passaggio precedente è definita con un attributo CustomValidationAttribute. Nell'attributo, la proprietà specifica una classe RegistrationValidator e un metodo denominato IsPasswordConfirmed. È ora necessario definire questa classe di convalida personalizzata.
Aggiungere una nuova classe denominata RegistrationValidator.shared.cs o RegistrationValidator.shared.vb.
Aggiungere il codice seguente al file 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."); } } } }
Aggiungere un nuovo elemento al progetto server e selezionare il modello Classe di DomainService.
Denominare il file RegistrationDomainService.cs o RegistrationDomainService.vb, quindi fare clic sul pulsante Aggiungi.
Nella finestra di dialogo Aggiungi una nuova classe DomainService, selezionare <Classe DomainService vuota> dall'elenco Classi DataContext/ObjectContext disponibili.
Fare clic su OK.
Per creare un'operazione di dominio che aggiunga un nuovo utente tramite il framework di appartenenza e salvi una proprietà del profilo, aggiungere il codice seguente alla classe RegistrationDomainService.
Il metodo GetUsers deve essere incluso per garantire che la classe di entità NewUser venga generata per il progetto client. Nel progetto client vengono generate solo le classi esposte mediante un'operazione di query pubblica.
Dopo avere creato l'utente, viene impostata la proprietà del profilo denominata DefaultRows. In questo caso, la proprietà del profilo viene impostata come parte dell'operazione di dominio per la creazione di un utente. In una sezione successiva si aggiungerà codice per impostare la proprietà del profilo dal progetto 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(); } } }
Per configurare il progetto client per l'aggiunta di nuovi utenti
Aprire il file Home.xaml.
Dopo il tag di fine per il controllo
LoginBorder
Border, aggiungere il seguente codice XAML per creare un secondo controllo Border con i controlli di input necessari alla raccolta delle informazioni per creare nuovi utenti.I controlli accettano valori per nome utente, password, conferma della password, indirizzo di posta elettronica, domanda di sicurezza, risposta di sicurezza e il numero di record da visualizzare sui report. Il numero di record da visualizzare verrà salvato come proprietà del profilo. Tutti gli altri valori vengono utilizzati per creare l'utente mediante il framework di appartenenza 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>
Aprire il file code-behind Home.xaml.cs (o Home.xaml.vb).
Aggiungere un'istruzione using o Imports per gli spazi dei nomi System.ServiceModel.DomainServices.Client, System.ComponentModel.DataAnnotations e ExampleNavigationApplication.Web.
Aggiungere un gestore eventi per l'evento Click sul pulsante di registrazione e aggiungere un metodo di callback per operazioni di dominio. Il metodo di callback include codice per fornire l'accesso all'utente dopo la corretta creazione dell'account.
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; }
Modificare il metodo SetControlVisibility per impostare la visibilità dell'elemento RegisterBorder, come mostrato nel codice riportato di seguito.
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; } }
Nell'esempio riportato di seguito viene mostrato il file code-behind completo.
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; } } }
Eseguire la soluzione.
Fornire valori per registrare un nuovo utente.
Chiudere il browser Web.
Limitazione dell'accesso alle operazioni di dominio
È possibile limitare l'accesso a un'operazione di dominio applicando l'attributo RequiresAuthenticationAttribute oppure RequiresRoleAttribute all'operazione di dominio. Le operazioni di dominio senza un attributo sono disponibili a tutti gli utenti. L'applicazione di un attributo a un'operazione di dominio non impedisce all'utente di chiamare l'operazione di dominio stessa; tuttavia, gli utenti privi delle credenziali necessarie riceveranno un'eccezione.
Per limitare dati visualizzati in base ai ruoli
Nella finestra Esplora soluzioni selezionare il progetto server e fare clic sul pulsante Mostra tutti i file.
Fare clic con il pulsante destro del mouse sulla cartella App_Data e scegliere Includi nel progetto.
Fare clic con il pulsante destro del mouse sulla cartella App_Data, scegliere Aggiungi, quindi Elemento esistente.
Nella finestra di dialogo Aggiungi elemento esistente, aggiungere il database di esempio AdventureWorksLT.
Nel progetto server aggiungere un nuovo elemento e selezionare il modello ADO.NET Entity Data Model.
Denominare il modello AdventureWorksModel.edmx, quindi fare clic su Aggiungi.
Viene visualizzata la procedura guidata Entity Data Model.
Selezionare l'opzione Genera da database, quindi fare clic su Avanti.
Selezionare il database AdventureWorksLT e fare clic su Avanti.
Dall'elenco di oggetti di database, selezionare le tabelle Customer, Product e SalesOrderHeader, quindi fare clic su Fine.
Il modello Entity Data Model verrà visualizzato nella finestra di progettazione.
Compilare la soluzione.
Aggiungere un nuovo elemento al progetto server e selezionare il modello Classe di DomainService.
Denominare il servizio del dominio AdventureWorksDomainService, quindi fare clic su Aggiungi.
Nella finestra di dialogo Aggiungi una nuova classe DomainService, selezionare le entità Customer, Product e SalesOrderHeader.
Fare clic su OK per finalizzare la creazione del servizio del dominio.
Nel file di classe AdventureWorksDomainService, aggiungere l'attributo RequiresAuthenticationAttribute al metodo
GetSalesOrderHeader
.<RequiresAuthentication()> _ Public Function GetSalesOrderHeaders() As IQueryable(Of SalesOrderHeader) Return Me.ObjectContext.SalesOrderHeaders End Function
[RequiresAuthentication()] public IQueryable<SalesOrderHeader> GetSalesOrderHeaders() { return this.ObjectContext.SalesOrderHeaders; }
Aggiungere l'attributo RequiresRoleAttribute al metodo
GetCustomers
e denominare il ruolo richiesto "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'operazione di dominio
GetProducts
è disponibile per qualsiasi utente,GetSalesOrderHeaders
è disponibile per gli utenti autenticati eGetCustomers
è disponibile solo per gli utenti nel ruolo Managers.Nell'esempio riportato di seguito viene illustrato il servizio del dominio completo.
<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; } }
Utilizzo del servizio di autenticazione dal client
Prima di chiamare un'operazione di dominio con autorizzazioni limitate, è necessario controllare che l'utente disponga delle credenziali necessarie; in caso contrario, viene generata un'eccezione. In questa sezione, verranno verificate le credenziali dell'utente e verranno popolati da uno a tre controlli DataGrid in base alle credenziali dell'utente. Verrà inoltre recuperato il numero di record in base a una proprietà nel profilo utente. Un valore predefinito di 10 viene utilizzato per gli utenti non autenticati. In questa sezione non è incluso alcun metodo per consentire agli utenti di impostare la proprietà del profilo DefaultRows, ma tale opzione verrà aggiunta in una sezione successiva.
Per aggiungere una pagina Silverlight per la visualizzazione dei dati
Nel progetto client aggiungere un nuovo elemento alla cartella Views.
Selezionare il modello Pagina Silverlight e denominare la nuova pagina Reports.xaml.
Aprire il file MainPage.xaml e aggiungere un collegamento alla pagina Reports aggiungendo il seguente codice XAML dopo l'elemento HyperlinkButton denominato
Link2
che collega alla pagina Informazioni su.<Rectangle x:Name="Divider2" Style="{StaticResource DividerStyle}"/> <HyperlinkButton x:Name="Link3" Style="{StaticResource LinkStyle}" NavigateUri="/Reports" TargetName="ContentFrame" Content="reports"/>
Aprire il file Reports.xaml e aggiungere il seguente codice XAML tra i tag
Grid
per adeguarsi alla formattazione delle altre pagine nel sito e includere un controllo HyperlinkButton che avvierà una finestra per la modifica di una proprietà del profilo.<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>
Trascinare tre controlli DataGrid dalla casella degli strumenti inserendoli subito prima del tag di fine del pannello Stack denominato
ContentStackPanel
.Quando si trascinano i controlli DataGrid dalla casella degli strumenti, viene aggiunto al progetto un riferimento all'assembly System.Windows.Controls.Data e viene aggiunto alla pagina un prefisso per lo spazio dei nomi System.Windows.Controls.
Denominare i controlli DataGrid
ProductsGrid
,SalesOrdersGrid
eCustomersGrid
e impostare l'elementoMargin
su 5.Nell'esempio seguente viene illustrato il file Reports.xaml completo.
<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>
Aprire il file Reports.xaml.cs o Reports.xaml.vb e aggiungere istruzioni using o Imports per gli spazi dei nomi System.ServiceModel.DomainServices.Client e ExampleNavigationApplication.Web.
Creare un'istanza di AdventureWorksDomainContext denominata context, quindi creare una variabile denominata numberOfRows che contiene il numero di righe da recuperare.
Private context As New AdventureWorksDomainContext Private numberOfRows As Integer = 10
private AdventureWorksDomainContext context = new AdventureWorksDomainContext(); int numberOfRows = 10;
Aggiungere un metodo denominato
LoadRestrictedReports
che chiama il metodoGetSalesOrderHeaderQuery
e il metodoGetCustomersQuery
se l'utente appartiene al ruolo Managers e popola le griglie dei dati corrispondenti con i risultati.Se si chiama un'operazione di dominio quando l'utente non dispone delle credenziali necessarie, l'operazione di dominio restituisce un'eccezione. È possibile evitare questa situazione controllando le credenziali prima di chiamare l'operazione di dominio.
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; } }
Aggiungere un metodo denominato
LoadReports
che controlla se l'utente è autenticato e, in tal caso, chiama il metodoLoadRestrictedReports
. Viene inoltre recuperata la proprietà del profilo denominataDefaultRows
e viene aggiunto un gestore eventi per l'evento PropertyChanged sull'oggetto utente. Infine, viene chiamato il metodoGetProductsQuery
per tutti gli utenti.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; }
Aggiungere un gestore eventi per l'evento PropertyChanged che chiama
LoadReports
se la proprietàDefaultRows
è stata modificata.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(); } }
Aggiungere il codice seguente al costruttore. Questo codice consente di caricare i report e di rendere visibile il collegamento alle impostazioni per gli utenti autenticati.
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; } }
Aggiungere un gestore eventi per l'evento Click al collegamento alle impostazioni.
L'oggetto
ProfileWindow
verrà aggiunto in un passaggio successivo.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(); }
Di seguito viene riportato il file di codice completo.
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(); } } }
È possibile consentire agli utenti di modificare la proprietà del profilo DefaultRows aggiungendo una finestra figlio. Quando il valore viene modificato, è possibile chiamare il metodo SaveUser per salvare il valore nell'origine dati. Viene recuperato il valore corrente tramite le proprietà nell'oggetto utente dell'istanza WebContext corrente.
Per aggiungere una finestra per l'impostazione della proprietà del profilo
Nel progetto client aggiungere un nuovo elemento alla cartella Views.
Selezionare il modello Finestra secondaria Silverlight e denominarla ProfileWindow.xaml.
Fare clic sul pulsante Aggiungi.
Nel file ProfileWindow.xaml, aggiungere il seguente codice XAML per includere un oggetto ComboBox per la selezione del numero di righe da visualizzare nei report.
<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>
Nel file code-behind ProfileWindow.xaml.cs o ProfileWindow.xaml.vb, aggiungere il codice seguente per recuperare e impostare la proprietà del profilo.
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; } }
Eseguire la soluzione.
Fare clic sul collegamento reports.
Notare che quando il sito viene avviato e l'utente non ha effettuato l'accesso, nella pagina Reports viene visualizzata soltanto la tabella dei prodotti.
Nella home page, effettuare la registrazione e l'accesso come nuovo utente.
Fare clic sul collegamento reports.
Notare che vengono visualizzate le tabelle per prodotti e ordini di vendita.
Disconnettersi e riaccedere come CustomerManager.
Notare che vengono visualizzate le tabelle per prodotti, ordini di vendita e clienti.
Fare clic sul collegamento Regola impostazioni e impostare il numero predefinito di righe da visualizzare nei rapporti.
Notare che l'elemento DataGrid contiene ora il numero di righe che si è selezionato.
Chiudere il browser Web.