GIGO MIND DEV BLOG

ASP.NET FRAMEWORK WEBFORM(1)

개념 정리

.NET Framework의 새로운 웹 어플리케이션 (C# 솔루션)을 만들때, 유저는 다음의 3가지 핵심 참조 중 1개 이상을 선택 할 수 있다.

  • Web Forms
  • MVC
  • Web API

이번에 다뤄 볼 내용은 Web Form 이다.


처음 템플랫 생성 구간에서 클라우드를 사용할 것인지, docker을 사용할 것인지, 인증 변경을 할 것인지를 정할 수 있다.
인증 변경을 개별 사용자 계정으로 하게 되면, 로그인, 로그아웃, 회원가입의 기능을 기본으로 제공해 준다.


닷넷 개발에 적합한 환경인 Microsoft Visual Studio의 인터페이스를 알면 닷넷 프레임워크의 이용이 더 수월해진다.

기본적으로는 보기(V)의 솔루션탐색기를 켜줌으로써, 오른쪽 화면에 어떤 파일 시스템으로 솔루션이 이루어졌는지 확인해야한다.

C#에서는 하나의 솔루션 (자바의 패키지같은 개념)에 여러개의 프로젝트가 들어갈 수 있다.

프로젝트의 하위 폴더들로는 App_Data, App_Start, Model, Controller, View, Content, 등등 여러가지 폴더들이 있을 수 있는데 이는 처음 탬플렛을 뭐로 했냐에 따라 정해진다.
하지만 기본적으로, Empty Template을 쓴다고 가정할 경우, 이 폴더들은 지워져도 무관하다.

여기서 알아야 할 중요한 개념은 각 프로젝트의 Root는 웹사이트의 Root라는 것이며, 이 프로젝트의 하위 파일로는 웹 서버가 클라이언트에게 전해 줄 웹 페이지의 파일들이 자리잡게 될 것이다.

즉, car.com 이라는 웹 사이트가 있을 때, 프로젝트의 Root가 car.com의 Root과 같다는 뜻은 프로젝트의 하위 파일로써 index.html, about.aspx등의 파일이 오게 될 경우,
car.com/,
car.com/about.aspx
식의 요청이 가능하며, 그에 맞는 웹 페이지를 받아온다는 것이다.

이런 파일의 추가는 프로젝트에 오른쪽 클릭, 추가(D)를 이용해 할 수 있다 (혹은 CTRL+SHIFT+A 단축키).
이 때 확인할 수 있는 내용은 확장자에 대한 것으로, aspx는 webform을 위한 확장자, master은 마스터 페이지를 위한 확장자, cshtml은 mvc 5의 확장자라는 사실을 간략하게 알 수 있다.

이렇게 생성된 html과 같은 파일은 비쥬얼 스튜디오 내부에서는 VS code와는 다르게 emmet과 같은 플러그인을 제공하지 않아 직접 태그를 작성해줘야 한다는 불편함이 있다.

단축키 또한 조금 다른데 CTRL+D로 같은 구문을 선택 할 수 있는 vsc 명령어는 Shift+Alt+. 으로 쓸 수 있다.
그 외에도, 자동 indentation은 CTRL+K+D, 코멘트 처리는 CTRL+K+C, 코멘트 처리해제는 CTRL+K+U등이 있다.

웹 페이지를 작성한 후에는, 오른쪽 솔루션 브라우저에서 해당 파일에 오른쪽 클릭 후 브라우저에서 보기를 하면 된다.
IDE로써 비쥬얼 스튜디오의 좋은 점은 느리지만 이러한 컴파일 (html말고도 컴파일이 필요한 코드를) 기능을 수행한다는 점에 있다.
혹은, 프로젝트에 오른쪽 클릭 후 시작 프로젝트로 설정을 한 후, F5나 CTRL+F5(디버깅 x)를 통해 컴파일 후 실행도 가능하다.

이렇게 프로젝트의 내부는 웹 애플리케이션의 루트와 같다는 것을 확인한 순간부터, HTML, CSS, JAVASCRIPT를 통한 웹 프로그래밍이 가능해진다.
하지만 ASP의 고유의 기능을 쓰고 싶은 우리들의 입장에서는 .aspx (asp extended)파일의 쓰임새를 알 필요가 있다.

즉 아까전에 프로젝트에 돌아가서 CTRL+SHIFT+A를 통해 새 항목을 만들고 WEBFORM, 즉 .aspx의 파일을 만들어 내용을 확인해보자.


CLASSIC ASP, ASP.NET, HTML Server Controls

html의 index처럼, JSP나 ASPX과 같은 파일들은 기본적으로 Default라는 이름을 사용한다.
Default.aspx라는 파일을 만들면 Default.aspx.cs와 Default.aspx.designer.cs 라는 두가지 파일이 추가적으로 만들어진 것을 확인할 수 있다.

Default.aspx라는 파일 자체는 User Interface의 영역으로, 실제적으로 유저가 쓰는 html태그라던가의 부분을 담고 있다.
Default.aspx.cs는 Code-behind file로 불리고, UI의 코드를 담당하는 C#파일이다.
Default.aspx.designer.cs는 자동으로 생성되는 코드가 들어가는, 굳이 따지자면 건들 필요가 없는 파일이다.

이러한 솔루션의 파일 구조는 WPF와 Window Form과 동일하다.

aspx는 asp extended를 뜻하고, 실제로 html의 파일을 aspx 확장자로 바꾸기만 해도 html의 페이지가 보인다는 걸 알 수 있다.
asp 파일 자체가 원래 이러한 특성을 가지고 있었는데, classic asp와 aspx의 차이는 가독성의 차이가 크다고 볼 수 있다.
asp는 코드블럭이 실행이 되는 그 자리에만 있을 수 있는 것에 비해, aspx는 Server Controls (서버가 알아들을 수 있는 태그) 라는 것을 이용해 가독성을 늘렸다.

서버 컨트롤에는 다음과 같은 서버 컨트롤들이 존재한다.

  • HTML Server Controls - Traditional HTML tags
  • Web Server Controls - New ASP.NET tags
  • Validation Server Controls - For input validation

aspx 파일의 구조를 보면 기본적인 html에 <% %>과 같은 inline server code, 그리고 그 안에는 Page 지시문이 존재한다.
이 때, 제일 윗줄에 생성된 Page 지시문을 확인하면, CodeBehind 파일을 AutoEventWireup을 통해 같이 쓰겠다는 것을 적어놓았는데, 이러한 CodeBehind의 파일로 넘어가기 위해선 F7 키를 누르면 된다.

또한 코드를 잘 살펴보면 HTML 태그들에 runat=”server” attribute가 존재하는 것을 확인할 수 있는데, 이는 일반적으로 aspx페이지 자체가 서버에서 작동하는, 즉 기존의 static html과는 다르게 브라우저에게 넘겨지기 전에 서버 쪽에서의 preprocess 단계가 존재한다는 것을 의미한다.
HTML 자체를 코딩하는 것이 아닌, aspx라는 파일을 server 사이드에서 compile, execute를 하고 나서, HTML을 보내준다는 의미이다.
이처럼 HTML의 태그에 attribute 특성으로 runat=”server” 이 붙는 컨트롤들을 HTML Server Controls 이라 부른다. HTML Server Controls의 특징이라 할 수 있는 점은, 모든 HTML Server Controls는 <form runat="server"> 태그 안에 존재해야 한다는 것이다.
이가 뜻하는 바는, form은 서버에서 process 돼야 하며, form 안에 존재하는 컨트롤들은 서버 스크립트에 의해 access 될 수 있음을 뜻한다.

저번 포스팅에서 다뤘던 Web Pages와는 다르게, Web Form자체는 Event-driven architecture을 따르고 있다.
모든 페이지는 System.Web.UI 라는 namespace에 존재하는 Page라는 클래스의 derivatives이며, Page는 Page_Load라는 이벤트가 실행될 때, 자체적으로 가지고 있는 properties를 이용, 페이지를 render해주는 역할을 하는 것이다.
head에 들어있는 runat attribute는 이러한 html의 메타데이터를 포함하고 있는 Page의 properties들에 추가적인 내용을 넣어줌으로써, Page_Load같은 이벤트에 맞춰 이벤트 핸들러를 설정해 주는 것이다.

<script runat="server">
Sub Page_Load
link1.HRef="http://www.w3schools.com"
End Sub
</script>
<html>
<body>
<form runat="server">
<a id="link1" runat="server">Visit W3Schools!</a>
</form>
</body>
</html>

Web Server Controls, Web Form의 디자인 모드

웹 폼에 존재하는 단연코 가장 유니크한 특징은 Web Server Controls ( 컴포넌트 ) 의 존재이다.
이 특징은 윈도우 폼으로부터 확장된 것이며, 컨트롤은 비쥬얼 스튜디오 보기>도구 상자(CTRL+ALT+X)에서 찾을 수 있다.

도구 상자에서 제공하는 컨트롤들은 기존의 HTML태그 등으로 구현해야했던 코드 혹은 더 복잡한 요소를 구현해준다.
이 각각의 컨트롤들은 ID나 Name같은 attribute를 통해 access 할 수 있으며, runat attribute를 통해 서버 사이드에서 동작한다는 것을 확인할 수 있다.

<asp:control_name id="some_id" runat="server"> </asp:control_name>

<script runat="server">
Sub submit(Source As Object, e As EventArgs)
button1.Text="You clicked me!"
End Sub
</script>

<html>
<body>

<form runat="server">
<asp:Button id="button1" Text="Click me!"
runat="server" OnClick="submit"/>
</form>

</body>
</html>

위에 존재하는 웹 서버 컨트롤, 즉 , <asp:/>의 형태를 띈 컴포넌트는 버튼이며, OnClick 시에 submit이라는 Subroutine을 실행한다는 사실을 알 수 있다.  

이는 흔히 아는 XML태그의 syntax과 동일하며, jsp에서는 jsp:actions 라는 비슷하게 생긴 것이 존재하지만, jsp가 javaBean을 사용해 객체를 받아와 값을 넣고 결과값을 받아오는 것에 대부분 쓰이기 때문에 인지를 못하지만, jsp:plugin이라는 action자체는 asp와 굉장히 비슷하다고 볼 수 있다.

예시 )
<jsp:plugin type = "applet" codebase = "dirname" code = "MyApplet.class"
   width = "60" height = "80">
   <jsp:param name = "fontcolor" value = "red" />
   <jsp:param name = "background" value = "black" />
 
   <jsp:fallback>
      Unable to initialize Java Plugin
   </jsp:fallback>
 
</jsp:plugin>

control들은 id나 name을 가지고 있기에, event listener을 정해줄 수도 있다.
예를 들어서, 버튼이라는 컨트롤을 생성 했을때, 디자인 모드에서는 더블클릭을 하거나, 소스 코드에서는 기존의 html에 존재하는 OnClick = ““을 추가해줌으로써, 이벤트 리쓰너를 추가해줄 수 있다.
그리고 나서의 이벤트는 f7을 눌러 코드 비하인드로 간 뒤, sender (this 와 같은 개념) 과 event e에 맞춰서 이벤트 핸들러를 작성 해 줄 수 있다.

한가지 특이한 점은, Javascript나 Jquery로 구현한 이벤트 리쓰너, 핸들러인 경우는 새로고침이 없이 이 벤트가 진행되는 것에 비해서, 웹 폼의 이벤트 핸들러는 페이지의 새로고침 (Page_Load) 을 유도해 깜빡임이 보이게 된다.

if (!Page.IsPostBack) 
{
	//temp 는 controller의 ID이다.
	temp.Border = System.Drawing.Color.Red;
} 

위의 컨디션은 Page_Load에 넣어주게 되면, 첫 Load때 동작한다.

또한, 이렇게 stateless한 웹 페이지에서 새로고침을 유도하기에, 숨겨진 state들을 Hidden_State로써 html에 넣어야 한다는 단점이 있다.
이는 뒤에 자세하게 다뤄질 것이다.

WEBFORM은 이렇게 코딩하기가 쉽다는 장점과 대신 코드가 더러워진다는 단점이 같이 존재한다.


Validation Server Controls, User input check

Validation Server Controls는 유저의 인풋을 체크한다.
그리고, validation이 실패할 경우, 유저에게 에러 메세지를 출력해준다.
기본적으로 Page Validation은 버튼과 같은 코드가 클릭 되었을시 실행이 되는데, CausesValidation = 을 false로 바꿨을 시, 실행되지 않는다.

<asp:control_name id="some_id" runat="server"/>

<html>
<body>

<form runat="server">
<p>Enter a number from 1 to 100:
<asp:TextBox id="tbox1" runat="server" />
<br /><br />
<asp:Button Text="Submit" runat="server" />
</p>

<p>
<asp:RangeValidator
ControlToValidate="tbox1"
MinimumValue="1"
MaximumValue="100"
Type="Integer"
Text="The value must be from 1 to 100!"
runat="server" />
</p>
</form>

</body>
</html>

기존의 HTML 태그도 minlength, maxlength같은 것이 존재하나, 클라이언트쪽에서 체크하는 것이였다.
하지만 validation controls같은 경우는 서버쪽에서 체크를 하기에 다르다고 할 수 있겠다.

이는 클라이언트에서 html을 바꿔서 잘못된 정보를 넣을 수 없다는 것을 뜻하며, 개인적으로는 조금 더 보안상 안전하다고 고려된다.


Event Driven Architecture

Event Driven Architecture을 구성하는 요소들은 미리 정해진 Events, 그리고 그 이벤트를 감지하는 Event Listeners, 그리고 감지된 이벤트에 따라 특정 기능을 수행하는 Event Handlers가 있다.

이벤트의 유무는 시간축을 하나 더 제공하여, 기존의 정적이던 웹 페이지를 동적으로 바꿔준다고 볼 수 있겠다.

저번 Javascript DOM 포스팅 에서 보았듯, 시간축의 유무가 변화의 유무와 같기 때문이다.

ASP.NET의 event의 종류는 HTML DOM events를 생각하면 편하다.
HTML의 button과 같은 태그에 onclick같은 event handler이 기본적으로 쓰인다는 점, 자바스크립트의 custom event handler 함수를 넣을 수 있다는 점, onkeypress등으로 기본과 다른 handler을 쓸 수 있다는 점 등이 있다.
즉, ASP에는 control events라 하는 각 control 마다 기본적으로 많이 쓰이는 default event가 있다.
그리고, OnCommand라는 attribute를 사용할 시, 기존에 없는 이벤트 핸들러를 만들어 넣는 것도 가능하다.
특정 체크박스의 체크가 바뀌거나 텍스트가 바뀌는 것도 감지할 수 있으며, 마지막으로 기본적으로 쓰이는 defeault events외에도, 다른 attributes를 통해 event handlers를 넣을 수 있다.

이러한 control events는 AutoPostBack property를 true로 만드냐 false로 만드냐에 따라서 postback events로 만들지 non-postback events로 만들지 정할 수 있다.
postback이란 이벤트가 실행되면 바로 서버로 포스트가 되는 버튼 클릭과 같은 것이 있다.
non-postback은 바로 서버로 포스트 되지 않는 checkbox.CheckedChanged 나 TextChanged과 같은 것이 있다.

User Action에 의해 생기는 events외에도 application, session, 그리고 page가 진행되는 과정에서 생기는 events 또한 존재한다.

  • Application_Start
  • Application_End
  • Session_Start
  • Session_End
  • Data_Binding - control binds to a data source
  • Disposed - page or control is released
  • Error - unhandled exception is thrown
  • Init - page or control is initialized
  • Load - page or control is loaded
  • PreRender - page or control is rendered
  • Unload - page or control is unloaded from memory

C#이나 VB script로 만드는 실제 이벤트 핸들러의 구조는 ?

이벤트 핸들러의 구조: 
private void EventName (object sender, EventArgs e)

이벤트의 구조는 1) object raising the event, 2) event argument를 받아와 void를 return 하는 구조로 되어있다.

이 함수 안에는 어떤 태그의 텍스트를 바꾼다던가, 스타일을 바꾼다던가, 받아온 데이터를 토대로 백엔드와 상호작용 한다던가 등의 내용이 들어간다.


ASP.NET의 유저의 액션없는 대표적인 이벤트는 Page_Load 이벤트이다.

이름에서 알 수 있듯, event 자체가 유저의 액션 없이 실행되기에, object reference나 event arguments 가 없다!

<script runat="server">
Sub Page_Load
lbl1.Text="The date and time is " & now()
End Sub
</script>

<html>
<body>
<form runat="server">
<h3><asp:label id="lbl1" runat="server" /></h3>
</form>
</body>
</html>

Page에는 IsPostBack이라는 property가 존재하며, 이는 처음에 페이지가 로드될 때, 한번만 true를 반환한다.

<script runat="server">
Sub Page_Load
if Not Page.IsPostBack then
  lbl1.Text="The date and time is " & now()
end if
End Sub

Sub submit(s As Object, e As EventArgs)
lbl2.Text="Hello World!"
End Sub
</script>

<html>
<body>
<form runat="server">
<h3><asp:label id="lbl1" runat="server" /></h3>
<h3><asp:label id="lbl2" runat="server" /></h3>
<asp:button text="Submit" onclick="submit" runat="server" />
</form>
</body>
</html>

이렇게 위에서 다룬 서버 컨트롤들은 <form runat="server"> 태그 안에 등장해야한다.
그리고 이 <form runat="server"> 태그는 .aspx 페이지에서 한번만 등장해야한다!!

HTML의 form 태그랑 다르지 않기에, action attribute로 어디로 form-data를 보내줄지 정해주고, method attribute로 post request를 보낼지 get request를 보낼지 정해줄 수 있다.
만약, action attribute를 정해주지 않는다면, form-data는 자동으로 지금 페이지에 form-data를 보내고, method는 자동으로 post가 된다.
또한 .aspx 페이지에서 name과 id를 정해두지 않았을시, 이는 ASP.NET framework에 의해 자동으로 지정된다.

이렇게 정해진 name 과 id로 상호작용을 한다고 했을 때, 유저가 옳은 정보를 보낼 시에는 문제가 없으나, 잘못된 정보를 보냈다고 생각해보자.
ASP의 단점이라고 할 수 있는 각 request마다 page_load를 한다는 특징 때문에 사실상 form안에 유저가 기입한 내용들은 깜박거림 현상과 함께 사라져야 정상이다.
하지만 앞에서 설명한 것 과 같이, 이 깜박거림과 함께 사라지는 내용을 지키기 위해서, ASP.NET은 Hidden_State를 html에 넣어 보관한다.

그리고 이 Hidden_State를 이 상황에선 ViewState라고 부른다.
ViewState는 서버로 요청을 했을 시의 페이지의 상태를 나타낸다.
그리고 이 기능은 ASP.NET WebForm에서 그냥 처리해주는 것으로, 개발자가 따로 viewstate를 정해주거나 할 필요는 없다.
하지만 이는 당연하게도 성능의 저하로 이어지니, 개발자가 원한다면 그 페이지의 ViewState는 해제할 수가 있다.

해제를 원할 시, <%@ Page EnableViewState="false" %> 라는 디렉티브를 문서의 최상단에 놓으면 된다.  

Web Pages에서는 데이터를 import 할 때, .txt, .xml, .csv 포맷을 지닌 파일인 Flat files는 App_Data에 넣고 C#상의 함수인 File.ReadAllLines()를 이용해서 Array의 형태로 받았었다.

Web Form에서는 이렇게 받아온 데이터의 Collections를 몇몇 components의 요소로 쓸 수 있는 Data Binding이라는 것을 제공한다.

또한, XML 파일 같은 경우, 사용할 수 있는 Collection의 형태로 바꿔서 이용될 수 있도록 한다.

  • asp:RadioButtonList
  • asp:CheckBoxList
  • asp:DropDownList
  • asp:Listbox

이름에서로부터 알 수 있듯이, 리스트의 요소들을 보통은 하나하나 추가해줘야 하는 컴포넌트들이라는 사실을 알 수 있다.

하지만 Data Binding은 콜렉션 타입을 이용해 한번에 이를 채워줄 수 있다는 장점이 있다.


ArrayList는 하나의 데이터 타입으로 이루어진 collection object이다.
아이템을 넣기 위해서는 Add() 메소드를 쓰며, 이는 자바와 동일하다고 볼 수 있다.

기존 ArrayList와 동일하게 처음 initial size가 존재하며, Add()는 amortized constant time으로 사이즈를 일정 수준 증가시키며 아이템을 넣는, 다이나믹한 구조를 가지고 있다.
이렇게 쓸 데 없이 존재하는 빈 공간을 없애기 위해서, TrimToSize() 라는 메소드가 존재한다.
이는 맨 처음 사이즈 16으로 만들어진 ArrayList를 들어있는 엘러먼트의 양만큼의 사이즈로 줄여주는 것이다.
또한, Sort()나 Reverse()와 같은 자바에서는 Collections에 static 메소드로 존재할 법한 메소드도 따로 인스턴스 메소드로 존재한다.

VB script subroutine, ArrayList initialization
<script runat="server">
Sub Page_Load
...
dim arr = New ArrayList
arr.Add("Male")
arr.Add("Female")
arr.TrimToSize()
arr.Sort()
...
end sub
</script>

이렇게 만들어진 콜렉션은 데이터바인딩에 이용되는데, 이는 간편하게도 등의 id를 이용하고, 해당 컴포넌트의 DataSource property를 세팅해주고 DataBind() 메소드를 실행시킴으로써 데이터바인딩이 이루어지게 된다.

arr.Sort()
...
id.DataSource=arr
id.DataBind()
...
<form runat="server">
<asp:RadioButtonList id="id" runat="server">
</form>

하나 명심해야 할 점은 RadioButton의 Text가 곧 서버에게 넘어갈 Value라는 점이다.
이를 다르게 설정하고 싶을 경우엔 key-map associate을 쓰는 mapping을 쓰는 hashtable object를 써야한다.


Hashtable은 key/value의 pair로 이루어진 타입으로 이루어진 collection object이다.
아이템을 넣기 위해서는 Add() 메소드를 쓰며, 이는 자바의 put과 동일하다고 볼 수 있다.

이렇게 만들어진 콜렉션은 데이터바인딩에 이용되는데, 이는 간편하게도 등의 id를 이용하고, 해당 컴포넌트의 DataSource property를 세팅해주고 DataBind() 메소드를 실행시킴으로써 데이터바인딩이 이루어지게 된다.

<script runat="server">
sub Page_Load
if Not Page.IsPostBack then
  dim map=New Hashtable
  map.Add("N","Norway")
  map.Add("S","Sweden")
  map.Add("F","France")
  map.Add("I","Italy")
  id.DataSource=mycountries
  id.DataValueField="Key"
  id.DataTextField="Value"
  id.DataBind()
end if
end sub
</script>
...
sub routine(s as Object, e as EventArgs)
lbl1.text="result is " & id.SelectedItem.Text
end sub
...
<form runat="server">
<asp:RadioButtonList id="id" runat="server" AutoPostBack="True" onSelectedIndexChanged="routine" />
<asp:label id="lbl1" runat="server" />
</form>

하나 명심해야 할 점은 HashTable은 기존의 Hashmap과 동일하게 sort되어있지 않다는 것이다.
SortedList과 같은 Object를 쓰게 될 경우 정렬이 되어있는 리스트를 사용할 수 있다.


SortedList는 key/value의 pair로 이루어진 타입으로 이루어진 collection object이다.
SortedList는 키의 정렬을 유지하며, 이는 자바의 TreeMap과 유사하다.
아이템을 넣기 위해서는 Add() 메소드를 쓰며, 이는 자바의 put과 동일하다고 볼 수 있다.
하지만, ArrayList의 특징을 물려받았기에, 처음 initialization 시의 크기는 정해져 있고, 요소의 양만큼 사이즈를 줄이는 것 또한 TrimToSize()를 통해 가능하다.

이렇게 만들어진 콜렉션은 데이터바인딩에 이용되는데, 이는 간편하게도 등의 id를 이용하고, 해당 컴포넌트의 DataSource property를 세팅해주고 DataBind() 메소드를 실행시킴으로써 데이터바인딩이 이루어지게 된다.

그리고 이 방법은 HashTable과 완전히 동일하다.


XML 파일은 HTML과 비슷한 태그를 이용해 문서의 속성 혹은 규칙을 정의하는 파일이라 생각하면 된다.
그리고 당연하게도 이런 속성이 들어있는 오브젝트의 콜렉션 형태도 가능하다. 왜냐하면 같은 태그가 쓰이기 때문이다.
이러한 DataSet 오브젝트는 System.Data라는 namespace를 import 할 시 사용할 수 있게 된다.
aspx의 razor syntax를 이용할 시, 다음과 같이 import 할 수 있다.

<% Import Namespace="System.Data" %>

그리고, XML파일은 DataSet의 오브젝트로 load 될 수 있다. 이 때, ReadXml()이라는 메소드가 사용된다.

이렇게 만들어진 콜렉션은 데이터바인딩에 이용되는데, 이는 간편하게도 등의 id를 이용하고, 해당 컴포넌트의 DataSource property를 세팅해주고 DataBind() 메소드를 실행시킴으로써 데이터바인딩이 이루어지게 된다.

<script runat="server">
sub Page_Load
if not Page.isPostBack then
   dim xml = New Dataset
   xml.ReadXml(MapPath("cars.xml"))
   id.DataSource=xml
   id.DataValueField="value"
   id.DataTextField="text"
   id.DataBind()   
end if
end sub
</script>

이런 식으로 asp:RadioButtonList, asp:CheckBoxList, asp:DropDownList, asp:Listbox 같은 컨트롤러에 데이터가 요소로써 이용될 수도 있겠지만, 사실 데이터 베이스나 데이터 테이블을 들고 오는 경우에는 테이블의 요소로 쓰인다던가 하는 경우도 있을 것이다.

이는 jsp에서의 doTag()와 비슷하다.
JSP에서는 데이터베이스에서 데이터를 콜렉션 형태로 받을 시에, 각각 데이터를 iterate하며 getJspContext().setAttribute() 를 통해 jsp파일에서 쓰일 수 있는 attribute를 설정해 줄 수 있고, 각 요소마다 getJspBody.invoke()를 해줌으로써 여러개의 요소들이 각각 표현될 수 있는것이다.

<temp:list query="${sent-attribute}">
<tr><td>${attribute1}</td><td>${attribute2}</td></tr>
</temp:list>

위와 같은 xml태그를 이용할 시에, *.tld라는 tag library descriptor이라는 파일에 xml 파일이 어떠한 서블릿을 이용하는지를 구성해줘야하며, 서블릿 내부에서의 invoke()를 통해 attribute1, attribute2가 날아올 때마다, 요소가 추가된다는 사실을 알 수 있다.

asp에선 xml파일을 컬렉션 형태로 받는 법은 이전 섹션에서 배웠다.
System.Data라는 namespace를 import 해준 뒤, page_load 이벤트 시에, ReadXml()을 통해 New DataSet의 인스턴스를 만드는것이다.

그럼 이렇게 컬렉션의 형태로 있는 xml 파일을 DataSet이라는 오브젝트로 얻을 수 있는데, 그렇게 얻어진 오브젝트를 Repeater이라는 asp control에 이용 하기만 하면 된다.
바로 Repeater control의 id의 DataSource로 지정하고, DataBind()를 해주면 된다.

Control이라고 했으니, 당연히 기존 asp control의 모양새를 따른다.
이 컨트롤의 특징은 HeaderTemplate, ItemTemplate, FooterTemplate으로 이루어져 있다는 점이며,
HeaderTemplate, FooterTemplate은 ItemTemplate 이전, 이후에 한번 실행된다.
ItemTemplate은 record 하나 당 repeat 된다는 특성을 가지고 있어, 테이블을 예시로 들 경우, Header에서 table 해더 태그를 셋업해주고, Item에서 tr 태그의 아이템을 넣어주고, Footer에서 태그를 닫아주는 형태로 생각 할 수 있다.
이 기본적인 형태에서 이나 을 ItemTemplate 과 FooterTemplate 사이에 넣어 줄 수 있는데, 이름에서 알 수 있듯, 한번씩 번갈아 가면서 나올 item, 그리고 매번 아이템 이후에 자동적으로 넣어줄 separator을 정해주는 템플릿이다.

<form runat="server">
...
<asp:Repeater id="id" runat="server">

<HeaderTemplate> ... </HeaderTemplate>
<ItemTemplate> 
...
<td> <%#Container.DataItem("fieldname")%></td>
...
</ItemTemplate>
<FooterTemplate> ... </FooterTemplate>

</asp:Repeater>
...
</form>

Repeater를 테이블의 형태안에 넣어준다고 할 때 <table>, <tr>, <td> 등 반복적으로 써야 하는 태그들이 있는데, 이걸 테이블용으로 따로 컨트롤로 만든 것이 있는데 이를 DataList라고 한다.

DataList의 구조는 완벽히 Repeater과 동일하다.
하지만 그저 테이블의 태그 부분만 뺀 것이다.


ASP.NET framework에는 ADO.NET이라는 데이터베이스를 이용하는데 도움이 되는 것이 있다. 이에서도 데이터베이스에서 데이터를 액세스 하는 것은 모든 데이터베이스와 동일한 과정으로 진행된다.

처음에는 데이터베이스와 연결을 해야하고, 이를 위해 SQL 데이터베이스의 드라이버를 import 해줘야 한다.

<%@ Import Namespace="System.Data.OleDb" %>

<script runat="server">
sub Page_Load
dim dbconn
dbconn=New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;
data source=" & server.mappath("northwind.mdb"))
dbconn.Open()
end sub
</script>

위 예제에서는 OleDb라는 드라이버를 이용, dbconn이라는 connection object를 만들어 냈다. 이 connection은 connection string을 통해 sql 쿼리를 받아들이는 하나의 인스턴스가 된 것이며, DB가 켜져있는 동안은 유효하다.

이렇게 dbconn을 open 한 뒤에는, query string을 넣어주고, execute를 진행하면 된다.

그리고 이렇게 받아온 query의 결과는 DataSet과 동등하게 이용될 수 있다.
Repeater, DataList과 같은 Control의 아이디를 이용, DataSource를 db result로 정하고, DataBind()를 진행해 후에 ItemTemplate 에서 Container.DataItem() 메소드를 통해 출력할 수 있게 되는 것이다.

<%@ Import Namespace="System.Data.OleDb" %>

<script runat="server">
sub Page_Load
dim dbconn,sql,dbcomm,dbread
dbconn=New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;
data source=" & server.mappath("northwind.mdb"))
dbconn.Open()
sql="SELECT * FROM customers"
dbcomm=New OleDbCommand(sql,dbconn)
dbread=dbcomm.ExecuteReader()

customers.DataSource=dbread
customers.DataBind()

dbread.Close()
dbconn.Close()
end sub
</script>

하나의 웹 프로젝트를 진행할 때, 웹 사이트의 웹 페이지들에게서 중요한 특징 중 하나는 통일성 이여야 한다.

이 통일성을 위해서, 레이 아웃을 짜고, header, footer등을 태그 디렉티브를 통해 들고 오는 등, 각각 프레임워크들은 여러가지 방식으로 통일성을 유지한다.

ASP.NET 웹 폼에서의 레이아웃은 Master Page라는 것을 통해 쉽게 구현가능하다.
이는 웹 폼으로 프로젝트를 만들 시에, 기본으로 제공되어 있는 Site.Master 파일 또는 Site.Mobile.Master이 그 역할을 해준다.

Master Page는 *.Master이라는 확장자를 가진다.
하지만 들어있는 컨텐츠의 문법 자체는 정확히 *.aspx의 그것과 동일하다.
(html에 asp control, in-line server script, 그리고 VB script를 끼얹은 형태이다.)

Master page의 독특한 특징이라고 할 수 있는 것은 첫번째로, @ Master directive를 첫 줄에 정의해야 한다는 것이다.

<%@ Master %>
외에도 추가적인 attribute를 정의할 수 있다.  

또한, 레이아웃 정해놓고 지정된 위치에 다른 컨텐츠 내용을 다른 aspx파일에서 받아오는 형태이므로, ContentPlaceHolder이라는 Placeholder tag를 사용한다.
이는 웹 서버 컨트롤과 조금 다른게, form의 내부에 있을 필요도 없고, 독자적으로 html의 한 부분을 자리하고 있는 “태그”이다.

<%@ Master %>

<html>
<body>
<h1>Standard Header From Masterpage</h1>
<asp:ContentPlaceHolder id="CPH1" runat="server">
</asp:ContentPlaceHolder>
</body>
</html>

이렇게 레이아웃이 생성 되면, Content Page는 그 레이아웃에 컨텐츠를 넣어 줄 수가 있게 된다.
Content page의 독특한 특징은 첫 줄에 @ Page directive를 정의해야 한다는 점이다.
그리고 이 @ Page directive는 MasterPageFile을 정의함으로써, 레이아웃을 이용할 수 있게 된다.

<%@ Page MasterPageFile="master1.master" %>

또한, 정해진 레이아웃의 지정된 위치에 이 파일에 정해진 컨텐츠 내용을 넣는 형태이므로, Content라는 tag를 사용한다.
이 때, Content tag에는 ContentPlaceHolderId 라는 reference attribute가 필요하다. 어느 위치에 들어가는지 정의해야 하기 때문이다.
이 태그 또한 웹 서버 컨트롤과 조금 다른게, form의 내부에 있을 필요도 없고, 독자적으로 html의 한 부분을 자리하고 있는 “태그”이다.
내부 컨텐츠는 기존의 aspx와 동일하며, Form tag 내부의 Web Server Controls 또한 이용 가능하다.

<%@ Page MasterPageFile="master1.master" %>

<asp:Content ContentPlaceHolderId="CPH1" runat="server">
  <h2>Individual Content</h2>
  <p>Paragraph 1</p>
  <p>Paragraph 2</p>
</asp:Content>