Share via


逐步解說:搭配 Silverlight 商務應用程式使用驗證服務

Silverlight 商務應用程式範本建立的方案會自動啟用驗證 (驗證模式為表單驗證)、角色和設定檔。此方案包含用於登入現有使用者和註冊新使用者的資料表單。您不需要撰寫任何其他程式碼,即可使用這些功能。您可以定義角色和設定檔屬性來自訂方案。

在本逐步解說中,您將學習如何在 Silverlight 商務應用程式中使用驗證、角色和設定檔。您將根據使用者的認證存取某些網域作業,並根據使用者喜好設定自訂使用者介面。您將使用 ASP.NET 網站管理工具,以管理網站中的角色和使用者。

必要條件

除了 WCF RIA Services 和 WCF RIA Services 工具組之外,在 RIA Services 文件中呈現的這個逐步解說和其他逐步解說還需要正確安裝並設定數個必要程式 (例如 Visual Studio 2010 和 Silverlight 開發人員執行階段與 SDK)。要執行逐步解說還需要安裝並設定 SQL Server 2008 R2 Express with Advanced Services,以及安裝 AdventureWorks OLTP 和 LT 資料庫。

WCF RIA Services 的必要條件節點中的主題也提供符合這些必要條件的詳細指示。請先按照該處提供的指示進行,然後再進行本逐步解說,以確保您在進行本 RIA Services 逐步解說時,盡可能碰到較少的問題。

建立使用者和角色

您可以在 Silverlight 商務應用程式中使用提供的功能快速實作驗證。在下一節中,您將使用 ASP.NET 組態工具建立使用者和角色,然後以該使用者的身分登入。您將透過 Silverlight 商務應用程式中提供的註冊表單,註冊新使用者。

若要建立網站、角色和使用者

  1. 在 Visual Studio 2010 中,依序選取 [檔案]、[新增] 和 [專案]。

    [新增專案] 對話方塊隨即出現。

  2. 選取 [Silverlight] 專案類型。

  3. 選取 [Silverlight 商務應用程式] 範本,並將應用程式命名為 ExampleBusinessApplication

    RIA_ServicesCreateBizApp

  4. 按一下 [確定]。

    請注意,建立的專案結構。Silverlight 用戶端專案在 [Views] 資料夾中包含 Silverlight 頁面。這些頁面可用來登入使用者及註冊新使用者。

  5. 若要開啟 ASP.NET 網站管理工具,請先在 [方案總管] 中選取伺服器專案 (ExampleBusinessApplication.Web),然後開啟 [ASP.NET 組態] 工具。

  6. 在 [專案] 功能表上選取 [ASP.NET 組態]。

    如果 [專案] 功能表中沒有顯示 [ASP.NET 組態] 選項,有可能是因為您選取了用戶端專案。

    RIA_OpenAdminTool

  7. 在 ASP.NET 網站管理工具中選取 [安全性] 索引標籤。

    RIA_WebAdminSecurity

  8. 按一下 [角色] 區段中的 [建立或管理角色] 連結。

  9. 加入一個名為 Managers 的新角色,並選取 [加入角色] 按鈕。

    WebAdmin_CreateRole

  10. 按一下右下角的 [上一步]。

  11. 按一下 [使用者] 區段中的 [建立使用者] 連結。

  12. 使用下列值建立新使用者,並選取 [Managers] 角色核取方塊。

    使用者名稱:CustomerManager

    密碼:P@ssword

    電子郵件:someone@example.com

    安全性問題:最喜歡的顏色?

    安全性解答:藍色

    Managers 角色:已選取

    WebAdmin_CreateUser

  13. 按一下 [建立使用者] 按鈕。

  14. 關閉 ASP.NET 網站管理工具。

  15. 執行方案。

    應用程式的首頁隨即出現在 Web 瀏覽器中。

  16. 按一下頁面右上角的 [登入] 連結。

    [登入] 對話方塊隨即出現。

  17. 使用者名稱輸入 CustomerManager,密碼輸入 P@ssword,然後按一下 [確定] 按鈕。

    RIA_LoginManager

    您現在便是以該使用者的身分登入。請注意,右上角的「歡迎 CustomerManager」文字。

  18. 按一下 [登出] 連結。

    您已經沒有以 CustomerManager 身分登入。在下列步驟中,您將透過註冊表單建立新使用者。

  19. 再按一次 [登入] 連結。

  20. 按一下 [登入] 對話方塊中的 [立即註冊] 連結。

    註冊表單隨即出現。

  21. 填寫註冊表單以建立新使用者帳戶。為新使用者使用下列值。

    使用者名稱:SalesUser

    易記名稱:SalesUser

    電子郵件:someone@example.com

    密碼:P@ssword

    安全性問題:第一輛車是什麼顏色?

    安全性解答:綠色

    RIA_RegisterUser

  22. 按一下 [確定] 建立新使用者。

    請注意,您現在便是以 SalesUser 身分登入。

  23. 關閉瀏覽器。

  24. 再一次開啟 ASP.NET 網站管理工具,然後按一下 [安全性] 索引標籤。

    請注意,目前在網站中有 2 個使用者和 2 個角色,即使您只建立了一個角色。

  25. 按一下 [建立或管理角色],並留意 Managers 角色和 Registered Users。

    商務應用程式範本已經自動建立 Registered Users 角色。

    RIA_ManageRoles

  26. 為 Registered Users,按一下 [管理] 連結。

    請注意,您透過應用程式加入的 SalesUser 使用者是在 Registered Users 角色中。

  27. 關閉 ASP.NET 網站管理工具。

定義存取和設定檔屬性

RequiresAuthenticationAttribute 屬性或 RequiresRoleAttribute 屬性套用至網域作業,即可限制存取該網域作業。無屬性的網域作業可供所有使用者使用。將屬性套用至網域作業並不會防止使用者呼叫網域作業,但是沒有必要的認證的使用者會收到例外狀況。

依角色限制顯示的資料

  1. 在 [方案總管] 中,以滑鼠右鍵按一下伺服器專案中的 [App_Data] 資料夾,然後依序選取 [加入] 和 [現有項目]。

  2. 在 [加入現有項目] 對話方塊中加入 AdventureWorksLT 範例資料庫。

  3. 在伺服器專案中加入新項目,然後從 [資料] 範本選取 [ADO.NET 實體資料模型] 範本。

  4. 將模型命名為 AdventureWorksModel.edmx,然後按一下 [加入]。

    [實體資料模型精靈] 隨即出現。

  5. 選取 [從資料庫產生] 選項,然後按 [下一步]。

  6. 選取 AdventureWorksLT 資料庫,然後按 [下一步]。

  7. 從資料庫物件清單中選取 Customer、Product 和 SalesOrderHeader 資料表,然後按一下 [完成]。

    實體資料模型就會出現在設計工具中。

  8. 建置方案。

  9. 在伺服器專案中加入新項目,然後從 [Web] 範本選取 [DomainService 類別] 範本。

  10. 將網域服務命名為 AdventureWorksDomainService,然後按一下 [加入]。

  11. 在 [加入新的 DomainService 類別] 對話方塊中選取 Customer、Product 和 SalesOrderHeader 實體。

    RIA_CreateDSForAuth

  12. 按一下 [確定] 完成建立網域服務。

  13. 在 AdventureWorksDomainService 類別檔中將 RequiresAuthenticationAttribute 屬性加入至 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. RequiresRoleAttribute 屬性加入至 GetCustomers 方法,並將必要角色的名稱設為 "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;
    }
    

    GetProducts 網域作業可供任何使用者使用,GetSalesOrderHeaders 可供已驗證的使用者使用,而 GetCustomers 只可供 Managers 角色的使用者使用。

    完整的網域服務列示如下。

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

您可以在 Web.config 檔案中定義設定檔屬性。將屬性加入至伺服器上的 User 類別時,會為用戶端專案產生對應的屬性。

加入設定檔屬性

  1. 在伺服器專案中,開啟 Web.config 檔案。

  2. <profile> 項目中加入名為 DefaultRows 的設定檔屬性。這個屬性會包含使用者對要顯示的資料列數目的喜好設定。

    Web.config 檔案的 profile 區段列示如下。

    <profile>
      <properties>
        <add name="FriendlyName" />
        <add type="System.Int32" defaultValue="10" name="DefaultRows"/>
      </properties>
    </profile>
    
  3. 儲存 Web.config 檔案。

  4. 在伺服器專案中,展開 [Models] 資料夾。

  5. 開啟 User.cs 或 User.vb 檔案,並加入名為 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; }
        }
    }
    

使用用戶端的驗證服務

以限制的權限呼叫網域作業之前,您必須檢查使用者是否有必要的認證,否則會擲回例外狀況。在下一節中,您將檢查使用者的認證,並根據使用者的認證,從一個 DataGrid 控制項填入三個 DataGrid 控制項。您也將根據使用者設定檔的屬性來擷取記錄數目。未經驗證的使用者使用的預設記錄數目為 10。本節不包含讓使用者設定 DefaultRows 設定檔屬性,但此部分將在後面小節說明。

加入要顯示資料的 Silverlight 頁面

  1. 在用戶端專案中,將新項目加入至 [Views] 資料夾。

  2. 選取 [Silverlight 頁面] 範本,並將新頁面命名為 Reports.xaml。

  3. 開啟 MainPage.xaml 檔案,將下列 XAML 加在名為 Link2HyperlinkButton (連結到 [關於] 頁面) 後面,以便為 [報表] 頁面加入連結。

    <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. 在 Assets\Resources 資料夾中,開啟 ApplicationStrings.resx 檔案。

  5. 加入值為 Reports 且名為 ReportsPageTitle 的新字串資源。

    RIA_AddReportResource

  6. 儲存並關閉 ApplicationStrings.resx 檔案。

  7. 開啟 Reports.xaml 檔案,並將下列 XAML 加入至 Grid 項目來符合網站中其他頁面的格式。

    <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. 將三個 DataGrid 控制項從 [工具箱] 拖曳至名為 ContentStackPanel 的堆疊面板的結束標記前面。

    DataGrid 控制項從 [工具箱] 拖曳時,System.Windows.Controls.Data 組件參考會加入至專案,System.Windows.Controls 命名空間的前置詞會加入至頁面。

  9. 分別將這三個 DataGrid 控制項命名為 ProductsGridSalesOrdersGridCustomersGrid

  10. 將每個 DataGrid 控制項的 Margin 屬性設為 5

    下列範例顯示完整的 Reports.xaml 檔案。

    <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. 開啟 Reports.xaml.cs 或 Reports.xaml.vb 檔案。

  12. 如果是使用 C#,請為 System.ServiceModel.DomainServices.ClientSystem.ServiceModel.DomainServices.Client.ApplicationServicesExampleBusinessApplication.Web 命名空間加上 using 陳述式。如果是使用 Visual Basic,請為 System.ServiceModel.DomainServices.ClientSystem.ServiceModel.DomainServices.Client.ApplicationServicesSystem.Windows.ControlsExampleBusinessApplication.Web 命名空間加上 Imports 陳述式。

  13. 建立名為 context 的 AdventureWorksDomainContext 的執行個體,並建立名為 numberOfRows 的變數 (內含要擷取的資料列數目)。

    Private context As New AdventureWorksDomainContext
    Private numberOfRows As Integer = 10
    
    private AdventureWorksDomainContext context = new AdventureWorksDomainContext();
    int numberOfRows = 10;
    
  14. 加入名為 LoadRestrictedReports 的方法,這個方法會在使用者屬於 Managers 角色的情況下呼叫 GetSalesOrderHeaderQuery 方法和 GetCustomersQuery 方法,並將結果填入對應的資料格。

    如果在使用者沒有必要的認證時呼叫網域作業,則網域作業會傳回例外狀況。呼叫網域作業之前先檢查認證,即可避免這種情況發生。

    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. 加入名為 LoadReports 的方法,這個方法可檢查使用者是否經過驗證,如果是,則呼叫 LoadRestrictedReports 方法。它也會擷取名為 DefaultRows 的設定檔屬性,並在 User 物件上加入 PropertyChanged 事件的事件處理常式。最後,它會為所有使用者呼叫 GetProductsQuery 方法。

    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. 加入 PropertyChanged 事件的事件處理常式,這個事件會在 DefaultRows 屬性變更時呼叫 LoadReports

    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. 加入 LoggedInLoggedOut 事件的事件處理常式,這兩個事件會根據使用者驗證認證的變更來載入或隱藏資料。

    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. 將下列程式碼加入至建構函式。這段程式碼會載入處理常式,並呼叫 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();
    }
    

    完整的程式碼檔案列示如下。

    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. 執行方案。

  20. 按一下 [報表] 連結。

    請注意,當您未登入時,只有產品資料表會顯示在 [報表] 頁面上。

  21. 按一下 [登入] 連結,並以 SalesUser 身分登入。

    請注意,產品和銷售訂單的資料表會顯示出來。

    RIA_DisplayReports

  22. 登出後再以 CustomerManager 身分登入。

    請注意,產品、銷售訂單和客戶的資料表會顯示出來。

  23. 關閉 Web 瀏覽器。

您可以加入子視窗,讓使用者編輯 DefaultRows 設定檔屬性。當值變更時,您要呼叫 SaveUser 方法,將值儲存在資料來源中。您要透過目前 WebContext 執行個體的 User 物件上的屬性,擷取目前的值。

加入用來設定設定檔屬性的視窗

  1. 在用戶端專案中,將新項目加入至 [Views] 資料夾。

  2. 選取 [Silverlight 子視窗] 範本,並將子視窗命名為 ProfileWindow.xaml。

    新增子視窗

  3. 按一下 [加入] 按鈕。

  4. 在 ProfileWindow.xaml 檔案中,將下列 XAML 加在 Grid.RowDefinitions 項目的後面來包含 ComboBox,以便選取要在報表中顯示的資料列數目。

    <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. ChildWindow 上的 Title 屬性設為 Select Preferences

  6. 在 ProfileWindow.xaml.cs 或 ProfileWindow.xaml.vb 檔案中加入下列程式碼,以便擷取和設定設定檔屬性。

    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. 如果是使用 Visual Basic,請為 System.Windows.ControlsSystem.Windows 命名空間加上 Imports 陳述式。

  8. 展開 Views\Login 資料夾,然後開啟 LoginStatus.xaml 檔案。

  9. 若要將設定連結加入至設定檔視窗,請將下列 XAML 加在登出按鈕的前面。

    <Button x:Name="SettingsButton" Click="SettingsButton_Click" Content="settings" Style="{StaticResource LoginRegisterLinkStyle}" Margin="0,0,0,0"></Button>
    <TextBlock Text="  |  " Style="{StaticResource SpacerStyle}"/>
    
  10. 在 LoginStatus.xaml.cs 或 LoginStatus.xaml.vb 檔案中,為設定連結加入下列 Click 事件處理常式。

    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. 執行方案。

  12. 以 CustomerManager 或 SalesUser 身分登入,並留意登入狀態列現在包含了設定連結。

    RIA_NewLoginStatusBar

  13. 按一下 [設定] 連結,並設定報表中要顯示的資料列數目。

    RIA_ShowProfileSettings

  14. 開啟 [報表] 頁面,並留意 DataGrid 現在包含了您所選取的資料列數目。