次の方法で共有


チュートリアル: Silverlight ナビゲーション アプリケーションでの認証サービスの使用

このチュートリアルでは、認証サービスを使用するように WCF RIA サービス ソリューションのサーバー プロジェクトとクライアント プロジェクトを設定する方法について説明します。Silverlight ナビゲーション アプリケーション テンプレートを使用してソリューションを作成し、RIA サービス を有効にすると、認証サービスを追加することで ASP.NET メンバーシップ フレームワークにアクセスできます。認証サービスは、サーバー プロジェクトからクライアント プロジェクトに対して認証、ロール、およびプロファイルを公開します。ユーザーの資格情報の検証、ロールに基づいたリソースへのアクセス制限、およびプロファイル プロパティの格納を実行するには、認証サービスを使用します。

note注 :
Silverlight ビジネス アプリケーションでは、認証サービスが自動的に実装されます。詳細については、「チュートリアル: Silverlight ビジネス アプリケーションでの認証サービスの使用」を参照してください。

前提条件

このチュートリアル、および 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 アプリケーションから認証サービスを使用するには、サーバー プロジェクトで認証を構成する必要があります。認証は、Web.config ファイルで構成します。認証を構成した後、ロールおよびプロファイルを Silverlight アプリケーションから使用する場合は、サーバー プロジェクトでこれらの機能も構成することができます。このチュートリアルでは、3 つの機能すべてを構成します。最後に、有効になった機能をクライアントに公開する認証サービスを追加します。

サーバー プロジェクトを構成するには

  1. Visual Studio 2010 で、[ファイル][新規作成][プロジェクト] の順に選択します。

    [新しいプロジェクト] ダイアログ ボックスが表示されます。

  2. プロジェクトの種類に [Silverlight] を選択します。

  3. [Silverlight ナビゲーション アプリケーション] テンプレートをクリックし、アプリケーションに ExampleNavigationApplication という名前を付けます。

  4. [OK] をクリックします。

    [新しい Silverlight アプリケーション] ダイアログ ボックスが表示されます。

  5. [Silverlight アプリケーションを新しい Web サイトでホストする] チェック ボックスがオンになっていること、および [新しい Web プロジェクトの種類] が [ASP.NET Web アプリケーション プロジェクト] に設定されていることを確認します。

  6. [WCF RIA サービスを有効にする] チェック ボックスをオンにします。

  7. [OK] をクリックして、ソリューションを作成します。

  8. サーバー プロジェクト (ExampleBusinessApplication.Web) で、Web.config ファイルを開きます。

  9. <system.web> 要素で、<authentication> 要素を追加し、mode プロパティを Forms に設定します。

    <authentication mode="Forms"></authentication>
    
  10. <system.web> 要素で、<roleManager> 要素を追加し、enabled プロパティを true に設定します。

    <roleManager enabled="true"></roleManager>
    
  11. <system.web> 要素で、<profile> 要素を追加し、enabled プロパティを true に設定して、DefaultRows という名前の profile プロパティを含めます。

    <profile enabled="true">
      <properties>
        <add type="System.Int32" defaultValue="10" name="DefaultRows"/>
      </properties>
    </profile>
    

    完成した <system.web> 要素には、次の要素が含まれています。

    <system.web>
      <compilation debug="true" targetFramework="4.0" />
      <authentication mode="Forms"></authentication>
      <roleManager enabled="true"></roleManager>
      <profile enabled="true">
        <properties>
          <add type="System.Int32" defaultValue="10" name="DefaultRows"/>
        </properties>
      </profile>
    </system.web>
    
  12. Web.config ファイルを保存します。

  13. ソリューション エクスプローラーで、サーバー プロジェクトを右クリックし、[追加] をポイントして、[新しい項目] をクリックします。

    [新しい項目の追加] ダイアログ ボックスが表示されます。

  14. [認証 DomainService] テンプレートをクリックし、AuthenticationDomainService という名前を付けます。

    RIA_ServicesAddAuth

  15. [追加] をクリックします。

  16. 認証サービスのコード ファイル (AuthenticationDomainService.cs または AuthenticationDomainService.vb) を開き、Web.config ファイルで定義した DefaultRows プロパティを User クラスに追加します。

    <EnableClientAccess()> _
    Public Class AuthenticationDomainService
        Inherits AuthenticationBase(Of User)
    
    End Class
    
    Public Class User
        Inherits UserBase
    
        Public Property DefaultRows As Integer
    
    End Class
    
    [EnableClientAccess]
    public class AuthenticationDomainService : AuthenticationBase<User>
    {
    }
    
    public class User : UserBase
    {
        public int DefaultRows { get; set; }
    }
    
  17. ソリューションをビルドします。

ここでは、ASP.NET Web サイト管理ツールを使用してユーザーおよびロールを作成します。後のセクションでは、このユーザーとしてログインします。

ASP.NET Web サイト管理ツールを使用してユーザーを追加するには

  1. ASP.NET Web サイト管理ツールを開くには、最初にソリューション エクスプローラーでサーバー プロジェクトを選択します。

  2. [プロジェクト] メニューの [ASP.NET 構成] をクリックします。

    [プロジェクト] メニューに [ASP.NET 構成] オプションが表示されていない場合は、クライアント プロジェクトを選択している可能性があります。

    RIA_OpenAdminTool

  3. ASP.NET Web サイト管理ツールの [セキュリティ] タブをクリックします。

    RIA_WebAdminSecurity

  4. [ロール] セクションで、[ロールの作成または管理] リンクをクリックします。

  5. Managers という名前の新しいロールを追加し、[ロールの追加] をクリックします。

    WebAdmin_CreateRole

  6. 右下隅の [戻る] をクリックします。

  7. [ユーザー] セクションで、[ユーザーの作成] リンクをクリックします。

  8. 次の値を使用して新しいユーザーを作成し、Managers ロールのチェック ボックスをオンにします。

    ユーザー名: CustomerManager

    パスワード: P@ssword

    電子メール: someone@example.com

    秘密の質問: 好きな色は?

    秘密の答え: 青

    Managers ロール: オン

    WebAdmin_CreateUser

  9. [ユーザーの作成] をクリックします。

  10. ASP.NET Web サイト管理ツールを閉じます。

認証用のクライアントの構成

サーバー プロジェクトで構成した認証モードと一致する認証モードを使用するように、クライアント プロジェクトを構成する必要があります。

クライアント プロジェクトを構成するには

  1. クライアント プロジェクトで、App.xaml ファイルの分離コード ファイル (App.xaml.cs または App.xaml.vb) を開きます。

  2. コンストラクターで、WebContext クラスの新しいインスタンスを作成します。

  3. Authentication プロパティを FormsAuthentication クラスの新しいインスタンスに設定し、WebContext インスタンスを ApplicationLifetimeObjects に追加します。

    Public Sub New()
        InitializeComponent()
    
        Dim webcontext As New WebContext
        webcontext.Authentication = New System.ServiceModel.DomainServices.Client.ApplicationServices.FormsAuthentication
        Me.ApplicationLifetimeObjects.Add(webcontext)
    End Sub
    
    public App()
    {
        this.Startup += this.Application_Startup;
        this.UnhandledException += this.Application_UnhandledException;
    
        InitializeComponent();
    
        WebContext webcontext = new WebContext();
        webcontext.Authentication = new System.ServiceModel.DomainServices.Client.ApplicationServices.FormsAuthentication();
        this.ApplicationLifetimeObjects.Add(webcontext);
    }
    

クライアントへのログイン機能の追加

このセクションでは、ユーザーがログイン時にユーザー名とパスワードを指定できるようにする Silverlight コントロールを追加します。ユーザーの資格情報を使用して Login メソッドを呼び出すコードを追加します。また、ユーザーがログインしているかどうかに基づいて表示されるコントロールを設定することもできます。

わかりやすくするために、ログイン ユーザー インターフェイスはチュートリアルのホーム ページに追加されます。アプリケーションでは、別のログイン ページを作成することもできます。

ユーザーのログインおよびログアウトを実行するには

  1. ソリューション エクスプローラーで、クライアント プロジェクトの Views フォルダーを展開します。

  2. Home.xaml ファイルを開きます。

  3. ContentText という名前の TextBlock の後に、次の XAML を追加します。

    XAML には、ユーザー名を指定するための TextBox、パスワードを指定するための PasswordBox、ログイン要求を送信するための Button、およびユーザーがログインした後のみに表示される、ログアウト用の TextBlockHyperlinkButton が含まれています。

    <TextBlock x:Name="WelcomeText" Style="{StaticResource ContentTextStyle}" Visibility="Collapsed"></TextBlock>
    <HyperlinkButton x:Name="LogoutButton" 
                     Content="Logout" 
                     Click="LogoutButton_Click" 
                     Visibility="Collapsed">
    </HyperlinkButton>
    <Border x:Name="LoginBorder" 
            Margin="10,10,0,0" 
            BorderThickness="2" 
            BorderBrush="Black" 
            HorizontalAlignment="Left" 
            CornerRadius="15" 
            Padding="10" 
            Background="BlanchedAlmond" 
            Width="300">
        <Grid HorizontalAlignment="Left">
            <Grid.RowDefinitions>
                <RowDefinition></RowDefinition>
                <RowDefinition Height="30" ></RowDefinition>
                <RowDefinition Height="30"></RowDefinition>
                <RowDefinition></RowDefinition>
                <RowDefinition></RowDefinition>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition></ColumnDefinition>
                <ColumnDefinition></ColumnDefinition>
            </Grid.ColumnDefinitions>
            <TextBlock Grid.Row="0" 
                       Grid.ColumnSpan="2" 
                       Grid.Column="0" 
                       FontWeight="Bold" 
                       HorizontalAlignment="Left" 
                       VerticalAlignment="Center" 
                       Text="Log In Existing User">
            </TextBlock>
            <TextBlock Grid.Row="1" 
                       Grid.Column="0" 
                       HorizontalAlignment="Right" 
                       VerticalAlignment="Center" 
                       Text="User Name: ">
            </TextBlock>
            <TextBox x:Name="UserName" 
                     VerticalAlignment="Center" 
                     Grid.Row="1" 
                     Grid.Column="1"  
                     Width="100">
            </TextBox>
            <TextBlock Grid.Row="2" 
                       HorizontalAlignment="Right" 
                       Grid.Column="0" 
                       VerticalAlignment="Center" 
                       Text="Password: ">
            </TextBlock>
            <PasswordBox x:Name="Password" 
                         VerticalAlignment="Center" 
                         Grid.Row="2" 
                         Grid.Column="1"  
                         Width="100">
            </PasswordBox>
            <TextBlock x:Name="LoginResult" 
                       TextWrapping="Wrap" 
                       Visibility="Collapsed" 
                       Grid.Row="3" 
                       Grid.ColumnSpan="2" 
                       Foreground="Red">
            </TextBlock>
            <Button x:Name="LoginButton" 
                    Margin="0,5,0,0" 
                    Grid.Row="4" 
                    Grid.Column="1" 
                    Content="Log In" 
                    Click="LoginButton_Click">
            </Button>
        </Grid>
    </Border>
    
  4. ホーム ページの分離コード ファイル (Home.xaml.cs または Home.xaml.vb) を開きます。

  5. System.ServiceModel.DomainServices.Client.ApplicationServices 名前空間の using ステートメントまたは Imports ステートメントを追加します。

  6. 次のコードをホーム クラスに追加します。

    コードには、ログインとログアウト用のイベント ハンドラー、完了したログイン操作とログアウト操作のコールバック メソッド、およびユーザーが認証されているかどうかに基づいてコントロールを表示するかどうかを設定するメソッドが含まれています。

    Protected Overrides Sub OnNavigatedTo(ByVal e As System.Windows.Navigation.NavigationEventArgs)
        SetControlVisibility(WebContext.Current.User.IsAuthenticated)
    End Sub
    
    Private Sub LoginButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
        Dim lp As LoginParameters = New LoginParameters(UserName.Text, Password.Password)
        WebContext.Current.Authentication.Login(lp, AddressOf Me.LoginOperation_Completed, Nothing)
        LoginButton.IsEnabled = False
        LoginResult.Text = ""
    End Sub
    
    Private Sub LoginOperation_Completed(ByVal lo As LoginOperation)
        If (lo.HasError) Then
            LoginResult.Text = lo.Error.Message
            LoginResult.Visibility = System.Windows.Visibility.Visible
            lo.MarkErrorAsHandled()
        ElseIf (lo.LoginSuccess = False) Then
            LoginResult.Text = "Login failed. Please check user name and password."
            LoginResult.Visibility = System.Windows.Visibility.Visible
        ElseIf (lo.LoginSuccess = True) Then
            SetControlVisibility(True)
        End If
        LoginButton.IsEnabled = True
    End Sub
    
    Private Sub SetControlVisibility(ByVal isAuthenticated As Boolean)
        If (isAuthenticated) Then
            LoginBorder.Visibility = System.Windows.Visibility.Collapsed
            WelcomeText.Text = "Welcome " + WebContext.Current.User.Name
            WelcomeText.Visibility = System.Windows.Visibility.Visible
            LogoutButton.Visibility = System.Windows.Visibility.Visible
        Else
            LoginBorder.Visibility = System.Windows.Visibility.Visible
            WelcomeText.Visibility = System.Windows.Visibility.Collapsed
            LogoutButton.Visibility = System.Windows.Visibility.Collapsed
        End If
    End Sub
    
    Private Sub LogoutButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
        WebContext.Current.Authentication.Logout(AddressOf Me.LogoutOperation_Completed, Nothing)
    End Sub
    
    Private Sub LogoutOperation_Completed(ByVal lo As LogoutOperation)
        If (Not (lo.HasError)) Then
            SetControlVisibility(False)
        Else
            Dim ew As ErrorWindow = New ErrorWindow("Logout failed.", "Please try logging out again.")
            ew.Show()
            lo.MarkErrorAsHandled()
        End If
    End Sub
    
    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        SetControlVisibility(WebContext.Current.User.IsAuthenticated);
    }
    
    private void LoginButton_Click(object sender, RoutedEventArgs e)
    {
        LoginParameters lp = new LoginParameters(UserName.Text, Password.Password);
        WebContext.Current.Authentication.Login(lp, this.LoginOperation_Completed, null);
        LoginButton.IsEnabled = false;
        LoginResult.Text = "";
    }
    
    private void LoginOperation_Completed(LoginOperation lo)
    {
        if (lo.HasError)
        {
            LoginResult.Text = lo.Error.Message;
            LoginResult.Visibility = System.Windows.Visibility.Visible;
            lo.MarkErrorAsHandled();
        }
        else if (lo.LoginSuccess == false)
        {
            LoginResult.Text = "Login failed. Please check user name and password.";
            LoginResult.Visibility = System.Windows.Visibility.Visible;
        }
        else if (lo.LoginSuccess == true)
        {
            SetControlVisibility(true);
        }
        LoginButton.IsEnabled = true;
    }
    
    private void SetControlVisibility(bool isAuthenticated)
    {
        if (isAuthenticated)
        {
            LoginBorder.Visibility = System.Windows.Visibility.Collapsed;
            WelcomeText.Text = "Welcome " + WebContext.Current.User.Name;
            WelcomeText.Visibility = System.Windows.Visibility.Visible;
            LogoutButton.Visibility = System.Windows.Visibility.Visible;
        }
        else
        {
            LoginBorder.Visibility = System.Windows.Visibility.Visible;
            WelcomeText.Visibility = System.Windows.Visibility.Collapsed;
            LogoutButton.Visibility = System.Windows.Visibility.Collapsed;
        }
    }
    
    private void LogoutButton_Click(object sender, RoutedEventArgs e)
    {
        WebContext.Current.Authentication.Logout(this.LogoutOperation_Completed, null);
    }
    
    private void LogoutOperation_Completed(LogoutOperation lo)
    {
    
        if (!lo.HasError)
        {
            SetControlVisibility(false);
        }
        else
        {
            ErrorWindow ew = new ErrorWindow("Logout failed.", "Please try logging out again.");
            ew.Show();
            lo.MarkErrorAsHandled();
        }
    }
    
  7. ソリューションを実行します。

    RS_CustomLoginNav

  8. パスワードに P@ssword を使用して CustomerManager としてログインします。

    ログイン領域が表示されなくなり、開始テキストとログアウト リンクが表示されています。

    RIA_CustomLoggedInNav

  9. [ログアウト] リンクをクリックし、Web ブラウザーを閉じます。

クライアントからの新しいユーザーの追加

認証サービスには、新しいユーザーを作成する操作が含まれていません。新しいユーザーを登録するには、空のドメイン サービスを作成し、ASP.NET メンバーシップ フレームワークにユーザーを追加するための操作を追加します。

新しいユーザーを追加するためにサーバー プロジェクトを構成するには

  1. サーバー プロジェクトに、NewUser という名前の新しいクラス ファイルを追加します。

  2. NewUser クラスに次のコードを追加して、新しいユーザーを登録するためのプロパティを定義します。

    Imports System.ComponentModel.DataAnnotations
    
    Public Class NewUser
    
        <Key()> _
        <Required()> _
        <RegularExpression("^[a-zA-Z0-9_]*$", ErrorMessage:="Invalid user name. It must contain only alphanumeric characters")> _
        Public Property UserName As String
    
        <Key()> _
        <Required()> _
        <RegularExpression("^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$", ErrorMessage:="Invalid email. An email must use the format username@mycompany.com")> _
        Public Property Email As String
    
        <Required()> _
        <RegularExpression("^.*[^a-zA-Z0-9].*$", ErrorMessage:="A password needs to contain at least one special character e.g. @ or #")> _
        <StringLength(50, MinimumLength:=7, ErrorMessage:="Invalid password. It must be contain at least 7 characters and no more than 50 characters.")> _
        Public Property Password As String
    
        <Required()> _
        <CustomValidation(GetType(RegistrationValidator), "IsPasswordConfirmed")> _
        Public Property ConfirmPassword As String
    
        <Range(1, 20)> _
        Public Property RecordsToShow As Integer
    
        <Required()> _
        Public Property SecurityQuestion As String
    
        <Required()> _
        Public Property SecurityAnswer As String
    End Class
    
    using System;
    using System.ComponentModel.DataAnnotations;
    
    namespace ExampleNavigationApplication.Web
    {
        public class NewUser
        {
            [Key]
            [Required()]
            [RegularExpression("^[a-zA-Z0-9_]*$", ErrorMessage="Invalid user name. It must contain only alphanumeric characters")]
            public string UserName { get; set; }
    
            [Key]
            [Required()]
            [RegularExpression(@"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$", ErrorMessage="Invalid email. An email must use the format username@mycompany.com")]
            public string Email { get; set; }
    
            [Required()]
            [RegularExpression("^.*[^a-zA-Z0-9].*$", ErrorMessage="A password needs to contain at least one special character e.g. @ or #")]
            [StringLength(50, MinimumLength = 7, ErrorMessage="Invalid password. It must be contain at least 7 characters and no more than 50 characters.")]
            public string Password { get; set; }
    
            [Required()]
            [CustomValidation(typeof(RegistrationValidator), "IsPasswordConfirmed")]
            public string ConfirmPassword { get; set; }
    
            [Range(1, 20)]
            public int RecordsToShow { get; set; }
    
            [Required()]
            public string SecurityQuestion { get; set; }
    
            [Required()]
            public string SecurityAnswer { get; set; }
        }
    }
    

    前の手順の ConfirmPassword プロパティは、CustomValidationAttribute 属性を使用して定義されています。この属性で、RegistrationValidator クラスと、IsPasswordConfirmed という名前のメソッドを指定します。ここで、このカスタム検証クラスを定義する必要があります。

  3. RegistrationValidator.shared.cs または RegistrationValidator.shared.vb という名前の新しいクラスを追加します。

  4. RegistrationValidator.shared ファイルに次のコードを追加します。

    Imports System.ComponentModel.DataAnnotations
    
    Public Class RegistrationValidator
        Public Shared Function IsPasswordConfirmed(ByVal confirmPassword As String, ByVal context As ValidationContext) As ValidationResult
            Dim data As Web.NewUser = CType(context.ObjectInstance, Web.NewUser)
            If (data.Password = confirmPassword) Then
                Return ValidationResult.Success
            Else
                Return New ValidationResult("Please confirm your password by providing it again.")
            End If
        End Function
    End Class
    
    using System.ComponentModel.DataAnnotations;
    
    namespace ExampleNavigationApplication.Web
    {
        public class RegistrationValidator
        {
            public static ValidationResult IsPasswordConfirmed(string confirmPassword, ValidationContext context)
            {
                NewUser data = (NewUser)context.ObjectInstance;
                if (data.Password == confirmPassword)
                {
                    return ValidationResult.Success;
                }
                else
                {
                    return new ValidationResult("Please confirm your password by providing it again.");
                }
            }
        }
    }
    
  5. サーバー プロジェクトに新しい項目を追加し、[DomainService クラス] テンプレートをクリックします。

  6. ファイルに RegistrationDomainService.cs または RegistrationDomainService.vb という名前を付け、[追加] をクリックします。

  7. [新しいドメイン サービス クラスの追加] ダイアログ ボックスで、[使用できる DataContext/ObjectContext クラス] ボックスの一覧の [<空のドメイン サービス クラス>] を選択します。

  8. [OK] をクリックします。

  9. メンバーシップ フレームワークを使用して新しいユーザーを追加し、プロファイル プロパティを保存するドメイン操作を作成するには、RegistrationDomainService クラスに次のコードを追加します。

    クライアント プロジェクトに対して NewUser エンティティ クラスが生成されるように、GetUsers メソッドを含める必要があります。パブリック クエリ操作を通じて公開されるクラスのみがクライアント プロジェクトに生成されます。

    ユーザーを作成すると、DefaultRows という名前のプロファイル プロパティが設定されます。この場合、プロファイル プロパティは、ユーザーを作成するためのドメイン操作の一環として設定されます。後のセクションで、クライアント プロジェクトからプロファイル プロパティを設定するコードを追加します。

    Option Compare Binary
    Option Infer On
    Option Strict On
    Option Explicit On
    
    Imports System
    Imports System.Collections.Generic
    Imports System.ComponentModel
    Imports System.ComponentModel.DataAnnotations
    Imports System.Linq
    Imports System.ServiceModel.DomainServices.Hosting
    Imports System.ServiceModel.DomainServices.Server
    Imports System.Web.Profile
    
    <EnableClientAccess()>  _
    Public Class RegistrationDomainService
        Inherits DomainService
    
        Public Sub AddUser(ByVal user As NewUser)
            Dim createStatus As MembershipCreateStatus
            Membership.CreateUser(user.UserName, user.Password, user.Email, user.SecurityQuestion, user.SecurityAnswer, True, Nothing, createStatus)
    
            If (createStatus <> MembershipCreateStatus.Success) Then
                Throw New DomainException(createStatus.ToString())
            End If
    
            Dim profile = ProfileBase.Create(user.UserName, True)
            profile.SetPropertyValue("DefaultRows", user.RecordsToShow)
            profile.Save()
        End Sub
    
        Public Function GetUsers() As IEnumerable(Of NewUser)
            Throw New NotSupportedException()
        End Function
    End Class
    
    namespace ExampleNavigationApplication.Web
    {
        using System;
        using System.Collections.Generic;
        using System.ServiceModel.DomainServices.Hosting;
        using System.ServiceModel.DomainServices.Server;
        using System.Web.Security;
        using System.Web.Profile;
    
    
        [EnableClientAccess()]
        public class RegistrationDomainService : DomainService
        {
            public void AddUser(NewUser user)
            {
                MembershipCreateStatus createStatus;
                Membership.CreateUser(user.UserName, user.Password, user.Email, user.SecurityQuestion, user.SecurityAnswer, true, null, out createStatus);
    
                if (createStatus != MembershipCreateStatus.Success)
                {
                    throw new DomainException(createStatus.ToString());
                }
    
                ProfileBase profile = ProfileBase.Create(user.UserName, true);
                profile.SetPropertyValue("DefaultRows", user.RecordsToShow);
                profile.Save();
            }
    
            public IEnumerable<NewUser> GetUsers()
            {
                throw new NotSupportedException();
            }
        }  
    }
    

新しいユーザーを追加するためにクライアント プロジェクトを構成するには

  1. Home.xaml ファイルを開きます。

  2. LoginBorderBorder コントロールの終了タグの後に、次の XAML を追加して、新しいユーザーを作成するための情報を収集する入力コントロールを含むもう 1 つの Border コントロールを作成します。

    このコントロールでは、ユーザー名、パスワード、パスワードの確認、電子メール アドレス、秘密の質問、秘密の答え、およびレポートに表示するレコード数の各値をそのまま使用します。表示するレコードの数は、プロファイル プロパティとして保存されます。その他すべての値は、ASP.NET メンバーシップ フレームワークを通じてユーザーを作成する際に使用されます。

    <Border x:Name="RegisterBorder" 
            Margin="10,10,0,0" 
            BorderThickness="2" 
            BorderBrush="Black" 
            HorizontalAlignment="Left" 
            CornerRadius="15" 
            Padding="10" 
            Background="BurlyWood" 
            Width="400">
        <Grid HorizontalAlignment="Left">
            <Grid.RowDefinitions>
                <RowDefinition></RowDefinition>
                <RowDefinition Height="30" ></RowDefinition>
                <RowDefinition Height="30"></RowDefinition>
                <RowDefinition Height="30"></RowDefinition>
                <RowDefinition Height="30"></RowDefinition>
                <RowDefinition Height="30"></RowDefinition>
                <RowDefinition Height="30"></RowDefinition>
                <RowDefinition Height="30"></RowDefinition>
                <RowDefinition></RowDefinition>
                <RowDefinition></RowDefinition>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition></ColumnDefinition>
                <ColumnDefinition></ColumnDefinition>
            </Grid.ColumnDefinitions>
    
            <TextBlock Grid.Row="0" 
                       Grid.ColumnSpan="2" 
                       Grid.Column="0" 
                       FontWeight="Bold" 
                       HorizontalAlignment="Left" 
                       VerticalAlignment="Center" 
                       Text="Register New User">
            </TextBlock>
            <TextBlock Grid.Row="1" 
                       Grid.Column="0" 
                       HorizontalAlignment="Right" 
                       VerticalAlignment="Center" 
                       Text="User Name: ">
            </TextBlock>
            <TextBox x:Name="NewUsername" 
                     VerticalAlignment="Center" 
                     HorizontalAlignment="Left" 
                     Grid.Row="1" 
                     Grid.Column="1"  
                     Width="100">
            </TextBox>
            <TextBlock Grid.Row="2" 
                       HorizontalAlignment="Right" 
                       Grid.Column="0" 
                       VerticalAlignment="Center" 
                       Text="Password: ">
            </TextBlock>
            <PasswordBox x:Name="NewPassword" 
                         VerticalAlignment="Center" 
                         HorizontalAlignment="Left" 
                         Grid.Row="2" 
                         Grid.Column="1"  
                         Width="100">
            </PasswordBox>
            <TextBlock Grid.Row="3" 
                       HorizontalAlignment="Right" 
                       Grid.Column="0" 
                       VerticalAlignment="Center" 
                       Text="Confirm Password: ">
            </TextBlock>
            <PasswordBox x:Name="NewConfirmPassword" 
                         HorizontalAlignment="Left" 
                         VerticalAlignment="Center" 
                         Grid.Row="3" 
                         Grid.Column="1"  
                         Width="100">
            </PasswordBox>
            <TextBlock Grid.Row="4" 
                       HorizontalAlignment="Right" 
                       Grid.Column="0" 
                       VerticalAlignment="Center" 
                       Text="Email: ">
            </TextBlock>
            <TextBox x:Name="NewEmail" 
                     VerticalAlignment="Center" 
                     Grid.Row="4" 
                     Grid.Column="1"  
                     Width="200">
            </TextBox>
            <TextBlock Grid.Row="5" 
                       HorizontalAlignment="Right" 
                       Grid.Column="0" 
                       VerticalAlignment="Center" 
                       Text="Records to show: ">
            </TextBlock>
            <ComboBox Grid.Row="5" 
                      Grid.Column="1" 
                      x:Name="DefaultRows" 
                      HorizontalAlignment="Left" 
                      Width="50" 
                      Height="20" 
                      VerticalAlignment="Center">
                <ComboBoxItem Content="1"></ComboBoxItem>
                <ComboBoxItem Content="3"></ComboBoxItem>
                <ComboBoxItem Content="5"></ComboBoxItem>
                <ComboBoxItem Content="10" IsSelected="True"></ComboBoxItem>
                <ComboBoxItem Content="15"></ComboBoxItem>
                <ComboBoxItem Content="20"></ComboBoxItem>
            </ComboBox>
            <TextBlock Grid.Row="6" 
                       HorizontalAlignment="Right" 
                       Grid.Column="0" 
                       VerticalAlignment="Center" 
                       Text="Security Question: ">
            </TextBlock>
            <TextBox x:Name="SecurityQuestion" 
                     VerticalAlignment="Center" 
                     Grid.Row="6" 
                     Grid.Column="1"  
                     Width="200">
            </TextBox>
            <TextBlock Grid.Row="7" 
                       HorizontalAlignment="Right" 
                       Grid.Column="0" 
                       VerticalAlignment="Center" 
                       Text="Security Answer: ">
            </TextBlock>
            <TextBox x:Name="SecurityAnswer" 
                     VerticalAlignment="Center" 
                     Grid.Row="7" 
                     Grid.Column="1"  
                     Width="200">
            </TextBox>
            <TextBlock x:Name="registerResult" 
                       TextWrapping="Wrap" 
                       Visibility="Collapsed" 
                       Grid.Row="8" 
                       Grid.ColumnSpan="2" 
                       Foreground="Red">
            </TextBlock>
            <Button x:Name="RegisterButton" 
                    Click="RegisterButton_Click" 
                    Margin="0,5,0,0" 
                    Grid.Row="9" 
                    Grid.Column="1" 
                    Content="Register" >
            </Button>
        </Grid>
    </Border>
    
  3. Home.xaml.cs (または Home.xaml.vb) 分離コード ファイルを開きます。

  4. System.ServiceModel.DomainServices.ClientSystem.ComponentModel.DataAnnotations、および ExampleNavigationApplication.Web の各名前空間の using ステートメントまたは Imports ステートメントを追加します。

  5. 登録ボタン クリック イベントのイベント ハンドラーを追加し、ドメイン操作のコールバック メソッドを追加します。コールバック メソッドには、ユーザー アカウントの作成に成功した後にユーザーをログインするためのコードが含まれています。

    Private Sub RegisterButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
        RegisterButton.IsEnabled = False
        Dim context = New RegistrationDomainContext()
        Dim nu = New NewUser()
        Try
            nu.UserName = NewUsername.Text
            nu.Password = NewPassword.Password
            nu.Email = NewEmail.Text
            nu.ConfirmPassword = NewConfirmPassword.Password
            nu.RecordsToShow = Integer.Parse(DefaultRows.SelectionBoxItem.ToString())
            nu.SecurityQuestion = SecurityQuestion.Text
            nu.SecurityAnswer = SecurityAnswer.Text
            context.NewUsers.Add(nu)
    
            context.SubmitChanges(AddressOf RegisterUser_Completed, Nothing)
        Catch ve As ValidationException
            registerResult.Visibility = System.Windows.Visibility.Visible
            registerResult.Text = ve.Message
            RegisterButton.IsEnabled = True
        End Try
    End Sub
    
    Private Sub RegisterUser_Completed(ByVal so As SubmitOperation)
        If (so.HasError) Then
            Dim ew = New ErrorWindow("Registration failed.", "Please try registering again.")
            ew.Show()
            so.MarkErrorAsHandled()
        Else
            Dim lp = New LoginParameters(NewUsername.Text, NewPassword.Password)
            WebContext.Current.Authentication.Login(lp, AddressOf Me.LoginOperation_Completed, Nothing)
            NewUsername.Text = ""
            NewPassword.Password = ""
            NewConfirmPassword.Password = ""
            NewEmail.Text = ""
            DefaultRows.SelectedIndex = 0
            SecurityQuestion.Text = ""
            SecurityAnswer.Text = ""
        End If
        RegisterButton.IsEnabled = True
    End Sub
    
    private void RegisterButton_Click(object sender, RoutedEventArgs e)
    {
        RegisterButton.IsEnabled = false;
        RegistrationDomainContext context = new RegistrationDomainContext();
        NewUser nu = new NewUser();
        try
        {
            nu.UserName = NewUsername.Text;
            nu.Password = NewPassword.Password;
            nu.Email = NewEmail.Text;
            nu.ConfirmPassword = NewConfirmPassword.Password;
            nu.RecordsToShow = int.Parse(DefaultRows.SelectionBoxItem.ToString());
            nu.SecurityQuestion = SecurityQuestion.Text;
            nu.SecurityAnswer = SecurityAnswer.Text;
            context.NewUsers.Add(nu);
    
            context.SubmitChanges(RegisterUser_Completed, null);
        }
        catch (ValidationException ve)
        {
            registerResult.Visibility = System.Windows.Visibility.Visible;
            registerResult.Text = ve.Message;
            RegisterButton.IsEnabled = true;
        }
    }
    
    private void RegisterUser_Completed(SubmitOperation so)
    {
        if (so.HasError)
        {
            ErrorWindow ew = new ErrorWindow("Registration failed.", "Please try registering again.");
            ew.Show();
            so.MarkErrorAsHandled();
        }
        else
        {
            LoginParameters lp = new LoginParameters(NewUsername.Text, NewPassword.Password);
            WebContext.Current.Authentication.Login(lp, this.LoginOperation_Completed, null);
            NewUsername.Text = "";
            NewPassword.Password = "";
            NewConfirmPassword.Password = "";
            NewEmail.Text = "";
            DefaultRows.SelectedIndex = 0;
            SecurityQuestion.Text = "";
            SecurityAnswer.Text = "";
        }
        RegisterButton.IsEnabled = true;
    }
    
  6. 次のコードに示すように、RegisterBorder の可視性を設定するように SetControlVisibility メソッドを変更します。

    Private Sub SetControlVisibility(ByVal isAuthenticated As Boolean)
        If (isAuthenticated) Then
            LoginBorder.Visibility = System.Windows.Visibility.Collapsed
            RegisterBorder.Visibility = Windows.Visibility.Collapsed
            WelcomeText.Text = "Welcome " + WebContext.Current.User.Name
            WelcomeText.Visibility = System.Windows.Visibility.Visible
            LogoutButton.Visibility = System.Windows.Visibility.Visible
        Else
            LoginBorder.Visibility = System.Windows.Visibility.Visible
            RegisterBorder.Visibility = Windows.Visibility.Visible
            WelcomeText.Visibility = System.Windows.Visibility.Collapsed
            LogoutButton.Visibility = System.Windows.Visibility.Collapsed
        End If
    End Sub
    
    private void SetControlVisibility(bool isAuthenticated)
    {
        if (isAuthenticated)
        {
            LoginBorder.Visibility = System.Windows.Visibility.Collapsed;
            RegisterBorder.Visibility = System.Windows.Visibility.Collapsed;
            WelcomeText.Text = "Welcome " + WebContext.Current.User.Name;
            WelcomeText.Visibility = System.Windows.Visibility.Visible;
            LogoutButton.Visibility = System.Windows.Visibility.Visible;
        }
        else
        {
            LoginBorder.Visibility = System.Windows.Visibility.Visible;
            RegisterBorder.Visibility = System.Windows.Visibility.Visible;
            WelcomeText.Visibility = System.Windows.Visibility.Collapsed;
            LogoutButton.Visibility = System.Windows.Visibility.Collapsed;
        }
    }
    

    完全な分離コード ファイルを次に示します。

    Imports System.ServiceModel.DomainServices.Client.ApplicationServices
    Imports System.ServiceModel.DomainServices.Client
    Imports System.ComponentModel.DataAnnotations
    
    Partial Public Class Home
        Inherits Page
    
        Public Sub New()
            InitializeComponent()
        End Sub
    
        Protected Overrides Sub OnNavigatedTo(ByVal e As System.Windows.Navigation.NavigationEventArgs)
            SetControlVisibility(WebContext.Current.User.IsAuthenticated)
        End Sub
    
        Private Sub LoginButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
            Dim lp As LoginParameters = New LoginParameters(UserName.Text, Password.Password)
            WebContext.Current.Authentication.Login(lp, AddressOf Me.LoginOperation_Completed, Nothing)
            LoginButton.IsEnabled = False
            LoginResult.Text = ""
        End Sub
    
        Private Sub LoginOperation_Completed(ByVal lo As LoginOperation)
            If (lo.HasError) Then
                LoginResult.Text = lo.Error.Message
                LoginResult.Visibility = System.Windows.Visibility.Visible
                lo.MarkErrorAsHandled()
            ElseIf (lo.LoginSuccess = False) Then
                LoginResult.Text = "Login failed. Please check user name and password."
                LoginResult.Visibility = System.Windows.Visibility.Visible
            ElseIf (lo.LoginSuccess = True) Then
                SetControlVisibility(True)
            End If
            LoginButton.IsEnabled = True
        End Sub
    
        Private Sub SetControlVisibility(ByVal isAuthenticated As Boolean)
            If (isAuthenticated) Then
                LoginBorder.Visibility = System.Windows.Visibility.Collapsed
                RegisterBorder.Visibility = Windows.Visibility.Collapsed
                WelcomeText.Text = "Welcome " + WebContext.Current.User.Name
                WelcomeText.Visibility = System.Windows.Visibility.Visible
                LogoutButton.Visibility = System.Windows.Visibility.Visible
            Else
                LoginBorder.Visibility = System.Windows.Visibility.Visible
                RegisterBorder.Visibility = Windows.Visibility.Visible
                WelcomeText.Visibility = System.Windows.Visibility.Collapsed
                LogoutButton.Visibility = System.Windows.Visibility.Collapsed
            End If
        End Sub
    
        Private Sub LogoutButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
            WebContext.Current.Authentication.Logout(AddressOf Me.LogoutOperation_Completed, Nothing)
        End Sub
    
        Private Sub LogoutOperation_Completed(ByVal lo As LogoutOperation)
            If (Not (lo.HasError)) Then
                SetControlVisibility(False)
            Else
                Dim ew As ErrorWindow = New ErrorWindow("Logout failed.", "Please try logging out again.")
                ew.Show()
                lo.MarkErrorAsHandled()
            End If
        End Sub
    
        Private Sub RegisterButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
            RegisterButton.IsEnabled = False
            Dim context = New RegistrationDomainContext()
            Dim nu = New NewUser()
            Try
                nu.UserName = NewUsername.Text
                nu.Password = NewPassword.Password
                nu.Email = NewEmail.Text
                nu.ConfirmPassword = NewConfirmPassword.Password
                nu.RecordsToShow = Integer.Parse(DefaultRows.SelectionBoxItem.ToString())
                nu.SecurityQuestion = SecurityQuestion.Text
                nu.SecurityAnswer = SecurityAnswer.Text
                context.NewUsers.Add(nu)
    
                context.SubmitChanges(AddressOf RegisterUser_Completed, Nothing)
            Catch ve As ValidationException
                registerResult.Visibility = System.Windows.Visibility.Visible
                registerResult.Text = ve.Message
                RegisterButton.IsEnabled = True
            End Try
        End Sub
    
        Private Sub RegisterUser_Completed(ByVal so As SubmitOperation)
            If (so.HasError) Then
                Dim ew = New ErrorWindow("Registration failed.", "Please try registering again.")
                ew.Show()
                so.MarkErrorAsHandled()
            Else
                Dim lp = New LoginParameters(NewUsername.Text, NewPassword.Password)
                WebContext.Current.Authentication.Login(lp, AddressOf Me.LoginOperation_Completed, Nothing)
                NewUsername.Text = ""
                NewPassword.Password = ""
                NewConfirmPassword.Password = ""
                NewEmail.Text = ""
                DefaultRows.SelectedIndex = 0
                SecurityQuestion.Text = ""
                SecurityAnswer.Text = ""
            End If
            RegisterButton.IsEnabled = True
        End Sub
    End Class
    
    using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Navigation;
    using System.ServiceModel.DomainServices.Client.ApplicationServices;
    using System.ServiceModel.DomainServices.Client;
    using System.ComponentModel.DataAnnotations;
    using ExampleNavigationApplication.Web;
    
    namespace ExampleNavigationApplication
    {
        public partial class Home : Page
        {
            public Home()
            {
                InitializeComponent();
    
            }
    
            // Executes when the user navigates to this page.
            protected override void OnNavigatedTo(NavigationEventArgs e)
            {
                SetControlVisibility(WebContext.Current.User.IsAuthenticated);
            }
    
            private void LoginButton_Click(object sender, RoutedEventArgs e)
            {
                LoginParameters lp = new LoginParameters(UserName.Text, Password.Password);
                WebContext.Current.Authentication.Login(lp, this.LoginOperation_Completed, null);
                LoginButton.IsEnabled = false;
                LoginResult.Text = "";
            }
    
            private void LoginOperation_Completed(LoginOperation lo)
            {
                if (lo.HasError)
                {
                    LoginResult.Text = lo.Error.Message;
                    LoginResult.Visibility = System.Windows.Visibility.Visible;
                    lo.MarkErrorAsHandled();
                }
                else if (lo.LoginSuccess == false)
                {
                    LoginResult.Text = "Login failed. Please check user name and password.";
                    LoginResult.Visibility = System.Windows.Visibility.Visible;
                }
                else if (lo.LoginSuccess == true)
                {
                    SetControlVisibility(true);
                }
                LoginButton.IsEnabled = true;
            }
    
            private void SetControlVisibility(bool isAuthenticated)
            {
                if (isAuthenticated)
                {
                    LoginBorder.Visibility = System.Windows.Visibility.Collapsed;
                    RegisterBorder.Visibility = System.Windows.Visibility.Collapsed;
                    WelcomeText.Text = "Welcome " + WebContext.Current.User.Name;
                    WelcomeText.Visibility = System.Windows.Visibility.Visible;
                    LogoutButton.Visibility = System.Windows.Visibility.Visible;
                }
                else
                {
                    LoginBorder.Visibility = System.Windows.Visibility.Visible;
                    RegisterBorder.Visibility = System.Windows.Visibility.Visible;
                    WelcomeText.Visibility = System.Windows.Visibility.Collapsed;
                    LogoutButton.Visibility = System.Windows.Visibility.Collapsed;
                }
            }
    
            private void LogoutButton_Click(object sender, RoutedEventArgs e)
            {
                WebContext.Current.Authentication.Logout(this.LogoutOperation_Completed, null);
            }
    
            private void LogoutOperation_Completed(LogoutOperation lo)
            {
    
                if (!lo.HasError)
                {
                    SetControlVisibility(false);
                }
                else
                {
                    ErrorWindow ew = new ErrorWindow("Logout failed.", "Please try logging out again.");
                    ew.Show();
                    lo.MarkErrorAsHandled();
                }
            }
    
            private void RegisterButton_Click(object sender, RoutedEventArgs e)
            {
                RegisterButton.IsEnabled = false;
                RegistrationDomainContext context = new RegistrationDomainContext();
                NewUser nu = new NewUser();
                try
                {
                    nu.UserName = NewUsername.Text;
                    nu.Password = NewPassword.Password;
                    nu.Email = NewEmail.Text;
                    nu.ConfirmPassword = NewConfirmPassword.Password;
                    nu.RecordsToShow = int.Parse(DefaultRows.SelectionBoxItem.ToString());
                    nu.SecurityQuestion = SecurityQuestion.Text;
                    nu.SecurityAnswer = SecurityAnswer.Text;
                    context.NewUsers.Add(nu);
    
                    context.SubmitChanges(RegisterUser_Completed, null);
                }
                catch (ValidationException ve)
                {
                    registerResult.Visibility = System.Windows.Visibility.Visible;
                    registerResult.Text = ve.Message;
                    RegisterButton.IsEnabled = true;
                }
            }
    
            private void RegisterUser_Completed(SubmitOperation so)
            {
                if (so.HasError)
                {
                    ErrorWindow ew = new ErrorWindow("Registration failed.", "Please try registering again.");
                    ew.Show();
                    so.MarkErrorAsHandled();
                }
                else
                {
                    LoginParameters lp = new LoginParameters(NewUsername.Text, NewPassword.Password);
                    WebContext.Current.Authentication.Login(lp, this.LoginOperation_Completed, null);
                    NewUsername.Text = "";
                    NewPassword.Password = "";
                    NewConfirmPassword.Password = "";
                    NewEmail.Text = "";
                    DefaultRows.SelectedIndex = 0;
                    SecurityQuestion.Text = "";
                    SecurityAnswer.Text = "";
                }
                RegisterButton.IsEnabled = true;
            }
        }
    }
    
  7. ソリューションを実行します。

    RIA_LoginandRegister

  8. 新しいユーザーを登録するための値を指定します。

  9. Web ブラウザーを閉じます。

ドメイン操作へのアクセスの制限

ドメイン操作へのアクセスを制限するには、ドメイン操作に RequiresAuthenticationAttribute 属性または RequiresRoleAttribute 属性を適用します。属性を持たないドメイン操作は、すべてのユーザーが使用できます。属性をドメイン操作に適用しても、ユーザーがドメイン操作を呼び出せなくなることはありませんが、必要な資格情報を持っていないユーザーの場合は、例外が発生します。

ロール別に表示データを制限するには

  1. ソリューション エクスプローラーで、サーバー プロジェクトを選択し、[すべてのファイルを表示] をクリックします。

  2. App_Data フォルダーを右クリックし、[プロジェクトに含める] をクリックします。

  3. App_Data フォルダーを右クリックし、[追加] をポイントして、[既存の項目] をクリックします。

  4. [既存項目の追加] ダイアログ ボックスで、AdventureWorksLT サンプル データベースを追加します。

  5. サーバー プロジェクトで、新しい項目を追加し、[ADO.NET エンティティ データ モデル] テンプレートをクリックします。

  6. モデルに AdventureWorksModel.edmx という名前を付けて、[追加] をクリックします。

    Entity Data Model ウィザードが表示されます。

  7. [データベースから生成] を選択し、[次へ] をクリックします。

  8. AdventureWorksLT データベースを選択し、[次へ] をクリックします。

  9. データベース オブジェクトの一覧から、Customer、Product、および SalesOrderHeader の各テーブルを選択し、[完了] をクリックします。

    エンティティ データ モデルがデザイナーに表示されます。

  10. ソリューションをビルドします。

  11. サーバー プロジェクトで、新しい項目を追加し、[DomainService クラス] テンプレートをクリックします。

  12. ドメイン サービスに AdventureWorksDomainService という名前を付けて、[追加] をクリックします。

  13. [新しいドメイン サービス クラスの追加] ダイアログ ボックスで、Customer、Product、および SalesOrderHeader エンティティを選択します。

    RIA_CreateDSForAuth

  14. [OK] をクリックして、ドメイン サービスの作成を完了します。

  15. 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;
    }
    
  16. 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;
        }
    }
    

クライアントからの認証サービスの使用

アクセス許可が制限されたドメイン操作を呼び出す前に、ユーザーに必要な資格情報があることを確認する必要があります。必要な資格情報がない場合は、例外がスローされます。ここでは、ユーザーの資格情報を確認し、ユーザーの資格情報に基づいて 1 ~ 3 個の DataGrid コントロールを設定します。また、ユーザー プロファイルのプロパティに基づいてレコードの数を取得します。既定値の 10 は、認証されていないユーザーに使用されます。このセクションでは、ユーザーが DefaultRows プロファイル プロパティを設定するための方法は説明しませんが、このプロファイル プロパティは後のセクションで追加します。

データを表示するための Silverlight ページを追加するには

  1. クライアント プロジェクトで、Views フォルダーに新しい項目を追加します。

  2. [Silverlight ページ] テンプレートを選択し、新しいページに Reports.xaml という名前を付けます。

  3. 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="reports"/>
    
  4. Reports.xaml ファイルを開き、Grid タグ内に次の XAML を追加し、サイト内の他のページの書式設定と一致させ、プロファイル プロパティを編集するためのウィンドウを起動する HyperlinkButton コントロールを追加します。

    <ScrollViewer x:Name="PageScrollViewer" Style="{StaticResource PageScrollViewerStyle}">
    
        <StackPanel x:Name="ContentStackPanel">
    
            <TextBlock x:Name="HeaderText" 
                       Style="{StaticResource HeaderTextStyle}"
                       Text="Reports"/>
            <TextBlock x:Name="ContentText" 
                       Style="{StaticResource ContentTextStyle}"
                       Text="Display reports based on user permissions"/>
            <HyperlinkButton x:Name="SettingsButton" 
                             Content="Adjust Settings" 
                             Click="SettingsButton_Click" 
                             Visibility="Collapsed">
            </HyperlinkButton>
    
        </StackPanel>
    
    </ScrollViewer>
    
  5. ContentStackPanel という名前のスタック パネルの終了タグの直前に、ツールボックスから 3 つの DataGrid コントロールをドラッグします。

    ツールボックスから DataGrid コントロールをドラッグすると、System.Windows.Controls.Data アセンブリへの参照がプロジェクトに追加され、System.Windows.Controls 名前空間のプレフィックスがページに追加されます。

  6. DataGrid コントロールに ProductsGridSalesOrdersGrid、および CustomersGrid という名前を付け、Margin を 5 に設定します。

    完全な Reports.xaml ファイルの例を次に示します。

    <navigation:Page 
          x:Class="ExampleNavigationApplication.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:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"
          xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"
          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">
    
                    <TextBlock x:Name="HeaderText" 
                               Style="{StaticResource HeaderTextStyle}"
                               Text="Reports"/>
                    <TextBlock x:Name="ContentText" 
                               Style="{StaticResource ContentTextStyle}"
                               Text="Display reports based on user permissions"/>
            <HyperlinkButton x:Name="SettingsButton" 
                                     Content="Adjust Settings" 
                                     Click="SettingsButton_Click" 
                                     Visibility="Collapsed">
                    </HyperlinkButton>
                    <data:DataGrid Name="ProductsGrid" Margin="5" />
                    <data:DataGrid Name="SalesOrdersGrid" Margin="5" />
                    <data:DataGrid Name="CustomersGrid" Margin="5" />
                </StackPanel>
    
            </ScrollViewer>
        </Grid>
    </navigation:Page>
    
  7. Reports.xaml.cs ファイルまたは Reports.xaml.vb ファイルを開き、System.ServiceModel.DomainServices.Client 名前空間および ExampleNavigationApplication.Web 名前空間の using ステートメントまたは Imports ステートメントを追加します。

  8. context という名前の AdventureWorksDomainContext のインスタンスを作成し、取得する行数を含む numberOfRows という名前の変数を作成します。

    Private context As New AdventureWorksDomainContext
    Private numberOfRows As Integer = 10
    
    private AdventureWorksDomainContext context = new AdventureWorksDomainContext();
    int numberOfRows = 10;
    
  9. ユーザーが 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;
        }
    }
    
  10. ユーザーが認証されているかどうかを確認し、認証されている場合は 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;
    }
    
  11. プロパティ 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();
        }
    }
    
  12. 次のコードをコンストラクターに追加します。このコードにより、レポートが読み込まれ、設定リンクが認証済みユーザーに表示されます。

    Public Sub New()
        InitializeComponent()
        LoadReports()
        If (WebContext.Current.User.IsAuthenticated) Then
            SettingsButton.Visibility = System.Windows.Visibility.Visible
        End If
    End Sub
    
    public Reports()
    {
        InitializeComponent();
        LoadReports();
        if (WebContext.Current.User.IsAuthenticated)
        {
            SettingsButton.Visibility = System.Windows.Visibility.Visible;
        }
    }
    
  13. 設定リンクに Click イベントのイベント ハンドラーを追加します。

    ProfileWindow は後の手順で追加されます。

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

    完全なコード ファイルを次に示します。

    Imports System.ServiceModel.DomainServices.Client
    Imports ExampleNavigationApplication.Web
    
    Partial Public Class Reports
        Inherits Page
    
        Private context As New AdventureWorksDomainContext
        Private numberOfRows As Integer = 10
    
        Public Sub New()
            InitializeComponent()
            LoadReports()
            If (WebContext.Current.User.IsAuthenticated) Then
                SettingsButton.Visibility = System.Windows.Visibility.Visible
            End If
        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 SettingsButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
            Dim settingsWindow = New ProfileWindow()
            settingsWindow.Show()
        End Sub
    End Class
    
    using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Navigation;
    using System.ServiceModel.DomainServices.Client;
    using ExampleNavigationApplication.Web;
    
    namespace ExampleNavigationApplication.Views
    {
        public partial class Reports : Page
        {
            private AdventureWorksDomainContext context = new AdventureWorksDomainContext();
            int numberOfRows = 10;
    
            public Reports()
            {
                InitializeComponent();
                LoadReports();
                if (WebContext.Current.User.IsAuthenticated)
                {
                    SettingsButton.Visibility = System.Windows.Visibility.Visible;
                }
            }
    
            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 User_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
            {
                if (e.PropertyName == "DefaultRows")
                {
                    LoadReports();
                }
            }
    
            private void SettingsButton_Click(object sender, RoutedEventArgs e)
            {
                Views.ProfileWindow settingsWindow = new Views.ProfileWindow();
                settingsWindow.Show();
            }
        }
    }
    

子ウィンドウを追加することで、ユーザーが DefaultRows プロファイル プロパティを編集できるようにすることができます。値を変更した場合は、SaveUser メソッドを呼び出して、値をデータ ソースに保存します。現在の WebContext インスタンスのユーザー オブジェクトのプロパティを使用して、現在の値を取得します。

プロファイル プロパティを設定するためのウィンドウを追加するには

  1. クライアント プロジェクトで、Views フォルダーに新しい項目を追加します。

  2. [Silverlight 子ウィンドウ] テンプレートを選択し、名前を ProfileWindow.xaml に設定します。

    子ウィンドウの追加

  3. [追加] をクリックします。

  4. ProfileWindow.xaml ファイルで、レポートに表示する行数を選択するための ComboBox を追加するために次の XAML を追加します。

    <controls:ChildWindow x:Class="ExampleNavigationApplication.Views.ProfileWindow"
               xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
               xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
               xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"
               Width="300" Height="200"
               Title="ProfileWindow">
      <Grid x:Name="LayoutRoot" Margin="2">
        <Grid.RowDefinitions>
          <RowDefinition />
          <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
    
        <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="3"></ComboBoxItem>
            <ComboBoxItem Content="5"></ComboBoxItem>
            <ComboBoxItem Content="10"></ComboBoxItem>
            <ComboBoxItem Content="15"></ComboBoxItem>
            <ComboBoxItem Content="20"></ComboBoxItem>
          </ComboBox>
        </StackPanel>
    
        <Button x:Name="CancelButton" 
                Content="Cancel" 
                Click="CancelButton_Click" 
                Width="75" 
                Height="23" 
                HorizontalAlignment="Right" 
                Margin="0,12,0,0" 
                Grid.Row="1" />
        <Button x:Name="OKButton" 
                Content="OK" 
                Click="OKButton_Click" 
                Width="75" 
                Height="23" 
                HorizontalAlignment="Right" 
                Margin="0,12,79,0" 
                Grid.Row="1" />
      </Grid>
    </controls:ChildWindow>
    
  5. ProfileWindow.xaml.cs 分離コード ファイルまたは ProfileWindow.xaml.vb 分離コード ファイルで、次のコードを追加して、プロファイル プロパティを取得および設定します。

    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;
        }
    }
    
  6. ソリューションを実行します。

  7. [レポート] リンクをクリックします。

    サイトが開かれたときにログインしていない場合は、Reports ページに製品テーブルのみが表示されます。

  8. ホーム ページで、新しいユーザーを登録し、そのユーザーとしてログインします。

  9. [レポート] リンクをクリックします。

    製品および販売注文に関するテーブルが表示されます。

  10. ログアウトして、CustomerManager としてログインします。

    製品、販売注文、および顧客に関するテーブルが表示されます。

  11. [設定の調整] リンクをクリックし、レポートに表示する既定の行数を設定します。

    RIA_ShowProfileSettings

    選択した行数が DataGrid に含まれていることを確認します。

  12. Web ブラウザーを閉じます。

参照

処理手順

チュートリアル: Silverlight ビジネス アプリケーションでの認証サービスの使用