다음을 통해 공유


연습: Silverlight 탐색 응용 프로그램에서 인증 서비스 사용

이 연습에서는 인증 서비스와 작동하도록 WCF RIA Services 솔루션에서 서버 및 클라이언트 프로젝트를 설정하는 방법을 알아봅니다. Silverlight 탐색 응용 프로그램 템플릿을 사용하여 솔루션을 만들고 RIA Services 를 사용하도록 설정하는 경우 인증 서비스를 추가하여 ASP.NET 멤버 자격 프레임워크에 액세스할 수 있습니다. 인증 서비스는 인증, 역할 및 프로필을 서버 프로젝트에서 클라이언트 프로젝트로 노출합니다. 인증 서비스를 사용하여 사용자 자격 증명의 유효성을 검사하고 역할을 기반으로 리소스에 대한 액세스를 제한할 수 있으며 프로필 속성을 저장할 수 있습니다.

[!참고] Silverlight 비즈니스 응용 프로그램은 자동으로 인증 서비스를 구현합니다. 자세한 내용은 연습: Silverlight 비즈니스 응용 프로그램에서 인증 서비스 사용을 참조하십시오.

필수 구성 요소

RIA Services 설명서에서 제공하는 이 연습 및 다른 연습을 실행하려면 WCF RIA Services 및 WCF RIA Services 도구 키트 외에도 Visual Studio 2010, Silverlight Developer 런타임 및 SDK 등의 몇 가지 필수 구성 요소 프로그램을 올바르게 설치하고 구성해야 합니다. 또한 SQL Server 2008 R2 Express with Advanced Services를 설치하고 구성해야 하며 AdventureWorks OLTP 및 LT 데이터베이스를 설치해야 합니다.

이러한 각 사전 요구 사항을 충족하기 위한 자세한 지침은 WCF RIA Services의 사전 요구 사항 노드의 항목에서 제공합니다. 이 RIA Services 연습을 수행할 때 발생할 수 있는 문제를 최소화하려면 이 연습을 진행하기 전에 여기서 제공하는 지침을 따르십시오.

인증, 역할 및 프로필에 대해 서버 프로젝트 구성

Silverlight 응용 프로그램에서 인증 서비스를 사용하려면 서버 프로젝트에서 인증을 구성해야 합니다. Web.config 파일에서 인증을 구성할 수 있습니다. 인증을 구성한 후 Silverlight 응용 프로그램에서 역할 및 프로필을 사용하려는 경우 서버 프로젝트에서 역할 및 프로필을 구성할 수도 있습니다. 이 연습에서는 세 기능을 모두 구성하며, 사용하도록 설정된 기능을 노출하는 인증 서비스를 클라이언트에 추가합니다.

서버 프로젝트를 구성하려면

  1. Visual Studio 2010에서 파일, 새로 만들기, 프로젝트를 차례로 선택합니다.

    새 프로젝트 대화 상자가 나타납니다.

  2. Silverlight 프로젝트 형식을 선택합니다.

  3. Silverlight 탐색 응용 프로그램 템플릿을 선택하고 응용 프로그램의 이름을 ExampleNavigationApplication으로 지정합니다.

  4. 확인을 클릭합니다.

    새 Silverlight 응용 프로그램 대화 상자가 나타납니다.

  5. 새 웹 사이트에서 Silverlight 응용 프로그램 호스트 확인란이 선택되어 있고 새 웹 프로젝트 형식이 ASP.NET 웹 응용 프로그램 프로젝트로 설정되어 있는지 확인합니다.

  6. WCF RIA 서비스 사용 확인란을 선택합니다.

  7. 확인을 클릭하여 솔루션을 만듭니다.

  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. 인증 도메인 서비스 템플릿을 선택하고 이름을 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 웹 사이트 관리 도구를 사용하여 사용자와 역할을 만듭니다. 이후 단원에서는 이 사용자로 로그인합니다.

ASP.NET 웹 사이트 관리 도구를 사용하여 사용자를 추가하려면

  1. ASP.NET 웹 사이트 관리 도구를 열려면 먼저 솔루션 탐색기에서 서버 프로젝트를 선택합니다.

  2. 프로젝트 메뉴에서 ASP.NET 구성을 선택합니다.

    프로젝트 메뉴에 ASP.NET 구성 옵션이 보이지 않는 경우 클라이언트 프로젝트를 선택했기 때문일 수 있습니다.

    RIA_OpenAdminTool

  3. ASP.NET 웹 사이트 관리 도구에서 보안 탭을 선택합니다.

    RIA_WebAdminSecurity

  4. 역할 섹션에서 역할 만들기 또는 관리 링크를 클릭합니다.

  5. Managers라는 새 역할을 추가하고 역할 추가 단추를 클릭합니다.

    WebAdmin_CreateRole

  6. 오른쪽 아래 모퉁이에서 뒤로 단추를 클릭합니다.

  7. 사용자 섹션에서 사용자 만들기 링크를 클릭합니다.

  8. 다음 값을 사용하여 새 사용자를 만들고 Managers 역할 확인란을 선택합니다.

    사용자 이름: CustomerManager

    암호: P@ssword

    전자 메일: someone@example.com

    보안 질문: 가장 좋아하는 색상은?

    보안 대답: 파랑

    Managers 역할: 선택

    WebAdmin_CreateUser

  9. 사용자 만들기 단추를 클릭합니다.

  10. ASP.NET 웹 사이트 관리 도구를 닫습니다.

인증에 대해 클라이언트 구성

서버 프로젝트에서 구성한 인증 모드와 일치하는 인증 모드를 사용하도록 클라이언트 프로젝트를 구성해야 합니다.

클라이언트 프로젝트를 구성하려면

  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. 다음 코드를 Home 클래스에 추가합니다.

    이 코드에는 로그인 및 로그아웃에 대한 이벤트 처리기, 완료된 로그인 및 로그아웃 작업에 대한 콜백 메서드 및 사용자의 인증 여부에 따라 컨트롤의 표시 여부를 설정하는 메서드가 포함되어 있습니다.

    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. Logout 링크를 클릭하고 웹 브라우저를 닫습니다.

클라이언트에서 새 사용자 추가

인증 서비스에는 새 사용자를 만드는 작업이 포함되어 있지 않습니다. 새 사용자를 등록하려면 빈 도메인 서비스를 만들고 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. 서버 프로젝트에 새 항목을 추가하고 도메인 서비스 클래스 템플릿을 선택합니다.

  6. 파일의 이름을 RegistrationDomainService.cs 또는 RegistrationDomainService.vb로 지정한 다음 추가 단추를 클릭합니다.

  7. 새 도메인 서비스 클래스 추가 대화 상자의 사용 가능한 DataContexts/ObjectContexts 목록에서 **<빈 도메인 서비스 클래스>**를 선택합니다.

  8. 확인을 클릭합니다.

  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을 추가하여 새 사용자를 만들기 위한 정보를 수집하는 입력 컨트롤이 포함된 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.Client, System.ComponentModel.DataAnnotationsExampleNavigationApplication.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. 다음 코드와 같이 SetControlVisibility 메서드를 수정하여 RegisterBorder의 표시 여부를 설정합니다.

    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. 웹 브라우저를 닫습니다.

도메인 작업에 대한 액세스 제한

RequiresAuthenticationAttribute 특성 또는 RequiresRoleAttribute 특성을 도메인 작업에 적용하여 도메인 작업에 대한 액세스를 제한합니다. 특성이 없는 도메인 작업은 모든 사용자가 이용할 수 있습니다. 특성을 도메인 작업에 적용해도 사용자가 도메인 작업을 호출할 수 있지만 필수 자격 증명이 없는 사용자의 경우 예외가 발생합니다.

역할에 따라 표시되는 데이터를 제한하려면

  1. 솔루션 탐색기에서 서버 프로젝트를 선택하고 모든 파일 표시 단추를 클릭합니다.

  2. App_Data 폴더를 마우스 오른쪽 단추로 클릭하고 프로젝트에 포함을 선택합니다.

  3. App_Data 폴더를 마우스 오른쪽 단추로 클릭하고 추가를 선택한 다음 기존 항목을 선택합니다.

  4. 기존 항목 추가 대화 상자에서 AdventureWorksLT 샘플 데이터베이스를 추가합니다.

  5. 서버 프로젝트에서 새 항목을 추가하고 ADO.NET 엔터티 데이터 모델 템플릿을 선택합니다.

  6. 모델의 이름을 AdventureWorksModel.edmx로 지정하고 추가를 클릭합니다.

    엔터티 데이터 모델 마법사가 나타납니다.

  7. 데이터베이스에서 생성 옵션을 선택하고 다음을 클릭합니다.

  8. AdventureWorksLT 데이터베이스를 선택하고 다음을 클릭합니다.

  9. 데이터베이스 개체 목록에서 Customer, Product 및 SalesOrderHeader 테이블을 선택한 다음 마침을 클릭합니다.

    엔터티 데이터 모델이 디자이너에 나타납니다.

  10. 솔루션을 빌드합니다.

  11. 서버 프로젝트에서 새 항목을 추가하고 도메인 서비스 클래스 템플릿을 선택합니다.

  12. 도메인 서비스의 이름을 AdventureWorksDomainService로 지정하고 추가를 클릭합니다.

  13. 새 도메인 서비스 클래스 추가 대화 상자에서 Customer, Product 및 SalesOrderHeader 엔터티를 선택합니다.

    RIA_CreateDSForAuth

  14. 확인을 클릭하여 도메인 서비스 만들기를 마칩니다.

  15. AdventureWorksDomainService 클래스 파일에서 GetSalesOrderHeader 메서드에 RequiresAuthenticationAttribute 특성을 추가합니다.

    <RequiresAuthentication()> _
    Public Function GetSalesOrderHeaders() As IQueryable(Of SalesOrderHeader)
        Return Me.ObjectContext.SalesOrderHeaders
    End Function
    
    [RequiresAuthentication()]
    public IQueryable<SalesOrderHeader> GetSalesOrderHeaders()
    {
        return this.ObjectContext.SalesOrderHeaders;
    }
    
  16. GetCustomers 메서드에 RequiresRoleAttribute 특성을 추가하고 필수 역할의 이름을 "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;
        }
    }
    

클라이언트에서 인증 서비스 사용

제한된 권한으로 도메인 작업을 호출하기 전에 사용자에게 필수 자격 증명이 있는지 확인해야 합니다. 그렇지 않으면 예외가 throw됩니다. 이 단원에서는 사용자의 자격 증명을 확인하고 사용자의 자격 증명을 기준으로 1~3개의 DataGrid 컨트롤을 채웁니다. 사용자 프로필의 속성을 기준으로 레코드 수도 검색합니다. 인증되지 않은 사용자에 대해서는 기본값 10이 사용됩니다. 이 단원에는 사용자가 DefaultRows 프로필 속성을 설정하는 방법이 나와 있지 않지만 이후 단원에서 이 속성을 추가합니다.

데이터를 표시하기 위해 Silverlight 페이지를 추가하려면

  1. 클라이언트 프로젝트에서 Views 폴더에 새 항목을 추가합니다.

  2. Silverlight 페이지 템플릿을 선택하고 새 페이지의 이름을 Reports.xaml로 지정합니다.

  3. MainPage.xaml 파일을 열고 About 페이지에 연결하는 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이라는 스택 패널의 끝 태그 바로 앞으로 세 개의 DataGrid 컨트롤을 끌어 옵니다.

    도구 상자에서 DataGrid 컨트롤을 끌어 오면 System.Windows.Controls.Data 어셈블리에 대한 참조가 프로젝트에 추가되고 System.Windows.Controls 네임스페이스에 대한 접두사가 페이지에 추가됩니다.

  6. DataGrid 컨트롤의 이름을 ProductsGrid, SalesOrdersGridCustomersGrid로 지정하고 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.ClientExampleNavigationApplication.Web 네임스페이스에 대한 using 또는 Imports 문을 추가합니다.

  8. 컨텍스트라는 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라는 프로필 속성을 검색하고 User 개체의 PropertyChanged 이벤트에 대한 이벤트 처리기를 추가합니다. 마지막으로, 이 메서드는 모든 사용자에 대해 GetProductsQuery 메서드를 호출합니다.

    Private Sub LoadReports()
        If (WebContext.Current.User.IsAuthenticated) Then
            numberOfRows = WebContext.Current.User.DefaultRows
            AddHandler WebContext.Current.User.PropertyChanged, AddressOf User_PropertyChanged
            LoadRestrictedReports()
        Else
            CustomersGrid.Visibility = System.Windows.Visibility.Collapsed
            SalesOrdersGrid.Visibility = System.Windows.Visibility.Collapsed
        End If
    
        Dim loadProducts = context.Load(context.GetProductsQuery().Take(numberOfRows))
        ProductsGrid.ItemsSource = loadProducts.Entities
    End Sub
    
    private void LoadReports()
    {
        if (WebContext.Current.User.IsAuthenticated)
        {
            numberOfRows = WebContext.Current.User.DefaultRows;
            WebContext.Current.User.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(User_PropertyChanged);
            LoadRestrictedReports();
        }
        else
        {
            CustomersGrid.Visibility = System.Windows.Visibility.Collapsed;
            SalesOrdersGrid.Visibility = System.Windows.Visibility.Collapsed;
        }
    
        LoadOperation<Product> loadProducts = context.Load(context.GetProductsQuery().Take(numberOfRows));
        ProductsGrid.ItemsSource = loadProducts.Entities;
    }
    
  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 인스턴스의 User 개체 속성을 통해 현재 값을 검색합니다.

프로필 속성을 설정하기 위한 창을 추가하려면

  1. 클라이언트 프로젝트에서 Views 폴더에 새 항목을 추가합니다.

  2. Silverlight 자식 창 템플릿을 선택하고 자식 창의 이름을 ProfileWindow.xaml로 지정합니다.

    자식 창 추가

  3. 추가 단추를 클릭합니다.

  4. ProfileWindow.xaml 파일에서 다음 XAML을 추가하여 보고서에 표시할 행 수를 선택하기 위한 ComboBox를 포함합니다.

    <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 링크를 클릭합니다.

    사이트가 시작될 때 사용자가 로그인하지 않은 경우 제품에 대한 테이블만 Reports 페이지에 표시됩니다.

  8. 홈 페이지에서 새 사용자를 등록하고 새 사용자로 로그인합니다.

  9. reports 링크를 클릭합니다.

    제품 및 판매 주문에 대한 테이블이 표시됩니다.

  10. 로그아웃하고 CustomerManager로 로그인합니다.

    제품, 판매 주문 및 고객에 대한 테이블이 표시됩니다.

  11. Adjust Settings 링크를 클릭하고 보고서에 표시할 기본 행 수를 설정합니다.

    RIA_ShowProfileSettings

    DataGrid에 이제 선택한 행 수가 포함되어 있습니다.

  12. 웹 브라우저를 닫습니다.

참고 항목

작업

연습: Silverlight 비즈니스 응용 프로그램에서 인증 서비스 사용