ASP.NET Chart Control

ASP.NET Chart 컨트롤은 닷넷 프레임워크 안의 데이터 시각화를 확장하여 제공했습니다. Chart 컨트롤을 사용하면서, 당신은 쉽게 차트가 있는 ASP.NET 페이지들을 생성할 수 있습니다. 그차트는 복집한 통계 혹은 재무적 분석을 위하여, 직관적이고 시각적으로 강력한 차트입니다. ASP.NET 차트 컨트롤은 닷넷 프레임워크 3.5 SP1 배포에서 추가되어 소개되었습니다. 그리고 그것은 닷넷 프레임워크 4.0 배포의 일부가 될 것입니다.

차트 컨트롤의 주요 특징은 다음과 같습니다:

  • 35 개의 서로 다른 차트 유형.
  • 제한 없는 차트 범위, 제목, 설명 그리고 주석.
  • 모든 차트 요소들을 위한 아주 다양한 표현 설정.
  • 대부분의 차트 유형들에 지원하는 3-D.
  • 데이터 포인트 주변에 자동적으로 들어 맞는 스마트 데이터 레이블
  • 선 제거, 눈금 생략, 대수의 눈금.
  • 데이터 분석과 가공을 위한 50개 이상의 재무적, 통계적 공식.
  • 간단한 바인딩과 차트 데이터의 조작.
  • 날짜, 시간, 통화 같은 공통 데이터 양식을 위한 지원.
  • AJA를 사용하는 클라이언트 클릭 이벤트를 포함하면서, 상호작용과 이벤트 중심의 커스터마이즈 지원.
  • 상태 관리.
  • 이진 문자열.

다음의 표들은 ASP.NET 차트 컨트롤에 의하여 생성된 재무 차트의 예를 보여줍니다.

Figure 2: ASP.NET 차트 컨트롤의 예들

ASP.NET 차트 컨트롤을 사용하는 법의 더 많은 예를 위하여, MSDN의 웹사이트에서 다음의  Samples Environment for Microsoft Chart Controls 샘플 코드를 다운로드 하세요. 당신은 Chart Control Forum 에서 커뮤니티 내용에서 더 많은 예를 찾을 수 있습니다.

Adding the Chart Control to an ASP.NET Page

다음의 예는 마크업을 사용하여 ASP.NET 페이지에 Chart 컨트롤을 추가하는 법을 보여줍니다. 예를 들어, Chart 컨트롤은 정적 데이터 포인트를 위하여 컬럼 차트를 생성합니다.

 
<asp:Chart ID="Chart1" runat="server"> <Series> <asp:Series Name="Series1" ChartType="Column"> <Points> <asp:DataPoint AxisLabel="Product A" YValues="345"/> <asp:DataPoint AxisLabel="Product B" YValues="456"/> <asp:DataPoint AxisLabel="Product C" YValues="125"/> <asp:DataPoint AxisLabel="Product D" YValues="957"/> </Points> </asp:Series> </Series> <ChartAreas> <asp:ChartArea Name="ChartArea1"> <AxisY IsLogarithmic="True" /> </asp:ChartArea> </ChartAreas> <Legends> <asp:Legend Name="Legend1" Title="Product Sales" /> </Legends> </asp:Chart>

 

Using 3-D Charts

Chart 컨트롤은 ChartAreas 콜렉션을 포함합니다. 그것은 차트 영역의 특성을 정의 하는 ChartArea 객체를 포함 할 수 있습니다. 예를 들어, 차트 영역을 위하여 3-D를 사용하고, 다음의 예에서 처럼 Area3DStyle 속성을 사용합니다: 

 
<asp:ChartArea Name="ChartArea1"> <area3dstyle Rotation="10" Perspective="10" Enable3D="True" Inclination="15" IsRightAngleAxes="False" WallWidth="0" IsClustered="False" /> <%-- Additional markup here --%> </asp:ChartArea>
 

아래의 표는 Bar 차트 유형의 4개의 시리즈와 함께 3-D 차트를 보여줍니다.

Figure 3: 3-D Bar Chart

 

Using Scale Breaks and Logarithmic Scales

눈금 생략과 대수의 눈금은 차트에 세련미를 더하는 두가지 차가적인 방법이 있습니다. 이 특징들은 차트 영역에서 각각의 축에 명시합니다. 예를 들어, 차트 영역의 첫번째 Y 축에 이 특성을 사용하려면, ChartArea 객체안의 AxisY.IsLogarithmicScaleBreakStyle 속성을 사용하세요. 다음의 코드 조각은 첫번째 Y 축상에서 눈금 생략을 사용하는 법을 보여줍니다.
 

<asp:ChartArea Name="ChartArea1"> <axisy> <ScaleBreakStyle BreakLineStyle="Wave" CollapsibleSpaceThreshold="40" Enabled="True" /> </axisy> <%-- Additional markup here --%> </asp:ChartArea>







아래의 표는 눈금 생략을 활성화시켜 Y축을 보여줍니다.



Figure 4
: Scale Breaks

데이터 기반 웹페이지를 만드는 개발자들에게 데이터를 필터링은 아주 일반적인 작업입니다. 이것은 전통적으로 데이터 소스 컨트롤 안의 where 구문을 빌드하는 것에 의하여 처리되었습니다. 이 접근은 복잡하게 될 수 있고, 어떤 경우에는 where 문법이 기초 데이터의 모든 기능에 불이익을 주기도 합니다. 더 쉽게 필터링 하기 위하여, 새로운 QueryExtender 컨트롤이 ASP.NET 4에서 추가 되었습니다. 이 콘트롤들에 의하여 반환된 데이터를 필터링 하기 위하여, QueryExtenderEntityDataSource 혹은 LinqDataSource 에 추가 되었습니다. QueryExtender 는 LINQ에 의존하기 때문에, 그 필터는 데이터가 페이지에 보내지기 전에 데이터베이스 서버에 제공됩니다. 그 결과 아주 효율적인 처리가 이루어집니다. QueryExtender 컨트롤은 다양한 필터 옵션들을 제공합니다. 다음의 섹션은 이 옵션들을 설명하고, 그 사용법의 예시를 제공합니다.

Search

검색 옵션을 위하여, QueryExtender  컨트롤은 지정된 필드 안의 레코드들을 찾기위하여, 텍스트 검색을 사용합니다. 다음의 예에서, 이 컨트롤은 TextBoxSearch 컨트돌 안에 들어가는 텍스트를 사용합니다. 그리고 LinqDataSource 컨트롤로 부터 반환된 데이터의 ProductNameSupplier.CompanyName 컬럼 안의 내용에서 검색을 합니다.

<asp:LinqDataSource ID="dataSource" runat="server"> TableName="Products">
</asp:LinqDataSource>
<asp:QueryExtender TargetControlID="dataSource" runat="server">
  <asp:SearchExpression DataFields="ProductName, Supplier.CompanyName"
      SearchType="StartsWith">
    <asp:ControlParameter ControlID="TextBoxSearch" />
  </asp:SearchExpression>
</asp:QueryExtender>
 

Range

범위 옵션은 검색 옵션과 비슷합니다. 그러나 범위를 정의하기 위하여 한 쌍의 값을 지정합니다. 다음의 예에서, QueryExtender 컨트롤은 LinqDataSource 컨트롤로 부터 반환된 데이터 안의 UnitPrice 컬럼을 검색합니다. 범위는 페이지의 TextBoxFrom 과 TextBoxTo  컨트롤에서 읽어옵니다.

 
<asp:LinqDataSource ID="dataSource" runat="server"> TableName="Products"> </asp:LinqDataSource> <asp:QueryExtender TargetControlID="dataSource" runat="server"> <asp:RangeExpression DataField="UnitPrice" MinType="Inclusive" MaxType="Inclusive"> <asp:ControlParameter ControlID="TextBoxFrom" /> <asp:ControlParameter ControlID="TexBoxTo" /> </asp:RangeExpression> </asp:QueryExtender>

 

PropertyExpression

PropertyExpression 옵션은 속성값에 비교를 정의 할 수 있도록 합니다. PropertyExpression이 참이라면, 설명된 데이터가 반환 됩니다. 다음의 예에서, QueryExtender 컨트롤은 페이지의 CheckBoxDiscontinued 컨트롤의 값으로 Discontinued 컬럼의 데이터를 비교하여 필터링합니다.

 
<asp:LinqDataSource ID="dataSource" runat="server" TableName="Products"> </asp:LinqDataSource> <asp:QueryExtender TargetControlID="dataSource" runat="server"> <asp:PropertyExpression> <asp:ControlParameter ControlID="CheckBoxDiscontinued" Name="Discontinued" /> </asp:PropertyExpression> </asp:QueryExtender>

CustomExpression

마지막으로, QueryExtender 컨트롤에서 사용하는 CustomExpression을 설명합니다. 이 옵션은 사용자 정의 필터 로직을 정의하는 페이지 안의 함수를 호출 할 수 있게 합니다. 다음의 예는 QueryExtender 컨트롤 안의 사용자 정의 표현식을 선언적으로 지정하는 법을 보여줍니다.

 
<asp:LinqDataSource ID="dataSource" runat="server" TableName="Products"> </asp:LinqDataSource> <asp:QueryExtender TargetControlID="dataSource" runat="server"> <asp:CustomExpression OnQuerying="FilterProducts" /> </asp:QueryExtender>
 

다음의 예는 QueryExtender 컨트롤에 호출된 사용자 정의 함수를 보여줍니다. 이 경우에, Where 구문을 포함한 데이터베이스 쿼리를 사용하는 것 대신에, 이 코드는 데이터를 필터링 하기 위하여 LINQ 쿼리를 사용하였습니다.

 
protected void FilterProducts(object sender, CustomExpressionEventArgs e) { e.Query = from p in e.Query.Cast<Product>() where p.UnitPrice >= 10 select p; }

이 예는 QueryExtender 컨트롤에서 사용되고 있는 단지 하나의 표현을 한 번에 보여준 것입니다. 그러나, QueryExtender 컨트롤 내부에 다양한 표현식을 사용하는 것도 가능합니다.

 



Setting Client IDs

  ASP.NET 4.0의 새로 생긴 ClientIDMode 속성은, ASP.NET에서 컨트롤 ID의 네이미을 결정합니다. 랜더링된 HTML 요소의 ID속성을 자바스크립트에서 랜더링된 HTML을 ID 로 참조하기 위해 꼭 필요합니다.
  기존의 서버 컨트롤은 ClientID 속성을 통해 HTML 요소이 id를 생성하였습니다. 기존의 알고리즘은 컨테이너 기반으로 순차적으로 HTML 요소의 id를 생성하였고, 데이터그리드 같은 컨트롤은 기존ClientID+순번을 추가하여 랜더링 하였습니다. 그래야 HTML 페이지에서 ID 가 유일하다는 보장을 할 수 있었죠. 이런 문제로 컨트롤ID는 매우 복잡해져서 클라이언트 스크립트에서 HTML요소로 접근하기 매우 까다로웠습니다.

  새로운 ClientIDMode 속성은 당신이  클라이언트 ID가 컨트롤을 위하여 어떻게 발생될지를 더 정확하게 지정 할수 있게합니다.당신은 어떤 컨트롤을 위하여 ClientIDMode  속성을 해당 페이지에서 설정이 가능합니다. 가능한 설정들은 다음과 같습니다:

  • AutoID — 이것은 ASP.NET 초기 버전에서와 같이 ClientID  속성 값을 발생하는 알로리즘과 같습니다.
  • Static — 이것은 ClientID 값이 ID와 같게 지정합니다. 단 상위에서 지명하는 컨테이너들 중에 ID들을 연관짓는 것이 없을 경우입니다.
  • Predictable — 이 옵션은 본래 반복적인 템플릿을 사용하는 데이터 컨트롤 안에서의 사용을 위한 것입니다. 그것은 컨트롤의 이름있는 컨테이너의 ID 속성과 연관을 맺습니다. 그러나  ClientID 값은 "ctlxxx"와 같은 문자열은 포함하지 않습니다. 이 설정은 컨트롤의 ClientIDRowSuffix 속성과 연계하여 동작합니다.  당신은 데이터 필드의 이름으로 ClientIDRowSuffix  속성을 설정합니다. 그리고 그 필드의 값은 발생된 ClientID  위한 접미사로 사용됩니다.
  • Inherit — 이 설정은 컨트롤들을 위한 기본 속성입니다. 그리고 그것은 컨트롤ID 발생이 상위의 것과 같게 지정합니다.

  ASP.NET 4.0에서는 Page 지시자를 통해 ClientIDMode 속성을 설정할 수 있습니다. 이 속성을 통해 페이지의 모든 컨트롤의 랜더링 방식의 기본값을 설정할 수 있습니다.

  Page의 ClientIDModel의 기본값은 AutoID이며, 컨트롤 측면에서는 ClientIDMode 의 기본값은 Inherit입니다. 그래서 이 속성을 굳이 설정하지 않으면 AutoID 가 기본값이 됩니다.

 @ Page 지시문 안에서 페이지 레벨상의 값을 설정 할 수 있습니다. 다음의 예를 보세요:

<%@ Page Language="C#" AutoEventWireup="true"
  CodeFile="Default.aspx.cs"
  Inherits="_Default"
  ClientIDMode="Predictable" %>

당신은 또한 머신 레빌 혹은 어플리케이션 레벨의 구성 파일안에서 ClientIDMode 값을 설정 할 수 있습니다. 이것은 어플리케이션 상에서 모든 페이지의 코든 컨트롤들의 ClientIDMode 의 기본값을 설정을 정의합니다. 당신의 머신 레빌에서 값을 설정한다면, 그것은 그 컴퓨터의 모든 웹사이트의 ClientIDMode 값을 기본 설정합니다. 다음의 예는 구성 파일에서 ClientIDMode 를 설정하는 것을 보여드립니다:

<system.web>
  <pages clientIDMode="Predictable"></pages>
</system.web>

앞에 예제를 보면, ClientID 속성의 값은 컨트롤 상위의 네이밍 컨테이너로 부터 상속을 받습니다.어떤 시나리오에서
당신이 마스터 페이지를 사용하고 있는 상황이라면, 컨트롤들은 다음의 렌더링된 HTML 안의 그것들 처럼 ID와 함께 끝날
것입니다:

 

<div id="ctl00_ContentPlaceHolder1_ParentPanel">
<div id="ctl00_ContentPlaceHolder1_ParentPanel_NamingPanel1">
<input name="ctl00$ContentPlaceHolder1$ParentPanel$NamingPanel1$TextBox1" type="text" value="Hello!"       id="ctl00_ContentPlaceHolder1_ParentPanel_NamingPanel1_TextBox1" />
</div>
</div>

비록 마크업 안에서 보여진 (TextBox 컨트롤로 부터) input 요소가 (내포된 ContentPlaceholder  컨트롤들)페이지 깊숙한 곳에
단지 두 개의 네이밍 컨트롤이 있더라도, 마스터 페이지가 처리되는 방식 때문에, 마지막 결과물은 다음과 같은 컨트롤
아이디입니다.


ctl00_ContentPlaceHolder1_ParentPanel_NamingPanel1_TextBox1
 
이것은 긴 아이디입니다. 그것은 페이지 안에서 유니크한 것을 보장합니다. 그러나 대부분의 목적에는 불필요하게 깁니다.
생각해보라 당신이 랜더링된 아이디의 길이를 줄이기 원하고, 아이디가 어떻게 발생하는지를 더 말하기 원한다면...(예를들어, 당신은 앞에 붙은 'ctlxxx' 제거하기 원합니다.) 이것을 해결하는 가장 쉬운 방법은 다음의 예처럼 ClientIDMode 속성을 설정하는 것입니다:
<tc:NamingPanel runat="server" ID="ParentPanel" ClientIDMode="Static">  
<tc:NamingPanel runat="server" ID="NamingPanel1" ClientIDMode="Predictable">    
<asp:TextBox ID="TextBox1" runat="server" Text="Hello!"></asp:TextBox>  
</tc:NamingPanel>
</tc:NamingPanel>

   
   이 샘플에서 ClientIDMode 속성은 가장 바깥쪽에 있는 NamingPanel  요소를 위하여 Static 으로 설정하였습니다. 그리고 내부의 NamingControl  요소를 위하여 Predictable 으로 설정하였습니다. 이 설정은 다음의 마크업 같은 결과를 만듭니다.(나머지 페이지와 마스터 페이지는 이전의 예처럼 같게 되는 것을 취하게 됩니다. )

<div id="ParentPanel">
  <div id="ParentPanel_NamingPanel1">
    <input name="ctl00$ContentPlaceHolder1$ParentPanel$NamingPanel1$TextBox1"
      type="text" value="Hello!" id="ParentPanel_NamingPanel1_TextBox1" />
  </div>

 
   Static
설정은 가장 바깥 쪽의 NamingPanel 요소 안의 어떤 컨트롤들을 위한 네이밍 계층을 리셋하는 효과를 같고, 발생된 아이디로 부터 ContentPlaceHolderMasterPage 아이디의 제거를 합니다. (랜더링된 요소의 name 속성은 영향받지 않는다. 그 결과 정상적은 ASP.NET 기능은 이벤트, 뷰 스테이드 등을 유지하게 됨을 기억해라. ) 네이밍 계층을 리셋하는 멋진 부수 효과는 당신이 만약 다른 ContentPlaceholder 컨트롤로 NamingPanel  요소를 마크업을 이동하더라도, 랜더링된 클라이언트 아이디는 같게 남습니다.

   Note:  랜더링된 컨트롤 아이디들이 유니크한 것을 확실히 하는 것은 당신에게 달려 있습니다. 그것들이 유니크 하지 않다면, 그것은 개별적인 HTML 요소들을 위한 유니크 아이디들을 요구하는 기능이 깨질 수 있습니다. 예를들면 클라이언트의 document.getElementById  함수같은 것입니다.

 

Creating Predictable Client IDs in Data-Bound Controls

    레거시 알고리즘에 의한 데이터 바운드 리스트 컨트롤안의 컨트롤들이 발생 될 때의 ClientID 값은 길고 전혀 예상하지 못하게 될 수 있습니다. ClientIDMode 기능은 이 아이디들이 어떻게 발생되는지를 넘어서 당신이 더 많은 컨트롤을 같는데 도움을 줍니다.  ListView 컨트롤을 포함한 다음의 마크업을 보세요:

<asp:ListView ID="ListView1" runat="server" DataSourceID="SqlDataSource1"
    OnSelectedIndexChanged="ListView1_SelectedIndexChanged"
    ClientIDMode="Predictable"
    RowClientIDRowSuffix="ProductID">
</asp:ListView>


이전의 예에서 ClientIDModeRowClientIDRowSuffix 속성은 마크업 안에 설정이 됩니다. ClientIDRowSuffix 속성은 단지 데이터 바운드 컨트롤들 안에서 사용될 수 있습니다. 그리고 그것의 수행은 당신이 사용하는 컨트롤에 의존적이지 않게 합니다. 차이점은 이것들입니다:

  • GridView control —  당신은 데이터 소스 안에 하나 혹은 더 많은 컬럼들의 이름을 명기 할 수 있습니다.그리고 그것들은 클라이언트 아이디들을 창조하는 실행 시간에 조합이 됩니다. 예를들어 당신이 RowClientIDRowSuffix 를  "ProductName, ProductId"로 설정한다면, 랜더링된 요소들을 위한 클라이언트 아이디들은 다음과 같은 형식을 가질 것입니다:
 rootPanel_GridView1_ProductNameLabel_Chai_1
  • ListView control — 당신은 클라이언트 아이디에 덧붙여진 데이터 소스안의 한 컬럼을 명시 할 수 있습니다. 예를 들어, 당신이 ClientIDRowSuffix 속성을 "ProductName"으로 설정한다면, 랜더링된 컨트롤들의 아이디들은 다음과 같은 형식을 가질 것입니다:
 rootPanel_ListView1_ProductNameLabel_1


이 경우에, 1의 흔적은 현재 데이터 아이템의 product ID로 부터 상속을 받습니다.

  • Repeater control —  이 컨트롤은 ClientIDRowSuffix 속성을 지원하지 않습니다.  Repeater 컨트롤에서 현재 행의 인덱스가 사용되었습니다. 당신이  Repeater  컨트롤에서  ClientIDMode="Predictable" 를 사용 했을 때, 클라이언트 아이디들은 다음의 형식으로 발생 될 것입니다:
Repeater1_ProductNameLabel_0


0의 흔적은 현재 행의 인덱스 입니다. FormViewDetailsView 컨트롤들은 다중 행을 보여주지 않습니다. 그래서 그것들은 ClientIDRowSuffix 지원하지 않습니다.

Persisting Row Selection in Data Controls


   GridView
ListView 컨트롤들은 사람들에게 행을 선택하게 할 수 있습니다. 이전의 ASP.NET 버전에서, 선택은 페이지 상의 행 인덱스에 기반하였습니다.  예를 들어, 당신이 페이지 1의 세번째 아이템을 선택하고, 페이지 2로 넘어가면, 두번째 페이지의 세번째 아이템이 선택됩니다.  지속된 선택은 .NET Framework 3.5 SP1의 동적 데이터 프로젝트안에서만 초기에 지원이 되었던 새로운 특성입니다. 이 특성을 활성화 했을 때, 현재 선택된 아이템은 그것들을 위한 데이터키에 기반합니다. 이것이 의미하는 것은 당산이 1 페이지의 세번째 행을 클릭한 다음 2 페이지로 이동하더라도 2 페이지에는 어떤 것도 선택된 것이 없습니다. 당신이 1 페이지로 돌아 갔을 때, 세번째 행이 여전히 선택되어 집니다.

   이 것은 초기 ASP.NET 버전에서의 수행 보다 훨신 더 자연스러운 선택 방법입니다. 지속된 선택은 지금 EnablePersistedSelection 속성을 사용하는 모든 프로젝트 상의 GridViewListView 에 지원이 됩니다. 다음의 예를 보세요.

<asp:GridView id="GridView2" runat="server" EnablePersistedSelection="true">
</asp:GridView>

Routing in ASP.NET 4

ASP.NET 4 는 웹폼에서 라우팅하는 것을 사용하기 위한 지원이 추가로 내장되었습니다. 라우팅은 당신이 요청한  URL 들을 받아들이기위한 어플리케이션을 확인하게 합니다. 그 URL들은 물리적 파일경로를 보여주지 않습니다. 대신에, 당신은 사용자들에게 의미있고, 당신의 어플리케이션을 위한 검색엔진 옵티마이저에 도움을 줄 수 있는 URL로 정의하여 라우팅을 사용 할 수 있습니다. 예를들어,  존재하고 있는 어플리케이션안에서 제품 종류를 보여주는 페이지를 위한 URL은 다음의 예와 같이 보여 줄 수 있습니다.

http://website/products.aspx?categoryid=12

라우팅을 사용사면, 당신은 같은 정보를 랜더링하기 위하여 다음의 URL을 받아들이기 위하여 어플리케이션을 확인 할 수 있습니다.

http://website/products/software

라우팅은 ASP.NET 3.5 SP1 에서 사용이 가능했습니다. (ASP.NET 3.5 SP1 에서 라우팅을 사용하는 방법에 대한 예는, Phil Haack의 블로그의 Using Routing With WebForms 에 들어가 보세요) 그러나, ASP.NET 4은 라우팅을 사용하기 더 쉽게 만들어진 다음의 몇가지 특징이 있습니다.

  • PageRouteHandler  클래스는 당신이 경로를 정의할 때 사용하는 간단한 HTTP 핸들러입니다.
  • HttpRequest.RequestContext  과Page.RouteData(HttpRequest.RequestContext.RouteData 객체를 위한 대리의 것) 새로운 속성. 이 속성들은 경로로 부터 통과되었을 때의 정보에 접근을 더 쉽게 합니다.
  • System.Web.Compilation.RouteUrlExpressionBuilderSystem.Web.Compilation.RouteValueExpressionBuilder 안에 정의된 다음의 새로운 표현의 빌더들
    • RouteUrl 은 ASP.NET 서버 컨트롤에서 경로 URL 형식에 일치하는 URL을 창조하는 간단한 방법을 제공한다.
    • RouteValue RouteContext 객체로 부터 정보를 추출하여 간단한 방법으로 제공한다.
  • RouteParameter 클래스는 데이터 소스 컨트롤을 위한 쿼리에서 RouteContext 객체안에 포함된 데이터를 넘기기 쉽게 합니다.(FormParameter 에서 유사하다).

 

Routing for Web Forms Pages

다음의 예는 Route 클래스의 새로운 MapPageRoute  매소드를 사용하는 것에 의하여 웹폼 라우트를 정의하는 법을 보여줍니다:

public class Global : System.Web.HttpApplication
{
  void Application_Start(object sender, EventArgs e)
  {
    RouteTable.Routes.MapPageRoute("SearchRoute",
      "search/{searchterm}", "~/search.aspx");
    RouteTable.Routes.MapPageRoute("UserRoute",
      "users/{username}", "~/users.aspx");
  }
}

ASP.NET 4 는 MapPageRoute 매소드를 소개합니다. 다음의 예는 이전의 예에서 보여준 SearchRoute 정의와 같습니다. 그러나 PageRouteHandler 클래스를 사용합니다. 

RouteTable.Routes.Add("SearchRoute", new Route("search/{searchterm}",
  new PageRouteHandler("~/search.aspx")));

예시 코드는 물리적 페이지에서 경로는 보여줍니다(첫번째 라우트안에서, ~/search.aspx 로). 첫번째 라우트 정의는 또한 searchterm 이라고 이름지어진 파라미터는 URL로 부터 추출 되어지고, 페이지로 넘겨지게 되는 것을 명시합니다.

MapPageRoute 매소드는 다음의 매소드 오버로드를 지원합니다:

  • MapPageRoute(string routeName, string routeUrl, string physicalFile, bool checkPhysicalUrlAccess)
  • MapPageRoute(string routeName, string routeUrl, string physicalFile, bool checkPhysicalUrlAccess, RouteValueDictionary defaults)
  • MapPageRoute(string routeName, string routeUrl, string physicalFile, bool checkPhysicalUrlAccess, RouteValueDictionary defaults, RouteValueDictionary constraints)

checkPhysicalUrlAccess 파라미터는 다음을 명시합니다. 그것은 라우트된 물리적 페이지(이 때는 search.aspx)를 위한 보안 승인과 들어오는 URL(이 때는 search/{searchterm})의 승인을 체크해야 되는지입니다. checkPhysicalUrlAccess 의 값이 false 라면, 단지 들어오는 URL의 승인만 체크 될 것입니다. 이 승인은 다음과 같은 설정으로 Web.config 파일안에서 정의 됩니다.

<configuration>
  <location path="search.aspx">
    <system.web>
      <authorization>
        <allow roles="admin"/>
        <deny users="*"/>
      </authorization>
    </system.web>
  </location>
  <location path="search">
    <system.web>
      <authorization>
        <allow users="*"/>
      </authorization>
    </system.web>
  </location>
</configuration>
 

예시의환경설정에서, admin권한을 가진 사람들을 제외하고 모든 사용자들은 물리적 페이지 search.aspx 에 접근이
거부됩니다.
checkPhysicalUrlAccess 파라미터가 true (기본 값)로 설정 되었을 때, 단지 admin 사용자가 URL /search/{searchterm} 에 접근이 허용됩니다. 왜냐하면 물리적 페이지 search.aspx는 그 역할안에 있는 사용자들에게 제한이 됩니다. checkPhysicalUrlAccessfalse 로 설정되고 그 사이트가 이전 예에서 보여준것 처럼 환경설정이 되어 있다면, 모든 권한받은 사용자들이 URL /search/{searchterm}에 접근이 허용됩니다.

Reading Routing Information in a Web Forms Page

웹폼의 물리적 페이지상의 코드에서 당신은 두 가지 새로운 속성을 사용하는 것에 의하여 라우팅이 URL(혹은 다른 객체가 RouteData 객체에 추가한 다른 정보)로 부터 추출한 정보에 접근 할 수 있습니다: HttpRequest.RequestContextPage.RouteData. (Page.RouteData wraps HttpRequest.RequestContext.RouteData.) 다음의 예는 Page.RouteData 를 사용하는 법을 보여줍니다.

protected void Page_Load(object sender, EventArgs e)
{
  string searchterm = Page.RouteData.Values["searchterm"] as string;
  label1.Text = searchterm;
}

예시의 라우트는 더 쉽게 정의 됨으로써, 그 코드는 searchterm 파라미터를 위하여 넘겨진 값을 추출합니다. 다음의 요청 URL을 고려해 봅시다:

http://localhost/search/scott/

이 요청이 만들어 졌을 때 "scott"이라는 단어는 search.aspx 페이지안에 랜더링 될 것입니다.

Accessing Routing Information in Markup

이전의 섹션에서 설명된 매소드는 웹폼 페이지 상의 코드에서 라우트 데이터를 얻는 법을 보여주었습니다. 당신은 또한 마크업 안에 표현들을 사용할 수 있는데, 그 마크업은 당신이 같은 정보에 접근할 수 있게 합니다. Expression builders는 "ASP.NET의 숨겨진 보석"으로 설명되어 졌습니다. (Phil Haack의 블로그의 Express Yourself With Custom Expression Builders 에 들어가 보세요). 아주 불행하게도 그것들은 잘 알려지지 않았습니다. 왜냐하면 표현 빌더들은 명령형 코드와 함께 작업하기 강력하고 센련되었기 때문입니다.

ASP.NET 4는 웹폼 라우팅을 위한 두 가지의 새로운 표현 빌더들을 포함합니다. 다음의 예는 그것들을 사용하는 방법을 보여줍니다.

<asp:HyperLink ID="HyperLink1" runat="server"
  NavigateUrl="<%$RouteUrl:SearchTerm=scott%>">Search for Scott</asp:HyperLink>

예제에서, RouteUrl  표현은 라우트 파라미터에 기반한 URL을 정의하기 위하여 사용되었습니다. 이것은 마크업으로 완전한 URL을 하드코드 해야하는 것으로 부터 당신을 구해줍니다. 그리고 당신이 이 링크에서 변화를 요청하는 것 없이 후에 URL 구조를 바꿀 수 있게 합니다.

더 쉽게 라우트를 정의하게 되면서, 이 마크업은 다음의 URL을 발생합니다.

http://localhost/search/scott

ASP.NET은 자동적으로 인풋 파라미터에 기반해서 올바른 라우트(즉, 올바른 URL을 발생합니다)로 동작합니다. 당신은 또한 표현 안에 라우트 이름을 포함 할 수 있습니다. 그것은 사용할 라우트를 명시하게 합니다.

다음의 예는 RouteValue 표현을 사용하는 법을 보여줍니다. 

<asp:Label ID="Label1" runat="server" Text="<%$RouteValue:SearchTem%>" />

이 컨트롤을 포함한 페이지가 동작할 때, 레이블은 "scott"이라는 값을 표시합니다.

RouteValue 표현은 마크업 안의 라우트 데이터 사용을 아주 쉽게 만들고, 그것은 마크업안의 더 복잡한 Page.RouteData["x"] 문법과 함께 동작해야 하는 것을 피할 수 있습니다.

Using Route Data for Data Source Control Parameters

RouteParameter 클래스는 당신이 데이터 소스 컨트롤 안의 쿼리를 위한 파라미터 값으로 라우트 데이터를 상세화하게 합니다. 다음의 예에서 보여지듯이, 그것이 FormParameter 처럼 잘 작동합니다:

<asp:sqldatasource id="SqlDataSource1" runat="server"
    connectionstring="<%$ ConnectionStrings:MyNorthwind %>"
    selectcommand="SELECT CompanyName,ShipperID FROM Shippers where
      CompanyName=@companyname"
  <selectparameters>
    <asp:routeparameter name="companyname" RouteKey="searchterm" />
  </selectparameters>
</asp:sqldatasource> 


 이 경우에, 라우트 파라미터 searchterm의 값은 Select 구문의 안에 @companyname 파라미터를 위하여 사용 될 것입니다다.


Caching the HttpBrowserCapabilities Object

  앞의 예는 한가지 문제점을 가지고 있습니다. 그것은 그 코드가 동작할 때마다,  HttpBrowserCapabilities  객체를 얻기위하여 커스텀 공급자가 인보크 되어야 하는 것입니다. 이것은 각 요청들 동안 복합적인 시간이 발생합니다. 예를들어, 보통 공급자를 위한 코드는 많이 발생하지 않습니다. 그러나 당신의 커스텀 공급자 안의 코드가 HttpBrowserCapabilities  객체를 얻기위하여 중요한 작업을 수행한다면, 이것은 큰 오버헤드를 초래할 수 있습니다:

이러한 것을 예방하기위해서 당신은 HttpBrowserCapabilities 객체를 캐쉬 할 수 있습니다. 다음을 보세요.

  1. Create a class that derives from HttpCapabilitiesProvider, like the one in the following example: HttpCapabilitiesProvider 를 상속 받기 위한 클래스를 창조하세요. 다음의 예가 있어요.   
public class CustomProvider : HttpCapabilitiesProvider { public override HttpBrowserCapabilities GetBrowserCapabilities(HttpRequest request) { string cacheKey = BuildCacheKey(); int cacheTime = GetCacheTime(); HttpBrowserCapabilities browserCaps = HttpContext.Current.Cache[cacheKey] as HttpBrowserCapabilities; if (browserCaps == null) { HttpBrowserCapabilities browserCaps = new HttpBrowserCapabilities(); Hashtable values = new Hashtable(180, StringComparer.OrdinalIgnoreCase); values[String.Empty] = request.UserAgent; values["browser"] = "MyCustomBrowser"; browserCaps.Capabilities = values; HttpContext.Current.Cache.Insert(cacheKey, browserCaps, null, DateTime.MaxValue, TimeSpan.FromSeconds(cacheTime)); } return browserCaps; } }

  예를 보면, 코드는  커스텀 BuildCacheKey 매소드를 부르는 것에 의하여 캐쉬키를 발생합니다. 그리고 그것은 커스텀 GetCacheTime 매소드를 부르는 것에 의하여 캐쉬에 걸린 시간을 얻습니다. 그 다음에 코드는 캐쉬에서 결정된 HttpBrowserCapabilities 객체를 더합니다. 객체는 캐쉬로부터 찾아 질 수 있고, 당신의 커스텀 공급자를 필요로하는 하부 요청시 재사용됩니다.

  1. 앞의 예제에서 설명되었듯이 어플리케이션과 함께 공급자를 등록합니다.

Extending ASP.NET Browser Capabilities Functionality

이전의 섹션은 ASP.NET 4에서의 새로운 HttpBrowserCapabilities  객체를 생성하는 법을 설명했습니다. 당신은 또한 ASP.NET 4 브라우저의 성능, 기능성을 향상 시킬 수 있습니다. 그 방법은 새로운 브라우저의 성능이 ASP.NET에 이미 있는 그것들을 정의한 것을 덧붙이는 것입니다.

당신은 XML브라우저 정의들을 사용하는 것 없이 이것을 할 수 있습니다. 다음의 프로시저는 그 방법을 보여줍니다.

  1. Create a class that derives from HttpCapabilitiesEvaluator and that overrides the GetBrowserCapabilities method, like the one in the following example: HttpCapabilitiesEvaluator 부터 상속 받고, GetBrowserCapabilities 매소드를 오버라이드하여 클래스를 생성합니다. 다음의 예를 보세요.
public class CustomProvider : HttpCapabilitiesEvaluator
        {
          public override HttpBrowserCapabilities
            GetBrowserCapabilities(HttpRequest request)
            {
              HttpBrowserCapabilities browserCaps =
                base.GetHttpBrowserCapabilities(request);
              if (browserCaps.Browser == "Unknown")
              {
                browserCaps = MyBrowserCapabilitiesEvaulator(request);
              }
            return browserCaps;
          }
        }

먼저 이 코드는 브라우저를 확인하기 위한 ASP.NET 브라우저의 성능 기능을 사용합니다. 그러나, 브라우저가 확인 되지 않는다면, 리퀘스트에 정의된 정보를 통하여 확인합니다. (즉,  HttpBrowserCapabilities  객체의 Browser 속성이 스트링형의 "Unknown" 이라면) 코드는 브라우저를 확인하기 위하여 커스텀 공급자인 MyBrowserCapabilitiesEvaluator를 호출합니다.

  1.  앞의 예제에서 설명되었듯이 어플리케이션과 함께 공급자를 등록합니다.

 

Extending Browser Capabilities Functionality by Adding New Capabilities to Existing Capabilities Definitions

  커스텀 브라우저 정의 공급자를 창조하는 것과 동적으로 새로운 브라우저 정의를 창조하는 것에 추가적으로, 당신은 추가적인 성능과 함께 존재하는 브라우저 정의를 확장 할 수 있습니다. 이것은 당신이 당신이 원했던 것과 가깝지만 단지 약간의 기능이 부족한 정의를 사용 하게 합니다. 이것을 하기위하여, 다음의 단계를 따르세요.

  1. 객체를 상속받고, GetBrowserCapabilities 매소드를 오버라이드하는 클래스를 생성합니다. 다음 예를 보세요.



    public class CustomProvider : HttpCapabilitiesEvaluator
            {
              public override HttpBrowserCapabilities
                GetBrowserCapabilities(HttpRequest request)
              {
                HttpBrowserCapabilities browserCaps =
                  base.GetHttpBrowserCapabilities(request);
                if (browserCaps.Browser == "Unknown")
                {
                  browserCaps = MyBrowserCapabilitiesEvaulator(request);
                }
                return browserCaps;
              }
            }
      예제 코드는 존재하는 ASP.NET HttpCapabilitiesEvaluator 클래스를 확장하고, 다음 코드를 사용하는 
  2. 것에 의하여 현재 요청 정의와 일치 했는지를 HttpBrowserCapabilities 객체로 얻습니다.   
            HttpBrowserCapabilities browserCaps =
              base.GetHttpBrowserCapabilities(request);


    코드는 이 브라우저를 위한 성능을 더하거나 수정할 수 있습니다. 새로운 브라우저 성능을 상세화하기 위한 두 가지 방법이 있습니다.

  • 객체에 키와 값을 쌍으로 덧붙입니다. 그리고 그것에  Capabilities  속성과 HttpCapabilitiesBase 객체에 의하여 노출 시킵니다.  앞의 예제에서, 코드는 값을 true로 하여 MultiTouch 불리는 성능을 덧붙입니다.

  • 객체의 존재하는 속성을 설정합니다. 앞의 예제에서 코드는  Frames 속성을 true로 설정합니다이 속성은 간단하게 IDictionary 객체를 위한 접근자입니다. IDictionary  객체는 Capabilities 속성에 의하여 노출 되었습니다.

Note: 컨트롤 어뎁터를 포함하면서, 이 모델은 HttpBrowserCapabilities 의 속성에 적용합니다.

  1. 앞의 프로시저에서 설명 되었듯이 어플리케이션과 함께 공급자를 등록합니다.

Razor in WebMatrix(3) – WebMatrix Helper

ASP.NET 4.0 2010. 7. 19. 12:57 Posted by 알 수 없는 사용자

제가 처음 했던 포스팅에서 , Twitter.Profile 을 호출해서 트윗 위젯을 간단히 구성하는 것을 소개해 드렸습니다.

이는 WebMatrix에서 제공하는 헬퍼로써 , Microsoft.WebPages.Helpers.dll 안에 포함되어 있습니다.


 아마 Razor 가 Visual Studio 에 정식적으로 포함될 때 이 helper 가 포함되면 , 개발자분들이 좀더 활용할수 있을거 같습니다. 해당 헬퍼는 서드 파티 벤더의 위젯을 설치할수 있는 것 외에도 analytics , 파일 업로드 , 아바타 , 메일등 폭넓은 기능을 제공하므로 꼭 한번 둘러보시기 바랍니다.


 MSDN 블로그 바로가기

Razor in WebMatrix(2) 코드의 재 사용

ASP.NET 4.0 2010. 7. 19. 12:12 Posted by 알 수 없는 사용자
 지난 아티클에서는 간단하게 Razor 를 이용해서 프로그램을 구동하는 방법에 대해 알아보았습니다. 그런데 이 아티클을 읽으신 개발자 분들은 아마도 , 자신이 만든 메서드를 Razor 로 꺼내서 사용하는 방법에 대해 궁금하셨을 겁니다.(저는 궁금했습니다.. 개발자니까!)  그래서 이번시간에는 간단하게 자신이 만든 객체를 활용해서 메서드를 재 활용해보는 방법을 알아보도록 하겠습니다.



 일단 WebMatrix에서 프로젝트를 생성하고 클래스파일을 생성합시다. 클래스 파일은 기본적으로 노출되어 있지 않으므로 , FileType 에서 All 을 선택해야 합니다. 이곳에서 cs 파일을 선택한후 이름을 선택하고 , OK 버튼을 눌러서 파일을 생성합시다. 

이제 해당 메서드를 렌더링 해서 보여줄 html 페이지를 만들 차례 입니다. 같은 순서대로 Test.cshtml 파일을 생성합시다.


메서드의 재활용을 위해서 저는 3개의 메서드를 static 으로 생성하였습니다.

//문자열 반환!

public static string GetHelloString()

{

    return "Hello Ciel!";

}

 

//문자열의 길이 반환(1개의 변수 받음)

public static string GetStringLength(string orgStr)

{

    return orgStr.Length.ToString();

}

 

//문자열의 길이 * int 변수 , (2개의 변수 받음)

public static string GetStringLengthMix(string orgStr , int mulVal)

{

    return (orgStr.Length * mulVal).ToString();

}


그후에 cshtml 에 razor 코드를 삽입하고 웹 페이지를 구동 시켜보도록 하겠습니다.
 
처음 코드를 구동시키면 대부분 이 에러를 보시게 될 겁니다. 이 에러를 이해하기 위해서는 이 webmatrix의 웹 프로젝트의 성격을 이해하셔야 합니다….만
.
.
.
사실 그닥 특별한 건 없습니다. 이 웹 메트릭스는 Visual Studio 에서 생성되는 프로젝트중 website 프로젝트의 형태를 띄고 있습니다. 그렇기 때문에 모든 컴파일 되는 cs 파일은 App_Code 폴더 안에 삽입되야 합니다.
 

이런 식으로 폴더를 이동시키고 구동시켜 보도록 하겠습니다.


<body>

    헬로우 문자열 반환 : @StringHandler.GetHelloString()

    <br/>

    문자열 길이 반환 : @StringHandler.GetStringLength(StringHandler.GetHelloString())

    <br/>

    여러개의 파라미터1 : @StringHandler.GetStringLengthMix("Hello" ,100  )

    <br/>

    여러개의 파라미터2 : @StringHandler.GetStringLengthMix(mulVal :  500 , orgStr : "Hello2" )

</body>


저는 이렇게 4개번 메서드를 구동시키도록 하였습니다.


정상적으로 호출되는것을 확인할수 있습니다. ^^

1~3 번 메서드는 일반적인 C#코드를 재 호출하는것으로써 특이할 부분이 없지만 ,
마지막 부분에서 처음 부분에 변수명을 명시해줌으로써 Json 형태로 변수를 선언해 줄 수 있다는 부분이 다소 흥미로운 부분이 될 거 같습니다.

Summary
이번 포스팅에서는 간단하게 cs코드에서 메서드를 선언하고 그 메서드를 호출하는 법을 살펴보았습니다. 사실 이정도만 하더라도 , 대부분의 작업을 대체 하는데는 무리가 없을겁니다. 다음 포스팅에서는 처음 포스팅에서 언급했던 부분인 webmatrix 헬퍼에 대해서 알아보도록 하겠습니다.

Razor in WebMatrix

ASP.NET 4.0 2010. 7. 15. 22:28 Posted by 알 수 없는 사용자

지난 7월 2일경 스캇구스리 옹의 블로그에서는 Razor 라는 새로운 view 엔진이 소개되었습니다. Razor 는 기존에 <%%> 으로 통칭되던 코드 블록을 좀더 간소화 시키기 위해 고안되었으며 , 스파케티 코드의 늪에서 허덕이는 개발자를 위해서 새로 고안되었습니다. 특히 이 코드블록은 기존에 미칠듯이 복잡하고 어려웠던 asp.net 인라인 코드를 좀더 html스럽게 보여줄수 있게되었다는 것에서 차별화 됩니다


스캇옹의 블로그 에서 Razor를 감상해BoA요



 


[기존 <%%> 코드블록으로 구성된 코드]

 


[Razor 스타일로 재구성된 코드]

 

현재 우리가 이 Razor를 테스트 해볼수 있는 환경은 크게 두가지로 나뉠수 있습니다.


첫번째는 WebMatrix 를 설치하고 , 그 안에서 CSHtml 파일을 직접 작성해보는것이고 ,

두번째는 ASP.NET 프로젝트에서 Microsoft.WebPages.dll 을 참조하는 것 입니다.

 

애석하게도 아직 Visual studio 에서는 Razor 관련 인텔리센스를 지원하고 있지 않으나 , 스캇 블로그에서 이미 인텔리센스 데모를 선보이고 있기 때문에 빠른 시일내에 , 관련 자료가 배포될것으로 보입니다. 이와 관련된 내용은 발표되는대로바로 알려드리도록 하겠습니다.

 



Razor in WebMatrix



현재 가장 빠르게 Razor 를 접해보는 방법은 WebMatrix 를 설치하는 것 입니다. 설치에 대한 부분은 준서아빠님이 소개해주셨으니 간략하게 넘어가도록 하겠습니다. 설치에 대해서는 WebMatrix 설치부터 HelloWorld까지 를 참조해 주시기 바랍니다.


WebMatrix 를 설치하게 되면 처음에 Website1 이라는 페이지가 생성되어 있는 것을 알수 있습니다. Razor 를 간단하게 살펴볼수 있는 데모프로젝트라고 이해하시면 될거 같습니다. ^^



WebSite1을 더블클릭하거나 선택하고 Ok 버튼을 클릭합니다.




프로젝트를 로드하고 나면 한눈에 웹 페이지의 상태를 볼수 있는 화면이 나옵니다. Url 과 소스코드가 있는 폴더가 나오고 있네요. 일단은 Run 버튼을 눌러 사이트를 구동시켜보도록 하겠습니다





깔끔한 웹 페이지가 나오네요
. 이 페이지는 Razor 과 간단한 html 로 구성되어 있습니다. 그럼 한번 코드를 보도록 하겠습니다.




 

Files를 클릭하면 현재 구동중인 웹 사이트 프로젝트를 수정할수 있습니다. 이곳에서 우리는 default.cshtml 을 살펴보도록 하겠습니다.

 

<div class="twitter">

<div class="twitterfeed">

@Twitter.Search("@vsts2010", caption: "#helloworld", width: 740, height: 150)

       </div>

</div>

 

해당 파일에서는 Twitter 위젯을 Razor 코드로 처리하고 있는 것을 확인할수 있습니다. Twitter 객체는 WebMatrix엔진에서 제공되는것으로 보입니다만 , 특별히 선언된 부분이나 참조되는 dll 찾는 것은 조금 힘들어보였습니다. 또한 특정 벤더의 API 사용 하는 부분은 효용성이 떨어지므로 , 데모 이외의 용도로 사용시 문제가 될수 있을것으로 보입니다.

해당 객체는 WebMatrix 에서 제공되는것이 맞네요. 많은 흥미로운 WebMatrix Helper 들을 확인해보세요 이부분에 대해서도 따로 한번 다루도록 하겠습니다 ^^



페이지에서는 Twitter 검색어를 조회해서 보여주는 위젯을 선보여주고 있습니다만, 저는 이것보다는 트윗을 노출시키고자 합니다. 이를 위해 기존 코드를 간단하게 주석처리하고 트윗을 노출시켜보도록 하겠습니다.

 


<div class="twitterfeed">              

@//Twitter.Search("@vsts2010", caption: "#helloworld", width: 740, height: 150)

@Twitter.Profile("@vsts2010")

</div>


이제 어플리케이션을 다시 구동시키면!




의도했던 트윗이 노출되는 것을 확인할수 있습니다. ^^

 

Summary


이번 글에서는 WebMatrix 에 포함된 기본 프로젝트에서 Razor 를 사용하는 부분과 함께 , 외부 함수를 끌어오고 기존의 프로그래밍 경험을 접목시켜보는 것을 보여드렸습니다. 다음 글에서는 외부 함수를 직접 구현하고 그 함수를 사용하는 방법에 대해 알아보도록 하겠습니다.

- 이번엔 웹디자이너와 배포에 대해서

부족한 번역이지만, 이번엔 웹 디자이너와 배포에 대해서 적어볼까 합니다.


- Visual Studio 2010 Web Designer Improvement

 

Visual Studio 2010의 웹페이지 디자이너는 더 뛰어난 CSS 호환성, HTML ASP.NET 마크업의 코드조각에 대한 추가적인 지원과 Jscript를 위해서 다시 디자인된 인텔리센스등으로 더 향상된 기능을 제공합니다.

 

 

- Improved CSS Compatibility

 

Visual Studio 2010 Visual Web Developer 디자이너는 CSS 2.1 표준과 호환되는데요. 이 디자이너는 HTML 소스와의 통합성을 높이면서 기존의 버전의 Visual Studio보다 전체적으로 더 견고한 기능을 제공합니다. 내부적으로는 앞으로 추가될 렌더링, 레이아웃, 사용성 및 유지보수를 위한 설계적인 측면에서의 향상도 있었습니다.

 

 

- HTML and Jscript Snippets

 

HTML에디터는 인텔리센스를 이용해서 태크이름을 자동완성합니다. 그리고 인텔리센스의 코드조각 기능이 전체 태그와 기타 부분을 완성합니다. VisualStudio 2010에서는 인텔리센스의 코드조각 가능이 C# Visual Basic에 적용되었던 것 처럼 Jscript에 대해서도 지원될 것입니다.

 

VisualStudio 2010에는 200개 이상의 코드조각이 ASP.NET HTML의 일반적인 태그와 필요한 속성(runat=”server” 같은)과 특정 태그들에 공통적인 속성들(ID, DataSourceID, ControlToValidate, Text같은)의 자동완성을 도와줍니다.

 

추가적인 코드조각들을 다운받을 수 있으며, 팀의 공동작업이나 개인작업에 공통으로 쓰이는 마크업의 블록을 코드조각으로 뽑아내서 사용할 수도 있습니다.

 

 

- Jscript IntelliSense Enhancements

 

VisualStudio 2010에선 더 풍부한 편집을 위해서 Jscript의 인텔리센스가 다시 디자인 되었습니다. 이젠 인텔리센스가 registerNamespace같은 메서드나 기타 비슷한 자바스크립트 프레임워크의 기술을 이용해서 동적으로 생성되는 객체를 인식할 수 있습니다. 그리고 방대한 스크립트 라이브러리를 분석하고 화면에 인텔리센스를 표시하는데 걸리는 시간을 사용자가 거의 못 느낄 정도로 향상시켰습니다. 호환성 역시 대단히 향상되어서 외부 라이브러리나 다양한 코딩 스타일도 지원할 수 있게 되었습니다. 문서화를 위한 주석은 타이핑하는 즉시 파싱되어서 인텔리센스에서 바로 활용할 수 있습니다.

 

 

- Web Application Deployment with Visual Studio 2010

 

현재 웹 어플리케이션을 배포하는 작업은 우리가 꿈꾸었던 것만큼 쉽지 않았죠. ASP.NET 개발자는 종종 아래와 같은 문제에 직면하곤 합니다.

 

  FTP같은 기술을 사용해야 하는 공동 호스팅 사이트에 배포하는 경우. 게다가 데이터베이스를 세팅하기 위한 SQL스크립트를 직접 실행해야 하거나 가상 디렉토리같은 IIS세팅도 바꿔야 한다.

  엔터프라이즈 환경에서는 웹 어플리케이션을 배포하는 것으로 끝나지 않고, ASP.NET 설정파일이나 IIS세팅도 수정해야 한다. 데이터베이스 관리자는 데이터베이스를 돌리기 위해 필요한 SQL스크립트를 돌려야 한다. 그런 설치작업은 종종 몇 시간을 잡아먹으며 노동에 가까운 일이 되며, 세세하게 문서화 되어야 한다.

 

VisualStudio 2010은 웹 어플리케이션을 중단없이 배포할 수 있게 도와주는 새로운 기술을 통해서 이런문제들을 해결합니다. 이런 기술들중의 하나가 IIS Web Deployment Tool(MsDeploy.exe)이죠.

 

VisualStudio 2010에서 웹배포에 관련된 요소들은 아래와 같이 크게 분류할 수 있습니다.

 

  Web packaging

  Web.config Transformation

  Database deployment

One-Click Publish for Web applications

 

아래의 섹션들에서 하나씩 자세하게 설명을 해보겠습니다.

 

 

Web Packaging

 

VisualStudio 2010에서는 MSDeploy 툴을 사용해서 어플리케이션을 압축해서 압축파일(.zip)을 생성하는데, 그 파일을 웹 패키지라고 부릅니다. 패키지파일은 어플리케이션에 대한 메타데이터와 아래의 내용들을 포함합니다.

 

 어플리케이션 풀 세팅과 에러페이지 세팅, 등등을 포함하는 IIS세팅

  웹페이지와 사용자 정의 컨트롤, 정적인 컨텐츠(이미지와 HTML파일), 등등을 포함하는 실제 웹 컨텐츠

  SQL 서버의 데이터베이스 스카마와 데이터

  보안 인증서, GAC에 설치할 컴포넌트, 레지스트리 세팅, 등등

 

웹 패키지는 아무 서버에나 복사할 수 있고, IIS 매니저를 사용해서 수동으로 설치할 수 있습니다. 또는, 커맨드라인 명령어나 배포API를 사용해서 자동으로 배포할 수도 있습니다.

 

VS2010에서는 웹패키지를 만들기 위해서 사용가능한 MSBuild task target을 제공합니다. 더 많은 정보는 Vishal Joshi의 블로그에 있는 10 + 20 reasons why you should create a Web Package를 참조하시길 바랍니다.

 

 

Web.config Transformation

 

웹 어플리케이션의 배포를 위해서 VisualStudio 2010에서는 XML Document Transform (XDT)가 도입되었는데, 이 요소는 개발설정에서 Web.config를 읽어와서 제품설정(production setting)으로 변환하게 도와줍니다. 변환에 관련된 세팅은 변환파일인 web.debug.config, web.release.config, 그리고 기타파일(이 파일들의 이름은 MSBuild 설정과 매치된다)등에 명시되어 있습니다. 변환파일에는 Web.config파일을 배포하기 위해 필요한 수정사항들만 포함되어 있습니다. 이런 수정사항들을 간단한 문법으로 명시해주면 되는거죠.

 

아래의 예제는 배포의 릴리즈설정에 의해 생성가능한 web.release.config파일의 일부분인데요. 예제의 내용중에서 Replace키워드를 보면, 배포과정에서 Web.config파일의 connectionString 노드의 값이 어떻게 바뀌어야 하는지 명시해주고 있습니다.

 

<connectionStrings xdt:Transform="Replace">

  <add name="BlogDB" connectionString="connection string detail]" />

</connectionStrings>

 

더 자세한 정보는, Vishal Joshi의 블로그의 Web Deployment: Web.Config Transformation를 보시면 됩니다.

 

 

- Database Deployment

 

VisualStudio 2010의 배포 패키지에는 SQL 서버 데이터베이스에 대한 의존성 역시 포함될 수 있습니다. 패키지 정의의 일부분으로 원본 데이터베이스의 연결문자열을 명시해줄 수 있습니다. 웹 패키지를 만들때 VisualStudio2010에 의해서 데이터베이스 스키마와 선택적으로 데이터에 대해서 SQL 스크립트가 만들어지고 패키지에 포함됩니다. 사용자 정의 SQL 스크립트를 만들어서 서버에서 순차적으로 실행되어야 할 순서를 지정해줄 수도 있습니다. 배포할때, 타겟 서버에 대한 연결문자열을 제공하고, 배포 프로세스에서 이 연결문자열을 이용해서 해당 데이터베이스에 SQL 스크립트를 실행해서 데이터베이스 스키마를 만들고 데이터를 추가합니다.

 

추가적으로, One-Click Publish를 이용하면 어플리케이션이 원격의 공용 호스트에 게시된 후에 데이터베이스를 직접적으로 게시할 수 있도록 배포를 설정할 수 있습니다. 자세한 내용은 Vishal Joshi의 블로그의 Database Deployment with VS 2010를 참조하시면 됩니다.

 

 

- One-Click Publish for Web Application

 

VisualStudio 2010에서는 IIS 원격 관리 서비스를 이용해서 원격의 서버에 웹 어플리케이션을 게시할 수 있도록 도와줍니다. 게시를 위해서 호스팅 계정이나 테스트 서버나 스테이징 서버를 위한 게시 프로파일(publish profile)을 생성할 수 있습니다. 각각의 프로파일은 안전하게 계정정보를 저장할 수 있구요. 그러면 Web One Click Publish 툴바를 이용해서 한번의 클릭으로 타겟서버에 배포할 수 있게 됩니다. VisualStudio2010에서는 MSBuild 커맨드 라인을 통해서도 배포할 수 있는데요. 이 기능을 통해서 지속적인 통합 모델을 이용하는 팀 빌드 환경에 게시작업을 포함할 수 있습니다.

 

더 자세한 정보는, Vishal Joshi의 블로그의 Web 1-Click Publish with VS 2010를 보시면 되구요, VisualStudio 2010에서의 웹 어플리케이션 배포에 대한 비디오 영상을 보려면, Vishal Joshi의 블로그의  VS 2010 for Web Developer Previews를 보시면 됩니다.

 

- 이어서 이어서!

지난 시간에 이어서 Dynamic Data에 관련된 기능들을 보시겠습니다.



- Entity Templates

 

Entity Templates를 이용하면 사용자 정의 페이지를 만들지 않고도 데이터의 레이아웃을 사용자가 편집할 수 있습니다. 페이지 템플릿은 FormView 컨트롤(기존 버전의 Dynamic Data의 페이지 템플릿에서 사용하던 DetailView컨트롤 대신에) DynamicEntity 컨트롤을 사용해서 Entity templates를 렌더링합니다. 이렇게 하면 사용자는 Dynamica Data가 렌더링한 마크업에 대해서 더 많은 제어를 할 수 있게 되죠.

 

아래의 목록은 Entity templates를 포함하고 있는 새로운 프로젝트 폴더의 구조입니다.

 

\DynamicData\EntityTemplates

\DynamicData\EntityTemplates\Default.ascx

\DynamicData\EntityTemplates\Default_Edit.ascx

\DynamicData\EntityTemplates\Default_Insert.ascx

 

EntityTemplates폴더는 모델 객체들을 어떻게 화면에 표시할지에 대한 템플릿을 담고 있습니다. 기본적으로 객체들은 ASP.NET 3.5 SP1 Dynamic Data에서 생성된 DetailsView의 마크업과 유사한 모양의 마크업을 생성해주는 Default.ascx를 이용해서 렌더링되는데요. 다음의 예제는 Default.ascx 컨트롤의 마크업 입니다.

 

<asp:EntityTemplate runat="server" ID="TemplateContainer1">

  <ItemTemplate>

    <tr

      <td>

        <asp:Label ID="Label1" runat="server" OnInit="Label_Init" />

      </td>

      <td>

        <asp:DynamicControl runat="server" OnInit="DynamicControl_Init" />

      </td>

    </tr>

  </ItemTemplate>

</asp:EntityTemplate>

 

기본 템플릿은 전체 사이트의 디자인과 느낌을 바꾸기 위해서 수정가능합니다. 기본 템플릿에는 디스플레이, 수정, 그리고 삽입을 위한 템플릿이 포함되어 있습니다. 새로 추가하는 템플릿들은 데이터객체의 이름을 기반으로 해서 추가될 수도 있는데, 그 타입의 객체의 디자인과 느낌을 수정하고 싶을때가 그렇습니다. 예를들면, 아래와 같은 템플릿을 추가할 수 있습니다.

 

\DynamicData\EntityTemplates\Products.aspx

이 템플릿은 아래와 같은 마크업을 포함하고 있겠죠.

 

<tr>

  <td>Name</td>

  <td><asp:DynamicControl runat="server" DataField="ProductName" /></td>

  <td>Category</td>

  <td><asp:DynamicControl runat="server" DataField="Category" /></td>

</tr>

 

새로운 Entity templates DynamicEntity 컨트롤을 사용하는 페이지에서 화면에 나타납니다. 런타임에 이 컨트롤은 Entity template의 내용으로 대체되는데요. 아래의 마크업은 Entity template를 사용하는 Detail.aspx 페이지 템플릿의 FormView컨트롤입니다. 마크업의 DynamicEntity 요소을 주목해서 보시죠.

 

<asp:FormView runat="server" ID="FormView1"

    DataSourceID="DetailsDataSource"

    OnItemDeleted="FormView1_ItemDeleted">

  <ItemTemplate>

    <table class="DDDetailsTable" cellpadding="6">

      <asp:DynamicEntity runat="server" />

      <tr class="td">

        <td colspan="2">

          <asp:DynamicHyperLink ID="EditHyperLink" runat="server"

              Action="Edit" Text="Edit" />

          <asp:LinkButton ID="DeleteLinkButton" runat="server"

              CommandName="Delete"

              CausesValidation="false"

              OnClientClick='return confirm("Are you sure you want to delete this item?");'

              Text="Delete" />

        </td>

      </tr>

    </table>

  </ItemTemplate>

</asp:FormView>

 

 

- New Field Templates for URLs and E-mail Addresses

 

ASP.NET 4 에서는 새로운 내장 필드 템플릿인 EmailAddress.ascx, Url.ascx가 추가되었습니다. 이 템플릿들은 DataType 속성과 함께 EmailAddress Url로 선언된 필드에 사용됩니다. EmailAddress타입의 객체의 경우에는 필드가 ‘mailto:protocol’를 사용해서 만든 하이퍼링크로 표시되구요, 사용자가 이걸 클릭하면 사용자의 이메일 클라이언트 프로그램을 실행하고 기본메세지를 생성해줍니다. Url타입의 객체는 그냥 일반적인 하이퍼링크로 표시되구요.

 

아래의 예제는 필드를 마크하는 방법을 보여줍니다.

 

[DataType(DataType.EmailAddress)]

public object HomeEmail { get; set; }

 

[DataType(DataType.Url)]

public object Website { get; set; }

  

- Creating Links with the DynamicHyperLink Control

 

Dynamic Data는 사용자가 웹사이트가 접근했을 때 보여지는 URL을 컨트롤하기 위해서 .NET 프레임워크 3.5 SP1에 추가되었던 라우팅 기능을 사용합니다. DynamicHyperLink 컨트롤이 Dynamic Data를 사용한 사이트에 접근하는 링크를 쉽게 만들 수 있도록 도와줍니다. 아래의 예제는 DynamicHyperLink컨트롤을 사용하는 예제입니다.

 

<asp:DynamicHyperLink ID="ListHyperLink" runat="server"

    Action="List" TableName="Products">

  Show all products

</asp:DynamicHyperLink>

 

이 마크업은 Global.asax파일에 정의된 규칙대로 라우팅되는 링크를 만들고, 그 링크는 Products테이블의 List페이지를 가리킵니다. DynamicHyperLink컨트롤은 컨트롤이 위치한 Dynamic Data 페이지에 기반해서 자동으로 테이블의 이름을 명시해줍니다.

 

 

- Support for Inheritance in the Data Model

 

현재 Entity Framework LINQ to SQL 둘다 모두 데이터 모델상에서의 상속을 지원합니다. 예를 들면, InsurancePolicy 테이블이 있는 데이터베이스를 생각해볼 수 있는데요. 추가로 InsurancePolicy와 동일한 필드를 가지고 몇가지 추가적인 필드만 가지는 CarPolicy HousePolicy테이블도 가질 수 있습니다. Dynamic Data는 이렇게 데이터 모델에서 상속관계를 갖는 객체에 대해서 scaffolding을 할 수 있도록 개선되었습니다.

 

 

- Support for Many-to-Many Relationships(Entity Framework Only)

 

엔티티 프레임워크는 다대다 관계를 가지는 테이블을 풍부한 기능으로 지원하고 있고, 관계를 엔티티 객체들간의 컬렉션으로 노출하는 형태로 구현이 되어있습니다. ManyToMany.ascx ManyToMany_Edit.ascx 필드 템플릿은 다대다 관계를 갖는 데이터를 표시하고 수정하는 걸 지원하기 위해서 추가되었습니다.

 

 

- New Attributes to Control Display and Support Enumerations

 

DisplayAttribute를 통해서 필드가 어떻게 화면에 표시될지를 추가적으로 컨트롤 할 수 있습니다.기존 Dynamic Data버전에 있던 DisplayName 속성은 필드의 캡션으로 쓰일 이름을 변경할 수 있도록 지원했었는데요. 새로운 DisplayAttribute 클래스는 필드를 표시하는데 있어서 필드의 데이터를 어떻게 정렬할 것인지, 필드에 필터를 적용할 것인지 같은 옵션을 제공합니다. 그리고 이 속성은 추가적으로 GridView컨트롤의 레이블, DetailsView컨트롤의 이름, 필드의 도움말, 필드의 워터마크(필드가 텍스트입력을 받는다면)등에 대한 독립적인 제어를 제공합니다.

 

EnumDataTypeAttribute 클래스는 필드를 열거형데이터 타입에 연결해주기 위해서 추가되었습니다. 이 속성을 필드에 주게되면, 열거형 타입을 명시하게 되는데요. Dynamic Data에서는 열거형 값을 표시하고 수정하는데 Enumeration.ascx를 사용합니다. 이 템플릿은 데이터의 값을 열거형의 이름과 연결합니다.

 

 

- Enhanced Support for Filters

 

Dynamic Data 1.0boolean열과 외래키열에 대한 내장필터를 갖고 릴리즈 되었었습니다. 하지만,이 필터들은 열을 화면에 표시할지, 열의 데이터를 어떤 순서로 출력할지 명시해줄 수는 없었는데요. 새로운 DisplayAttribute 속성은 이 문제를 화면에 열을 필터로 표시할지 그리고 어떤 순서로 표시할지 설정할 수 있게 함으로써 해결해줍니다.

추가적으로 향상된 부분은 필터링을 지원하는 부분이 웹폼의 QueryExtender를 이용하도록 재작성됐다는 점입니다. 이로써 필터가 사용될 데이터 소스 컨트롤을 몰라도 필터를 작성할 수 있습니다. 이런 확장과 더불어서 이젠 필터도 템플릿 컨트롤로 작성되게 되어서 새로운 필터를 작성해서 추가할 수 있게 되었습니다. 마지막으로, DisplayAttribute 클래스는 UIHint가 기본적인 필드템플릿을 오버라이드할 수 있게 지원하는 것 처럼, 기본적인 필터를 오버라이드할 수 있도록 지원합니다.



- 마치면서

다음번에는 웹 디자이너와 배포에 어떤 새로운 기능들이 추가되고 개선되었는지에 대해서 말씀드리겠습니다!

- 이건 또 뭥미

이 포스트 시리즈는 http://www.asp.net/learn/whitepapers/aspnet40/ 에 올라와있는 "ASP.NET 4.0 and Visual Studio 2010 Web Development Beta 2 Overview"를 번역하는 시리즈입니다. 번역이라서 조금은 딱딱할 수도 있고, 내공의 부족으로 제대로 번역이 힘든 부분도 있습니다.(반드시 있습니다-_-) 따쓰한 피드백으로 격려를 부탁드립니다. 냐하하하하. 두부분으로 나눠서 번역을 맡았는데요, 제가 맡은 부분은 Dynamic Data, Studio 2010 Web Designer Improvement, Web Application Deployment with Visual Studio 2010 이렇게 세부분입니다. 그럼 시작해볼까효?


- Dynamic Data

 

Dynamic Data 2008년 중반에 릴리즈되었던 .NET 프레임워크 3.5 서비스팩 1에서 처음 소개가 됐습니다. 이 기술은 데이터 중심 개발을 하는데 있어서 많은 유용한 기능을 제공하는데요. 예를 들면 아래와 같습니다.

 

l  데이터 중심의 웹사이트를 RAD(빠른 속도의 어플리케이션 개발)처럼 작성

l  데이터 모델에 명세된 제약조건을 기반으로 자동으로 유효성검사

l  Dynamic Data 프로젝트의 일부인 필드 템플릿을 이용해서 GridView DetailsView의 자동생성된 필드의 마크업을 쉽게 변경할 수 있음

 

더 상세한 정보는 MSDN에 있는 Dynamic Data documentation을 참조하시면 됩니다.

 

ASP.NET 4 에선 기존의 기능보다 더 강력해진 지원으로 데이터중심의 웹사이트를 더 빠르게 개발할 수 있도록 도와줍니다.

 

- Enabling Dynamic Data for Existing Projects

 

.NET 프레임워크 3.5 서비스팩 1 에 추가되었던 Dynamic Data는 아래와 같은 새로운 기능들을 소개했었죠.

 

l  필드 템플릿 데이터 바운드 가능한 컨트롤에 대해서 데이터 타입에 기반한 템플릿을 제공한다. 필드 템플릿은 기존에 각각에 필드에 템플릿 필드를 이용해서 설정해줘야 하던것에 비해서 컨트롤의 모양을 입맛에 맞게 커스터마이즈하는 좀 더 간편한 방법을 제공한다.

l  유효성검사 데이터 클래스에 어트리뷰트를 이용해서 값의 유무, 범위 체크, 타입 체크, 정규식을 이용한 패턴매칭, 사용자 정이 유효성검사와 같은 일반적인 경우에 대한 유효성검사를 명시해줄 수 있다.

 

하지만, 이런 기능들은 아래와 같은 요구사항이 있었습니다.

 

l  데이터 엑세스 레이어는 반드시 Entity Framework LINQ to SQL이어야 한다.

l  데이터 소스 컨트롤은 EntityDataSource LinqDataSouce컨트롤 이 두가지 외에는 지원되지 않는다.

l  위와 같은 기능들을 모두 사용하기 위해서는 필요한 파일들이 모두 포함된 템플릿인 Dynamic Data Dynamic Data Entities를 통해 생성된 웹 프로젝트여야만 했다.

 

ASP.NET 4에 추가될 Dynamic Data에서 가장 초점을 둔 부분중의 하나는 어떤 ASP.NET 어플리케이션이라고 해도 Dynamic Data의 기능을 활용할 수 있도록 한다는 것 입니다. 아래의 예제코드는 이런 목표에 맞게, 기존에 존재하던 페이지에 Dynamic Data의 기능을 활용하기 위해서 명시해줘야 하는 코드입니다.

 

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="True"

    DataKeyNames="ProductID" DataSourceID="LinqDataSource1">

</asp:GridView>

<asp:LinqDataSource ID="LinqDataSource1" runat="server"

    ContextTypeName="DataClassesDataContext" EnableDelete="True" EnableInsert="True"

    EnableUpdate="True" TableName="Products">

</asp:LinqDataSource>

 

페이지의 코드비하인드에서 이 컨트롤들의 Dynamic Data기능을 켜려면 아래와 같은 코드를 반드시 추가해야 합니다.

 

GridView1.EnableDynamicData(typeof(Product));

 

GridView 컨트롤이 수정모드에 있을 때, 사용자가 입력한 값이 적절한 포맷인지 아닌지를 Dynamic Data가 자동으로 검사를 하고, 포맷에 맞지 않는다면 에러메세지를 보여줍니다.

 

이 기능은 입력모드에서 사용될 기본값을 명시해줄 수 있는 것 같이 다른 장점도 가지는데요. Dynamic Data를 쓰지 않고 필드의 기본값을 설정하려면, 이벤트를 걸어야 되고, FindControl등의 메서드를 이용해서 컨트롤을 찾아야 되고, 값을 설정해야 하는등의 작업을 해야합니다. 하지만 ASP.NET 4에서는, EnableDynamicData메서드에서 아래의 예제코드에서 처럼 어떤 필드에도 기본값을 설정해줄 수 있습니다.

 

DetailsView1.EnableDynamicData(typeof(Product), new { ProductName = "DefaultName" });

 

 

- Declarative DynamicDataManager Control Syntax

 

다른 ASP.NET컨트롤들이 그렇듯이 DynamicDataManager컨트롤도 이제는 코드에서 뿐만 아니라 선언적으로 속성을 명시해줄 수 있게 개선되었습니다. 아래 예제에서 DynamicDataManager 컨트롤의 마크업을 확인할 수 있습니다.

 

<asp:DynamicDataManager ID="DynamicDataManager1" runat="server"

    AutoLoadForeignKeys="true">

  <DataControls>

    <asp:DataControlReference ControlID="GridView1" />

  </DataControls>

</asp:DynamicDataManager>

 

<asp:GridView id="GridView1" runat="server"

</asp:GridView>

 

이 마크업은 DataControls섹션에 나와있듯이 GridView1 Dynamic Data기능을 적용시킵니다.



- 마치면서

쫌 이상해 보이긴 하네요-_-ㅋ 다음 포스트에서는 Entity Templates부터 시작해서 템플릿에 대한 내용을 설명드리도록 하겠습니다.

[ASP.NET 4.0] 2. AJAX - Declarative Client Template Rendering

ASP.NET 4.0 2009. 7. 8. 17:43 Posted by 알 수 없는 사용자
New Feature of Ajax

ATLAS라는 코드명으로 2006년 ASP.NET에 추가된 Ajax가 점점 견고해 지고 있습니다. 2006년 CTP버전 이었던 ATLAS를 겁없이(?) 프로젝트에 적용했었던 기억이 떠오르는 군요. 2006년을 기억하면, 참 MS에서 새로운 기술이 쏟아져 나오던 한해 였습니다. Vista가 공개 되고 WinFX와 WPF, WF(그때는 WWF 로 소개 되었었죠), WCF, ASP.NET에 Ajax 등등 많은 기술이 소개되어 .NET 개발자들의 정신 건강을 악화시켰던 때였습니다.
Ajax는 Google을 선두로 하여 Web 2.0에 적절한 패러다임을 제공하였으며, 국내에서도 많은 파장을 일으켰습니다. 특히, MS에서 나온 Ajax는 개발자의 개발 편의성을 확장시켜 Ajax 대중화에 큰 역활을 하였습니다.

이번 ASP.NET 4.0에 Ajax는 Data Provider의 접근 용이성에 중점을 둔듯 합니다. WCF와 ADO.NET을 이용하여 Client Based Development를 확장시켰으며, DataView는 Client Side에서 개발자가 편하게 화면을 개발 할 수 있도록 리스트 컨트롤을 제공하고 있습니다.

Client Template Rendering - DataView

DataView는 이번에 추가된 기능으로 이전까지는 Server Control을 이용한 리스트를 제공한 반면, Client Side Control을 사용함으로써, Server의 부하를 줄일 수 있도록하는 기능입니다. 예전에는 반복문을 통해 DOM을 생성한다든지, 아니면 개발자 자신의 라이브러리를 활용하거나, Third party 솔루션을 이용하는 방법이 있었습니다만, System.Web.Extention 4.0버전 부터는 기본적으로 DataView라는 컨트롤을 제공해 주고 있습니다. 그리고, 굳이 ASP.NET 언어가 아닌 다른 Framework에서도 사용가능한 독립형 스크립트로 제공하여 주고 있어 플랫폼 대한 제약을 많이 완화 시켰습니다.


간략하게 기능을 알아보도록 하겠습니다.

선언적 구문으로 생성하는 DataView

WebSite 프로젝트를 생성하고 간단한 html문서 또는 aspx 문서를 생성해 보겠습니다. <head>섹션에
<script type="text/javascript" src="../MicrosoftAjax/MicrosoftAjax.debug.js"></script><script type="text/javascript" src="../MicrosoftAjax/MicrosoftAjaxTemplates.debug.js"></script>

AJAX Template을 사용하려면 이 스크립트 참조를 꼭 기입하여야 정상적으로 Template이 생성되는 보실 수 있습니다. 그리고 Body 부분에 해당 Namespace와 Command를 추가해 줍니다.
<body xmlns:sys="javascript:Sys" xmlns:dataview="javascript:Sys.UI.DataView" sys:activate="*">
xmlns:sys="javascript:Sys"는 Sys라는 Namespace를 등록 시켜 줌으로써 선언적(Declarative) 또는 명령적(Imperative)인 모든 Template을 활성화 하는데 필요합니다. 아마도 Ajax를 프로그래밍적으로 접근 하셨던 분들은 Microsoft Ajax Library의 Namespace가 Sys. 이렇게 접두어를 붙여 사용되는 것을 보셨겁니다. 그리고 나머지 두 Attribute는 선언적(Declarative)으로 활성화하거나 바인딩 하는데 필요한 Attribute입니다. dataview또한 네임스페이스로써 Sys.UI.DataView의 AJAX 컨트롤을 의미합니다. 그리고 sys:activate="*"라는 Attribute는 페이지 로드시에 Template을 바인딩하는 특정 개체를 의미하는데 '*'(Asterisk)를 편의상 어떤것이든 활성화 하겠다는 뜻이고 만약 pane1, panel2에 Template을 바인딩 하려면 sys:activate="panel1, panel2"라고 명시적으로 코딩하시면 됩니다.
그리고 실제 Template이 들어갈 개체의 코드를 구현하여 보겠습니다.

<ul id="testDataView" class="sys-template" sys:attach="dataview" dataview:data="{{ testData }}">        <li>            <span class="name">{{ Name }}</span>            <span class="value">{{ Value }}</span>        </li></ul>
ul안에 id와 class 그리고 sys:attach, dataview:data와 같은 예전에 보던 Attribute와 생전 처음 쌩뚱 맞은 Attribute가 ul 태그 안에 들어와 있는 것을 보실 수 있습니다. 일단 "sys-template"이 거슬리는 군요.
sys-template은 일종에 예약된 스타일이라고 이해하시면 됩니다. 만약 Template을 구현 하고 class에 sys-template을 명시적으로 넣어 주시지 않으시면, 효과가 즉빵 나타납니다. 어떤 효과일까요? 리스트가 아예 안나옵니다. 헐~ 필자도 처음에는 내 나름대로의 스타일을 줬다가 몇분 삽질하고, 이런 교훈을 얻었습니다. 아무튼  testStyleSheet.css스타일 시트를 만드셨다면 그 시트 안에는 .sys-template { display:none; } 이라는 스타일이 있어야 합니다. 다시 정리 하자면 sys-template 은 Template에 바인딩이 일어나기 전까지 Template을 숨기는 예약된 스타일이라고 정의하겠습니다. 

그리고, sys:attatch는 또 뭐하는 아이이길래 우리를 헷깔리게 하는 것일까요? 음, 예전에 Microsoft AJAX Library를 프로그래밍적으로 다루어 보셨던 분들이라면 생소 하지 않는 $Create라는 메서드를 기억하실 겁니다. 이놈은 개체를 생성하는 아이인데 Sys.으로 파생되는 개체들을 생성하는 메서드라고 할 수 있습니다. 즉 Microsoft AJAX Library에서만 파생된 개체들을 쉽게 생성하고자 만들어진 메서드입니다. 그럼 sys:attatch와 $Create와는 무슨 관계일까요? 답은 같은 놈입니다. 다만 선언적으로 태그의 Attribute에 위치하느냐, 프로그래밍적으로 접근하느냐하는 방법의 차이일 뿐이지 같은 의미를 지녔습니다. 마지막으로 dataview:data는 body태그에서 Namespace를 정의해 주었던거 생각 나시죠? 그 접두어에 data는~~~~~~~ 네 맞습니다. Data Source입니다. 우리가 리스트를 주욱 바인딩 할 데이터 소스 개체를 정의해 주는 Attribute입니다.
그럼, 이제 어느정도 Attribute에 대한 이해가 되었으리라 생각하고 다음 코딩으로 넘어 가겠습니다.

Add array DataSource

다음과 같이 Array로 DataSource를 생성합니다. 다음에는 ADO.NET과 WCF로 바인딩하는 포스팅을 하도록 하겠습니다.
<script type="text/javascript">        
var testData = [
            { Name: "홍길동", Value: "의적" },
            { Name: "김혜자", Value: "영화배우" },
            { Name: "원빈", Value: "영화배우" },
            { Name: "김태희", Value: "이쁜이" },
            { Name: "전지현", Value: "절세미인" },
            { Name: "2PM", Value: "가수" },
            { Name: "장동건", Value: "영화배우." },
            { Name: "카라", Value: "귀염둥이들" },
            { Name: "이수근", Value: "코메디언" },
            { Name: "강호동", Value: "돼랑이" },
            { Name: "유재석", Value: "메뚜기" },
            { Name: "이효리", Value: "횰" },
            { Name: "정형돈", Value: "정체불명" },
            { Name: "길", Value: "가수" }        ];
</script>

다들 아시겠지만 굳이 부연 설명 드리도록 하겠습니다. javascript는 함수형 언어로써 강력한 기능을 제공합니다. 보시는 바와 같이 단순히 Array 이지만 testData라는 개체에 Name과 Value라는 Attribute가 있는 개체들의 집합이 들어 가게 되는 것입니다. 우리가 생각 하는 new의 연산자와 javascript의 new 연산자는 다른 의미라는 것을 알고 계실 듯 합니다. 여기에서도 유추를 하실 수 있습니다. 혹, testData[0].Name일 경우 홍길동이 나타나는 결과를 얻으실 수 있습니다.
이제 실제 결과 페이지를 보고 이번 포스팅을 마무리 하겠습니다.

[ASP.NET 4.0] 1. Core Service - Extensible Output Caching

ASP.NET 4.0 2009. 6. 24. 20:03 Posted by 알 수 없는 사용자
Evolution of ASP.NET

.NET Framework 4.0 beta 1와 함께 ASP.NET도 새로운 변화를 시도하였습니다. ASP.NET 2.0의 변화 보다는 덜 파격적이지만, 그 동안 .NET Framework 업데이트가 진행되는 동안 ASP.NET의 변화가 미미했던 것을 감안 한다면, 이번 .NET Framework 4.0 업데이트와 함께 동승한 ASP.NET의 업데이트는 놀라울 만큼 바뀌었습니다.(스캇 구스리 아저씨가 힘좀 쓰셨나 봅니다.ㅋㅋ)
그 중 Core Service 업데이트는 Performance 측면과 기존 ASP.NET Issue를 처리하는데 두드러진 발전을 이루어 냈습니다. 그럼, Core Service의 주요 업데이트 사항을 간략하게 소개하고 넘어가도록 하겠습니다.

1. Extensible Output Caching - 확장 가능한 출력 캐쉬 정도로 직역하겠습니다. 기존에도 있던 페이지 캐싱을 개발자 나름대로 커스트마이징 할 수 있도록 확장 시켜준 기능입니다.
2. Auto-Start Web Application - HTTP Request에 대하여 콜드 스타트 또는 개별 응용프로그램의 재사용에 소모되는 비용을 절감하기 위한 기능인 듯 합니다. 왜 ASP.NET 맨처음 띄우면 밥먹고 담배피고 와야 하잖아요.(오바입니다만...) 그런 비용을 절감 하기 위해 나온 기술인듯합니다. 허나, Windows Server 2008 R2에 탑재 가능한 IIS 7.5에서만 지원되는 기능이라니 OTL이 아닐 수 없습니다. 한 3년동안은 이 기술 볼 수 없을 듯합니다.(회사에서 2008을 깔아야 뭘 하죠? 아직 2000 쓰는 곳도 많이 있는데....)
3. Permanently Redirecting a Page - 영원히 헤어지는 이전 페이지와의 관계, 참 무슨 영화 제목 같 군요. 이전에 이슈가 되었던 Request가 여러번 일어나던 오래된 페이지에서 Redirect를 시킬 경우 HTTP 302 요청 이슈에 대한 대처 방안입니다. 이건 뭐 다들 아실만한 내용이겠네요.
4. The Incredible Shrinking Session State - 깜놀하게하는 세션 상태정보의 감소로 의역(?)하죠. ASP.NET 에서 단일 서버라면 모르지만, 웹팜(Web farm - 모르신다면 당장 찾아 보세요. 롸잇 놔우)에서는 세션 상태 정보를 저장하기 위해서 세션 State Server를 구성하거나 MS SQL을 이용하여 세션 정보를 저장할 수  있도록 저장소를 두는 방법이 있었습니다. 근데, 문제는 두 State Server 다 거의 Raw데이타에 가까운 정보들이 날(Raw)로 저장되어 엥간한 동시접속자 수를 자랑하는 사이트에서는 엄청난 데이터량이 문제였습니다. 데이터 양도 문제지만 Network Traffic도 데이터 양 비례하게 올라가는 문제를 양산하게 됐죠. 이를 해결하기 위해 Gzip Compression을 사용했다는 군요.
그럼, 본격적으로 Extensible Output Caching에 대해 알아 보도록 하겠습니다.



What is Extensible Output Caching?  

말 그대로 확장 가능한 출력 캐쉬 기능입니다. 쉽게 설명 하자면, 엄연히 Caching 기능은 ASP.NET 1.0부터 있었습니다. 페이지나 컨트롤, HTTP Response의 출력물(뭐 쉽게 말하자면 컴파일러에서 html 코드로 완전히 변환된 상태의 코드)을 서버의 메모리 내에 상주시킴으로써 재생산에 드는 비용을 감소 시키는 데에 일조 하던 기능입니다. 하지만, 이것도 만만찮게 다른 문제를 일으키고는 했는데요 저장소는 무조건 메모리로 박치기 하다보니, 다른 웹 어플리케이션과 메모리 선점 전쟁을 하게 되는 문제가 생기고, 서버 자체적으로는 쓰잘때기 없는 것(일명 쓸애기) 까지 메모리 영역을 점령함으로써 서버 리소스를 잡아먹게 되는 문제가 생긴 것이지요.

그래서, 기존에 있던 기능은 살리고~ 살리고~ 살리고 살리고 살리고 커스텀한 Provider만 Implement(구현)하여 대체 저장소를 선택할 수 있도록 한 기능입니다. 물론 MS SQL 서버에도 저장이 되도록 기능을 갖추고 있습니다.

그럼 실전으로 들어가 정확히 뭐하는 기능인지 코드로 살펴 보도록 하겠습니다.

Walkthrough : Step 1. Create a Web Project

웹 프로젝트를 그림 1-1 과 같이 선택하여 생성합니다.

<그림 1-1>

<그림 1-2>

자~! 여기까지는 많이 하셨을 테니 거두 절미 하고, 솔루션에 CustomOutputCacheProvider Class를 추가하기 위해 클래스 라이브러리 프로젝트를 생성하도록 하겠습니다.
                                                                                                                   <그림 1-3>
                                                                                                                                    <그림 1-4>

프로젝트를 생성하셨다면 TestCustomOutputCacheProvider 클래스를 추가 시킵니다. 그리고, CustomOutputCacheProvider 프로젝트에 System.Web과 System.Confihuration을 참조 추가 시키겠습니다. 이제 어느정도 구색이 갖추어졌습니다.

Walkthrough : Step 2. Implement OutputCacheProvider

이번 단계에서는 개발자 특정 저장소를 지정할 수 있도록 커스텀한 CacheProvider를 생성도록 하겠습니다.

<그림 1-5>

그림 1-5와 같이 System.Web.Caching.OutputCacheProvider 추상 클래스를 Implement할 경우 자동으로 오버라이드 메서드가 생성되는 것을 볼수 있습니다.
                                                                                                                           <그림 1-6>

기능 구현에 많은 시간을 할애 할 수 없는 관계로 간단하게 세션에다가 캐싱을 하도록 구현 하겠습니다. 저장소를 선택하고 구현 하는 부분은 각자 구미가 땡기는 대로 구현하여 보세요.

Walkthrough : Step 3. Setting WebSite

먼저 그림 1-7과 같이 Web.Config파일에 caching 섹션을 추가하고 Provider 섹션을 구성하도록 하겠습니다.
<그림 1-7>
 
여기서 부연 설명 드리겠습니다. <outputCache> 섹션의 Attribute인 defaultProvider는 Web Application에 기본적으로 제공할 OutputCacheProvider입니다. 나중에 나올 Global.asax에서 설정해 주지 않는 이상 자동적으로 AspNetInternalProvider를 제공합니다. 그리고 하위 섹션인 <providers> 섹션 이하 섹션에는 개발자가 커스텀 하게 만들어 놓은 Provider를 넣는 부분입니다. 복수 개의 CacheProvider를 제공할 수 있어 좀 더 성능 향상에 기여 할 수 있습니다.(점점 말투가 딱딱해 지고 있습니다. 퇴근 시간이 훌쩍 넘어서 인지 정신적 압박이...)

그리고나서, Global.asax를 추가 시켜보도록 하겠습니다. 그림 1-8과 같이 새로운 아이템 추가 버튼을 클릭하면 대화 상자에서 Global.asax파일을 선택하여 확인 버튼을 선택합니다.
                                                                                                     <그림 1-8>

추가된 Global.asax 파일을 열고 그림 1-9의 코드를 추가 시켜 줍니다.
                                                                                                                       <그림 1-9>

 
GetOutputCacheProviderName 메서드는 Web.config 파일에 <caching>섹션이 추가 되어 있어야만 호출 되는 메서드 입니다. 그리고 코드를 보면 특정 페이지 에만 "SessionCache"라는 Provider명을 리턴하게 되어 있는데 이 부분은 Web.config의 <provider> 하위 노드의 Name Attribute와 매핑되는 키값입니다. 즉, 특정 페이지에 접근 시 개발자가 원하는 CacheProvider에 접근하여 커스텀한 저장소에 저장하게 하는 기능의 Entry Point 라고 보셔도 무방합니다.

그리고 UserControl을 생성하여 간단한 컨트롤을 작성하여 보겠습니다. 그리고 UserControl 선언적 구문 페이지 상단에는 <%@ OutputCache Duration="60" VaryByParam="None" providerName="SessionCache" %>
을 기입하여 줍니다. Duration의 의미는 소멸되기 까지 대기 시간으로 60초이고 VaryByParam은 Post든 QuerString이든 파라미터가 넘어오는 건마다 페이지를 저장시킬지의 여부를 선택합니다. 그리고 providerName은 해당 UserControl에서 제공할 Provider를 선택하는 Attribute입니다다.
그리고, 한가지 재미 있는점은 여러개의 Provider를 구현 하고 Web.config에 등록 시킨 후 각각 UserControl에 다른 Provider를 등록 시키면 Global.asax에서 한가지 ProviderName을 리턴 하더라도 각각의 Provider 저장소에 저장이 된다는 것입니다.

이제 마지막으로 웹 프로젝트에 CustomOutputCacheProvider 프로젝트를 참조한다. 그림 1-10r과 같이 전체적인 Test 솔루션 구성이 끝이 났습니다.

                                                                                                   <그림 1-10>

Walkthrough : Step 4. Running Web Application and Result

이제 마지막 단계 Test Application을 구동하고 값을 확인하는 작업만 남겨두고 있습니다. F5를 눌러 빌드를 한 후 정상적으로 빌드 성공이 되면 Web browser가 화면에 나타날 것 입니다. 제가 값을 확인 하기 위해 몇개 중단점을 찍어 값을 확인 하는 것으로 이번 아티클을 마무리 할까 합니다.

맨 처음 브라우저가 화면에 나타나고 그림 1-11처럼 Global.asax의 GetOutputCacheProviderName메서드에 중단 점이 걸리는 것을 확인 할 수 있습니다.
                                                                                                                              <그림 1-11>
그 다음 F5를 다시한번 눌러 다음 중단점으로 이동하면  우리가 만들어 놓은 TestCustomOutputCacheProvider 클래스의 Set메서드를 호출하는 것을 확인 할 수 있습니다.

                                                                                                                              <그림 1-12>
Text Visualizer로 값을 확인한 결과 그림 1-13과 같이 렌더된 Html 태그값이 저장소에 저장되는 것을 확인 할 수 있습니다.

                                                                                                         <그림 1-13>
마지막으로 인위적으로 포스트 백을 일으켜 저장소에 저장된 값을 가지고 오는 과정을 확인 하도록 하겠습니다. 화면에 버튼 이벤트를 일으키면 서버 쪽 Global.asax의 GetOutputCacheProviderName메서드를 재 호출 하여 페이지에 할당된 ProviderName을 리턴받은 후 TestCustomOutputCacheProvider 클래스의 Get메서드를 호출하는 것을 확인 할 수 있습니다. Get메서드에서는 이미 저장소에 캐싱된 Html 값이 반환 되어 사용자에게 전달되는 것을 확인 할 수 있습니다.

<그림 1-14>

정말 오늘 길게도 썼습니다. 씁씁후후~ 어떤 메카니즘을 가지고 동작하는지 대충 이해하셨을 듯 합니다. 그럼 다음에도 ASP.NET 4.0에 다른 기능에 대하여 알아보도록 하겠습니다.