Compartir a través de


Tutorial: utilizar el servicio de autenticación con una aplicación de navegación de Silverlight

En este tutorial, aprenderá a configurar sus proyectos de servidor y de cliente en una solución de WCF RIA Services para trabajar con un servicio de autenticación. Cuando se crea una solución con la plantilla Aplicación de navegación de Silverlight y se habilita RIA Services , se puede tener acceso al marco de pertenencia a ASP.NET agregando un servicio de autenticación. El servicio de autenticación expone autenticación, roles y perfiles del proyecto de servidor en el proyecto de cliente. Puede utilizar el servicio de autenticación para validar credenciales de usuario, restringir el acceso a los recursos basándose en roles y almacenar propiedades de perfil.

[!NOTA] La Aplicación de negocios de Silverlight implementa automáticamente el servicio de autenticación. Para obtener más información, vea Tutorial: utilizar el servicio de autenticación con una aplicación de negocios de Silverlight.

Requisitos previos

Este tutorial y los demás tutoriales presentados en la documentación de RIA Services requieren la instalación y configuración correctas de varios programas de requisitos previos, como Visual Studio 2010 y Silverlight Developer Runtime y SDK, además de WCF RIA Services y el Kit de herramientas de WCF RIA Services. También requieren la instalación y configuración de SQL Server 2008 R2 Express con Advanced Services, así como la instalación de las bases de datos OLTP y LT de AdventureWorks.

Los temas del nodo Requisitos previos para WCF RIA Services proporcionan instrucciones detalladas para el cumplimiento de cada uno de estos requisitos previos. Siga las instrucciones proporcionadas en ellos antes de realizar este tutorial para asegurarse de encontrar el menor número de problemas posibles al trabajar en estos tutoriales de RIA Services .

Configurar el proyecto de servidor para autenticación, roles y perfiles

Para utilizar el servicio de autenticación de una aplicación de Silverlight, se debe configurar la autenticación en el proyecto de servidor. La autenticación se configura en el archivo Web.config. Después de configurar la autenticación, también se pueden configurar roles y perfiles en el proyecto de servidor, si se desea utilizar esas características de la aplicación de Silverlight. En este tutorial, configurará las tres características. Finalmente, agregará un servicio de autenticación que expone las características habilitadas al cliente.

Para configurar el proyecto de servidor

  1. En Visual Studio 2010, seleccione Archivo, Nuevo y, a continuación, Proyecto.

    Aparece el cuadro de diálogo Nuevo proyecto.

  2. Seleccione el tipo de proyecto Silverlight.

  3. Seleccione la plantilla Aplicación de navegación de Silverlight y asigne a la aplicación el nombre ExampleNavigationApplication.

  4. Haga clic en Aceptar.

    Aparece el cuadro de diálogo Nueva aplicación de Silverlight.

  5. Asegúrese de que la casilla Hospedar la aplicación de Silverlight en un nuevo sitio web esté activada y de que el tipo de proyecto web nuevo esté establecido en Proyecto de aplicación web ASP.NET.

  6. Active la casilla Habilitar WCF RIA Services.

  7. Haga clic en Aceptar para crear la solución.

  8. En el proyecto de servidor (ExampleBusinessApplication.Web), abra el archivo Web.config.

  9. En el elemento <system.web>, agregue un elemento <authentication> y establezca el valor de la propiedad mode en Forms.

    <authentication mode="Forms"></authentication>
    
  10. En el elemento <system.web>, agregue un elemento <roleManager> y establezca el valor de la propiedad enabled en true.

    <roleManager enabled="true"></roleManager>
    
  11. En el elemento <system.web>, agregue un elemento <profile>, establezca la propiedad enabled en true e incluya una propiedad profile denominada DefaultRows.

    <profile enabled="true">
      <properties>
        <add type="System.Int32" defaultValue="10" name="DefaultRows"/>
      </properties>
    </profile>
    

    El elemento <system.web> completado debe incluir los elementos siguientes.

    <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. Guarde el archivo Web.config.

  13. En el Explorador de soluciones, haga clic con el botón secundario en el proyecto de servidor, seleccione Agregar y, a continuación, Nuevo elemento.

    Aparece el cuadro de diálogo Agregar nuevo elemento.

  14. Seleccione la plantilla DomainService de autenticación y denomínela AuthenticationDomainService.

  15. Haga clic en Agregar.

  16. Abra el archivo de código de servicio de autenticación (AuthenticationDomainService.cs o AuthenticationDomainService.vb) y agregue la propiedad DefaultRows que definió en el archivo Web.config a la clase 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. Genere la solución.

En esta sección, utilizará la herramienta Administración de sitios Web de ASP.NET para crear un usuario y un rol. Iniciará sesión como este usuario en una sección posterior.

Para agregar usuarios con la herramienta Administración de sitios Web de ASP.NET

  1. Para abrir la herramienta Administración de sitios Web de ASP.NET, primero seleccione el proyecto de servidor en el Explorador de soluciones.

  2. En el menú Proyecto, seleccione Configuración de ASP.NET.

    Si no ve la opción Configuración de ASP.NET en el menú Proyecto, puede que se deba a haber seleccionado el proyecto de cliente.

  3. Seleccione la pestaña Seguridad en la herramienta Administración de sitios Web de ASP.NET.

  4. En la sección Roles, haga clic en el vínculo Crear o administrar roles.

  5. Agregue un nuevo rol denominado Managers y haga clic en el botón Agregar rol.

  6. En la esquina inferior derecha, haga clic en el botón Atrás.

  7. En la sección Usuarios, haga clic en el vínculo Crear usuario.

  8. Cree un nuevo usuario con los valores siguientes y active la casilla de rol Managers.

    Nombre de usuario: CustomerManager

    Contraseña: P@ssword

    Correo electrónico: alguien@ejemplo.com

    Pregunta de seguridad: ¿Color favorito?

    Respuesta de seguridad: Azul

    Rol Managers: seleccionado

  9. Haga clic en el botón Crear usuario.

  10. Cierre la herramienta Administración de sitios Web de ASP.NET.

Configurar el cliente para la autenticación

Debe configurar el proyecto de cliente para utilizar el modo de autenticación que coincida con el modo de autenticación que configuró en el proyecto de servidor.

Para configurar el proyecto de cliente

  1. En el proyecto de cliente, abra el archivo de código subyacente para el archivo App.xaml (App.xaml.cs o App.xaml.vb).

  2. En el constructor, cree una nueva instancia de la clase WebContext.

  3. Establezca la propiedad Authentication en una nueva instancia de la clase FormsAuthentication y agregue la instancia de WebContext al elemento 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);
    }
    

Agregar funcionalidad de inicio de sesión al cliente

En esta sección, agregará controles de Silverlight que permiten al usuario proporcionar nombre de usuario y contraseña para el inicio de sesión. Agregará código que llama al método Login con las credenciales del usuario. También establecerá qué controles están visibles basándose en si el usuario ha iniciado sesión.

Para simplificar, la interfaz de usuario de inicio de sesión se agrega a la página Inicio en este tutorial. En la aplicación, puede crear una página de inicio de sesión independiente.

Para el inicio y cierre de sesión de un usuario

  1. En el Explorador de soluciones, expanda la carpeta Views en el proyecto de cliente.

  2. Abra el archivo Home.xaml.

  3. A continuación del TextBlock denominado ContentText, agregue el código XAML siguiente.

    El código XAML incluye un control TextBox para proporcionar un nombre de usuario, un control PasswordBox para proporcionar una contraseña, un control Button para enviar la solicitud de inicio de sesión y un control TextBlock y HyperlinkButton para el cierre de sesión que solo se mostrarán después de que el usuario haya iniciado sesión.

    <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. Abra el archivo de código subyacente para la página principal (Home.xaml.cs o Home.xaml.vb).

  5. Agregue una instrucción using o Imports al espacio de nombres System.ServiceModel.DomainServices.Client.ApplicationServices.

  6. Agregue el código siguiente a la clase Home.

    El código incluye controladores de eventos para el inicio y cierre de sesión, métodos de devolución de llamada para las operaciones completadas de inicio y cierre de sesión, y un método que establece la visibilidad de los controles basándose en si el usuario está autenticado.

    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. Ejecute la solución.

  8. Inicie sesión como CustomerManager con la contraseña P@ssword.

    Observe que ya no se muestra el área de inicio de sesión, pero ahora se muestran el texto de bienvenida y el vínculo de cierre de sesión.

  9. Haga clic en el vínculo Cerrar sesión y cierre el explorador web.

Agregar nuevos usuarios del cliente

El servicio de autenticación no contiene una operación para crear nuevos usuarios. Para registrar un nuevo usuario, debe crear un servicio de dominio vacío y agregar una operación para agregar un usuario al marco de pertenencia a ASP.NET.

Para configurar el proyecto de servidor para agregar a un nuevo usuario

  1. En el proyecto de servidor, agregue un nuevo archivo de clase denominado NewUser.

  2. Defina las propiedades para registrar un nuevo usuario agregando el siguiente código a la clase 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 propiedad ConfirmPassword del paso anterior se define con un atributo CustomValidationAttribute. En el atributo, especifique una clase RegistrationValidator y un método denominado IsPasswordConfirmed. Ahora debe definir esta clase de validación personalizada.

  3. Agregue una nueva clase denominada RegistrationValidator.shared.cs o RegistrationValidator.shared.vb.

  4. Agregue el código siguiente al archivo 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. Agregue un nuevo elemento al proyecto de servidor y seleccione la plantilla Clase de servicio de dominio.

  6. Asigne al archivo el nombre RegistrationDomainService.cs o RegistrationDomainService.vb y, a continuación, haga clic en el botón Agregar.

  7. En el cuadro de diálogo Agregar nueva clase de servicio de dominio, seleccione <clase de servicio de dominio vacía> en la lista Available DataContexts/ObjectContexts.

  8. Haga clic en Aceptar.

  9. Para crear una operación de dominio que agregue un nuevo usuario mediante el marco de pertenencia y guarde una propiedad de perfil, agregue el código siguiente a la clase RegistrationDomainService.

    Se debe incluir el método GetUsers para asegurarse de que la clase de entidad NewUser se genera para el proyecto de cliente. Solo las clases que se exponen a través de una operación de consulta pública se generan en el proyecto de cliente.

    Después de crear el usuario, se establece la propiedad de perfil denominada DefaultRows. En este caso, la propiedad de perfil se establece como parte de la operación de dominio para crear un usuario. En una sección posterior, agregará código para establecer la propiedad de perfil del proyecto de cliente.

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

Para configurar el proyecto de cliente para agregar nuevos usuarios

  1. Abra el archivo Home.xaml.

  2. Después de la etiqueta de cierre para el control BorderLoginBorder , agregue el código XAML siguiente para crear un segundo control Border con controles de entrada para recopilar información para la creación de nuevos usuarios.

    Los controles aceptan valores para el nombre de usuario, la contraseña, la confirmación de contraseña, la dirección de correo electrónico, la pregunta de seguridad, la respuesta de seguridad y el número de registros para mostrar en los informes. El número de registros para mostrar se guardará como una propiedad de perfil. Todos los demás valores se utilizan para crear al usuario mediante el marco de pertenencia a 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. Abra el archivo de código subyacente Home.xaml.cs (o Home.xaml.vb).

  4. Agregue una instrucción using o Imports a los espacios de nombres System.ServiceModel.DomainServices.Client, System.ComponentModel.DataAnnotations y ExampleNavigationApplication.Web.

  5. Agregue un controlador de eventos para el evento Click del botón de registro y agregue un método de devolución de llamada para la operación de dominio. El método de devolución de llamada incluye código para el inicio de sesión del usuario después de crearse correctamente la cuenta de usuario.

    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. Modifique el método SetControlVisibility para establecer la visibilidad de RegisterBorder, como se muestra en el código siguiente.

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

    En el ejemplo siguiente se muestra el archivo de código subyacente 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. Ejecute la solución.

  8. Proporcione valores para registrar un nuevo usuario.

  9. Cierre el explorador web.

Restringir el acceso a las operaciones de dominio

Puede restringir el acceso a una operación de dominio aplicando el atributo RequiresAuthenticationAttribute o el atributo RequiresRoleAttribute a la operación de dominio. Las operaciones de dominio sin un atributo están disponibles para todos los usuarios. La aplicación de un atributo a la operación de dominio no impide que el usuario llame a la operación de dominio; sin embargo, los usuarios sin las credenciales necesarias recibirán una excepción.

Para restringir los datos mostrados mediante roles

  1. En el Explorador de soluciones, seleccione el proyecto de servidor y haga clic en el botón Mostrar todos los archivos.

  2. Haga clic con el botón secundario en la carpeta App_Data y seleccione Incluir en el proyecto.

  3. Haga clic con el botón secundario en la carpeta App_Data, seleccione Agregar y, a continuación, haga clic en Elemento existente.

  4. En el cuadro de diálogo Agregar elemento existente, agregue la base de datos de ejemplo AdventureWorksLT.

  5. En el proyecto de servidor, agregue un nuevo elemento y seleccione la plantilla Entity Data Model de ADO.NET.

  6. Asigne al modelo el nombre AdventureWorksModel.edmx y haga clic en Agregar.

    Aparecerá el Asistente para Entity Data Model.

  7. Seleccione la opción Generar desde la base de datos y, a continuación, haga clic en Siguiente.

  8. Seleccione la base de datos AdventureWorksLT y, a continuación, haga clic en Siguiente.

  9. En la lista de objetos de base de datos, seleccione las tablas Customer, Product y SalesOrderHeader y, a continuación, haga clic en Finalizar.

    Aparece Entity Data Model en el diseñador.

  10. Genere la solución.

  11. En el proyecto de servidor, agregue un nuevo elemento y seleccione la plantilla Clase de servicio de dominio.

  12. Asigne el nombre AdventureWorksDomainService al servicio de dominio y, a continuación, haga clic en Agregar.

  13. En el cuadro de diálogo Agregar nueva clase de servicio de dominio, seleccione las entidades Customer, Product y SalesOrderHeader.

  14. Haga clic en Aceptar para finalizar la creación del servicio de dominio.

  15. En el archivo de clase AdventureWorksDomainService, agregue el atributo RequiresAuthenticationAttribute al método 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. Agregue el atributo RequiresRoleAttribute al método GetCustomers y establezca el nombre del rol necesario en "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;
    }
    

    La operación de dominio GetProducts está disponible para cualquier usuario, GetSalesOrderHeaders está disponible para los usuarios autenticados y GetCustomers está disponible solo para los usuarios del rol Managers.

    En el ejemplo siguiente se muestra el servicio de 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;
        }
    }
    

Utilizar el servicio de autenticación del cliente

Antes de llamar a una operación de dominio con permisos restringidos, debe comprobar que el usuario tiene las credenciales necesarias; de lo contrario, se producirá una excepción. En esta sección, comprobará las credenciales del usuario y rellenará de uno a tres controles DataGrid basándose en las credenciales del usuario. También recuperará el número de registros basándose en una propiedad del perfil de usuario. Se utiliza un valor predeterminado de 10 para los usuarios que no se autentican. En esta sección no se incluye una fórmula para que los usuarios establezcan la propiedad de perfil DefaultRows, pero la agregará en una sección posterior.

Para agregar una página de Silverlight para mostrar datos

  1. En el proyecto de cliente, agregue un nuevo elemento a la carpeta Views.

  2. Seleccione la plantilla Página de Silverlight y asigne a la nueva página el nombre Reports.xaml.

  3. Abra el archivo MainPage.xaml y agregue un vínculo para la página Informes agregando el siguiente código XAML a continuación del HyperlinkButton denominado Link2 que vincula a la página Acerca de.

     <Rectangle x:Name="Divider2" Style="{StaticResource DividerStyle}"/>
    
     <HyperlinkButton x:Name="Link3" Style="{StaticResource LinkStyle}" 
    NavigateUri="/Reports" TargetName="ContentFrame" Content="reports"/>
    
  4. Abra el archivo Reports.xaml y agregue el siguiente código XAML dentro de las etiquetas Grid para que coincida con el formato de las demás páginas del sitio y para incluir un control HyperlinkButton que iniciará una ventana para editar una propiedad de perfil.

    <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. Arrastre tres controles DataGrid desde el Cuadro de herramientas hasta un punto situado justo delante de la etiqueta de cierre del panel de pila denominado ContentStackPanel.

    Al arrastrar los controles DataGrid desde el Cuadro de herramientas, se agrega al proyecto una referencia al ensamblado System.Windows.Controls.Data y se agrega a la página un prefijo para el espacio de nombres System.Windows.Controls.

  6. Asigne a los controles DataGrid los nombres ProductsGrid, SalesOrdersGrid y CustomersGrid, y establezca Margin en 5.

    En el ejemplo siguiente se muestra el archivo 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. Abra el archivo Reports.xaml.cs o Reports.xaml.vb y agregue las instrucciones Imports o using a los espacios de nombres ExampleNavigationApplication.Web y System.ServiceModel.DomainServices.Client.

  8. Cree una instancia del contexto con nombre AdventureWorksDomainContext y cree una variable denominada numberOfRows que contenga el número de filas que se van a recuperar.

    Private context As New AdventureWorksDomainContext
    Private numberOfRows As Integer = 10
    
    private AdventureWorksDomainContext context = new AdventureWorksDomainContext();
    int numberOfRows = 10;
    
  9. Agregue un método denominado LoadRestrictedReports que llama al método GetSalesOrderHeaderQuery y al método GetCustomersQuery, si el usuario pertenece al rol Managers, y rellena las cuadrículas de datos correspondientes con los resultados.

    Si llama a una operación de dominio pero el usuario no tiene las credenciales necesarias, la operación de dominio devuelve una excepción. Puede evitar esta situación comprobando las credenciales antes de llamar a la operación de 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. Agregue un método denominado LoadReports que comprueba si el usuario está autenticado y, en ese caso, llame al método LoadRestrictedReports. También recupera la propiedad de perfil denominada DefaultRows y agrega un controlador de eventos para el evento PropertyChanged en el objeto User. Finalmente, llama al método GetProductsQuery para todos los usuarios.

    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. Agregue un controlador de eventos para el evento PropertyChanged que llama a LoadReports si la propiedad DefaultRows ha cambiado.

    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. Agregue el código siguiente al constructor. Este código carga los informes y hace que el vínculo de configuración esté visible para los usuarios autenticados.

    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. Agregue un controlador de eventos para el evento Click en el vínculo de configuración.

    El elemento ProfileWindow se agregará en un paso posterior.

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

    En el ejemplo siguiente se muestra el archivo de código 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();
            }
        }
    }
    

Puede permitir a los usuarios que editen la propiedad de perfil DefaultRows agregando una ventana secundaria. Cuando se cambia el valor, debe llamar al método SaveUser para guardar el valor en el origen de datos. El valor actual se recupera mediante las propiedades del objeto User de la instancia de WebContext actual.

Para agregar una ventana para establecer la propiedad de perfil

  1. En el proyecto de cliente, agregue un nuevo elemento a la carpeta Views.

  2. Seleccione la plantilla Ventana secundaria de Silverlight y asigne a la ventana secundaria el nombre ProfileWindow.xaml.

  3. Haga clic en el botón Agregar.

  4. En el archivo ProfileWindow.xaml, agregue el código XAML siguiente para incluir un control ComboBox para seleccionar el número de filas para mostrar en los informes.

    <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. En el archivo de código subyacente ProfileWindow.xaml.cs o ProfileWindow.xaml.vb, agregue el código siguiente para recuperar y establecer la propiedad de perfil.

    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. Ejecute la solución.

  7. Haga clic en el vínculo de informes.

    Observe que si el sitio se inicia y no ha iniciado sesión, solo se mostrará la tabla de productos en la página Informes.

  8. En la página Inicio, registre e inicie sesión como un nuevo usuario.

  9. Haga clic en el vínculo de informes.

    Observe que se muestran las tablas de productos y pedidos de ventas.

  10. Cierre la sesión e inicie sesión como CustomerManager.

    Observe que se muestran las tablas de productos, pedidos de ventas y clientes.

  11. Haga clic en el vínculo Ajustar configuración y establezca el número predeterminado de filas que se van a mostrar para los informes.

    Observe que el control DataGrid contiene ahora el número de filas seleccionado.

  12. Cierre el explorador web.

Vea también

Tareas

Tutorial: utilizar el servicio de autenticación con una aplicación de negocios de Silverlight