逐步解說:搭配 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 商務應用程式中提供的註冊表單,註冊新使用者。
若要建立網站、角色和使用者
在 Visual Studio 2010 中,依序選取 [檔案]、[新增] 和 [專案]。
[新增專案] 對話方塊隨即出現。
選取 [Silverlight] 專案類型。
選取 [Silverlight 商務應用程式] 範本,並將應用程式命名為 ExampleBusinessApplication。
按一下 [確定]。
請注意,建立的專案結構。Silverlight 用戶端專案在 [Views] 資料夾中包含 Silverlight 頁面。這些頁面可用來登入使用者及註冊新使用者。
若要開啟 ASP.NET 網站管理工具,請先在 [方案總管] 中選取伺服器專案 (ExampleBusinessApplication.Web),然後開啟 [ASP.NET 組態] 工具。
在 [專案] 功能表上選取 [ASP.NET 組態]。
如果 [專案] 功能表中沒有顯示 [ASP.NET 組態] 選項,有可能是因為您選取了用戶端專案。
在 ASP.NET 網站管理工具中選取 [安全性] 索引標籤。
按一下 [角色] 區段中的 [建立或管理角色] 連結。
加入一個名為 Managers 的新角色,並選取 [加入角色] 按鈕。
按一下右下角的 [上一步]。
按一下 [使用者] 區段中的 [建立使用者] 連結。
使用下列值建立新使用者,並選取 [Managers] 角色核取方塊。
使用者名稱:CustomerManager
密碼:P@ssword
電子郵件:someone@example.com
安全性問題:最喜歡的顏色?
安全性解答:藍色
Managers 角色:已選取
按一下 [建立使用者] 按鈕。
關閉 ASP.NET 網站管理工具。
執行方案。
應用程式的首頁隨即出現在 Web 瀏覽器中。
按一下頁面右上角的 [登入] 連結。
[登入] 對話方塊隨即出現。
使用者名稱輸入 CustomerManager,密碼輸入 P@ssword,然後按一下 [確定] 按鈕。
您現在便是以該使用者的身分登入。請注意,右上角的「歡迎 CustomerManager」文字。
按一下 [登出] 連結。
您已經沒有以 CustomerManager 身分登入。在下列步驟中,您將透過註冊表單建立新使用者。
再按一次 [登入] 連結。
按一下 [登入] 對話方塊中的 [立即註冊] 連結。
註冊表單隨即出現。
填寫註冊表單以建立新使用者帳戶。為新使用者使用下列值。
使用者名稱:SalesUser
易記名稱:SalesUser
電子郵件:someone@example.com
密碼:P@ssword
安全性問題:第一輛車是什麼顏色?
安全性解答:綠色
按一下 [確定] 建立新使用者。
請注意,您現在便是以 SalesUser 身分登入。
關閉瀏覽器。
再一次開啟 ASP.NET 網站管理工具,然後按一下 [安全性] 索引標籤。
請注意,目前在網站中有 2 個使用者和 2 個角色,即使您只建立了一個角色。
按一下 [建立或管理角色],並留意 Managers 角色和 Registered Users。
商務應用程式範本已經自動建立 Registered Users 角色。
為 Registered Users,按一下 [管理] 連結。
請注意,您透過應用程式加入的 SalesUser 使用者是在 Registered Users 角色中。
關閉 ASP.NET 網站管理工具。
定義存取和設定檔屬性
將 RequiresAuthenticationAttribute 屬性或 RequiresRoleAttribute 屬性套用至網域作業,即可限制存取該網域作業。無屬性的網域作業可供所有使用者使用。將屬性套用至網域作業並不會防止使用者呼叫網域作業,但是沒有必要的認證的使用者會收到例外狀況。
依角色限制顯示的資料
在 [方案總管] 中,以滑鼠右鍵按一下伺服器專案中的 [App_Data] 資料夾,然後依序選取 [加入] 和 [現有項目]。
在 [加入現有項目] 對話方塊中加入 AdventureWorksLT 範例資料庫。
在伺服器專案中加入新項目,然後從 [資料] 範本選取 [ADO.NET 實體資料模型] 範本。
將模型命名為 AdventureWorksModel.edmx,然後按一下 [加入]。
[實體資料模型精靈] 隨即出現。
選取 [從資料庫產生] 選項,然後按 [下一步]。
選取 AdventureWorksLT 資料庫,然後按 [下一步]。
從資料庫物件清單中選取 Customer、Product 和 SalesOrderHeader 資料表,然後按一下 [完成]。
實體資料模型就會出現在設計工具中。
建置方案。
在伺服器專案中加入新項目,然後從 [Web] 範本選取 [DomainService 類別] 範本。
將網域服務命名為 AdventureWorksDomainService,然後按一下 [加入]。
在 [加入新的 DomainService 類別] 對話方塊中選取 Customer、Product 和 SalesOrderHeader 實體。
按一下 [確定] 完成建立網域服務。
在 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; }
將 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 類別時,會為用戶端專案產生對應的屬性。
加入設定檔屬性
在伺服器專案中,開啟 Web.config 檔案。
在
<profile>
項目中加入名為 DefaultRows 的設定檔屬性。這個屬性會包含使用者對要顯示的資料列數目的喜好設定。Web.config 檔案的 profile 區段列示如下。
<profile> <properties> <add name="FriendlyName" /> <add type="System.Int32" defaultValue="10" name="DefaultRows"/> </properties> </profile>
儲存 Web.config 檔案。
在伺服器專案中,展開 [Models] 資料夾。
開啟 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 頁面
在用戶端專案中,將新項目加入至 [Views] 資料夾。
選取 [Silverlight 頁面] 範本,並將新頁面命名為 Reports.xaml。
開啟 MainPage.xaml 檔案,將下列 XAML 加在名為
Link2
的 HyperlinkButton (連結到 [關於] 頁面) 後面,以便為 [報表] 頁面加入連結。<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}}"/>
在 Assets\Resources 資料夾中,開啟 ApplicationStrings.resx 檔案。
加入值為 Reports 且名為 ReportsPageTitle 的新字串資源。
儲存並關閉 ApplicationStrings.resx 檔案。
開啟 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>
將三個 DataGrid 控制項從 [工具箱] 拖曳至名為
ContentStackPanel
的堆疊面板的結束標記前面。將 DataGrid 控制項從 [工具箱] 拖曳時,System.Windows.Controls.Data 組件參考會加入至專案,System.Windows.Controls 命名空間的前置詞會加入至頁面。
分別將這三個 DataGrid 控制項命名為
ProductsGrid
、SalesOrdersGrid
和CustomersGrid
。將每個 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>
開啟 Reports.xaml.cs 或 Reports.xaml.vb 檔案。
如果是使用 C#,請為 System.ServiceModel.DomainServices.Client、System.ServiceModel.DomainServices.Client.ApplicationServices 和 ExampleBusinessApplication.Web 命名空間加上 using 陳述式。如果是使用 Visual Basic,請為 System.ServiceModel.DomainServices.Client、System.ServiceModel.DomainServices.Client.ApplicationServices、System.Windows.Controls 和 ExampleBusinessApplication.Web 命名空間加上 Imports 陳述式。
建立名為 context 的 AdventureWorksDomainContext 的執行個體,並建立名為 numberOfRows 的變數 (內含要擷取的資料列數目)。
Private context As New AdventureWorksDomainContext Private numberOfRows As Integer = 10
private AdventureWorksDomainContext context = new AdventureWorksDomainContext(); int numberOfRows = 10;
加入名為
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; } }
加入名為
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; }
加入 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(); } }
加入 LoggedIn 和 LoggedOut 事件的事件處理常式,這兩個事件會根據使用者驗證認證的變更來載入或隱藏資料。
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; }
將下列程式碼加入至建構函式。這段程式碼會載入處理常式,並呼叫
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(); } } } }
執行方案。
按一下 [報表] 連結。
請注意,當您未登入時,只有產品資料表會顯示在 [報表] 頁面上。
按一下 [登入] 連結,並以 SalesUser 身分登入。
請注意,產品和銷售訂單的資料表會顯示出來。
登出後再以 CustomerManager 身分登入。
請注意,產品、銷售訂單和客戶的資料表會顯示出來。
關閉 Web 瀏覽器。
您可以加入子視窗,讓使用者編輯 DefaultRows 設定檔屬性。當值變更時,您要呼叫 SaveUser 方法,將值儲存在資料來源中。您要透過目前 WebContext 執行個體的 User 物件上的屬性,擷取目前的值。
加入用來設定設定檔屬性的視窗
在用戶端專案中,將新項目加入至 [Views] 資料夾。
選取 [Silverlight 子視窗] 範本,並將子視窗命名為 ProfileWindow.xaml。
按一下 [加入] 按鈕。
在 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>
將 ChildWindow 上的 Title 屬性設為
Select Preferences
。在 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; } }
如果是使用 Visual Basic,請為 System.Windows.Controls 和 System.Windows 命名空間加上 Imports 陳述式。
展開 Views\Login 資料夾,然後開啟 LoginStatus.xaml 檔案。
若要將設定連結加入至設定檔視窗,請將下列 XAML 加在登出按鈕的前面。
<Button x:Name="SettingsButton" Click="SettingsButton_Click" Content="settings" Style="{StaticResource LoginRegisterLinkStyle}" Margin="0,0,0,0"></Button> <TextBlock Text=" | " Style="{StaticResource SpacerStyle}"/>
在 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(); }
執行方案。
以 CustomerManager 或 SalesUser 身分登入,並留意登入狀態列現在包含了設定連結。
按一下 [設定] 連結,並設定報表中要顯示的資料列數目。
開啟 [報表] 頁面,並留意 DataGrid 現在包含了您所選取的資料列數目。