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

La plantilla Aplicación de negocios de Silverlight crea una solución que habilita automáticamente autenticación (con autenticación mediante formularios para el modo de autenticación), roles y perfiles. La solución incluye formularios de datos para el inicio de sesión de usuarios existentes y el registro de nuevos usuarios. Puede utilizar estas características sin escribir ningún código adicional. Puede personalizar la solución definiendo roles y propiedades de perfil.

En este tutorial, aprenderá a usar autenticación, roles y perfiles en una aplicación de negocios de Silverlight. Restringirá el acceso a ciertas operaciones de dominio basándose en las credenciales del usuario y personalizará la interfaz de usuario basándose en las preferencias del usuario. Utilizará la herramienta Administración de sitios Web de ASP.NET para administrar roles y usuarios en el sitio.

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 este tutorial de RIA Services .

Crear usuarios y roles

Puede utilizar las características proporcionadas en una aplicación de negocios de Silverlight para implementar la autenticación rápidamente. En la sección siguiente, utilizará la herramienta Configuración de ASP.NET para crear un usuario y un rol y, a continuación, iniciar sesión como ese usuario. Registrará un nuevo usuario mediante el formulario de registro que se proporciona en la aplicación de negocios de Silverlight.

Para crear un sitio, roles y usuarios

  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 negocios de Silverlight y asigne a la aplicación el nombre ExampleBusinessApplication.

    RIA_ServicesCreateBizApp

  4. Haga clic en Aceptar.

    Observe la estructura de proyecto que se crea. El proyecto de cliente de Silverlight incluye páginas de Silverlight en la carpeta Views. Estas páginas permiten el inicio de sesión de usuarios y el registro de nuevos usuarios.

  5. Para abrir la herramienta Administración de sitios Web de ASP.NET, seleccione primero el proyecto de servidor (ExampleBusinessApplication.Web) en el Explorador de soluciones y abra la herramienta Configuración de ASP.NET.

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

    RIA_OpenAdminTool

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

    RIA_WebAdminSecurity

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

  9. Agregue un nuevo rol denominado Managers y seleccione el botón Agregar rol.

    WebAdmin_CreateRole

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

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

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

    WebAdmin_CreateUser

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

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

  15. Ejecute la solución.

    Aparece la página principal de la aplicación en un explorador web.

  16. En la esquina superior derecha de la página, haga clic en el vínculo de inicio de sesión.

    Aparece un cuadro de diálogo Inicio de sesión.

  17. Escriba CustomerManager para el nombre de usuario y P@ssword para la contraseña, y haga clic en el botón Aceptar.

    RIA_LoginManager

    Iniciará sesión como ese usuario. Observe el texto de bienvenida a CustomerManager en la esquina superior derecha.

  18. Haga clic en el vínculo de cierre de sesión.

    Habrá dejado de iniciar sesión como CustomerManager. En los pasos siguientes, creará un nuevo usuario mediante el formulario de registro.

  19. Haga clic de nuevo en el vínculo de inicio de sesión.

  20. En el cuadro de diálogo Inicio de sesión, haga clic en el vínculo Registrarse.

    Se mostrará el formulario de registro.

  21. Rellene el formulario de registro para crear una nueva cuenta de usuario. Utilice los siguientes valores para el nuevo usuario.

    Nombre de usuario: SalesUser

    Nombre descriptivo: SalesUser

    Correo electrónico: alguien@ejemplo.com

    Contraseña: P@ssword

    Pregunta de seguridad: ¿Cuál era el color de su primer coche?

    Respuesta de seguridad: Verde

    RIA_RegisterUser

  22. Haga clic en Aceptar para crear el nuevo usuario.

    Observe que ha iniciado sesión como SalesUser.

  23. Cierre el explorador.

  24. Abra de nuevo la herramienta Administración de sitios Web de ASP.NET y haga clic en la pestaña Seguridad.

    Observe que existen 2 usuarios en el sitio y 2 roles, aunque solo ha creado un rol.

  25. Haga clic en Crear o administrar roles y observe los roles Managers y Registered Users.

    El rol Registered Users lo creó automáticamente la plantilla Aplicación de negocios.

    RIA_ManageRoles

  26. Para Registered Users, haga clic en el vínculo Administrar.

    Observe que el usuario denominado SalesUser que agregó en la aplicación está en el rol Registered Users.

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

Definir el acceso y las propiedades de perfil

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.

Restringir los datos mostrados mediante roles

  1. En el Explorador de soluciones, haga clic con el botón secundario en la carpeta App_Data en el proyecto de servidor, seleccione Agregar y, después, Elemento existente.

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

  3. En el proyecto de servidor, agregue un nuevo elemento y seleccione la plantilla Entity Data Model de ADO.NET en las plantillas Datos.

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

    Aparecerá el Asistente para Entity Data Model.

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

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

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

  8. Genere la solución.

  9. En el proyecto de servidor, agregue un nuevo elemento y seleccione la plantilla Clase de servicio de dominio de las plantillas web.

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

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

    RIA_CreateDSForAuth

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

  13. 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;
    }
    
  14. 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;
        }
    }
    

Puede definir una propiedad de perfil en el archivo Web.config. Cuando agregue la propiedad a la clase User en el servidor, se generará la propiedad correspondiente para el proyecto de cliente.

Agregar propiedades de perfil

  1. En el proyecto de servidor, abra el archivo Web.config.

  2. En el elemento <profile>, agregue una propiedad de perfil denominada DefaultRows. La propiedad contendrá la preferencia del usuario para el número de filas que se van a mostrar.

    En el ejemplo siguiente se muestra la sección de perfil del archivo Web.config.

    <profile>
      <properties>
        <add name="FriendlyName" />
        <add type="System.Int32" defaultValue="10" name="DefaultRows"/>
      </properties>
    </profile>
    
  3. Guarde el archivo Web.config.

  4. En el proyecto de servidor, expanda la carpeta Models.

  5. Abra el archivo User.cs o User.vb y agregue una propiedad denominada DefaultRows.

    Imports System.ServiceModel.DomainServices.Server.ApplicationServices
    Imports System.Runtime.Serialization
    Namespace Web
        Partial Public Class User
            Inherits UserBase
    
            Public Property FriendlyName As String
    
            Public Property DefaultRows As Integer
    
        End Class
    End Namespace
    
    namespace ExampleBusinessApplication.Web
    {
        using System.Runtime.Serialization;
        using System.ServiceModel.DomainServices.Server.ApplicationServices;
    
        public partial class User : UserBase
        {
            public string FriendlyName { get; set; }
    
            public int DefaultRows { get; set; }
        }
    }
    

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 la sección siguiente, 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.

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="{Binding Path=ApplicationStrings.ReportsPageTitle, Source={StaticResource ResourceWrapper}}"/>
    
  4. En la carpeta Assets\Resources, abra el archivo ApplicationStrings.resx.

  5. Agregue un nuevo recurso de cadena denominado ReportsPageTitle con el valor de Reports.

    RIA_AddReportResource

  6. Guarde y cierre el archivo ApplicationStrings.resx.

  7. Abra el archivo Reports.xaml y agregue el siguiente código XAML al elemento Grid para que coincida con el formato de las otras páginas del sitio.

    <ScrollViewer x:Name="PageScrollViewer" Style="{StaticResource PageScrollViewerStyle}">
        <StackPanel x:Name="ContentStackPanel" Style="{StaticResource ContentStackPanelStyle}">
            <TextBlock x:Name="HeaderText" Style="{StaticResource HeaderTextStyle}"
                       Text="{Binding Path=ApplicationStrings.ReportsPageTitle, Source={StaticResource ResourceWrapper}}"/>
            <TextBlock x:Name="ContentText" Style="{StaticResource ContentTextStyle}"
                       Text="Display reports based on user permissions"/>
    
        </StackPanel>
    </ScrollViewer>
    
  8. 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.

  9. Asigne a los controles los nombres DataGrid, ProductsGrid, SalesOrdersGrid y CustomersGrid.

  10. Para cada control DataGrid, establezca el valor de la propiedad Margin en 5.

    En el ejemplo siguiente se muestra el archivo Reports.xaml completo.

    <navigation:Page x:Class="ExampleBusinessApplication.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:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"
               xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"
               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" Style="{StaticResource ContentStackPanelStyle}">
                    <TextBlock x:Name="HeaderText" Style="{StaticResource HeaderTextStyle}"
                               Text="{Binding Path=ApplicationStrings.ReportsPageTitle, Source={StaticResource ResourceWrapper}}"/>
                    <TextBlock x:Name="ContentText" Style="{StaticResource ContentTextStyle}"
                               Text="Display reports based on user permissions"/>
                    <data:DataGrid Name="ProductsGrid" Margin="5" />
                    <data:DataGrid Name="SalesOrdersGrid" Margin="5" />
                    <data:DataGrid Name="CustomersGrid" Margin="5" />
                </StackPanel>
            </ScrollViewer>
        </Grid>
    </navigation:Page>
    
  11. Abra el archivo Reports.xaml.cs o Reports.xaml.vb.

  12. Para C#, agregue instrucciones using para los espacios de nombres System.ServiceModel.DomainServices.Client, ExampleBusinessApplication.Web y System.ServiceModel.DomainServices.Client.ApplicationServices. Para Visual Basic, agregue instrucciones Imports para los espacios de nombres System.ServiceModel.DomainServices.Client, System.ServiceModel.DomainServices.Client.ApplicationServices, ExampleBusinessApplication.Web y System.Windows.Controls.

  13. 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;
    
  14. 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;
        }
    }
    
  15. 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;
    }
    
  16. 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();
        }
    }
    
  17. Agregue controladores de eventos para los eventos LoggedOut y LoggedIn que cargan u ocultan datos basándose en el cambio de las credenciales de autenticación de usuario.

    Private Sub Authentication_LoggedIn(ByVal sender As Object, ByVal e As ApplicationServices.AuthenticationEventArgs)
        LoadReports()
    End Sub
    
    Private Sub Authentication_LoggedOut(ByVal sender As Object, ByVal e As ApplicationServices.AuthenticationEventArgs)
        CustomersGrid.Visibility = System.Windows.Visibility.Collapsed
        SalesOrdersGrid.Visibility = System.Windows.Visibility.Collapsed
    End Sub
    
    void Authentication_LoggedIn(object sender, AuthenticationEventArgs e)
    {
        LoadReports();
    }
    
    void Authentication_LoggedOut(object sender, AuthenticationEventArgs e)
    {
        CustomersGrid.Visibility = System.Windows.Visibility.Collapsed;
        SalesOrdersGrid.Visibility = System.Windows.Visibility.Collapsed;
    }
    
  18. Agregue el código siguiente al constructor. Este código carga los controladores y llama a LoadReports.

    Public Sub New()
        InitializeComponent()
    
        Me.Title = ApplicationStrings.ReportsPageTitle
    
        AddHandler WebContext.Current.Authentication.LoggedIn, AddressOf Authentication_LoggedIn
        AddHandler WebContext.Current.Authentication.LoggedOut, AddressOf Authentication_LoggedOut
    
        LoadReports()
    End Sub
    
    public Reports()
    {
        InitializeComponent();
    
        this.Title = ApplicationStrings.ReportsPageTitle;
    
        WebContext.Current.Authentication.LoggedIn += new System.EventHandler<AuthenticationEventArgs>(Authentication_LoggedIn);
        WebContext.Current.Authentication.LoggedOut += new System.EventHandler<AuthenticationEventArgs>(Authentication_LoggedOut);
    
        LoadReports();
    }
    

    En el ejemplo siguiente se muestra el archivo de código completo.

    Imports System.Windows.Navigation
    Imports System.Windows.Controls
    Imports System.ServiceModel.DomainServices.Client
    Imports System.ServiceModel.DomainServices.Client.ApplicationServices
    Imports ExampleBusinessApplication.Web
    
    Partial Public Class Reports
        Inherits Page
    
        Private context As New AdventureWorksDomainContext
        Private numberOfRows As Integer = 10
    
        Public Sub New()
            InitializeComponent()
    
            Me.Title = ApplicationStrings.ReportsPageTitle
    
            AddHandler WebContext.Current.Authentication.LoggedIn, AddressOf Authentication_LoggedIn
            AddHandler WebContext.Current.Authentication.LoggedOut, AddressOf Authentication_LoggedOut
    
            LoadReports()
        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 Authentication_LoggedIn(ByVal sender As Object, ByVal e As ApplicationServices.AuthenticationEventArgs)
            LoadReports()
        End Sub
    
        Private Sub Authentication_LoggedOut(ByVal sender As Object, ByVal e As ApplicationServices.AuthenticationEventArgs)
            CustomersGrid.Visibility = System.Windows.Visibility.Collapsed
            SalesOrdersGrid.Visibility = System.Windows.Visibility.Collapsed
        End Sub
    End Class
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    using System.Windows.Navigation;
    using System.ServiceModel.DomainServices.Client;
    using System.ServiceModel.DomainServices.Client.ApplicationServices;
    using ExampleBusinessApplication.Web;
    
    namespace ExampleBusinessApplication.Views
    {
        public partial class Reports : Page
        {
            private AdventureWorksDomainContext context = new AdventureWorksDomainContext();
            int numberOfRows = 10;
    
            public Reports()
            {
                InitializeComponent();
    
                this.Title = ApplicationStrings.ReportsPageTitle;
    
                WebContext.Current.Authentication.LoggedIn += new System.EventHandler<AuthenticationEventArgs>(Authentication_LoggedIn);
                WebContext.Current.Authentication.LoggedOut += new System.EventHandler<AuthenticationEventArgs>(Authentication_LoggedOut);
    
                LoadReports();
            }
    
            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 Authentication_LoggedIn(object sender, AuthenticationEventArgs e)
            {
                LoadReports();
            }
    
            void Authentication_LoggedOut(object sender, AuthenticationEventArgs e)
            {
                CustomersGrid.Visibility = System.Windows.Visibility.Collapsed;
                SalesOrdersGrid.Visibility = System.Windows.Visibility.Collapsed;
            }
    
            void User_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
            {
                if (e.PropertyName == "DefaultRows")
                {
                    LoadReports();
                }
            }
        }
    }
    
  19. Ejecute la solución.

  20. Haga clic en el vínculo Informes.

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

  21. Haga clic en el vínculo de inicio de sesión e inicie sesión como SalesUser.

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

    RIA_DisplayReports

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

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

  23. Cierre el explorador web.

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.

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.

    Agregar ventana secundaria

  3. Haga clic en el botón Agregar.

  4. En el archivo ProfileWindow.xaml, agregue el siguiente código XAML a continuación del elemento Grid.RowDefinitions para incluir un elemento ComboBox con el fin de seleccionar el número de filas que se van a mostrar en los informes.

    <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="2"></ComboBoxItem>
            <ComboBoxItem Content="3"></ComboBoxItem>
            <ComboBoxItem Content="4"></ComboBoxItem>
            <ComboBoxItem Content="5"></ComboBoxItem>
            <ComboBoxItem Content="6"></ComboBoxItem>
            <ComboBoxItem Content="7"></ComboBoxItem>
            <ComboBoxItem Content="8"></ComboBoxItem>
            <ComboBoxItem Content="9"></ComboBoxItem>
            <ComboBoxItem Content="10"></ComboBoxItem>
            <ComboBoxItem Content="15"></ComboBoxItem>
            <ComboBoxItem Content="20"></ComboBoxItem>
        </ComboBox>
    </StackPanel>
    
  5. Establezca la propiedad Title del control ChildWindow en Select Preferences.

  6. En el archivo ProfileWindow.xaml.cs o ProfileWindow.xaml.vb, agregue el siguiente código para recuperar y establecer la propiedad de perfil.

    Imports System.Windows.Controls
    Imports System.Windows
    
    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;
        }
    }
    
  7. Para Visual Basic, agregue instrucciones Imports para los espacios de nombres System.Windows.Controls y System.Windows.

  8. Expanda la carpeta Views\Login y abra el archivo LoginStatus.xaml.

  9. Para agregar un vínculo de configuración a la ventana de perfil, agregue el siguiente código XAML delante del botón de cierre de sesión.

    <Button x:Name="SettingsButton" Click="SettingsButton_Click" Content="settings" Style="{StaticResource LoginRegisterLinkStyle}" Margin="0,0,0,0"></Button>
    <TextBlock Text="  |  " Style="{StaticResource SpacerStyle}"/>
    
  10. En el archivo LoginStatus.xaml.cs o LoginStatus.xaml.vb, agregue el siguiente controlador de eventos Click para el vínculo de configuración.

    Private Sub SettingsButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
        Dim settingsWindow As New ProfileWindow
        settingsWindow.Show()
    End Sub
    
    private void SettingsButton_Click(object sender, RoutedEventArgs e)
    {
        ExampleBusinessApplication.Views.ProfileWindow settingsWindow = new ExampleBusinessApplication.Views.ProfileWindow();
        settingsWindow.Show();
    }
    
  11. Ejecute la solución.

  12. Inicie sesión como CustomerManager o SalesUser y observe que la barra de estado de inicio de sesión incluye ahora un vínculo para la configuración.

    RIA_NewLoginStatusBar

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

    RIA_ShowProfileSettings

  14. Abra la página Informes y observe que el elemento DataGrid contiene el número de filas que seleccionó.