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

  1. In Visual Studio 2010, selezionare File, Nuovo, quindi Progetto.

    Verrà visualizzata la finestra di dialogo Nuovo progetto.

  2. Selezionare il tipo di progetto Silverlight.

  3. Selezionare il modello Applicazione di navigazione Silverlight e denominare l'applicazione ExampleNavigationApplication.

  4. Fare clic su OK.

    Verrà visualizzata la finestra di dialogo Nuova applicazione Silverlight.

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

  6. Selezionare la casella di controllo Abilita WCF RIA Services.

  7. Fare clic su OK per creare la soluzione.

  8. Nel progetto server (ExampleBusinessApplication.Web) aprire il file Web.config.

  9. Nell'elemento <system.web> aggiungere un elemento <authentication> e impostare la proprietà mode su Form.

    <authentication mode="Forms"></authentication>
    
  10. Nell'elemento <system.web> aggiungere un elemento <roleManager> e impostare la proprietà enabled su true.

    <roleManager enabled="true"></roleManager>
    
  11. 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>
    
  12. Salvare il file Web.config.

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

  14. Selezionare il modello DomainService di autenticazione e denominarlo AuthenticationDomainService.

    RIA_ServicesAddAuth

  15. Fare clic su Aggiungi.

  16. 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; }
    }
    
  17. 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

  1. Per aprire lo strumento Amministrazione sito Web di ASP.NET, selezionare innanzitutto il progetto server in Esplora soluzioni.

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

    RIA_OpenAdminTool

  3. Selezionare la scheda Sicurezza nello strumento Amministrazione sito Web di ASP.NET.

    RIA_WebAdminSecurity

  4. Nella sezione Ruoli, fare clic sul collegamento Crea o gestisci ruoli.

  5. Aggiungere un nuovo ruolo denominato Managers e fare clic sul pulsante Aggiungi ruolo.

    WebAdmin_CreateRole

  6. Nell'angolo inferiore destro, fare clic sul pulsante Indietro.

  7. Nella sezione Utenti, fare clic sul collegamento Crea utente.

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

    WebAdmin_CreateUser

  9. Fare clic sul pulsante Crea utente.

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

  1. Nel progetto client aprire il file code-behind per il file App.xaml (App.xaml.cs o App.xaml.vb).

  2. Nel costruttore creare una nuova istanza della classe WebContext.

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

  1. In Esplora soluzioni espandere la cartella Views nel progetto client.

  2. Aprire il file Home.xaml.

  3. 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>
    
  4. Aprire il file code-behind per la home page (Home.xaml.cs or Home.xaml.vb).

  5. Aggiungere un'istruzione using o Imports per lo spazio dei nomi System.ServiceModel.DomainServices.Client.ApplicationServices.

  6. 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();
        }
    }
    
  7. Eseguire la soluzione.

    RS_CustomLoginNav

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

    RIA_CustomLoggedInNav

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

  1. Nel progetto server, aggiungere un nuovo file di classe denominato NewUser.

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

  3. Aggiungere una nuova classe denominata RegistrationValidator.shared.cs o RegistrationValidator.shared.vb.

  4. 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.");
                }
            }
        }
    }
    
  5. Aggiungere un nuovo elemento al progetto server e selezionare il modello Classe di DomainService.

  6. Denominare il file RegistrationDomainService.cs o RegistrationDomainService.vb, quindi fare clic sul pulsante Aggiungi.

  7. Nella finestra di dialogo Aggiungi una nuova classe DomainService, selezionare <Classe DomainService vuota> dall'elenco Classi DataContext/ObjectContext disponibili.

  8. Fare clic su OK.

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

  1. Aprire il file Home.xaml.

  2. Dopo il tag di fine per il controllo LoginBorderBorder, 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>
    
  3. Aprire il file code-behind Home.xaml.cs (o Home.xaml.vb).

  4. Aggiungere un'istruzione using o Imports per gli spazi dei nomi System.ServiceModel.DomainServices.Client, System.ComponentModel.DataAnnotations e ExampleNavigationApplication.Web.

  5. 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;
    }
    
  6. 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;
            }
        }
    }
    
  7. Eseguire la soluzione.

    RIA_LoginandRegister

  8. Fornire valori per registrare un nuovo utente.

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

  1. Nella finestra Esplora soluzioni selezionare il progetto server e fare clic sul pulsante Mostra tutti i file.

  2. Fare clic con il pulsante destro del mouse sulla cartella App_Data e scegliere Includi nel progetto.

  3. Fare clic con il pulsante destro del mouse sulla cartella App_Data, scegliere Aggiungi, quindi Elemento esistente.

  4. Nella finestra di dialogo Aggiungi elemento esistente, aggiungere il database di esempio AdventureWorksLT.

  5. Nel progetto server aggiungere un nuovo elemento e selezionare il modello ADO.NET Entity Data Model.

  6. Denominare il modello AdventureWorksModel.edmx, quindi fare clic su Aggiungi.

    Viene visualizzata la procedura guidata Entity Data Model.

  7. Selezionare l'opzione Genera da database, quindi fare clic su Avanti.

  8. Selezionare il database AdventureWorksLT e fare clic su Avanti.

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

  10. Compilare la soluzione.

  11. Aggiungere un nuovo elemento al progetto server e selezionare il modello Classe di DomainService.

  12. Denominare il servizio del dominio AdventureWorksDomainService, quindi fare clic su Aggiungi.

  13. Nella finestra di dialogo Aggiungi una nuova classe DomainService, selezionare le entità Customer, Product e SalesOrderHeader.

    RIA_CreateDSForAuth

  14. Fare clic su OK per finalizzare la creazione del servizio del dominio.

  15. 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;
    }
    
  16. 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 e GetCustomers è 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

  1. Nel progetto client aggiungere un nuovo elemento alla cartella Views.

  2. Selezionare il modello Pagina Silverlight e denominare la nuova pagina Reports.xaml.

  3. 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"/>
    
  4. 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>
    
  5. 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.

  6. Denominare i controlli DataGridProductsGrid, SalesOrdersGrid e CustomersGrid e impostare l'elemento Margin 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>
    
  7. 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.

  8. 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;
    
  9. Aggiungere un metodo denominato LoadRestrictedReports che chiama il metodo GetSalesOrderHeaderQuery e il metodo GetCustomersQuery 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;
        }
    }
    
  10. Aggiungere un metodo denominato LoadReports che controlla se l'utente è autenticato e, in tal caso, chiama il metodo LoadRestrictedReports. Viene inoltre recuperata la proprietà del profilo denominata DefaultRows e viene aggiunto un gestore eventi per l'evento PropertyChanged sull'oggetto utente. Infine, viene chiamato il metodo GetProductsQuery 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;
    }
    
  11. 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();
        }
    }
    
  12. 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;
        }
    }
    
  13. 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

  1. Nel progetto client aggiungere un nuovo elemento alla cartella Views.

  2. Selezionare il modello Finestra secondaria Silverlight e denominarla ProfileWindow.xaml.

    Finestra Aggiungi figlio

  3. Fare clic sul pulsante Aggiungi.

  4. 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>
    
  5. 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;
        }
    }
    
  6. Eseguire la soluzione.

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

  8. Nella home page, effettuare la registrazione e l'accesso come nuovo utente.

  9. Fare clic sul collegamento reports.

    Notare che vengono visualizzate le tabelle per prodotti e ordini di vendita.

  10. Disconnettersi e riaccedere come CustomerManager.

    Notare che vengono visualizzate le tabelle per prodotti, ordini di vendita e clienti.

  11. Fare clic sul collegamento Regola impostazioni e impostare il numero predefinito di righe da visualizzare nei rapporti.

    RIA_ShowProfileSettings

    Notare che l'elemento DataGrid contiene ora il numero di righe che si è selezionato.

  12. Chiudere il browser Web.

Vedere anche

Attività

Procedura dettagliata: utilizzo del servizio di autenticazione con l'applicazione aziendale di Silverlight