Silverlight를 설치하려면 여기를 클릭합니다.*
Korea 대한민국변경|Microsoft 전체 사이트
MSDN
|개발자 센터
MSDN Home   MSDN Home

Extreme ASP.NET
컨트롤 어댑터


이 문서에 사용된 코드 다운로드: ExtremeASPNET2006_10.exe (187KB)

Fritz Onion (영문)

목차
컨트롤 어댑터 만들기
브라우저 인식
CSS 지원 어댑터
응용 프로그램에서 컨트롤 어댑터 사용
요약


ASP.NET 2.0 릴리스에는 컨트롤을 다른 방식으로 렌더링하도록 지정할 수 있는 컨트롤 어댑터라는 기술이 추가되었습니다. 컨트롤 어댑터에 대해 들어 보았다면 아마도 모바일 장치용 컨트롤 렌더링에 관련된 내용이었을 것입니다. 하지만 실제로 컨트롤 어댑터는 클라이언트의 브라우저 유형에 따라 컨트롤 렌더링을 완전히 변경할 수 있는 기능을 제공하므로 다양한 상황에서 유용하게 활용할 수 있습니다.

모바일 장치 렌더링은 컨트롤 어댑터의 가장 눈에 띄는 활용 사례입니다. 휴대폰을 예로 들면 컨트롤의 내용을 HTML이 아닌 WML로 렌더링해야 합니다. 개발자는 Calendar 및 GridView와 같은 익숙한 ASP.NET 컨트롤을 그대로 사용하고 이러한 컨트롤을 WML 장치를 통해 액세스하는 경우에만 컨트롤 어댑터가 작동하여 클라이언트 장치의 제약 조건을 충족하는 대체 렌더링을 제공하는 것이 이상적일 것입니다. 새로운 장치가 시장에 출시될 때마다 컨트롤 어댑터 모음도 업데이트되므로 개발자는 실제 코드나 페이지 내용을 변경할 필요 없이 간단하게 컨트롤 어댑터 목록만 업데이트하면 이러한 새로운 장치에서 기존 웹 콘텐츠를 사용할 수 있게 됩니다.

그러나 서로 다른 규격과 렌더링 기능을 가진 모바일 장치가 기하급수적으로 증가함에 따라 표준 ASP.NET 컨트롤에서 이러한 모든 장치로의 매핑을 만드는 작업이 매우 힘들게 되었습니다. 더 문제가 되는 것은 1024×768 이상 해상도 화면을 대상으로 사이트를 구축하는 개발자들이 상당한 양의 개발자 작업을 거치지 않고는 모바일 장치로 이식할 수 없다고 단정하고 있다는 것입니다. 따라서 현재는 여러 다른 장치에서 잘 작동하는 사이트를 원한다면 사용자의 편의를 위해 독특한 각 장치를 위한 별도의 UI를 만들어야 합니다. ASP.NET 1.x에 추가 기능으로 도입되었으며 2.0에도 포함된 Mobile Control Toolkit을 사용하면 도움이 되지만 아직은 컨트롤 어댑터를 사용하여 다양한 장치에서 훌륭하게 렌더링되는 사이트를 구축한다는 목표가 성취된 것은 아닙니다.

ASP.NET 팀에서 이러한 기술을 CSS Control Adapter Toolkit이라는 형식으로 활용할 수 있는 새롭고 매력적인 방법을 개발했다는 좋은 소식이 있습니다. 이 도구 키트는 www.asp.net/cssadapters (영문)에서 다운로드할 수 있습니다. 이 도구 키트는 특정 장치용 컨트롤을 위한 대체 렌더링을 만드는 대신, Menu, TreeView 및 FormView와 같은 몇 가지 컨트롤에 대한 표 기반의 기본 렌더링을 표를 사용하지 않도록 하고, 대신 이제는 사이트 설계의 일반적인 요구 사항이라고 볼 수 있는 CSS 스타일시트에 정의된 스타일을 <ul>, <div> 및 <span> 요소에 연계하여 컨트롤을 렌더링하는 방식의 여러 컨트롤 어댑터를 정의하고 있습니다. 이 칼럼에서는 컨트롤 어댑터 아키텍처를 소개하고 사용자 에이전트 문자열에 따라 컨트롤 렌더링을 완전히 변경하는 방법을 소개합니다. 그 다음 CSS Control Adapter Toolkit에 대해 설명하고 이 기능을 현재의 사이트에 통합하는 방법을 살펴볼 것입니다.


컨트롤 어댑터 만들기

근본적으로 컨트롤 어댑터는 컨트롤 자체를 수정하지 않고도 컨트롤을 다르게 렌더링할 수 있는 방법입니다. 컨트롤 어댑터는 다른 클라이언트를 위한 대체 렌더링을 제공하기 위해 설계되었으므로 사용자 에이전트 문자열과 브

그림 1 컨트롤 어댑터 아키텍처
그림 1 컨트롤 어댑터 아키텍처
라우저 기능 정의 간의 연결을 정의하는 .browser 파일에 컨트롤 어댑터 매핑을 지정할 수 있습니다. 컨트롤 어댑터 클래스 자체는 Control 기본 클래스와 매우 비슷한 추상 기본 클래스인 System.Web.UI.Adapters.ControlAdapter에서 상속해야 합니다. 여기에는 Init, Load, PreRender 및 Unload 이벤트와 가상 Render 메서드가 있습니다.

컨트롤을 렌더링할 때 내부적으로 Control 기본 클래스는 먼저 컨트롤과 연결된 컨트롤 어댑터가 있는지 확인합니다. 컨트롤 어댑터가 있는 경우 해당 어댑터의 Render 메서드를 호출하며 그렇지 않으면 컨트롤의 표준 Render 메서드를 호출합니다. 그림 1은 컨트롤 어댑터 아키텍처를 보여 줍니다.

자체 컨트롤 어댑터를 만들려면 ControlAdapter 기본 클래스, 또는 이 클래스의 파생 클래스인 WebControlAdapter에서 상속하는 새로운 클래스를 만드는 것으로 시작해야 합니다. 상속할 컨트롤 어댑터 클래스는 어떤 컨트롤에 사용할 어댑터를 만드는가에 따라 결정됩니다. 기본 제공 WebControl에 사용할 어댑터를 만드는 경우에는 WebControl이 렌더링하는 방식을 더 비슷하게 구현할 수 있도록 가상 RenderBeginTag, RenderEndTag 및 RenderContents 메서드를 제공하는 WebControlAdapter를 선택해야 합니다. 데이터 바인딩 컨트롤 및 Menu 컨트롤 역시 각각의 독특한 기능을 액세스하고 수정하기 위한 가상 메서드를 제공하는 컨트롤 어댑터가 정의되어 있습니다.

컨트롤 어댑터를 만들어 특정 컨트롤의 렌더링을 변경하는 방법을 설명하기 위해 여기에서는 BulletedList 컨트롤을 위한 BulletedListControlAdapter라는 이름의 컨트롤 어댑터를 만들 것입니다. 이 간단한 컨트롤은 항목 컬렉션을 순서 있는 목록 또는 순서 없는 목록으로 렌더링합니다(<ol> 또는 <ul>). 어댑터 모델이 얼마나 유연한지 증명하기 위해, 렌더링을 완전히 표 기반으로 변경하는 컨트롤 어댑터를 만들 것입니다. BulletedList는 WebControl에서 파생되므로 WebControlAdapter에서 파생되는 BulletedListControlAdapter 클래스를 만드는 것으로 시작할 것입니다. 다음은 테이블의 여는 태그와 닫는 태그를 렌더링하는 RenderBeginTag 및 RenderEndTag 메서드를 재정의한 다음 마지막으로 BulletedList 컨트롤의 항목을 대상으로 반복하여 별표(*) 접두사를 붙인 표의 한 행으로 렌더링하도록 RenderContents를 재정의할 것입니다. 그림 2는 전체 컨트롤 어댑터 구현을 보여 줍니다.

다음 단계는 BulletedListControlAdapter 클래스를 BulletedList 컨트롤과 연결하는 것입니다. 앞에서 설명한 대로 이 작업은 대상으로 하는 브라우저의 종류를 지정하는 과정에 해당합니다. 여기에서는 간단하게 필자의 .browser 파일에 있는 browser 요소의 refID 특성 값을 Default로 지정하여 모든 브라우저를 이 어댑터와 연결했습니다. 좀 더 세부적인 연결을 만드는 방법은 다음 섹션에서 설명합니다. 이 샘플에서는 MyAdapters.browser라는 이름으로 새 파일을 만들고 응용 프로그램의 App_Browsers 디렉터리에 저장하였습니다.

<browsers>
  <browser refID="Default">
    <controlAdapters>
      <adapter 
        controlType="System.Web.UI.WebControls.BulletedList"
        adapterType="MsdnMagazine.BulletedListControlAdapter" 
      />
    </controlAdapters>
  </browser>
</browsers>

이 로컬 파일에 정의되는 추가 브라우저 정의 또는 컨트롤 어댑터는 시스템의 브라우저 구성 파일에 이미 정의된 브라우저 및 어댑터 컬렉션에 추가됩니다.

마지막 단계는 그림 3에서 볼 수 있는 것처럼 BulletedList 컨트롤의 인스턴스에 약간의 항목을 추가하여 페이지에 표시하는 것입니다.

.browser 파일을 제거하거나 표준 XML 주석 구문을 사용하여 .browser 파일에서 컨트롤 어댑터 매핑 부분을 주석으로 처리하는 방식으로 컨트롤 어댑터를 사용하지 않고 페이지를 실행하면 BulletedList는 예상대로 <ul> 요소와 <li> 하위 요소를 사용하여 렌더링됩니다.

<ul id="_bulletedList">
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
  <li>Item 4</li>
</ul>

그러나 컨트롤 어댑터를 사용하면 실제 .aspx 페이지는 전혀 변경하지 않고 렌더링 프로세스를 사용자 지정 어댑터에 정의된 새로운 표 기반 방식으로 변경할 수 있습니다(그림 4 참조).

여기서 알 수 있듯이 컨트롤 아키텍처를 사용하여 컨트롤의 대체 렌더링을 만드는 과정은 그리 어렵지 않습니다. 그러나 이 시점에서 반드시 확인해야 하는 몇 가지 문제가 있습니다. 첫 번째로, BulletedList 렌더링은 단순화되어 있어 항목 컬렉션을 제외하고 BulletedList 컨트롤의 다른 특성은 고려하지 않습니다. 고려되지 않은 특성에는 렌더링하는 목록의 유형(순서 없는 목록, 숫자 목록, 영문자 목록 등)을 결정하는 중요한 BulletStyle 특성도 포함됩니다. 일반적으로 컨트롤 어댑터는 대상 컨트롤의 동작 특성을 모두 지원하는 것이 중요합니다. 반면에 스타일 특성을 렌더링에 반영하는 것이 이치에 맞지 않는 경우도 있습니다. 흑백 장치에서의 BackColor 특성과 같이 컨트롤 어댑터의 대상 장치에서 표시할 수 없는 스타일이 이러한 예입니다. 뒤에서 살펴보겠지만 CSS 컨트롤 어댑터는 렌더링하는 컨트롤의 스타일 특성 대부분을 무시하며 대신에 모양을 지정하기 위해 수정할 수 있는 CSS 클래스 집합을 제공합니다.

두 번째로, BulletedListControlAdapter는 단순한 예이므로 특정 사용자 에이전트를 이 어댑터와 연결하는 브라우저 매핑을 활용하지 않아 그다지 현실성이 없습니다. 대신 필자는 refID 특성을 Default로 지정하여 모든 브라우저 유형이 이 컨트롤 어댑터를 사용하도록 했습니다. 이것은 이 컨트롤 어댑터가 설치된 사이트에서는 절대 BulletedListControl의 표준 렌더링을 호출하지 않고 항상 컨트롤 어댑터에서 제공한 방식으로 렌더링한다는 것을 의미합니다. 기존 컨트롤과 다르게 컨트롤을 렌더링하는 것이 유일한 목표라면 기존 컨트롤 클래스에서 파생된 클래스를 만들고 렌더링을 변경하는 데 필요한 메서드만 재정의하는 것이 한 가지 방법입니다. 파생된 사용자 지정 컨트롤에 비해 컨트롤 어댑터가 가지는 잠재적인 이점은 페이지나 web.config 파일을 변경하지 않고도 웹 응용 프로그램에 적용할 수 있다는 것입니다. 따라서 컨트롤 어댑터는 응용 프로그램 작성과 배포가 완료되었지만 전체 사이트에 걸쳐 특정 컨트롤의 렌더링을 변경해야 하는 상황에서는 브라우저별로 렌더링을 다르게 할 필요가 없더라도 상당히 매력적인 선택 사항입니다.


페이지 맨 위로페이지 맨 위로

브라우저 인식

지금까지 살펴본 바와 같이 컨트롤 어댑터를 컨트롤에 매핑하기 위해서는 .browser 파일의 구성을 지정하면 됩니다. ASP.NET 2.0에서 브라우저 인식 기능은 machine.config 및 web.config의 <browserCaps> 요소에서 .browser 파일의 모음으로 옮겨졌습니다. <browserCaps> 요소는 계속 지원되지만 이보다는 응용 프로그램의 로컬 App_Browsers 디렉터리 또는 시스템의 %SYSTEM%\Microsoft.NET\Framework\v2.0.50727\Config\Browsers 디렉터리에 있는 .browser 파일에 브라우저 기능을 지정하는 것이 좋습니다. 브라우저 인식 파일의 목적에는 컨트롤 어댑터를 연결하는 것 이외에도 요청이 Request.Browser 속성을 통해 액세스할 수 있는 HttpBrowserCapabilities 클래스를 채우는 것이 있습니다. 이 클래스를 통해 요청 브라우저의 이름과 함께 JavaScript, 쿠키 및 기타 기능의 지원 여부를 알아낼 수 있습니다. 각 .browser 파일에는 이 클래스를 채우기 위한 <browser> 요소가 한 개 이상 포함되며 일반적으로 각 <browser> 요소에는 사용자 에이전트 문자열 또는 각 요청에 대해 상위 브라우저 클래스에서 가져온 특정한 기능과 비교하기 위한 정규식(선택적으로 제외 식도 지정 가능)을 포함하는 identification이라는 하위 요소가 있습니다. 이 요소가 일치하는 경우 브라우저가 무엇인지 확인된 것이며, 그에 따라 사용 가능한 기능 목록으로 HttpBrowserCapabilities 클래스가 채워집니다. 예를 들어 그림 5는 Internet Explorer에 해당하는 브라우저 정의(시스템의 Browsers 디렉터리에 있는 ie.browser 파일에 있음)를 보여 주고 있습니다.

그림 5 브라우저 유형 계층
그림 5 브라우저 유형 계층

브라우저 역시 <browser> 요소의 parentID 특성을 사용하여 계층적으로 그룹화됩니다. 다른 <browser> 요소를 참조하는 parentID가 있는 <browser> 요소가 적용되려면 상위 요소에 대한 정규식 조건이 먼저 맞아야 합니다. 계층의 루트인 "Default"는 모든 사용자 에이전트 문자열과 일치하는, 최소 기능을 갖춘 브라우저를 의미합니다. 다른 모든 브라우저 유형은 Default의 하위 항목입니다. 시스템의 Browsers 디렉터리에 있는 미리 정의된 브라우저 정의 집합에는 브라우저 하위 집합을 식별하는 데 사용할 수 있는 브라우저 유형 및 연관된 이름의 유용한 분류가 포함되어 있습니다. 예를 들어 Internet Explorer 버전 6.0 이상에서 전송한 모든 요청에 컨트롤 어댑터를 적용하려면 로컬 browser 요소의 refId 특성에 "IE6to9"라는 브라우저 이름을 사용하면 됩니다. 그림 6은 시스템 .browser 파일에 정의된 브라우저 유형의 계층을 보여 줍니다(이보다 두 배 이상 큰 별도 계층을 구성하는 모바일 장치는 제외).

컨트롤 어댑터를 할당할 때는 이러한 브라우저 이름 중 어떤 것이나 refID 특성에 사용할 수 있습니다. 한 예로 CSS Control Adapter Toolkit의 경우 도구 키트에 정의된 어댑터를 적용하려면 브라우저에서 CSS 기능을 지원해야 하므로 refID가 IE6to9, MozillaFirefox, Opera8to9 또는 Safari인 브라우저에만 어댑터를 적용합니다. 여기에 해당하지 않는 다른 브라우저에는 표준 컨트롤 렌더링을 사용합니다.


페이지 맨 위로페이지 맨 위로

CSS 지원 어댑터

2006년 4월 Microsoft는 CSS를 보다 잘 활용할 수 있도록 몇 가지 일반적인 ASP.NET 컨트롤의 렌더링을 변경하는 컨트롤 어댑터의 집합인 CSS-Friendly ASP.NET 2.0 Control Adapters 베타 1.1이라는 이름의 샘플 집합을 발표했습니다. 이 집합이 설계된 주요 이유는 ASP.NET을 사용하는 개발자들이 서버 쪽 특성 대신 CSS 스타일시트를 사용하여 레이아웃과 같은 컨트롤의 모든 스타일 특성을 지정해야 했기 때문입니다. 초기 릴리스에는 Menu, TreeView, DetailsView, FormView 및 DataList 컨트롤에 대한 어댑터가 포함되었습니다.

이 모음의 각 컨트롤 어댑터는 두 가지 스타일시트와 함께 제공됩니다. 첫 번째는 어댑터의 핵심 스타일 집합을 포함하며 이에 대해서는 개발자의 수정이 거의 필요하지 않습니다. 두 번째는 응용 프로그램에 포함된 컨트롤의 모양을 관리하기 위해 변경이 필요한 스타일 집합을 포함합니다. 예를 들어 MenuAdapter 샘플은 Menu.css 파일 및 MenuExample.css 파일과 함께 제공되는데 첫 번째 파일은 개발자가 변경할 필요가 거의 없는 반면 두 번째 파일에는 컨트롤 어댑터에서 렌더링하는 메뉴의 모양을 변경하는 배경색, 글꼴 및 오프셋과 같은 스타일 특성이 있습니다. 자주 변경되는 스타일 특성은 모두 최상위 CSS 클래스에 포함되므로 각각 다른 클래스 아래에 여러 스타일 집합을 만들 수 있습니다. CssSelectorClass 특성을 사용하여 특정 컨트롤이 사용할 스타일 집합을 지정할 수 있으며 컨트롤 어댑터는 이 특성을 확인하고 해당 컨트롤에서 CSS 클래스를 렌더링되는 HTML 요소에 매핑하는 데 사용합니다. 예를 들어 MenuAdapter는 MenuExample.css의 최상위 PrettyMenu CSS 클래스 아래에 스타일의 컬렉션을 정의합니다. MenuAdapter를 사용할 때 이 스타일 집합을 적용하려면 다음과 같이 CssSelectorClass를 PrettyMenu로 지정하면 됩니다.

<asp:Menu ID="_mainMenu" runat="server" 
          DataSourceID="_siteMapDataSource"
          CssSelectorClass="PrettyMenu" SkinID="MainNav"
          Orientation="Horizontal" />

이러한 컨트롤 중 하나에 대한 어댑터가 설치되면 해당 어댑터에 의해 렌더링이 수정되는 컨트롤의 모든 인스턴스가 사용자의 .css 파일에 정의된 스타일 특성을 사용하여 렌더링을 수행하며 해당 태그의 서버 쪽 컨트롤에 직접 정의된 스타일 속성은 무시하게 됩니다. Visual Studio® 디자이너는 컨트롤 어댑터 렌더링을 반영하지 않으므로 어댑터를 설치한 뒤에는 어댑터가 렌더링하는 컨트롤의 스타일 특성을 로컬에서 설정하더라도 이것이 유지될 것으로 기대할 수 없습니다.


페이지 맨 위로페이지 맨 위로

응용 프로그램에서 컨트롤 어댑터 사용

이러한 컨트롤 어댑터를 ASP.NET 응용 프로그램에 통합하는 방법을 설명하기 위해 기존 웹 응용 프로그램에 MenuAdapter를 추가하기 위한 단계를 순서대로 설명하겠습니다. 이러한 단계의 일부 세부 사항은 도구 키트 샘플의 이후 릴리스에서 미세하게 변경될 수 있지만 핵심 요소는 변경되지 않을 것입니다.

현재 도구 키트는 Visual Studio 웹 프로젝트 템플릿으로 제공되므로 첫 번째 단계는 CSS Friendly ASP.NET Control Adapters 템플릿을 사용하여 웹 사이트를 만드는 것입니다. 결과 프로젝트에는 각 컨트롤 어댑터의 예가 각각의 프로젝트로 포함됩니다.

다음은 MenuAdapter.cs 및 Utility.cs 소스 코드 파일(Visual Basic® 프로젝트를 선택한 경우 .vb 파일)을 생성된 프로젝트의 App_Code 디렉터리에서 웹 응용 프로그램의 App_Code 디렉터리로 복사합니다. 이러한 파일을 여러 프로젝트에 걸쳐 사용하려는 경우에는 어셈블리로 컴파일하고 GAC(전역 어셈블리 캐시)에 전역적으로 배포할 수 있습니다.

이제 CSSFriendlyAdapters.browser 파일을 생성된 프로젝트의 App_Browsers 디렉터리에서 웹 응용 프로그램의 App_Browsers 디렉터리로 복사합니다. CSSFriendlyAdapters.browser 파일을 수정하여 사용하지 않는 어댑터(이 예에서는 TreeView, DetailsView, FormView 및 DataList)에 대한 참조를 제거한 다음 생성된 프로젝트의 App_Themes 디렉터리에서 Basic 및 Enhanced 디렉터리를 웹 응용 프로그램의 App_Themes 디렉터리로 복사합니다. 이러한 디렉터리에는 MenuAdapter에 필요한 .css 파일과 지원 그래픽 파일이 포함됩니다. 프로젝트에서 이미 테마를 사용하고 있는 경우에는 이러한 디렉터리 중 하나(선호하는 모양 선택)의 내용만 Menu 컨트롤을 포함하는 모든 페이지에 적용될 기존 테마 디렉터리에 복사해도 됩니다.

이제 테마 디렉터리에서 사용하지 않는 css 파일은 제거해도 됩니다(이 예에서는 FormView.css 및 FormViewExample.css).

다음은 생성된 프로젝트의 JavaScript 디렉터리를 웹 응용 프로그램 루트로 복사해야 합니다. MenuAdapter 클래스가 작동하려면 이 디렉터리에 AdapterUtils.js 및 MenuAdapter.js 파일이 있어야 합니다. 그런 다음 Menu 컨트롤이 있는 모든 페이지를 Basic 또는 Enhanced 테마로 등록합니다. 마스터 페이지를 사용하는 경우에는 web.config 파일을 사용하여 이 작업을 전역적으로 수행할 수 있습니다. 이 단계는 테마에서 자동으로 관리하는 테마 디렉터리에 있는 필요한 .css 파일에 대한 링크를 Menu 컨트롤이 있는 각 페이지에 넣기 위한 것입니다.

마지막으로 각 Menu 컨트롤의 CssSelectorClass 특성을 각 컨트롤이 해당 모양과 레이아웃을 위해 사용할 최상위 CSS 클래스를 참조하도록 연결합니다. 앞서 소개했듯이 이 샘플에는 PrettyMenu를 사용합니다.

이제 모든 Menu 컨트롤은 표 대신 <ul> 요소를 사용하여 렌더링되며 MenuExample.css에 포함된 CSS 스타일에 의해 Menu 컨트롤의 모양이 정의됩니다. 이제 사용자의 스타일 정의를 사용하여 MenuExample.css를 모델링하는 새로운 스타일시트 클래스를 만든 다음 새 스타일 집합을 가리키도록 CssSelectorClass를 수정할 수 있습니다.


페이지 맨 위로페이지 맨 위로

요약

컨트롤 어댑터 아키텍처를 사용하면 컨트롤 자체에 대한 수정 없이도 요청을 수행한 브라우저의 유형에 따라 개별 컨트롤의 렌더링을 완전하게 변경하는 것이 가능합니다. 이 인프라는 원래 모바일 장치를 위한 대체 렌더링을 지원하기 위해 시작되었지만 CSS Control Adapter Toolkit에서 이 기술의 완전히 다른 새로운 용도를 제시했으며 이러한 용도는 모든 스타일을 CSS 파일에 중앙 집중 방식으로 정의하는 사이트를 구축하는 ASP.NET 개발자에게 상당히 유용합니다.


페이지 맨 위로페이지 맨 위로


Fritz에게 질문이나 의견이 있으면 메일을 보내시기 바랍니다.  xtrmasp@microsoft.com.

Fritz OnionFritz Onion은 Microsoft .NET 교육 제공업체인 Pluralsight의 공동 창립자이며 이곳에서 웹 개발 커리큘럼을 이끌고 있습니다. Fritz는 Essential ASP.NET(Addison Wesley, 2003) 및 출간 예정인 Essential ASP.NET 2.0(Addison Wesley, 2006)의 저자입니다. Fritz의 웹 사이트 주소는 pluralsight.com/fritz (영문)입니다.


페이지 맨 위로페이지 맨 위로QJ: 061012

Microsoft