Cheryl Simmons
Microsoft Corporation

2006년 8월

적용 대상:
Microsoft Visual Studio 2005
Microsoft .NET Framework 2.0
Microsoft Windows Forms

요약 : 바인딩된 데이터의 서식을 쉽게 지정할 수 있도록 지원하는 BindingControlBindingsCollection 클래스의 추가 기능에 대해 자세히 알아봅니다.

Microsoft 다운로드 센터 (영문)에서 C# 및 Visual Basic으로 작성된 코드 샘플을 다운로드하십시오(23KB).

목차

소개 소개
서식 지정 및 고급 바인딩 대화 상자 서식 지정 및 고급 바인딩 대화 상자
코드를 사용한 자동 서식 지정 코드를 사용한 자동 서식 지정
DataSourceUpdateMode 사용 DataSourceUpdateMode 사용
Null 및 DBNull 값 자동 처리 Null 및 DBNull 값 자동 처리
향상된 오류 및 예외 처리 향상된 오류 및 예외 처리
결론 결론

소개

Windows Forms 데이터 바인딩에 추가된 내용 중 가장 중요한 것은 아마도 BindingSource 구성 요소일 것입니다. BindingSource 구성 요소는 통화 관리, 변경 알림 및 바인딩된 목록에 있는 멤버에 대한 간편한 액세스 기능을 제공하여 개발자의 작업을 간소화해 줍니다. 한편, 데이터 바인딩에 추가된 몇 가지 기능은 잘 알려지지 않았지만 살펴볼 가치가 있으며 실제로 BindingSource 구성 요소에서 제공하는 기능을 보완하는 중요한 기능이 추가되었습니다.

Binding 개체는 .NET Framework 2.0에서 바인딩 작업에 대한 제어를 향상시키는 몇 가지 새로운 멤버를 갖고 있습니다. 예를 들어 데이터 원본이 업데이트될 경우 바인딩 컨트롤에서 데이터의 서식을 지정하는 방법과 데이터 원본에서 nullDBNull 값을 처리하는 방법을 제어할 수 있습니다. 이러한 새로운 멤버는 ControlBindingsCollection의 해당 Add 메서드에서도 지원됩니다. 이러한 추가 기능은 Visual Studio의 서식 지정 및 고급 바인딩 대화 상자를 사용하거나 코드를 통해 활용할 수 있습니다. 또한 BindingComplete 이벤트가 추가되어 Binding 개체는 바인딩 과정에서 발생할 수 있는 예외 및 오류 처리를 보다 효과적으로 지원할 수 있게 되었습니다. 이 문서에서는 BindingSource 구성 요소의 사용 여부에 관계없이 사용자의 응용 프로그램에서 활용할 수 있는 BindingControlBindingsCollection 개체의 이러한 변경 사항에 대해 설명합니다.

이 문서에서는 먼저 서식 지정 및 고급 바인딩 대화 상자에 대해 설명합니다. 그런 다음 코드를 사용하여 이 대화 상자에서 수행하는 것과 동일한 작업을 수행하는 방법에 대해 설명합니다. 처음 세 가지 예에서는 DataTable이 사용되고 네 번째 예에서는 BindingSource 개체가 사용됩니다. 모든 예에서 응용 프로그램의 데이터 원본으로 BindingSource를 사용할지 여부를 선택할 수 있지만 특히 동일한 데이터 원본에 대해 여러 컨트롤을 바인딩하는 경우에는 BindingSource를 사용하는 것이 좋습니다.

화면 맨 위로

서식 지정 및 고급 바인딩 대화 상자

Visual Studio에서 서식 지정 및 고급 바인딩 대화 상자를 사용하면 컨트롤 속성을 데이터 원본에 바인딩하고 결과의 서식을 지정할 수 있습니다. 이 대화 상자는 Binding 개체의 변경된 기능을 활용하도록 설계되었습니다. Visual Studio에서 서식 지정 및 고급 바인딩 대화 상자에 액세스하려면 데이터에 바인딩하려는 컨트롤을 마우스 오른쪽 단추로 클릭하고 속성을 선택합니다. 그림 1에 표시된 속성 창에서 (DataBindings) 항목을 확장하고 (고급) 항목을 선택합니다.

wfbindp101.gif

그림 1. 속성 창의 DataBindings 설정

(고급) 옆에 있는 줄임표 단추를 클릭하면 그림 2와 같은 서식 지정 및 고급 바인딩 대화 상자가 열립니다.

wfbindp102.gif

그림 2. 서식 지정 및 고급 바인딩 대화 상자

서식 지정 및 고급 바인딩 대화 상자에서는 응용 프로그램의 데이터 원본을 선택합니다. 데이터 원본은 BindingSource 개체, 데이터베이스 테이블, 웹 서비스 유형 또는 개체일 수 있습니다. BindingSource가 아닌 데이터 원본을 선택한 경우에는 해당 데이터 원본에 대한 BindingSource가 자동으로 생성됩니다. 그런 다음에는 컨트롤 값이 변경될 경우 데이터 원본을 업데이트하는 방법과 바인딩에 대한 서식 유형 및 Null 값을 설정할 수 있습니다.

참고 이 문서에서 설명하는 대부분의 작업은 서식 지정 및 고급 바인딩 대화 상자에서 수행할 수 있습니다.

화면 맨 위로

코드를 사용한 자동 서식 지정

이전 버전의 .NET Framework에서는 Binding 개체의 FormatParse 이벤트를 사용하여 형식 변환 및 서식 지정을 수동으로 수행해야 했습니다. 이제는 FormattingEnabled 속성을 직접 설정하거나 ControlBindingsCollectionAdd 메서드에 true를 전달하여 Binding 개체에 대한 서식 지정을 설정하면 됩니다. 또한 Add 메서드를 사용하거나 Binding 개체의 FormatString 속성을 설정하여 형식 문자열을 지정해야 합니다.

다음 코드에는 두 개의 서식 지정 예가 포함되어 있습니다. 첫 번째 서식 지정 예에서는 데이터 원본의 DateTime 값과 TextBox 컨트롤의 Text 값 간에 바인딩을 만드는 방법을 보여 줍니다. Binding 개체에서 FormattingEnabled 속성을 설정하고 FormatString 값은 DateTime에 자세한 날짜/시간 문자열 서식을 사용하도록 지정한 다음 컬렉션에 이 바인딩을 추가합니다.

두 번째 서식 지정 예에서는 DataTable의 데이터를 TextBox 컨트롤의 Text 속성에 바인딩하는 Binding 개체를 만들어 데이터의 서식을 지정하는 방법을 보여 줍니다. 고용 날짜 서식은 자세한 날짜로 지정하고 시작 급여 서식은 통화 단위로 지정합니다. 이 예에서는 ControlBindingsCollectionAdd 메서드를 사용하여 Binding 개체를 만듭니다. 또한 바인딩의 FormatString을 직접 설정합니다. 이 문서의 뒷부분에서는 ControlBindingsCollectionAdd 메서드를 사용하여 FormatString을 설정하는 방법을 설명합니다.

Dim table1 As New DataTable()
table1.Columns.Add("Name", GetType(String))
table1.Columns.Add("Hire Date", GetType(DateTime))
table1.Columns.Add("Starting salary", GetType(Integer))
table1.Rows.Add(New Object() {"Claus Hansen", New DateTime(2003, 5, 5), _   63000})
Dim dateBinding As New Binding("Text", table1, "Hire Date")
' Binding 개체에서 FormattingEnabled 및 FormatString을 직접 설정합니다.
' "D" 서식 지정자는 자세한 날짜 패턴을 나타냅니다.
dateBinding.FormattingEnabled = True
dateBinding.FormatString = "D"
' dateTextBox 바인딩 컬렉션에 바인딩을 추가합니다.
dateTextBox.DataBindings.Add(dateBinding)
' ControlBindingsCollection.Add 메서드의 
' 일부로 FormattingEnabled를 설정합니다.
Dim salaryBinding As Binding = salaryTextBox.DataBindings.Add("text", _   table1, "Starting Salary", True)
' "c" 서식 지정자는 통화 서식을 나타냅니다.
salaryBinding.FormatString = "c"
Dim nameBinding As Binding = nameTextBox.DataBindings.Add("Text", table1, _   "Name", True)

결과는 그림 3에 나와 있습니다.

wfbindp103.gif

그림 3. 서식 지정된 통화 및 날짜

화면 맨 위로

DataSourceUpdateMode 사용

DataSourceUpdateMode 열거형을 사용하면 컨트롤 속성의 변경 사항을 데이터 원본에 전파하는 시점을 지정할 수 있습니다. 기본값 DataSourceUpdateMode.OnValidation을 사용하면 사용자가 데이터가 바인딩된 값을 변경하고 Tab 키를 눌러 컨트롤에서 나올 때 데이터 원본이 업데이트됩니다. DataSourceUpdateNever를 사용하면 바인딩된 컨트롤의 변경된 값이 데이터 원본에 전파되지 않으며 OnPropertyChange를 사용하면 컨트롤 값이 변경될 때마다 변경된 값이 전파됩니다. OnPropertyChange 또는 OnValidation을 사용하는 경우 컨트롤 값이 유효성 검사를 통과하지 못하면 올바른 값을 입력하기 전에는 사용자가 Tab 키를 눌러 다른 컨트롤로 이동하거나 폼을 닫을 수 없습니다.

다음 예에서는 ControlBindingsCollectionAdd 메서드를 사용하여 DataSourceUpdateMode를 설정하는 방법을 보여 줍니다. DataTable의 고용 날짜는 고용 날짜 텍스트 상자의 내용이 변경될 때마다 업데이트됩니다. DataTable의 시작 급여는 시작 급여 텍스트 상자가 포커스를 잃고 값이 유효성 검사를 통과하면 업데이트됩니다. 시작 급여 텍스트 상자에 숫자가 아닌 잘못된 값(예: 하나 이상의 문자)을 입력하면 사용자는 Tab 키를 눌러도 텍스트 상자를 벗어날 수 없습니다.

Dim table1 As New DataTable()
table1.Columns.Add("Name", GetType(String))
table1.Columns.Add("Hire Date", GetType(DateTime))
table1.Columns.Add("Starting salary", GetType(Integer))
table1.Rows.Add(New Object() {"Claus Hansen", New DateTime(2003, 5, 5), _   63000})
' table1의 고용 날짜는 고용 날짜 텍스트 상자의 내용이 변경될 때
' 업데이트됩니다.
Dim dateBinding2 As Binding = dateTextBox.DataBindings.Add("Text", table1, _   "Hire Date", True, DataSourceUpdateMode.OnPropertyChanged)
dateBinding2.FormatString = "D"
' table1의 시작 급여는 시작 급여 텍스트 상자가
' 포커스를 잃고 값이 유효성 검사를 통과하면 업데이트됩니다.
Dim salaryBinding As Binding = salaryTextBox.DataBindings.Add("text", _   table1, "Starting salary", True, DataSourceUpdateMode.OnValidation)
salaryBinding.FormatString = "c"
Dim nameBinding As Binding = nameTextBox.DataBindings.Add("Text", table1, _   "Name", True)

화면 맨 위로

Null 및 DBNull 값 자동 처리

이전 버전의 Windows Forms 데이터 바인딩에서는 FormatParse 이벤트를 처리할 때 데이터 원본의 DBNull 또는 null 값을 컨트롤에서 어떻게 표시할지를 고려해야 했습니다. 이를 위해서는 데이터 원본의 특정 컨트롤 값을 구문 분석하여 null 또는 DBNull인지 확인할 수 있어야 했습니다. 이제는 Binding 개체의 NullValue 속성을 사용하여 이러한 작업을 훨씬 쉽게 수행할 수 있습니다.

다음 예에서는 데이터 원본의 DBNull 값을 NullValue 속성을 사용하여 바인딩된 컨트롤에 표시하는 방법을 보여 줍니다. 고용 날짜는 DataTable에서 DBNull 값이지만 텍스트 상자에는 "New Hire"로 표시됩니다.

Dim table1 As New DataTable()
table1.Columns.Add("Name", GetType(String))
table1.Columns.Add("Hire Date", GetType(DateTime))
table1.Columns.Add("Starting salary", GetType(Integer))
' 고용 날짜를 DBNull로 초기화합니다.
table1.Rows.Add(New Object() {"Claus Hansen", DBNull.Value, 63000})
' 고용 날짜가 Null 또는 DBNull인 경우 "New Hire"로 변경합니다.
Dim dateBinding2 As Binding = dateTextBox.DataBindings.Add("Text", table1, _   "Hire Date", True, DataSourceUpdateMode.OnValidation, "New Hire", "D")
Dim salaryBinding As Binding = salaryTextBox.DataBindings.Add("text", _   table1, "Starting salary", True)
salaryBinding.FormatString = "c"
Dim nameBinding As Binding = nameTextBox.DataBindings.Add("Text", table1, _   "Name", True)

결과는 그림 4에 나와 있습니다.

wfbindp104.gif

그림 4. "New Hire" 문자열로 서식이 지정된 DBNull

화면 맨 위로

향상된 오류 및 예외 처리

이제는 데이터 바인딩에 대한 서식 지정을 설정할 때마다 Binding 개체의 BindingComplete 이벤트를 사용하여 오류 및 예외 처리를 보다 효율적으로 제어할 수 있습니다.

다음 예에서는 바인딩된 컨트롤 값이 잘못된 값으로 변경된 경우 사용자에게 피드백을 제공하도록 BindingComplete 이벤트를 처리하는 방법을 보여 줍니다. 이 예에 사용된 Employee라는 비즈니스 개체는 Salary 속성에 20000 미만의 값을 사용하지 못하도록 합니다. 바인딩을 위해 Employee 개체는 BindingSource에 저장합니다.

여기에서는 먼저 BindingSource를 만들고 두 개의 Employee 개체를 추가한 다음 바인딩을 설정했습니다. 또한 BindingComplete 이벤트를 해당 이벤트 처리 메서드에 연결했습니다.

' Binding 개체를 선언합니다.
Dim WithEvents salaryBinding As Binding
Dim employeeBindingSource As New BindingSource()
employeeBindingSource.Add(New Employee("Hansen", "Claus", 63000, _   New DateTime(2002, 5, 5)))
employeeBindingSource.Add(New Employee("Han", "Mu", 54000, _   New DateTime(2001, 3, 4)))
nameTextBox.DataBindings.Add("Text", employeeBindingSource, _   "LastName", True)
dateTextBox.DataBindings.Add("Text", employeeBindingSource, _   "StartDate", True, DataSourceUpdateMode.OnValidation)
salaryBinding = salaryTextBox.DataBindings.Add("text", _   employeeBindingSource, "Salary", True, DataSourceUpdateMode.OnValidation, _   "Unknown", "c")

그런 다음 BindingComplete 이벤트를 처리합니다. 이 이벤트 처리기는 오류 메시지를 ErrorProvider 컨트롤에 전달합니다.

Sub salaryBinding_BindingComplete(ByVal sender As Object, _   ByVal e As BindingCompleteEventArgs) Handles salaryBinding.BindingComplete     ' BindingComplete 상태가 성공 이외인 경우     ' 오류 메시지에 대해 ErrorProvider를 설정합니다.     If e.BindingCompleteState <> BindingCompleteState.Success Then         errorProvider1.SetError( _           CType(e.Binding.BindableComponent, Control), e.ErrorText)     Else         errorProvider1.SetError( _           CType(e.Binding.BindableComponent, Control), "")     End If
End Sub

다음 코드는 Employee 비즈니스 개체를 보여 줍니다.

Public Class Employee     Private lastNameValue As String     Private firstNameValue As String     Private salaryValue As Integer     Private startDateValue As DateTime     Public Sub New(ByVal lastName As String, ByVal firstName As String, _       ByVal salary As Integer, ByVal startDate As DateTime)         lastNameValue = lastName         firstNameValue = firstName         salaryValue = salary         startDateValue = startDate     End Sub     Public Property LastName() As String         Get             Return lastNameValue         End Get         Set(ByVal value As String)             lastNameValue = value         End Set     End Property     Public Property FirstName() As String         Get             Return firstNameValue         End Get         Set             firstNameValue = value         End Set     End Property     Public Property Salary() As Integer         Get             Return salaryValue         End Get         Set             If value < 20000 Then                 Throw New Exception("Salary cannot be less than $20,000")             Else                 salaryValue = value             End If         End Set     End Property     Public Property StartDate() As DateTime         Get             Return startDateValue         End Get         Set             startDateValue = value         End Set     End Property     Public Overrides Function ToString() As String         Return LastName & ", " & FirstName & vbLf & "Salary:" _           & salaryValue & vbLf & "Start date:" & startDateValue     End Function
End Class

오류 처리가 이루어지는지 확인하려면 예제 코드를 실행하고 급여 값을 $20,000 미만의 값으로 변경해 보십시오. 그림 5는 BindingComplete 이벤트가 처리되어 사용자에게 피드백이 제공된 경우를 보여 줍니다.

wfbindp105.gif

그림 5. BindingComplete 이벤트를 사용하여 바인딩된 컨트롤의 데이터를 확인하는 예

뒷 이야기: .NET Framework 2.0에서 향상된 Windows Forms 데이터 바인딩 기술, 2부

Cheryl Simmons

Microsoft Corporation

2006년 8월

적용 대상:

Microsoft Visual Studio 2005

Microsoft .NET Framework 2.0

Microsoft Windows Forms

요약 : 제네릭 BindingList와 이 제네릭 컬렉션 형식을 확장하여 정렬 및 검색 기능을 추가하는 방법에 대해 자세히 알아봅니다.

Microsoft 다운로드 센터 (영문)에서 C# 및 Visual Basic으로 작성된 코드 샘플을 다운로드하십시오(29KB).

이 기사의 1부도 읽어 보십시오.

목차

소개 소개
제네릭 BindingList 정보 제네릭 BindingList 정보
코드 샘플 개요 코드 샘플 개요
제네릭 BindingList 검색 제네릭 BindingList 검색
제네릭 BindingList 정렬 제네릭 BindingList 정렬
다음 단계 다음 단계
소개 소개

소개

Windows Forms 데이터 바인딩의 새로운 기능 중 BindingSource 구성 요소는 가장 많은 주목을 받았습니다. 이 구성 요소는 통화 관리, 변경 알림 및 바인딩된 목록에 있는 멤버에 대한 간편한 액세스 기능을 제공하여 개발자의 작업을 간소화해 줍니다. 데이터 원본에 IBindingList 인터페이스와 검색 및 정렬 기능이 구현되어 있으면 BindingSource를 사용하여 데이터 원본을 검색하고 정렬할 수 있습니다. DataView 클래스는 IBindingList를 구현하는 형식 중 하나입니다. 그러나 IBindingList를 구현하는 클래스를 사용하지 않고 직접 IBindingList 인터페이스의 구현을 제공하여 사용자 지정 비즈니스 개체 목록을 만들고 바인딩해야 하는 경우도 있습니다. 이러한 경우를 위해 Microsoft .NET Framework에서는 TBindingList라고 하는 제네릭 BindingList 형식을 도입했습니다. 이 기사에서는 데이터 바인딩 응용 프로그램에서 제네릭 BindingList를 사용하여 검색 및 정렬이 가능한 사용자 지정 비즈니스 개체 목록을 제공하는 방법에 대해 설명합니다.

페이지 맨 위로

제네릭 BindingList 정보

제네릭 BindingListIBindingList 인터페이스의 제네릭 구현입니다. IBindingList 인터페이스는 Windows Forms 데이터 바인딩의 핵심 인터페이스인 IList 인터페이스의 확장입니다. IList 인터페이스에서 상속되는 기능 외에도 IBindingList를 구현하는 클래스는 정렬, 검색 및 변경 알림 기능을 선택적으로 지원할 수 있습니다. IBindingList 인터페이스는 상당히 복잡한 인터페이스이며 제네릭 BindingList 형식으로 제네릭 구현을 제공함으로써 Windows Forms 데이터 바인딩 엔진에 사용할 바인딩 가능한 사용자 지정 비즈니스 개체 목록을 훨씬 쉽게 작성할 수 있도록 해줍니다. 데이터 바인딩 시나리오에서 제네릭 BindingList를 사용하여 비즈니스 개체를 저장하는 경우 이 목록을 사용하면 항목을 쉽게 삽입 및 제거할 수 있으며 목록이 변경될 경우 변경 알림이 자동으로 제공됩니다. 또한 몇 가지 속성 및 메서드를 재정의하여 제네릭 BindingList에서 검색 및 정렬을 구현할 수 있습니다.

페이지 맨 위로

코드 샘플 개요

여기에서는 간단한 코드 샘플을 사용하여 데이터 원본에 검색 및 정렬 기능을 추가하는 방법을 설명하겠습니다. 몇 개의 Employee 개체가 포함된 목록이 있다고 가정해 보겠습니다. 목록에서 이름, 급여 및 입사 날짜별로 특정 직원을 검색하는 기능을 사용자의 응용 프로그램에 추가하려고 합니다. 응용 프로그램 사용자는 목록 검색 이외에도 이름, 급여, 고용 날짜별로 직원 목록을 정렬하는 기능을 원합니다. 이 예에서 볼 수 있듯이 DataGridView 컨트롤에 바인딩된 제네릭 BindingList에서 정렬 기능을 구현하면 추가 코드 없이도 DataGridView에서 정렬 기능을 제공할 수 있습니다.

Employee 비즈니스 개체 소개

이 코드 샘플에서는 간단한 Employee 비즈니스 개체가 사용됩니다. 다음은 Employee 형식의 구현입니다.

public class Employee
{     private string lastNameValue;     private string firstNameValue;     private int salaryValue;     private DateTime startDateValue;     public Employee()     {         lastNameValue = "Last Name";         firstNameValue = "First Name";         salaryValue = 0;         startDateValue = DateTime.Today;     }     public Employee(string lastName, string firstName,         int salary, DateTime startDate)     {         LastName = lastName;         FirstName = firstName;         Salary = salary;         StartDate = startDate;     }     public string LastName     {         get { return lastNameValue; }         set { lastNameValue = value; }     }     public string FirstName     {         get { return firstNameValue; }         set { firstNameValue = value; }     }     public int Salary     {         get { return salaryValue; }         set { salaryValue = value; }     }     public DateTime StartDate     {         get { return startDateValue; }         set { startDateValue = value; }     }     public override string ToString()     {         return LastName + ", " + FirstName + "\n" +         "Salary:" + salaryValue + "\n" +         "Start date:" + startDateValue;     }
}
제네릭 BindingList 확장

코드 샘플에서는 Employee 개체 목록에 대한 검색 및 정렬 기능을 구현하기 위해 BindingList를 기반으로 SortableSearchableList라는 이름의 형식을 만들었습니다. 검색 및 정렬을 구현하기 위해 재정의해야 하는 메서드 및 속성은 protected이기 때문에 제네릭 BindingList를 확장해야 합니다. 또한 클래스 선언에서 <T> 구문을 사용할 수 있도록 SortableSearchableList 형식을 제네릭 목록으로 만들도록 선택했습니다. 확장된 목록을 제네릭으로 만들면 여러 상황에서 이 목록을 다시 사용할 수 있습니다.

public class SortableSearchableList<T> : BindingList<T>

페이지 맨 위로

제네릭 BindingList 검색

제네릭 BindingList에서 검색을 구현하려면 여러 단계가 필요합니다. 우선 SupportsSearchingCore 속성을 재정의하여 검색이 지원됨을 나타내야 합니다. 그런 다음 검색을 수행하는 FindCore 메서드를 재정의해야 하며 마지막으로 검색 기능을 노출해야 합니다.

검색 지원 표시

SupportsSearchingCore 속성은 재정의해야 하는 읽기 전용 protected 속성입니다. SupportsSearchingCore 속성은 목록에서 검색이 지원되는지 여부를 나타냅니다. 기본적으로 이 속성은 false로 설정되어 있습니다. 목록에 검색이 구현되었음을 나타내려면 이 속성을 true로 설정합니다.

protected override bool SupportsSearchingCore{    get    {        return true;    }}
검색 기능 구현

그런 다음 FindCore 메서드를 재정의하고 목록을 검색하는 구현을 제공해야 합니다. FindCore 메서드는 목록을 검색하고 검색된 항목의 인덱스를 반환합니다. FindCore 메서드는 검색할 데이터 원본 형식의 속성 또는 열을 나타내는 PropertyDescriptor 개체와 검색할 값을 나타내는 키 개체를 받습니다. 다음 코드는 대/소문자를 구분하는 간단한 검색 기능을 구현한 것입니다.

protected override int FindCore(PropertyDescriptor prop, object key){    // 지정된 속성에 대한 속성 정보를 가져옵니다.     PropertyInfo propInfo = typeof(T).GetProperty(prop.Name);    T item;    if (key != null)    {        // 키 값이 속성 값과 일치하는지 확인하기 위해        // 루프로 항목을 조회합니다.         for (int i = 0; i < Count; ++i)        {            item = (T)Items[i];            if (propInfo.GetValue(item, null).Equals(key))                return i;        }    }    return -1;}
검색 기능 노출

마지막으로 공용 메서드를 사용하여 검색 기능을 노출하거나 기본 IBindingListFind 메서드를 사용하여 검색 기능을 호출할 수 있습니다. 검색 기능 호출을 단순화하기 위해 다음 코드에 나와 있는 공개적으로 노출된 Find 메서드는 검색할 문자열과 키를 받습니다. 그런 다음 코드는 속성 문자열을 PropertyDescriptor 개체로 변환하려고 시도합니다. 변환이 성공적이면 PropertyDescriptor와 키가 FindCore 메서드에 전달됩니다.

public int Find(string property, object key){    // 속성에서 지정한 이름의 속성을 확인합니다.     PropertyDescriptorCollection properties =         TypeDescriptor.GetProperties(typeof(T));    PropertyDescriptor prop = properties.Find(property, true);    // 일치하는 항목이 없으면 -1을 반환하고 그렇지 않으면    // FindCore 메서드로 검색을 전달합니다.     if (prop == null)        return -1;    else       return FindCore(prop, key);}

그림 1은 실행 중인 검색 기능을 보여 줍니다. 성을 입력하고 Search 단추를 클릭하면 검색된 항목이 있는 경우 표에서 해당 성이 나와 있는 첫 번째 행이 식별됩니다.

wfbindp201.gif

그림 1. 제네릭 BindingList 사용하여 구현된 검색 기능

페이지 맨 위로

제네릭 BindingList 정렬

응용 프로그램 사용자는 목록 검색 이외에도 이름, 급여, 고용 날짜별로 Employees 목록을 정렬하는 기능을 원합니다. SupportsSortingCore 속성과 ApplySortCoreRemoveSortCore 메서드를 재정의하여 제네릭 BindingList에서 정렬을 구현할 수 있습니다. 또한 선택적으로 SortDirectionCoreSortPropertyCore 속성을 재정의하여 정렬 방향 및 속성을 각각 반환할 수 있습니다. 마지막으로 목록에 추가된 새 항목이 정렬되도록 하려면 EndNew 메서드를 재정의해야 합니다.

정렬 지원 표시

SupportsSortingCore 속성은 재정의해야 하는 읽기 전용 protected 속성입니다. SupportsSortingCore 속성은 목록에서 정렬이 지원되는지 여부를 나타냅니다. 목록에 정렬이 구현되었음을 나타내려면 이 속성을 true로 설정합니다.

protected override bool SupportsSortingCore{    get { return true; }}
정렬 적용

그런 다음 ApplySortCore 메서드를 재정의하고 실제 정렬 세부 사항을 제공해야 합니다. ApplySortCore 메서드는 정렬할 목록 항목 속성을 식별하는 PropertyDescriptor 개체와 목록을 오름차순 또는 내림차순으로 정렬할지를 나타내는 ListSortDescription 열거를 사용합니다.

다음 코드에서는 선택한 속성에서 CompareTo 메서드를 제공하는 IComparable 인터페이스를 구현하는 경우에만 목록이 정렬됩니다. 문자열, 정수 및 DateTime 형식과 같은 대부분의 간단한 형식에서는 이 인터페이스가 구현됩니다. Employee 개체의 모든 속성이 간단한 형식이므로 이것은 합리적인 결정입니다. 또한 구현에서는 사용자가 간단한 형식이 아닌 속성으로 데이터 원본을 정렬하려고 시도하는 경우를 위해 간단한 오류 처리 기능을 제공합니다.

다음 코드에서는 RemoveSortCore 메서드에서 사용하기 위해 정렬되지 않은 목록의 복사본을 저장합니다. 그런 다음 지정된 속성의 값을 ArrayList에 복사합니다. ArrayList Sort 메서드에 대한 호출이 수행되며 이 메서드는 다시 해당 배열 멤버의 CompareTo 메서드를 호출합니다. 마지막으로 정렬된 배열의 값을 사용하여 정렬이 내림차순인지 또는 오름차순인지에 따라 제네릭 BindingList 값을 재구성합니다. 그런 다음 목록이 초기화되었음을 나타내는 ListChanged 이벤트가 발생하고 바인딩된 컨트롤의 값이 새로 고쳐집니다. 다음 코드는 정렬 기능을 구현한 것입니다.

ListSortDirection sortDirectionValue;
PropertyDescriptor sortPropertyValue;
protected override void ApplySortCore(PropertyDescriptor prop,     ListSortDirection direction)
{     sortedList = new ArrayList();     // 정렬 중인 속성 형식에서 IComparable 인터페이스가 구현되는지     // 확인합니다.     Type interfaceType = prop.PropertyType.GetInterface("IComparable");     if (interfaceType != null)     {         // 구현되는 경우에는 SortPropertyValue 및 SortDirectionValue를 설정합니다.         sortPropertyValue = prop;         sortDirectionValue = direction;         unsortedItems = new ArrayList(this.Count);         // 루프로 각 항목에 sortedItems ArrayList에 추가합니다.         foreach (Object item in this.Items) {             sortedList.Add(prop.GetValue(item));             unsortedItems.Add(item);         }         // ArrayList에서 Sort를 호출합니다.         sortedList.Sort();         T temp;         // 정렬 방향을 확인하고 정렬된 항목을 다시 목록에         // 복사합니다.         if (direction == ListSortDirection.Descending)             sortedList.Reverse();         for (int i = 0; i < this.Count; i++)         {             int position = Find(prop.Name, sortedList[i]);             if (position != i) {                 temp = this[i];                 this[i] = this[position];                 this[position] = temp;             }         }         // 바인딩된 컨트롤이 해당 값을 새로 고치도록 ListChanged 이벤트를         // 발생시킵니다.         OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));     }     else         // 속성 형식에서 IComparable이 구현되지 않으면 이를 사용자에게         // 알려 줍니다.         throw new NotSupportedException("Cannot sort by " + prop.Name +             ". This" + prop.PropertyType.ToString() +             " does not implement IComparable");
}
정렬 제거

다음 단계는 RemoveSortCore 메서드를 재정의하는 것입니다. RemoveSortCore 메서드는 목록에 적용된 마지막 정렬을 제거하고 목록이 초기화되었음을 나타내는 ListChanged 이벤트를 발생시킵니다. RemoveSort 메서드는 정렬 제거 기능을 노출합니다.

protected override void RemoveSortCore()
{     int position;     object temp;     // 목록이 정렬되었는지 확인합니다.     if (unsortedItems != null)     {         // 정렬되지 않은 항목에 대해 루프를 사용하고         // 정렬되지 않은 목록마다 목록을 다시 정렬합니다.         for (int i = 0; i < unsortedItems.Count; )         {             position = this.Find("LastName",                 unsortedItems[i].GetType().                 GetProperty("LastName").GetValue(unsortedItems[i], null));             if (position > 0 && position != i)             {                 temp = this[i];                 this[i] = this[position];                 this[position] = (T)temp;                 i++;             }             else if (position == i)                 i++;             else                 // 정렬되지 않은 목록에 항목이 더 이상 없으면                 // 이를 삭제합니다.                 unsortedItems.RemoveAt(i);         }         OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));     }
}
public void RemoveSort()
{     RemoveSortCore();
}
정렬 방향 및 속성 노출

마지막으로 prorected SortDirectionCoreSortPropertyCore 속성을 재정의합니다. SortDirectionCore 속성은 정렬 방향이 오름차순인지 또는 내림차순인지를 나타냅니다. SortPropertyCore 속성은 목록 정렬에 사용되는 속성 설명자를 나타냅니다.

ListSortDirection sortDirectionValue;PropertyDescriptor sortPropertyValue;protected override PropertyDescriptor SortPropertyCore{    get { return sortPropertyValue; }}protected override ListSortDirection SortDirectionCore{    get { return sortDirectionValue; }}
정렬 기능 노출

샘플에서는 Employees(SortableSearchableList)의 사용자 지정 제네릭 BindingListDataGridView 컨트롤에 바인딩하였습니다. DataGridView 컨트롤은 정렬이 구현되었는지 여부를 검색하는데 여기에서는 정렬이 구현되어 있기 때문에 DataGridView의 열을 클릭하면 DataGridView의 내용이 열 내용에 따라 오름차순으로 정렬됩니다. 열을 다시 클릭하면 항목이 내림차순으로 정렬됩니다. DataGridViewIBindingList 인터페이스를 통해 목록을 호출합니다.

검색 코드와 비슷하게 선택적으로 ApplySortCore를 호출하는 공용 메서드를 노출하거나 DataGridView 컨트롤과 비슷하게 기본 IBindingList를 호출할 수 있습니다.

((IBindingList)employees).ApplySort(somePropertyDescriptor,    ListSortDirection.Ascending);
목록에 추가된 항목의 정렬 보장

Employee 개체는 기본 생성자를 노출하므로 BindingListAllowNew 속성은 true를 반환하여 사용자가 목록에 직원을 추가할 수 있도록 합니다. 사용자가 새 항목을 추가할 수 있으므로 정렬이 적용된 경우에는 목록에 추가된 항목이 정렬된 순서에 맞게 추가되도록 해야 합니다. 이를 위해 EndNew 메서드를 재정의했습니다. 이 메서드 재정의에서는 SortPropertyValuenull이 아님을 확인하여 목록이 정렬되었음을 확인하고, 새 항목이 목록 끝에 추가되는지 확인(이 경우 목록을 다시 정렬해야 함)한 다음, 목록의 ApplySortCore를 호출합니다.

public override void EndNew(int itemIndex)
{     // 항목이 목록 끝에 추가되었는지 확인하고     // 목록 끝에 추가되었으면 목록을 다시 정렬합니다.     if (sortPropertyValue != null && itemIndex == this.Count - 1)         ApplySortCore(this.sortPropertyValue, this.sortDirectionValue);     base.EndNew(itemIndex);
}

그림 2는 실행 중인 정렬 기능을 보여 줍니다. DataGridView의 열을 클릭하면 내용이 정렬됩니다. Remove sort 단추를 클릭하면 마지막으로 적용된 정렬이 제거됩니다.

wfbindp202.gif

그림 2. 제네릭 BindingList 사용하여 구현된 정렬 기능

다음 단계

앞에서 설명한 대로 이 예는 제네릭 BindingList에서 검색 및 정렬 기능을 구현하는 방법을 보여 주는 간단한 샘플입니다. 이 샘플에서 사용하는 정렬 알고리즘은 IComparable 인터페이스를 구현하는 형식을 사용합니다. IComparable 인터페이스를 구현하지 않는 속성으로 정렬을 시도하면 예외가 발생합니다. 이 논리는 속성이 주로 간단한 형식인 사용자 지정 비즈니스 개체를 정렬하는 경우에 사용할 수 있습니다. 이 샘플의 기능을 향상시키려면 사용자 지정 비즈니스 개체에서 복잡한 형식을 갖는 모든 속성에 대해 IComparable 인터페이스를 구현하는 방법을 고려할 수 있습니다. 예를 들어 Employee 개체에 복잡한 Address 형식의 Address 속성이 포함된 경우 Address 형식을 정렬하기 위한 비즈니스 규칙을 결정하고(거리 이름, 번지 등) 적절하게 Address 형식에서 IComparable 인터페이스 및 CompareTo 메서드를 구현해야 합니다.

또한 목록 끝에 새 항목이 추가될 경우에는 목록이 자동으로 다시 정렬됩니다. 응용 프로그램의 비즈니스 논리에 따라 항목이 추가되는 위치에 관계없이 목록을 다시 정렬하도록 할 수도 있습니다.

마지막으로 데이터 원본에 필터링 및 다중 열 정렬 기능을 추가할 수도 있습니다. 이 경우에는 데이터 원본에 대한 IBindingListView 인터페이스를 구현할 것을 고려해 봅니다.

결론

BindingSource 구성 요소는 Windows Forms 데이터 바인딩에 추가된 매우 유용한 기능입니다. 그러나 사용자 지정 비즈니스 개체의 목록을 사용할 때는 검색 및 정렬 기능을 추가해야 할 경우가 있습니다. 새로운 제네릭 BindingList는 검색 및 정렬이 지원되는 사용자 지정 비즈니스 개체의 바인딩 목록을 보다 간단하게 만들 수 있게 해 줍니다. 이러한 기능 및 Windows Forms의 다른 기능에 대한 자세한 내용은 다음을 참조하십시오.

'/' 응용 프로그램에 서버 오류가 있습니다.

최대 요청 길이를 초과했습니다.

설명: 현재 웹 요청을 실행하는 동안 처리되지 않은 예외가 발생했습니다. 스택 추적을 검토하여 발생한 오류 및 코드에서 오류가 발생한 위치에 대한 자세한 정보를 확인하십시오.
예외 정보: System.Web.HttpException: 최대 요청 길이를 초과했습니다.
소스 오류:

현재 웹 요청을 실행하는 동안 처리되지 않은 예외가 생성되었습니다. 아래의 예외 스택 추적을 사용하여 예외의 원인 및 위치 정보를 확인할 수 있습니다.

스택 추적:

[HttpException (0x80004005): 최대 요청 길이를 초과했습니다.]
   System.Web.HttpRequest.GetEntireRawContent() +3315778
   System.Web.HttpRequest.GetMultipartContent() +56
   System.Web.HttpRequest.FillInFormCollection() +222
   System.Web.HttpRequest.get_Form() +65
   System.Web.HttpRequest.get_HasForm() +3309630
   System.Web.UI.Page.GetCollectionBasedOnMethod(Boolean dontReturnNull) +45
   System.Web.UI.Page.DeterminePostBackMode() +65
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +133


버전 정보: Microsoft .NET Framework 버전:2.0.50727.1433; ASP.NET 버전:2.0.50727.1433

web.config 에 다가 아래 항목추가하면됩니다

<!--

      파일 용량설정
-->
    <httpRuntime  maxRequestLength="52100" ></httpRuntime>

.NET Framework 일반 참조

httpRuntime 요소(ASP.NET 설정 스키마)

ASP.NET 응용 프로그램에 대한 요청을 처리하는 방법을 결정하는 ASP.NET HTTP 런타임 설정을 구성합니다.

configuration 요소(일반 설정 스키마)
system.web 요소(ASP.NET 설정 스키마)
httpRuntime 요소(ASP.NET 설정 스키마)

선택적 Int32 특성입니다.

입력 스트림 버퍼링 임계값 제한(KB)을 지정합니다. 이 제한을 설정하면 예를 들어 사용자가 서버에 큰 파일을 게시할 때 발생하는 서비스 거부 공격을 방지할 수 있습니다.

기본값은 4096(4MB)입니다.

http://www.microsoft.com/korea/msdn/library/ko-kr/UseRequest_Filtering/html/default.aspx

요청 필터링 사용 방법



역자 : 송원석 IIS MVP

• IIS 관리 자동화 전문가
• ASP.NET 을 기반의 리치 웹 응용 프로그램 개발 전문가
• 전자조달 솔루션 전문 구축 업체 코어베이스 재직중
• 개인 사이트 에고큐브 (www.egocube.pe.kr) 운영중
• Taeyo`s ASP & .NET 커뮤니티(www.taeyo.pe.kr) 활동중


서론

URLScan 은 이전 버전의 IIS 에 애드-온 형태로 제공되던 보안 도구로 관리자들은 이 도구를 사용하여 웹 서버에 엄격한 보안 정책을 적용할 수 있었습니다. IIS 7.0 에서는 URLScan 의 모든 핵심적인 기능들이 요청 필터링이라는 모듈에 병합되었으며 숨겨진 네임스페이스라는 기능이 추가되었습니다. 본문에서는 요청 필터링이 제공하는 각각의 기능들에 대해서 알아보고 여러분들이 접하고 있는 환경에 적용이 가능하도록 실제 상황에서의 예제를 살펴보겠습니다.


페이지 맨 위로

이중 인코딩 요청 필터링

기능 개요

이 기능은 이중 인코딩된 요청을 이용한 공격을 방지합니다. 이 시나리오는 공격자가 주의 깊게 만들어진 이중으로 인코딩된 교묘한 요청을 IIS 로 전송하는 경우에 적용됩니다. 이와 같은 공격이 발생한다면 IIS 는 요청이 유효한 경우에만 허용하고 그렇지 않다면 거부할 것입니다. 이 기능이 활성화되면 IIS 는 해당 URL 을 두 번 디코딩하는데, 만약 첫 번째 디코딩 결과와 두 번째 디코딩 결과가 다르다면 요청은 거부되어질 것입니다. 이 기능에 의해서 요청이 거부되면 404.11 오류 코드가 로그에 기록됩니다.

URLScan 의 동일한 기능

이 기능은 URLScan 의 VerifyNormalization 옵션의 기능과 동일합니다.

실제 예제

이 예제에서는 서버 관리자가 서버로 전송되는 이중으로 인코딩된 요청을 결코 허용하지 않기를 원한다고 가정합니다. 이 시나리오를 반영하기 위해 다음과 같은 구성설정을 사용할 수 있습니다.

<configuration>
    <system.webServer>
        <security>
            <requestFiltering allowDoubleEscaping="false"></requestFiltering>
        </security>
    </system.webServer>
</configuration>

페이지 맨 위로

최상위 비트 설정 문자 필터링

기능 개요

이 기능은 IIS 로 전달되는 비 ASCII 문자가 포함된 모든 요청들을 허용할지 또는 거부할지를 결정합니다. 이 기능에 의해서 요청이 거부되면 404.12 오류 코드가 로그에 기록됩니다.

URLScan 의 동일한 기능

이 기능은 URLScan 의 AllowHighBitCharacters 옵션의 기능과 동일합니다.

실제 예제

이 예제에서는 서버 관리자가 전체 서버에 전송되는 최상위 비트가 설정된 문자들을 허용하지 않기를 바라지만, 오직 하나의 응용 프로그램에서는 이를 허용하기 원한다고 가정합니다. 이를 위해서 서버 관리자는 applicationHost.config 파일에는 allowHighBitCharacters=”false” 를 설정했지만, 비 ASCII 문자를 받아들이기 바라는 응용 프로그램의 루트 아래에는 web.config 파일을 생성했습니다. 다음의 구성설정이 바로 그 web.config 파일에 사용된 설정입니다.

 <configuration>
    <system.webServer>
        <security>
            <requestFiltering allowHighBitCharacters="true"></requestFiltering>
        </security>
    </system.webServer>
</configuration>

페이지 맨 위로

파일 확장자에 기반한 필터링

기능 개요

이 기능은 IIS 가 서비스 할 수 있는 파일 확장자들의 집합을 정의합니다. 이 기능에 의해서 요청이 거부되면 404.7 오류 코드가 로그에 기록됩니다.

URLScan 의 동일한 기능

이 기능은 URLScan 의 AllowExtensions 옵션과 DenyExtensions 옵션의 기능과 동일합니다.

실제 예제

이 예제에서는 서버 관리자가 ASP 파일은 서비스 되지 않지만 그 외의 모든 파일들은 서비스 되기를 원한다고 가정합니다. 이를 위해서 서버 관리자는 allowUnlisted 옵션을 “true” 로 설정하고, 명시적으로 서비스 되지 않기를 바라는 ASP 파일을 위해 다음과 같은 파일 확장자 항목을 정의합니다.

 <configuration>
    <system.webServer>
        <security>
            <requestFiltering>
                <fileExtensions allowUnlisted="true" >
                    <add fileExtension=".asp" allowed="false" />
                </fileExtensions>
            </requestFiltering>
        </security>
    </system.webServer>
</configuration>

페이지 맨 위로

요청 제한에 기반한 필터링

기능 개요

이 기능은 다음 세 가지 기능들의 조합으로 이루어집니다.

  • maxAllowedContentLength ? Content-Length 요청 헤더값의 최대 크기를 지정합니다.
  • maxUrl ? 쿼리스트링을 제외한 URL 의 최대 길이를 지정합니다.
  • maxQueryString ? 쿼리스트링의 최대 길이를 지정합니다.

이 기능에 의해서 요청이 거부되면 다음과 같은 오류 코드가 로그에 기록됩니다.

  • 404.13 콘텐츠가 너무 큰 경우
  • 404.14 URL 이 너무 긴 경우
  • 404.15 쿼리스트링이 너무 긴 경우
URLScan 의 동일한 기능

이 각각의 기능들은 URLScan 의 다음 기능들과 동일합니다.

  • maxAllowedContentLength
  • maxUrl
  • maxQueryString
실제 예제

이는 소스 코드에 접근할 수 없는 소프트웨어를 구매하는 기업들에게는 매우 일반적인 상황입니다. 코드에 내제된 취약성들이 발견되었을 때, 그 영향을 받는 코드를 갱신하는 것이 매우 어려울 수도 있습니다. 이러한 취약성들은 대부분 응용 프로그램으로 전송되는 URL 이나 쿼리스트링이 단지 ‘너무 커서’ 또는 ‘콘텐츠가 너무 많아서’ 발생하는 경우가 대부분입니다. 서버 관리자가 안전한 최대값을 결정할 수 있다면, 응용 프로그램의 이진 파일들을 수정하지 않고서도 아래와 같은 구성설정을 사용해서 그 제한값을 적용할 수 있습니다.

 <configuration>
    <system.webServer>
        <security>
            <requestFiltering>
                <requestLimits
                    maxAllowedContentLength="30000000"
                    maxUrl="260"
                    maxQueryString="25" />
            </requestFiltering>
        </security>
    </system.webServer>
</configuration>

페이지 맨 위로

HTTP 동사 필터링

기능 개요

이 기능은 IIS 가 요청으로 받아들일 동사들의 목록을 정의할 수 있게 해줍니다. 이 기능에 의해서 요청이 거부되면 404.6 오류 코드가 로그에 기록됩니다.

URLScan 의 동일한 기능

이 기능은 URLScan 의 UseAllowVerbs 옵션, AllowVerbs 옵션, 그리고 DenyVerbs 옵션의 기능과 동일합니다.

실제 예제

이 예제에서는 서버 관리자가 오직 하나의 동사, 즉 GET 동사만 허용하기를 원한다고 가정합니다. 이를 위해서 서버 관리자는 먼저 구성설정 파일에 allowUnlisted=”false” 옵션을 설정하여 명시적으로 지정하지 않은 모든 동사를 허용하지 않도록 설정합니다. 그리고, 그 다음에 허용하고자 하는 동사들의 목록을 명시적으로 지정합니다. 이 예제에서는 오직 GET 동사만을 허용합니다.

 <configuration>
    <system.webServer>
        <security>
            <requestFiltering>
                <verbs allowUnlisted="false">
                    <add verb="GET" allowed="true" />
                </verbs>
            </requestFiltering>
        </security>
    </system.webServer>
</configuration>

페이지 맨 위로

URL 문자열 시퀀스에 기반한 필터링

가능 개요

이 기능은 IIS 가 거부할 문자열 시퀀스의 목록을 정의합니다. 이 기능에 의해서 요청이 거부되면 404.5 오류 코드가 로그에 기록됩니다.

URLScan 의 동일한 기능

이 기능은 URLScan 의 DenyUrlSequences 옵션의 기능과 동일합니다.

실제 예제

이 기능은 매우 강력합니다. 만약 IIS 에 의해 서비스 되지 않기를 바라는 어떤 문자열 시퀀스가 있다면, 그 문자열 시퀀스를 다음과 같이 구성설정에 추가할 수 있습니다.

 <configuration>
   <system.webServer>
      <security>
         <requestFiltering>
            <denyUrlSequences>
               <add sequence=".." />
            </denyUrlSequences>
         </requestFiltering>
      </security>
   </system.webServer>
</configuration>

이 예제에서는 ‘..’ 시퀀스를 거부합니다. 그러나, 보다 현실적인 시나리오는 여러분들이 이미 폐업한 판매자로부터 구매한 응용 프로그램을 갖고 있으며, 특수한 시퀀스의 문자열이 이 응용 프로그램으로 전송되었을 때 문제가 발생할 수 있다는 사실을 발견한 경우입니다. 여러분들은 이 기능을 사용하여 해당 응용 프로그램의 코드를 수정하지 않고서도 단순히 거부 목록에 URL 시퀀스를 추가하는 것만으로 응용 프로그램을 보호할 수 있습니다.


페이지 맨 위로

숨겨진 네임스페이스 필터링

기능 개요

이 기능은 ‘서비스 가능한’ 네임스페이스를 (또는 URL 구역) 정의할 수 있도록 해줍니다. 이 기능에 의해서 요청이 거부되면 404.8 오류 코드가 로그에 기록됩니다.

URLScan 의 동일한 기능

이 기능은 IIS 7.0 에서 새롭게 제공되는 기능으로 URLScan 에는 존재하지 않습니다.

실제 예제

이해를 돕기 위해서 서버에 다음과 같은 두 개의 URL 이 존재하는 경우의 예제를 생각해 보겠습니다.

  • http://site.com/bin
  • http://site.com/binary

우리들이 원하는 것은 binary 디렉터리의 콘텐츠들은 서비스를 허용하지만 bin 디렉터리의 콘텐츠들은 서비스를 허용되지 않는 것입니다. 그렇지만, 만약 URL 시퀀스 필터링 기능을 사용하여 “bin” 시퀀스를 거부하도록 설정한다면, 결국 두 개의 URL 이 모두 거부되고 말 것입니다. 다음과 같은 구성설정을 사용하여 오직 bin 디렉터리에 대한 접근만을 거부하고 binary 디렉터리 하위에 존재하는 콘텐츠에 대한 접근은 계속해서 허용하도록 지정할 수 있습니다.

 <configuration>
    <system.webServer>
        <security>
            <requestFiltering>
                <hiddenNamespaces>
                    <add hiddenDirectory="BIN" />
                </hiddenNamespaces>
            </requestFiltering>
        </security>
    </system.webServer>
</configuration>

페이지 맨 위로

요약

이전 버전의 IIS 에서 관리자들은 URLScan 을 사용하여 전역적인 수준의 보안 정책을 정의하고 자신들이 관리하는 시스템에 이를 적용할 수 있었습니다. IIS 7.0 에서 관리자들은 전역적인 수준뿐만 아니라 각각의 URL 들을 대상으로 동일한 정책을 적용할 수 있게 되었으며, 새롭고 풍부한 기능의 대체 모델이 제공하는 이점들을 이용할 수도 있습니다.

본문을 통해서 우리들은 요청이 거부될 때 요청 필터링이 리턴하는 몇 가지 새로운 오류 코드를 살펴보았습니다. 다음은 모든 IIS 로그 오류 코드를 정리한 간단한 참조 목록입니다.

오류

상태 코드

요청된 포트에서 웹 사이트에 액세스할 수 없습니다.

404.1

웹 서비스 확장 잠금 정책으로 인해 이 요청이 거부됩니다.

404.2

MIME 맵 정책으로 인해 요청이 거부됩니다.

404.3

핸들러가 존재하지 않습니다.

404.4

요청 필터링: URL 시퀀스로 인해 요청이 거부됩니다.

404.5

요청 필터링: HTTP 동사로 인해 요청이 거부됩니다.

404.6

요청 필터링: 파일 확장자로 인해 요청이 거부됩니다.

404.7

요청 필터링: 숨겨진 네밍스페이스로 인해 요청이 거부됩니다.

404.8

숨겨진 파일 속성이 설정되어 요청이 거부됩니다.

404.9

요청 필터링: 요청 헤더가 너무 길어서 요청이 거부됩니다.

404.10

요청 필터링: 이중 인코딩된 URL 로 인해 요청이 거부됩니다.

404.11

요청 필터링: 비 ASCII 문자로 인해 요청이 거부됩니다.

404.12

요청 필터링: 콘텐츠 길이가 너무 커서 요청이 거부됩니다.

404.13

요청 필터링: URL 이 너무 길어서 요청이 거부됩니다.

404.14

요청 필터링: 쿼리스트링이 너무 길어서 요청이 거부됩니다.

404.15


  • 이 문서는 한국 개발자를 위하여 Microsoft MVP가 번역하여 제공한 문서입니다.
  • Microsoft는 이 문서를 번역자의 의도대로 제공해 드리며 더 정확한 표현 또는 여러분의 의견을 환영합니다.
  • Microsoft는 커뮤니티를 위해 번역자의 의도대로 이 문서를 제공합니다. 

    [출처] 요청 필터링 사용 방법 (II7) ,sql 인젝션 방지|작성자 스토커

  • Prism: patterns & practices Composite Application Guidance for WPF and Silverlight site

    PrismV2StockTraderRIShell.png
    Overview

    The Composite Client Application Guidance is designed to help you more easily build modular Windows Presentation Foundation (WPF) and Silverlight client applications. These types of applications typically feature multiple screens, rich, flexible user interaction and data visualization, and role-determined behavior. They are "built to last" and "built for change." This means that the application's expected lifetime is measured in years and that it will change in response to new, unforeseen requirements. This application may start small and over time evolve into a composite client—composite applications use loosely coupled, independently evolvable pieces that work together in the overall application. Applications that do not demand these features and characteristics may not benefit from the Composite Application Guidance.
    The guidance includes a reference implementation, reusable library code (called the Composite Application Library), documentation, QuickStarts, and Hands-On Labs.

     

     

     

    http://www.codeplex.com/CompositeWPF

     

    image

    데이터 베이스를 만들어 줍니다

     

     

    image

    데이터 필드는 위와 같이 초간단 입니다

     

    그다음 아래와 같은 셀렉트 메소드를 만들어줍니다.

    image

     

     

     

    코드상에서 아래와 같이 하면 끝입니다.~

    private void Form1_Load(object sender, EventArgs e)
    {

        BindingSource binding1 = new BindingSource();
        binding1.DataSource = testTableAdapter.GetDataByTitle(2222);
        this.dataGrid1.DataSource = binding1;

    }

     

     

     

    image

     


    참고사항

     

    BindingSource 구성 요소는 다양한 용도로 사용됩니다. 먼저 이 구성 요소는 Windows Forms 컨트롤과 데이터 소스 간의 현재 위치 관리, 변경 알림 및 기타 서비스를 제공하므로 DataSource 속성으로 BindingSource 구성 요소를 데이터 소스에 연결하여 폼의 컨트롤을 데이터에 간단하게 바인딩할 수 있습니다. 복잡한 바인딩 시나리오의 경우 필요에 따라 DataMember 속성을 데이터 소스의 특정 열이나 목록으로 설정할 수 있습니다. 그런 다음 컨트롤을 BindingSource에 바인딩합니다. 데이터와의 모든 추가 상호 작용은 BindingSource 구성 요소 호출을 통해 이루어지며 BindingSource가 바인딩 프로세스를 단순화할 수 있는 방법에 대한 예제는 방법: DBNull 데이터베이스 값에 Windows Forms 컨트롤 바인딩 및 방법: 데이터 바인딩에서 발생하는 오류 및 예외 처리를 참조하십시오. 데이터 소스의 탐색과 업데이트는 MoveNext, MoveLast, Remove 등의 메서드를 통해 이루어집니다. 정렬과 필터링 등의 작업은 SortFilter 속성을 통해 처리됩니다. BindingSource로 정렬 및 필터링 사용에 대한 자세한 내용은 방법: Windows Forms BindingSource 구성 요소를 사용하여 ADO.NET 데이터 정렬 및 필터링을 참조하십시오.

    또한 BindingSource 구성 요소를 강력한 형식의 데이터 소스로 사용할 수 있습니다. 일반적으로 내부 데이터 소스의 형식은 다음 메커니즘 중 하나를 통해 고정됩니다.

    • Add 메서드를 사용하여 BindingSource 구성 요소에 항목을 추가합니다.
    • DataSource 속성을 목록, 단일 개체 또는 형식으로 설정합니다.

    이 두 메커니즘은 모두 강력한 형식의 목록을 만듭니다. BindingSource를 사용하여 형식에 바인딩하는 방법에 대한 자세한 내용은 방법: 형식에 Windows Forms 컨트롤 바인딩을 참조하십시오. BindingSource를 사용하여 팩터리 개체에 컨트롤을 바인딩할 수도 있습니다. 이 작업을 수행하는 방법에 대한 자세한 내용은 방법: 팩터리 개체에 Windows Forms 컨트롤 바인딩을 참조하십시오.

    clip_image001

    참고:

    BindingSource에서는 단순한 데이터 소스와 복잡한 데이터 소스 모두를 처리하므로 용어상의 문제가 있습니다. 이 클래스에 대한 설명에서 목록이라는 용어는 호스팅된 데이터 소스 내의 데이터 컬렉션을 나타내고 항목은 단일 요소를 나타냅니다. 복잡한 데이터 소스와 관련된 기능을 설명할 때는 같은 의미로 테이블과 행이라는 용어가 사용됩니다.

    BindingSource에서는 내부 데이터에 액세스하기 위한 멤버를 제공합니다. 현재 항목은 Current 속성을 통해 검색할 수 있으며 목록 전체는 List 속성을 통해 검색할 수 있습니다. 현재 항목에 대한 편집 작업은 Current 속성과 RemoveCurrent, EndEdit, CancelEdit, AddAddNew 메서드를 통해 지원됩니다. 통화 관리는 모든 내부 데이터 소스 형식에 대해 자동으로 처리되지만 이 클래스는 사용자 지정할 수 있는 CurrentItemChangedDataSourceChanged 등의 여러 이벤트를 노출합니다.

    목록 내의 항목을 탐색하기 위해 VCR과 비슷한 UI(사용자 인터페이스)를 제공하는 BindingNavigator 클래스를 사용하여 BindingSource 구성 요소에 바인딩된 데이터 소스를 탐색하거나 관리할 수도 있습니다. BindingNavigator는 모든 데이터 소스에 바인딩될 수 있지만 BindingNavigator.BindingSource 속성을 통해 BindingSource 구성 요소와 통합되도록 디자인되어 있습니다.

    BindingSource 클래스의 기본 속성은 DataSource입니다. 기본 이벤트는 CurrentChanged입니다.

     

     

    중첩마스터 페이지에서 컨트롤 찾아가기

    부모마스터페이지( MasterPage.master )

         ㄴ자식마스터페이지 (MasterPage03.master)

                       ㄴAspx Content Page (Default3.aspx)

     

    MasterPage.master  컨텐츠 영역

    <asp:ContentPlaceHolder ID="ContentPlaceHolderContent" runat="server"> 
    </asp:ContentPlaceHolder>

    MasterPage03.master

    <asp:Content ID="Content4" ContentPlaceHolderID="ContentPlaceHolderContent" Runat="Server">
        <asp:ContentPlaceHolder ID="ContentPlaceHolderContent" runat="server">

        </asp:ContentPlaceHolder>
    </asp:Content>

    Default3.aspx

    <asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolderContent" Runat="Server">
         <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
    </asp:Content>

    Default3.aspx에서 컨트롤 접근하기

    protected void Page_Load(object sender, EventArgs e)
    {

    //부모 * 젤 상위 부터 찾아 내려옵니다.

    ContentPlaceHolder content = this.Master.Master.FindControl("ContentPlaceHolderContent") as ContentPlaceHolder;

    //부모를 상속받아 구현한 마스터페이지 찾기
        ContentPlaceHolder sub_content = content.FindControl("ContentPlaceHolderContent") as ContentPlaceHolder;
        TextBox txt =  sub_content.FindControl("TextBox1") as TextBox;
        if (txt != null)
        {
            Response.Write(txt.ClientID.ToString());
        }
        else {
            Response.Write("컨트롤 못찾음");
        }

    }

     

     

    끝~

    마스터페이지에서는 접근이 바로 안됩니다.

    한단계 더 통해서 접근이 가능합니다.

     

    마스터페이지

    <%@ Master Language="C#" AutoEventWireup="true" CodeFile="MasterPage.master.cs" Inherits="MasterPage" %>

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
        <asp:ContentPlaceHolder id="head" runat="server">
        </asp:ContentPlaceHolder>
    </head>
    <body>
    maseter page
        <form id="form1" runat="server">
        <div>
            <br />
            <asp:ContentPlaceHolder id="ContentPlaceHolder1" runat="server">
            </asp:ContentPlaceHolder>
        </div>
        </form>
    </body>
    </html>

     

     

     

    마스터페이지로 만들어진 컨텐츠 페이지

    <%@ Page Title="" Language="C#" MasterPageFile="~/MasterPage.master" AutoEventWireup="true" CodeFile="Default6.aspx.cs" Inherits="Default6" %>

    <asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
    </asp:Content>
    <asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">

    <asp:FileUpload ID="FileUpload2" runat="server" />

    <br />
    <asp:Button ID="Button1" runat="server" onclick="Button1_Click" Text="Button" />
    <br />
    <br />
    </asp:Content>

     

    접근하기

     

    protected void Page_Load(object sender, EventArgs e)
    {

        ContentPlaceHolder content = this.Master.FindControl("ContentPlaceHolder1") as ContentPlaceHolder;
        if (content != null)
        {

            FileUpload fu = content.FindControl("FileUpload2") as FileUpload;
            if (fu != null) {

                Response.Write(fu.ClientID);
            }
        }
    }

     

     

    Video How to: Create a C# WPF Application


    Authors: Kathleen McGrath, Harry Miller, Jo Molnar, Microsoft Corporation

    Applies to: Microsoft Visual C# 2008 Express Edition

    Length: 00:05:35 | Size: 13.8 MB | Type: WMV file

    Watch the video

    Download the video and transcript

    Read the step-by-step article

    Video Summary

    Creating a WPF application is similar to creating a Windows Forms application in that you can drag controls from the Toolbox to the design surface and then write code to handle the events of the controls. You can create WPF applications that are more graphically appealing through the use of Extensible Application Markup Language (XAML). In addition to having a designer, Properties window, and Toolbox, the IDE in WPF projects has a window that contains XAML.

    This video shows you how to create your own Ink application, which enables you to draw pictures. The following tasks are included in the process:

    • How to create a WPF application.

    • How to switch between Code view and Design view.

    • How to use the XAML editor.

    • How to add WPF controls to the WPF application.

    • How to create event handlers for WPF controls.

    The Visual C# Help includes the code and the steps that are demonstrated in this video. See How to: Create a C# WPF Application.

    Additional Video Resources

    Video How Tos

    Visual C# Videos

    Video How to: Create a C# Console Application

    Video How to: Create a C# Windows Forms Application

    Video How to: Creating a Drawing Application by Using WPF

    Other Videos

    Additional Help Resources

    ResizeGrip - Resizing (Mostly Custom) Windows

     

    ResizeGrip 클래스

    업데이트: 2007년 11월

    Window가 크기를 변경할 수 있도록 하는 Thumb 컨트롤의 구현을 나타냅니다.

    ResizeGrip - Resizing (Mostly Custom) Windows

    August 18th, 2008     |     9 Comments

    In my most recent article, I write about how you can easily create a custom window. Custom windows are interesting because, for better or for worse, you get to override the default OS titlebar, minimize/maximize/close buttons, and related functionality. in favor of your own custom implementation:

    The benefit is obvious. You can really set your application apart by providing your own window design. The downside is that you have to re-create all of the window functionality yourself. Things like dragging a window, minimizing, maximizing, and closing are not free. They aren’t particularly hard either, and I provide the code snippets for them at the end of my article. What isn’t trivial, though, is being able to resize a window.

    In this post, I will provide a cheap solution for the window resizing problem. In a future post, I will talk about how to resize using a non-cheap but arguably better solution.

    The ResizeGrip Control
    When you make your window transparent, resizing (one of the features you normally would take for granted) is no longer available:

    To help with that, you have what is known as the ResizeGrip control:

    The ResizeGrip control, by default, positions itself on the bottom-right corner of your application window. When you hover over it with your mouse, you will get the familiar resize handles that indicate you can click and drag to resize your application as necessary:

    Because of its position and orientation, you will only be able to resize in a NW-SE (Northwest-Southeast) manner. At least, it is better than not being able to resize your application at all.

    Using ResizeGrip
    To use the ResizeGrip control, you can’t just drag and drop it into your window via the Asset Library using Expression Blend. Actually, you can, but it won’t do anything such as actually resizing your application when you click and drag it around. The way to add a ResizeGrip to your application is to select your Window in your Object Tree in Expression Blend:

    After you have done that, take a look in the Common Properties category in your Properties Inspector. There should be a drop-down menu labeled ResizeMode. Click on it and select the CanResizeWithGrip item:

    Once you have done that, you will see your ResizeGrip control appear on the bottom-right corner of your window. If you run your application, you will be able to resize your application by using the ResizeGrip control.

    Why I Don’t Prefer the ResizeGrip Control
    If you are in a rush and need to get something that enables resizing, the ResizeGrip is a great solution. My biggest problem with it is that it breaks the expectations your users would have when using your application. When you go with a custom window style to emulate a traditional window but fail to provide obvious functionality like 8-sided resizing, then you need to evaluate whether a custom design is worth the tradeoff. The answer may well be "Yes", so don’t feel that not having proper resizing automatically rules out having custom window styles.

    In a future post, I will describe how to implement window resizing by writing some code. It will be a great example of the old phrase, "No pain, no gain!"

    Get videos designed for all .NET Compact Framework developers, from the novice to the professional. If you are new to the .NET Compact Framework, you can learn the basics of how to create applications for devices, using either Visual Basic or C#.

    Categories include: the .NET Framework; Data and Services; Hardware, Performance, and Resource Management; Multithreaded Programming; Office; Security and Deployment; Testing and Debugging; User Interface Programming, Web Technologies, State and Notification Broker; and PowerToys.

    Check back often or subscribe to the RSS feed to be notified when new videos are added.

     

     

    모바일 개발 온라인강좌

    http://msdn.microsoft.com/ko-kr/windowsmobile/bb495180(en-us).aspx

    + Recent posts