チュートリアル: Silverlight ビジネス アプリケーションでの認証サービスの使用
Silverlight ビジネス アプリケーション テンプレートにより、(認証モードにフォーム認証を使用した) 認証、ロール、およびプロファイルを自動的に有効にするソリューションが作成されます。このソリューションには、既存のユーザーにログインしたり、新しいユーザーを登録したりするためのデータ フォームが含まれています。このような機能は、追加のコードを記述しなくても使用できます。ロールおよびプロファイル プロパティを定義することで、ソリューションをカスタマイズできます。
このチュートリアルでは、Silverlight ビジネス アプリケーションで認証、ロール、およびプロファイルを使用する方法について説明します。ユーザーの資格情報に基づいて特定のドメイン操作へのアクセスを制限し、ユーザー設定に基づいてユーザー インターフェイスをカスタマイズします。サイト内のロールおよびユーザーを管理する場合は ASP.NET Web サイト管理ツールを使用します。
前提条件
このチュートリアル、および RIA サービス のドキュメントで紹介されている他のチュートリアルでは、WCF RIA サービス および WCF RIA サービス Toolkit に加え、Visual Studio 2010 や Silverlight の開発者向けランタイムと SDK など、前提条件となっているいくつかのプログラムが適切にインストールおよび構成されている必要があります。また、SQL Server 2008 R2 Express with Advanced Services をインストールして構成し、AdventureWorks OLTP と LT データベースをインストールすることも必要です。
これらの各前提条件を満たしているかどうかを確認するための詳細な手順については、「WCF RIA Services の前提条件」ノード内のトピックを参照してください。このチュートリアルを進める前に、トピックに記載されている手順に従って、この RIA サービス チュートリアルを実行するときに発生する問題をできるだけ最小限に抑えるようにします。
ユーザーおよびロールの作成
Silverlight ビジネス アプリケーションに用意されている機能を使用すると、認証を簡単に実装できます。次のセクションでは、ASP.NET 構成ツールを使用してユーザーとロールを作成し、そのユーザーとしてログインします。Silverlight ビジネス アプリケーションに用意されている登録フォームを使用して新しいユーザーを登録します。
サイト、ロール、およびユーザーを作成するには
Visual Studio 2010 で、[ファイル]、[新規作成]、[プロジェクト] の順に選択します。
[新しいプロジェクト] ダイアログ ボックスが表示されます。
プロジェクトの種類に [Silverlight] を選択します。
テンプレートに [Silverlight ビジネス アプリケーション] を選択し、アプリケーションに ExampleBusinessApplication という名前を付けます。
[OK] をクリックします。
作成されたプロジェクトの構造を確認します。Silverlight クライアント プロジェクトでは Views フォルダー内の Silverlight ページが含まれています。これらのページでは、ユーザーにログインしたり、新しいユーザーを登録したりできます。
ASP.NET Web サイト管理ツールを開くには、まずソリューション エクスプローラーでサーバー プロジェクト (ExampleBusinessApplication.Web) を選択し、ASP.NET 構成ツールを開きます。
[プロジェクト] メニューの [ASP.NET 構成] をクリックします。
[プロジェクト] メニューに [ASP.NET 構成] オプションが表示されていない場合は、クライアント プロジェクトを選択している可能性があります。
ASP.NET Web サイト管理ツールの [セキュリティ] タブをクリックします。
[ロール] セクションで、[ロールの作成または管理] リンクをクリックします。
Managers という名前の新しいロールを追加し、[ロールの追加] をクリックします。
右下隅の [戻る] をクリックします。
[ユーザー] セクションで、[ユーザーの作成] リンクをクリックします。
次の値を使用して新しいユーザーを作成し、Managers ロールのチェック ボックスをオンにします。
ユーザー名: CustomerManager
パスワード: P@ssword
電子メール: someone@example.com
秘密の質問: 好きな色は?
秘密の答え: 青
Managers ロール: オン
[ユーザーの作成] をクリックします。
ASP.NET Web サイト管理ツールを閉じます。
ソリューションを実行します。
アプリケーションのホーム ページが Web ブラウザーに表示されます。
ページの右上隅にある [ログイン] リンクをクリックします。
[ログイン] ダイアログ ボックスが表示されます。
ユーザー名に「CustomerManager」、パスワードに「P@ssword」と入力し、[OK] をクリックします。
これで、そのユーザーとしてログインします。"ようこそ CustomerManager" というテキストが右上隅に表示されています。
[ログアウト] リンクをクリックします。
これで、CustomerManager としてログインしていない状態になりました。次の手順では、登録フォームを使用して新しいユーザーを作成します。
[ログイン] リンクを再びクリックします。
[ログイン] ダイアログ ボックスで、[今すぐ登録] リンクをクリックします。
登録フォームが表示されます。
登録フォームに入力して、新しいユーザー アカウントを作成します。新しいユーザーには次の値を使用します。
ユーザー名: SalesUser
表示名: SalesUser
電子メール: someone@example.com
パスワード: P@ssword
秘密の質問: 最初の自動車の色は?
秘密の答え: 緑
[OK] をクリックすると、新しいユーザーが作成されます。
ここで、SalesUser としてログインしていることがわかります。
ブラウザーを閉じます。
ASP.NET Web サイト管理ツールを再度開き、[セキュリティ] タブをクリックします。
サイトに 2 人のユーザーが存在し、作成したロールが 1 つだけの場合でも 2 つのロールが存在します。
[ロールの作成または管理] をクリックし、Managers ロールと登録済みユーザーを確認します。
登録済みユーザー ロールは、ビジネス アプリケーション テンプレートによって自動的に作成されました。
登録済みユーザーの場合は、[管理] リンクをクリックします。
アプリケーションを使用して追加した SalesUser という名前のユーザーが登録済みユーザー ロールに属していることがわかります。
ASP.NET Web サイト管理ツールを閉じます。
アクセスおよびプロファイル プロパティの定義
ドメイン操作へのアクセスを制限するには、ドメイン操作に RequiresAuthenticationAttribute 属性または RequiresRoleAttribute 属性を適用します。属性を持たないドメイン操作は、すべてのユーザーが使用できます。属性をドメイン操作に適用しても、ユーザーがドメイン操作を呼び出せなくなることはありませんが、必要な資格情報を持っていないユーザーの場合は、例外が発生します。
ロールごとに表示データを制限する
ソリューション エクスプローラーで、サーバー プロジェクト内の App_Data フォルダーを右クリックし、[追加]、[既存の項目] の順にクリックします。
[既存項目の追加] ダイアログ ボックスで、AdventureWorksLT サンプル データベースを追加します。
サーバー プロジェクトで、新しい項目を追加し、[データ] テンプレートから [ADO.NET エンティティ データ モデル] テンプレートをクリックします。
モデルに AdventureWorksModel.edmx という名前を付けて、[追加] をクリックします。
Entity Data Model ウィザードが表示されます。
[データベースから生成] を選択し、[次へ] をクリックします。
AdventureWorksLT データベースを選択し、[次へ] をクリックします。
データベース オブジェクトの一覧から、Customer、Product、および SalesOrderHeader の各テーブルを選択し、[完了] をクリックします。
エンティティ データ モデルがデザイナーに表示されます。
ソリューションをビルドします。
サーバー プロジェクトで、新しい項目を追加し、[Web] テンプレートから [DomainService クラス] テンプレートをクリックします。
ドメイン サービスに AdventureWorksDomainService という名前を付けて、[追加] をクリックします。
[新しいドメイン サービス クラスの追加] ダイアログ ボックスで、Customer、Product、および SalesOrderHeader エンティティを選択します。
[OK] をクリックして、ドメイン サービスの作成を完了します。
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 ファイルでプロファイル プロパティを定義します。このプロパティをサーバー上のユーザー クラスに追加すると、クライアント プロジェクトに対して対応するプロパティが生成されます。
プロファイル プロパティを追加する
サーバー プロジェクトで Web.config ファイルを開きます。
<profile>
要素に、DefaultRows という名前のプロファイル プロパティを追加します。このプロパティには、表示する行数に関するユーザー設定が含まれています。Web.config ファイルのプロファイル セクションを次に示します。
<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; } } }
クライアントからの認証サービスの使用
アクセス許可が制限されたドメイン操作を呼び出す前に、ユーザーに必要な資格情報があることを確認する必要があります。必要な資格情報がない場合は、例外がスローされます。次のセクションで、ユーザーの資格情報を確認し、ユーザーの資格情報に基づいて 1 ~ 3 つの DataGrid コントロールから設定します。また、ユーザー プロファイルのプロパティに基づいてレコードの数を取得します。既定値の 10 は、認証されていないユーザーに使用されます。このセクションでは、ユーザーが DefaultRows プロファイル プロパティを設定するための方法は説明しませんが、このプロファイル プロパティは後のセクションで追加します。
データを表示するための Silverlight ページを追加する
クライアント プロジェクトで、Views フォルダーに新しい項目を追加します。
[Silverlight ページ] テンプレートを選択し、新しいページに Reports.xaml という名前を付けます。
MainPage.xaml ファイルを開き、バージョン情報ページにリンクする
Link2
という名前の HyperlinkButton の後に次の XAML を追加して、Reports ページのリンクを追加します。<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 ファイルを開きます。
ReportsPageTitle という名前の新しい文字列リソースを、値を Reports に設定して追加します。
ApplicationStrings.resx ファイルを保存して閉じます。
Reports.xaml ファイルを開き、Grid 要素に次の XAML を追加して、サイト内の他のページの形式と一致させます。
<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>
ContentStackPanel
という名前のスタック パネルの終了タグの直前に、ツールボックスから 3 つの DataGrid コントロールをドラッグします。ツールボックスから 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;
ユーザーが Managers ロールに属しており、対応するデータ グリッドに結果を読み込む場合は、
GetSalesOrderHeaderQuery
メソッドおよびGetCustomersQuery
メソッドを呼び出す、LoadRestrictedReports
という名前のメソッドを追加します。ユーザーが必要な資格情報を持っていない場合にドメイン操作を呼び出すと、ドメイン操作は例外を返します。ドメイン操作を呼び出す前に資格情報を確認することで、この状況を回避できます。
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; } }
ユーザーが認証されているかどうかを確認し、認証されている場合は
LoadRestrictedReports
メソッドを呼び出す、LoadReports
という名前のメソッドを追加します。また、DefaultRows
という名前のプロファイル プロパティを取得し、ユーザー オブジェクトに 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; }
プロパティ
DefaultRows
が変更された場合にLoadReports
を呼び出す PropertyChanged イベントのイベント ハンドラーを追加します。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(); } } } }
ソリューションを実行します。
[レポート] リンクをクリックします。
ログインしていない場合、Reports ページには Products テーブルのみが表示されます。
[ログイン] リンクをクリックし、SalesUser としてログインします。
製品および販売注文に関するテーブルが表示されます。
ログアウトして、CustomerManager としてログインします。
製品、販売注文、および顧客に関するテーブルが表示されます。
Web ブラウザーを閉じます。
子ウィンドウを追加することで、ユーザーが DefaultRows プロファイル プロパティを編集できるようにすることができます。値を変更した場合は、SaveUser メソッドを呼び出して、値をデータ ソースに保存します。現在の WebContext インスタンスのユーザー オブジェクトのプロパティを使用して、現在の値を取得します。
プロファイル プロパティを設定するためのウィンドウを追加する
クライアント プロジェクトで、Views フォルダーに新しい項目を追加します。
[Silverlight 子ウィンドウ] テンプレートを選択し、子ウィンドウに ProfileWindow.xaml という名前を付けます。
[追加] をクリックします。
ProfileWindow.xaml ファイルで、Grid.RowDefinitions 要素の後に次の XAML を追加し、レポートに表示する行数を選択するための 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 ファイルで、設定リンクの次のクリック イベント ハンドラーを追加します。
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 としてログインすると、ログイン ステータス バーに設定のリンクが表示されます。
[設定] リンクをクリックし、レポートに表示する既定の行数を設定します。
Reports ページを開くと、選択した行数が DataGrid に表示されることがわかります。