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
En Visual Studio 2010, seleccione Archivo, Nuevo y, a continuación, Proyecto.
Aparece el cuadro de diálogo Nuevo proyecto.
Seleccione el tipo de proyecto Silverlight.
Seleccione la plantilla Aplicación de negocios de Silverlight y asigne a la aplicación el nombre ExampleBusinessApplication.
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.
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.
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.
Seleccione la pestaña Seguridad en la herramienta Administración de sitios Web de ASP.NET.
En la sección Roles, haga clic en el vínculo Crear o administrar roles.
Agregue un nuevo rol denominado Managers y seleccione el botón Agregar rol.
En la esquina inferior derecha, haga clic en el botón Atrás.
En la sección Usuarios, haga clic en el vínculo Crear usuario.
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
Haga clic en el botón Crear usuario.
Cierre la herramienta Administración de sitios Web de ASP.NET.
Ejecute la solución.
Aparece la página principal de la aplicación en un explorador web.
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.
Escriba CustomerManager para el nombre de usuario y P@ssword para la contraseña, y haga clic en el botón Aceptar.
Iniciará sesión como ese usuario. Observe el texto de bienvenida a CustomerManager en la esquina superior derecha.
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.
Haga clic de nuevo en el vínculo de inicio de sesión.
En el cuadro de diálogo Inicio de sesión, haga clic en el vínculo Registrarse.
Se mostrará el formulario de registro.
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
Haga clic en Aceptar para crear el nuevo usuario.
Observe que ha iniciado sesión como SalesUser.
Cierre el explorador.
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.
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.
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.
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
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.
En el cuadro de diálogo Agregar elemento existente, agregue la base de datos de ejemplo AdventureWorksLT.
En el proyecto de servidor, agregue un nuevo elemento y seleccione la plantilla Entity Data Model de ADO.NET en las plantillas Datos.
Asigne al modelo el nombre AdventureWorksModel.edmx y haga clic en Agregar.
Aparecerá el Asistente para Entity Data Model.
Seleccione la opción Generar desde la base de datos y, a continuación, haga clic en Siguiente.
Seleccione la base de datos AdventureWorksLT y, a continuación, haga clic en Siguiente.
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.
Genere la solución.
En el proyecto de servidor, agregue un nuevo elemento y seleccione la plantilla Clase de servicio de dominio de las plantillas web.
Asigne el nombre AdventureWorksDomainService al servicio de dominio y, a continuación, haga clic en Agregar.
En el cuadro de diálogo Agregar nueva clase de servicio de dominio, seleccione las entidades Customer, Product y SalesOrderHeader.
Haga clic en Aceptar para finalizar la creación del servicio de dominio.
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; }
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 yGetCustomers
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
En el proyecto de servidor, abra el archivo Web.config.
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>
Guarde el archivo Web.config.
En el proyecto de servidor, expanda la carpeta Models.
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
En el proyecto de cliente, agregue un nuevo elemento a la carpeta Views.
Seleccione la plantilla Página de Silverlight y asigne a la nueva página el nombre Reports.xaml.
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}}"/>
En la carpeta Assets\Resources, abra el archivo ApplicationStrings.resx.
Agregue un nuevo recurso de cadena denominado ReportsPageTitle con el valor de Reports.
Guarde y cierre el archivo ApplicationStrings.resx.
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>
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.
Asigne a los controles los nombres DataGrid,
ProductsGrid
,SalesOrdersGrid
yCustomersGrid
.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>
Abra el archivo Reports.xaml.cs o Reports.xaml.vb.
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.
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;
Agregue un método denominado
LoadRestrictedReports
que llama al métodoGetSalesOrderHeaderQuery
y al métodoGetCustomersQuery
, 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; } }
Agregue un método denominado
LoadReports
que comprueba si el usuario está autenticado y, en ese caso, llame al métodoLoadRestrictedReports
. También recupera la propiedad de perfil denominadaDefaultRows
y agrega un controlador de eventos para el evento PropertyChanged en el objeto User. Finalmente, llama al métodoGetProductsQuery
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; }
Agregue un controlador de eventos para el evento PropertyChanged que llama a
LoadReports
si la propiedadDefaultRows
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(); } }
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; }
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(); } } } }
Ejecute la solución.
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.
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.
Cierre la sesión e inicie sesión como CustomerManager.
Observe que se muestran las tablas de productos, pedidos de ventas y clientes.
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
En el proyecto de cliente, agregue un nuevo elemento a la carpeta Views.
Seleccione la plantilla Ventana secundaria de Silverlight y asigne a la ventana secundaria el nombre ProfileWindow.xaml.
Haga clic en el botón Agregar.
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>
Establezca la propiedad Title del control ChildWindow en
Select Preferences
.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; } }
Para Visual Basic, agregue instrucciones Imports para los espacios de nombres System.Windows.Controls y System.Windows.
Expanda la carpeta Views\Login y abra el archivo LoginStatus.xaml.
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}"/>
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(); }
Ejecute la solución.
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.
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.
Abra la página Informes y observe que el elemento DataGrid contiene el número de filas que seleccionó.