연습: Silverlight 비즈니스 응용 프로그램에서 인증 서비스 사용
Silverlight 비즈니스 응용 프로그램 템플릿은 인증(인증 모드를 위한 폼 인증 포함), 역할 및 프로필을 자동으로 사용하는 솔루션을 만듭니다. 이 솔루션에는 기존 사용자를 로그인하고 새 사용자를 등록하기 위한 데이터 폼이 포함됩니다. 추가 코드를 작성하지 않고 이러한 기능을 사용할 수 있습니다. 역할 및 프로필 속성을 정의하여 솔루션을 사용자 지정할 수 있습니다.
이 연습에서는 Silverlight 비즈니스 응용 프로그램에서 인증, 역할 및 프로필을 사용하는 방법을 배웁니다. 사용자 자격 증명을 기준으로 특정 도메인 작업에 대한 액세스를 제한하고 사용자 기본 설정을 기준으로 사용자 인터페이스를 사용자 지정합니다. ASP.NET 웹 사이트 관리 도구를 사용하여 사이트의 역할과 사용자를 관리합니다.
필수 구성 요소
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 비즈니스 응용 프로그램에서 제공하는 기능을 사용하여 인증을 빠르게 구현할 수 있습니다. 다음 단원에서는 ASP.NET 구성 도구를 사용하여 사용자와 역할을 만든 다음 해당 사용자로 로그인합니다. Silverlight 비즈니스 응용 프로그램에서 제공하는 등록 양식을 통해 새 사용자를 등록합니다.
사이트, 역할 및 사용자를 만들려면
Visual Studio 2010에서 파일, 새로 만들기, 프로젝트를 차례로 선택합니다.
새 프로젝트 대화 상자가 나타납니다.
Silverlight 프로젝트 형식을 선택합니다.
Silverlight 비즈니스 응용 프로그램 템플릿을 선택하고 응용 프로그램의 이름을 ExampleBusinessApplication으로 지정합니다.
확인을 클릭합니다.
만들어진 프로젝트 구조를 확인합니다. Silverlight 클라이언트 프로젝트의 Views 폴더에 있는 Silverlight 페이지에서 사용자를 로그인하고 새 사용자를 등록할 수 있습니다.
ASP.NET 웹 사이트 관리 도구를 열려면 먼저 솔루션 탐색기에서 서비스 프로젝트(ExampleBusinessApplication.Web)를 선택하고 ASP.NET 구성 도구를 엽니다.
프로젝트 메뉴에서 ASP.NET 구성을 선택합니다.
프로젝트 메뉴에 ASP.NET 구성 옵션이 보이지 않는 경우 클라이언트 프로젝트를 선택했기 때문일 수 있습니다.
ASP.NET 웹 사이트 관리 도구에서 보안 탭을 선택합니다.
역할 섹션에서 역할 만들기 또는 관리 링크를 클릭합니다.
Managers라는 새 역할을 추가하고 역할 추가 단추를 선택합니다.
오른쪽 아래 모퉁이에서 뒤로 단추를 클릭합니다.
사용자 섹션에서 사용자 만들기 링크를 클릭합니다.
다음 값을 사용하여 새 사용자를 만들고 Managers 역할 확인란을 선택합니다.
사용자 이름: CustomerManager
암호: P@ssword
전자 메일: someone@example.com
보안 질문: 가장 좋아하는 색깔은?
보안 대답: 파랑
Managers 역할: 선택
사용자 만들기 단추를 클릭합니다.
ASP.NET 웹 사이트 관리 도구를 닫습니다.
솔루션을 실행합니다.
응용 프로그램의 홈 페이지가 웹 브라우저에 나타납니다.
페이지의 오른쪽 위 모퉁이에서 로그인 링크를 클릭합니다.
로그인 대화 상자가 나타납니다.
사용자 이름에 CustomerManager를 입력하고 암호에 P@ssword를 입력한 다음 확인 단추를 클릭합니다.
이제 해당 사용자로 로그인됩니다. 오른쪽 위 모퉁이에 "시작 CustomerManager" 텍스트를 확인합니다.
로그아웃 링크를 클릭합니다.
이제 CustomerManager로 로그인되어 있지 않습니다. 다음 단계에서는 등록 양식을 통해 새 사용자를 만듭니다.
로그인 링크를 다시 클릭합니다.
로그인 대화 상자에서 지금 등록 링크를 클릭합니다.
이제 등록 양식이 표시됩니다.
다음 값으로 등록 양식을 작성하여 새 사용자 계정을 만듭니다.
사용자 이름: SalesUser
표시 이름: SalesUser
전자 메일: someone@example.com
암호: P@ssword
보안 질문: 처음 구입한 차의 색상은 무엇입니까?
보안 대답: 녹색
확인을 클릭하여 새 사용자를 만듭니다.
이제 SalesUser로 로그인됩니다.
브라우저를 닫습니다.
ASP.NET 웹 사이트 관리 도구를 다시 열고 보안 탭을 클릭합니다.
이제 두 명의 사용자가 사이트에 있으며 하나의 역할만 만들었지만 두 개의 역할이 존재합니다.
역할 만들기 또는 관리를 클릭하고 Managers 역할과 Registered Users를 확인합니다.
Registered Users 역할은 비즈니스 응용 프로그램 템플릿에서 자동으로 만들어졌습니다.
Registered Users에 대한 관리 링크를 클릭합니다.
응용 프로그램을 통해 추가한 SalesUser라는 사용자가 Registered Users 역할에 속하는지 확인합니다.
ASP.NET 웹 사이트 관리 도구를 닫습니다.
액세스 및 프로필 속성 정의
RequiresAuthenticationAttribute 특성 또는 RequiresRoleAttribute 특성을 도메인 작업에 적용하여 도메인 작업에 대한 액세스를 제한합니다. 특성이 없는 도메인 작업은 모든 사용자가 이용할 수 있습니다. 특성을 도메인 작업에 적용해도 사용자가 도메인 작업을 호출할 수 있지만 필수 자격 증명이 없는 사용자의 경우 예외가 발생합니다.
역할에 따라 표시되는 데이터 제한
솔루션 탐색기에서 서버 프로젝트의 App_Data 폴더를 마우스 오른쪽 단추로 클릭하고 추가를 선택한 다음 기존 항목을 선택합니다.
기존 항목 추가 대화 상자에서 AdventureWorksLT 샘플 데이터베이스를 추가합니다.
서버 프로젝트에서 새 항목을 추가하고 데이터 템플릿에서 ADO.NET 엔터티 데이터 모델 템플릿을 선택합니다.
모델의 이름을 AdventureWorksModel.edmx로 지정하고 추가를 클릭합니다.
엔터티 데이터 모델 마법사가 나타납니다.
데이터베이스에서 생성 옵션을 선택하고 다음을 클릭합니다.
AdventureWorksLT 데이터베이스를 선택하고 다음을 클릭합니다.
데이터베이스 개체 목록에서 Customer, Product 및 SalesOrderHeader 테이블을 선택한 다음 마침을 클릭합니다.
엔터티 데이터 모델이 디자이너에 나타납니다.
솔루션을 빌드합니다.
서버 프로젝트에서 새 항목을 추가하고 웹 템플릿에서 도메인 서비스 클래스 템플릿을 선택합니다.
도메인 서비스의 이름을 AdventureWorksDomainService로 지정하고 추가를 클릭합니다.
새 도메인 서비스 클래스 추가 대화 상자에서 Customer, Product 및 SalesOrderHeader 엔터티를 선택합니다.
확인을 클릭하여 도메인 서비스 만들기를 마칩니다.
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; }
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; } }
Web.config 파일에 프로필 속성을 정의합니다. 서버의 User 클래스에 속성을 추가하면 클라이언트 프로젝트에 대해 해당 속성이 생성됩니다.
프로필 속성 추가
서버 프로젝트에서 Web.config 파일을 엽니다.
<profile>
요소에서 DefaultRows라는 프로필 속성을 추가합니다. 이 속성에는 표시할 행 수에 대한 사용자 기본 설정이 포함됩니다.다음은 Web.config 파일의 profile 섹션을 보여 줍니다.
<profile> <properties> <add name="FriendlyName" /> <add type="System.Int32" defaultValue="10" name="DefaultRows"/> </properties> </profile>
Web.config 파일을 저장합니다.
서버 프로젝트에서 Models 폴더를 확장합니다.
User.cs 또는 User.vb 파일을 열고 DefaultRows라는 속성을 추가합니다.
Imports System.ServiceModel.DomainServices.Server.ApplicationServices Imports System.Runtime.Serialization Namespace Web Partial Public Class User Inherits UserBase Public Property FriendlyName As String Public Property DefaultRows As Integer End Class End Namespace
namespace ExampleBusinessApplication.Web { using System.Runtime.Serialization; using System.ServiceModel.DomainServices.Server.ApplicationServices; public partial class User : UserBase { public string FriendlyName { get; set; } public int DefaultRows { get; set; } } }
클라이언트에서 인증 서비스 사용
제한된 권한으로 도메인 작업을 호출하기 전에 사용자에게 필수 자격 증명이 있는지 확인해야 합니다. 그렇지 않으면 예외가 throw됩니다. 다음 단원에서는 사용자의 자격 증명을 확인하고 사용자의 자격 증명을 기준으로 1~3개의 DataGrid 컨트롤을 채웁니다. 사용자 프로필의 속성을 기준으로 레코드 수도 검색합니다. 인증되지 않은 사용자에 대해서는 기본값 10이 사용됩니다. 이 단원에는 사용자가 DefaultRows 프로필 속성을 설정하는 방법이 나와 있지 않지만 이후 단원에서 이 속성을 추가합니다.
데이터를 표시하기 위해 Silverlight 페이지 추가
클라이언트 프로젝트에서 새 항목을 Views 폴더에 추가합니다.
Silverlight 페이지 템플릿을 선택하고 새 페이지의 이름을 Reports.xaml로 지정합니다.
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="{Binding Path=ApplicationStrings.ReportsPageTitle, Source={StaticResource ResourceWrapper}}"/>
Assets\Resources 폴더에서 ApplicationStrings.resx 파일을 엽니다.
값이 Reports인 ReportsPageTitle이라는 새 문자열 리소스를 추가합니다.
ApplicationStrings.resx 파일을 저장하고 닫습니다.
Reports.xaml 파일을 열고 사이트에 있는 다른 페이지의 서식과 일치하도록 Grid 요소에 다음 XAML을 추가합니다.
<ScrollViewer x:Name="PageScrollViewer" Style="{StaticResource PageScrollViewerStyle}"> <StackPanel x:Name="ContentStackPanel" Style="{StaticResource ContentStackPanelStyle}"> <TextBlock x:Name="HeaderText" Style="{StaticResource HeaderTextStyle}" Text="{Binding Path=ApplicationStrings.ReportsPageTitle, Source={StaticResource ResourceWrapper}}"/> <TextBlock x:Name="ContentText" Style="{StaticResource ContentTextStyle}" Text="Display reports based on user permissions"/> </StackPanel> </ScrollViewer>
도구 상자에서
ContentStackPanel
이라는 스택 패널의 끝 태그 바로 앞으로 세 개의 DataGrid 컨트롤을 끌어옵니다.도구 상자에서 DataGrid 컨트롤을 끌어오면 System.Windows.Controls.Data 어셈블리에 대한 참조가 프로젝트에 추가되고 System.Windows.Controls 네임스페이스에 대한 접두사가 페이지에 추가됩니다.
DataGrid 컨트롤의 이름을
ProductsGrid
,SalesOrdersGrid
및CustomersGrid
로 지정합니다.각 DataGrid 컨트롤에 대해 Margin 속성을
5
로 설정합니다.다음 예제에서는 전체 Reports.xaml 파일을 보여 줍니다.
<navigation:Page x:Class="ExampleBusinessApplication.Views.Reports" xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="https://schemas.microsoft.com/expression/blend/2008" xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data" mc:Ignorable="d" xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation" d:DesignWidth="640" d:DesignHeight="480" Title="Reports Page" > <Grid x:Name="LayoutRoot"> <ScrollViewer x:Name="PageScrollViewer" Style="{StaticResource PageScrollViewerStyle}"> <StackPanel x:Name="ContentStackPanel" Style="{StaticResource ContentStackPanelStyle}"> <TextBlock x:Name="HeaderText" Style="{StaticResource HeaderTextStyle}" Text="{Binding Path=ApplicationStrings.ReportsPageTitle, Source={StaticResource ResourceWrapper}}"/> <TextBlock x:Name="ContentText" Style="{StaticResource ContentTextStyle}" Text="Display reports based on user permissions"/> <data:DataGrid Name="ProductsGrid" Margin="5" /> <data:DataGrid Name="SalesOrdersGrid" Margin="5" /> <data:DataGrid Name="CustomersGrid" Margin="5" /> </StackPanel> </ScrollViewer> </Grid> </navigation:Page>
Reports.xaml.cs 또는 Reports.xaml.vb 파일을 엽니다.
C#의 경우 System.ServiceModel.DomainServices.Client, System.ServiceModel.DomainServices.Client.ApplicationServices 및 ExampleBusinessApplication.Web 네임스페이스에 대해 using 문을 추가합니다. Visual Basic의 경우 System.ServiceModel.DomainServices.Client, System.ServiceModel.DomainServices.Client.ApplicationServices, System.Windows.Controls 및 ExampleBusinessApplication.Web 네임스페이스에 대해 Imports 문을 추가합니다.
컨텍스트라는 AdventureWorksDomainContext의 인스턴스를 만들고 검색할 행 수가 들어 있는 numberOfRows라는 변수를 만듭니다.
Private context As New AdventureWorksDomainContext Private numberOfRows As Integer = 10
private AdventureWorksDomainContext context = new AdventureWorksDomainContext(); int numberOfRows = 10;
사용자가 Managers 역할에 속하는 경우
GetSalesOrderHeaderQuery
메서드와GetCustomersQuery
메서드를 호출하고 해당 데이터 표를 결과로 채우는LoadRestrictedReports
라는 메서드를 추가합니다.사용자에게 필수 자격 증명이 없을 때 도메인 작업을 호출하면 도메인 작업에서 예외가 반환됩니다. 도메인 작업을 호출하기 전에 자격 증명을 확인하여 이러한 상황을 피할 수 있습니다.
Private Sub LoadRestrictedReports() Dim loadSales = context.Load(context.GetSalesOrderHeadersQuery().Take(numberOfRows)) SalesOrdersGrid.ItemsSource = loadSales.Entities SalesOrdersGrid.Visibility = System.Windows.Visibility.Visible If (WebContext.Current.User.IsInRole("Managers")) Then Dim loadCustomers = context.Load(context.GetCustomersQuery().Take(numberOfRows)) CustomersGrid.ItemsSource = loadCustomers.Entities CustomersGrid.Visibility = System.Windows.Visibility.Visible Else CustomersGrid.Visibility = System.Windows.Visibility.Collapsed End If End Sub
private void LoadRestrictedReports() { LoadOperation<SalesOrderHeader> loadSales = context.Load(context.GetSalesOrderHeadersQuery().Take(numberOfRows)); SalesOrdersGrid.ItemsSource = loadSales.Entities; SalesOrdersGrid.Visibility = System.Windows.Visibility.Visible; if (WebContext.Current.User.IsInRole("Managers")) { LoadOperation<Customer> loadCustomers = context.Load(context.GetCustomersQuery().Take(numberOfRows)); CustomersGrid.ItemsSource = loadCustomers.Entities; CustomersGrid.Visibility = System.Windows.Visibility.Visible; } else { CustomersGrid.Visibility = System.Windows.Visibility.Collapsed; } }
사용자가 인증되는지 확인하고 인증되는 경우
LoadRestrictedReports
메서드를 호출하는LoadReports
라는 메서드를 추가합니다. 또한 이 메서드는DefaultRows
라는 프로필 속성을 검색하고 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; }
속성
DefaultRows
가 변경된 경우LoadReports
를 호출하는 PropertyChanged 이벤트에 대한 이벤트 처리기를 추가합니다.Private Sub User_PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) If (e.PropertyName = "DefaultRows") Then LoadReports() End If End Sub
void User_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { if (e.PropertyName == "DefaultRows") { LoadReports(); } }
사용자 인증 자격 증명의 변경 내용을 기준으로 데이터를 로드하거나 숨기는 LoggedIn 및 LoggedOut 이벤트에 대한 이벤트 처리기를 추가합니다.
Private Sub Authentication_LoggedIn(ByVal sender As Object, ByVal e As ApplicationServices.AuthenticationEventArgs) LoadReports() End Sub Private Sub Authentication_LoggedOut(ByVal sender As Object, ByVal e As ApplicationServices.AuthenticationEventArgs) CustomersGrid.Visibility = System.Windows.Visibility.Collapsed SalesOrdersGrid.Visibility = System.Windows.Visibility.Collapsed End Sub
void Authentication_LoggedIn(object sender, AuthenticationEventArgs e) { LoadReports(); } void Authentication_LoggedOut(object sender, AuthenticationEventArgs e) { CustomersGrid.Visibility = System.Windows.Visibility.Collapsed; SalesOrdersGrid.Visibility = System.Windows.Visibility.Collapsed; }
다음 코드를 생성자에 추가합니다. 이 코드는 처리기를 로드하고
LoadReports
를 호출합니다.Public Sub New() InitializeComponent() Me.Title = ApplicationStrings.ReportsPageTitle AddHandler WebContext.Current.Authentication.LoggedIn, AddressOf Authentication_LoggedIn AddHandler WebContext.Current.Authentication.LoggedOut, AddressOf Authentication_LoggedOut LoadReports() End Sub
public Reports() { InitializeComponent(); this.Title = ApplicationStrings.ReportsPageTitle; WebContext.Current.Authentication.LoggedIn += new System.EventHandler<AuthenticationEventArgs>(Authentication_LoggedIn); WebContext.Current.Authentication.LoggedOut += new System.EventHandler<AuthenticationEventArgs>(Authentication_LoggedOut); LoadReports(); }
전체 코드 파일은 다음과 같습니다.
Imports System.Windows.Navigation Imports System.Windows.Controls Imports System.ServiceModel.DomainServices.Client Imports System.ServiceModel.DomainServices.Client.ApplicationServices Imports ExampleBusinessApplication.Web Partial Public Class Reports Inherits Page Private context As New AdventureWorksDomainContext Private numberOfRows As Integer = 10 Public Sub New() InitializeComponent() Me.Title = ApplicationStrings.ReportsPageTitle AddHandler WebContext.Current.Authentication.LoggedIn, AddressOf Authentication_LoggedIn AddHandler WebContext.Current.Authentication.LoggedOut, AddressOf Authentication_LoggedOut LoadReports() End Sub Private Sub LoadReports() If (WebContext.Current.User.IsAuthenticated) Then numberOfRows = WebContext.Current.User.DefaultRows AddHandler WebContext.Current.User.PropertyChanged, AddressOf User_PropertyChanged LoadRestrictedReports() Else CustomersGrid.Visibility = System.Windows.Visibility.Collapsed SalesOrdersGrid.Visibility = System.Windows.Visibility.Collapsed End If Dim loadProducts = context.Load(context.GetProductsQuery().Take(numberOfRows)) ProductsGrid.ItemsSource = loadProducts.Entities End Sub Private Sub LoadRestrictedReports() Dim loadSales = context.Load(context.GetSalesOrderHeadersQuery().Take(numberOfRows)) SalesOrdersGrid.ItemsSource = loadSales.Entities SalesOrdersGrid.Visibility = System.Windows.Visibility.Visible If (WebContext.Current.User.IsInRole("Managers")) Then Dim loadCustomers = context.Load(context.GetCustomersQuery().Take(numberOfRows)) CustomersGrid.ItemsSource = loadCustomers.Entities CustomersGrid.Visibility = System.Windows.Visibility.Visible Else CustomersGrid.Visibility = System.Windows.Visibility.Collapsed End If End Sub Private Sub User_PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) If (e.PropertyName = "DefaultRows") Then LoadReports() End If End Sub Private Sub Authentication_LoggedIn(ByVal sender As Object, ByVal e As ApplicationServices.AuthenticationEventArgs) LoadReports() End Sub Private Sub Authentication_LoggedOut(ByVal sender As Object, ByVal e As ApplicationServices.AuthenticationEventArgs) CustomersGrid.Visibility = System.Windows.Visibility.Collapsed SalesOrdersGrid.Visibility = System.Windows.Visibility.Collapsed End Sub End Class
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using System.Windows.Navigation; using System.ServiceModel.DomainServices.Client; using System.ServiceModel.DomainServices.Client.ApplicationServices; using ExampleBusinessApplication.Web; namespace ExampleBusinessApplication.Views { public partial class Reports : Page { private AdventureWorksDomainContext context = new AdventureWorksDomainContext(); int numberOfRows = 10; public Reports() { InitializeComponent(); this.Title = ApplicationStrings.ReportsPageTitle; WebContext.Current.Authentication.LoggedIn += new System.EventHandler<AuthenticationEventArgs>(Authentication_LoggedIn); WebContext.Current.Authentication.LoggedOut += new System.EventHandler<AuthenticationEventArgs>(Authentication_LoggedOut); LoadReports(); } private void LoadReports() { if (WebContext.Current.User.IsAuthenticated) { numberOfRows = WebContext.Current.User.DefaultRows; WebContext.Current.User.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(User_PropertyChanged); LoadRestrictedReports(); } else { CustomersGrid.Visibility = System.Windows.Visibility.Collapsed; SalesOrdersGrid.Visibility = System.Windows.Visibility.Collapsed; } LoadOperation<Product> loadProducts = context.Load(context.GetProductsQuery().Take(numberOfRows)); ProductsGrid.ItemsSource = loadProducts.Entities; } private void LoadRestrictedReports() { LoadOperation<SalesOrderHeader> loadSales = context.Load(context.GetSalesOrderHeadersQuery().Take(numberOfRows)); SalesOrdersGrid.ItemsSource = loadSales.Entities; SalesOrdersGrid.Visibility = System.Windows.Visibility.Visible; if (WebContext.Current.User.IsInRole("Managers")) { LoadOperation<Customer> loadCustomers = context.Load(context.GetCustomersQuery().Take(numberOfRows)); CustomersGrid.ItemsSource = loadCustomers.Entities; CustomersGrid.Visibility = System.Windows.Visibility.Visible; } else { CustomersGrid.Visibility = System.Windows.Visibility.Collapsed; } } void Authentication_LoggedIn(object sender, AuthenticationEventArgs e) { LoadReports(); } void Authentication_LoggedOut(object sender, AuthenticationEventArgs e) { CustomersGrid.Visibility = System.Windows.Visibility.Collapsed; SalesOrdersGrid.Visibility = System.Windows.Visibility.Collapsed; } void User_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { if (e.PropertyName == "DefaultRows") { LoadReports(); } } } }
솔루션을 실행합니다.
Reports 링크를 클릭합니다.
사용자가 로그인하지 않은 경우 products 테이블만 Reports 페이지에 표시됩니다.
로그인 링크를 클릭하고 SalesUser로 로그인합니다.
제품 및 판매 주문에 대한 테이블이 표시됩니다.
로그아웃하고 CustomerManager로 로그인합니다.
제품, 판매 주문 및 고객에 대한 테이블이 표시됩니다.
웹 브라우저를 닫습니다.
자식 창을 추가하여 사용자가 DefaultRows 프로필 속성을 편집하도록 허용할 수 있습니다. 값이 변경되면 SaveUser 메서드를 호출하여 데이터 원본에 값을 저장합니다. 현재 WebContext 인스턴스의 User 개체 속성을 통해 현재 값을 검색합니다.
프로필 속성을 설정하기 위한 창 추가
클라이언트 프로젝트에서 Views 폴더에 새 항목을 추가합니다.
Silverlight 자식 창 템플릿을 선택하고 자식 창의 이름을 ProfileWindow.xaml로 지정합니다.
추가 단추를 클릭합니다.
ProfileWindow.xaml 파일에서 다음 XAML을 Grid.RowDefinitions 요소 뒤에 추가하여 보고서에 표시할 행 수를 선택하기 위한 ComboBox를 포함합니다.
<StackPanel Orientation="Horizontal" Grid.Row="0"> <TextBlock Text="Number of rows to display for reports: "></TextBlock> <ComboBox x:Name="defaultRows" Height="20" VerticalAlignment="Top"> <ComboBoxItem Content="1"></ComboBoxItem> <ComboBoxItem Content="2"></ComboBoxItem> <ComboBoxItem Content="3"></ComboBoxItem> <ComboBoxItem Content="4"></ComboBoxItem> <ComboBoxItem Content="5"></ComboBoxItem> <ComboBoxItem Content="6"></ComboBoxItem> <ComboBoxItem Content="7"></ComboBoxItem> <ComboBoxItem Content="8"></ComboBoxItem> <ComboBoxItem Content="9"></ComboBoxItem> <ComboBoxItem Content="10"></ComboBoxItem> <ComboBoxItem Content="15"></ComboBoxItem> <ComboBoxItem Content="20"></ComboBoxItem> </ComboBox> </StackPanel>
ChildWindow에서 Title 속성을
Select Preferences
로 설정합니다.ProfileWindow.xaml.cs 또는 ProfileWindow.xaml.vb 파일에서 다음 코드를 추가하여 프로필 속성을 검색하고 설정합니다.
Imports System.Windows.Controls Imports System.Windows Partial Public Class ProfileWindow Inherits ChildWindow Public Sub New() InitializeComponent() Dim userDefaultRows = WebContext.Current.User.DefaultRows.ToString() For Each cbi As ComboBoxItem In defaultRows.Items If (cbi.Content.ToString() = userDefaultRows) Then defaultRows.SelectedItem = cbi Exit For End If Next End Sub Private Sub OKButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) Handles OKButton.Click Dim newSelection = Integer.Parse(defaultRows.SelectionBoxItem.ToString()) If (newSelection <> WebContext.Current.User.DefaultRows) Then WebContext.Current.User.DefaultRows = newSelection WebContext.Current.Authentication.SaveUser(True) End If Me.DialogResult = True End Sub Private Sub CancelButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) Handles CancelButton.Click Me.DialogResult = False End Sub End Class
public partial class ProfileWindow : ChildWindow { public ProfileWindow() { InitializeComponent(); string userDefaultRows = WebContext.Current.User.DefaultRows.ToString(); foreach (ComboBoxItem cbi in defaultRows.Items) { if (cbi.Content.ToString() == userDefaultRows) { defaultRows.SelectedItem = cbi; break; } } } private void OKButton_Click(object sender, RoutedEventArgs e) { int newSelection = int.Parse(defaultRows.SelectionBoxItem.ToString()); if (newSelection != WebContext.Current.User.DefaultRows) { WebContext.Current.User.DefaultRows = newSelection; WebContext.Current.Authentication.SaveUser(true); } this.DialogResult = true; } private void CancelButton_Click(object sender, RoutedEventArgs e) { this.DialogResult = false; } }
Visual Basic의 경우 System.Windows.Controls 및 System.Windows 네임스페이스에 대해 Imports 문을 추가합니다.
Views\Login 폴더를 확장하고 LoginStatus.xaml 파일을 엽니다.
설정 링크를 프로필 창에 추가하려면 다음 XAML을 로그아웃 단추 앞에 추가합니다.
<Button x:Name="SettingsButton" Click="SettingsButton_Click" Content="settings" Style="{StaticResource LoginRegisterLinkStyle}" Margin="0,0,0,0"></Button> <TextBlock Text=" | " Style="{StaticResource SpacerStyle}"/>
LoginStatus.xaml.cs 또는 LoginStatus.xaml.vb 파일에서 설정 링크에 대해 다음 클릭 이벤트 처리기를 추가합니다.
Private Sub SettingsButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) Dim settingsWindow As New ProfileWindow settingsWindow.Show() End Sub
private void SettingsButton_Click(object sender, RoutedEventArgs e) { ExampleBusinessApplication.Views.ProfileWindow settingsWindow = new ExampleBusinessApplication.Views.ProfileWindow(); settingsWindow.Show(); }
솔루션을 실행합니다.
CustomerManager 또는 SalesUser로 로그인하고 로그인 상태 표시줄에 설정에 대한 링크가 포함되는지 확인합니다.
설정 링크를 클릭하고 보고서에 표시할 기본 행 수를 설정합니다.
Reports 페이지를 열고 DataGrid에 선택한 행 수가 포함되는지 확인합니다.