태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.
   情  
Front Page
Tag | Location | Media | Guestbook | Admin   
 
'ASP.NET'에 해당하는 글(15)
2009.09.08   LINQ to SQL을 사용하는 Application의 성능향상을 위한 10가지 제안
2009.09.08   [ASP.NET] Calendar Extender의 줄바꿈 문제 해결하기
2009.05.06   ASP.NET VisualStudio의 localhost에서 FireFox 속도 저하현상 해결 (1)
2009.04.03   ASP.NET 중첩 마스터 페이지의 FindControl
2009.03.05   ASP.NET $get(), $find의 차이점 (1)
2009.02.02   ASP.NET Ajax Accordion Control
2008.12.05   ASP.NET 3.5 GridView에서 Ajax Pop-up을 이용한 상세정보 표시 (2)
2008.10.12   ASP.NET 잠재적 위험이 있는 Request.Form 값을 발견했습니다. (1)
2008.02.19   ASP.NET 다중 파일 저장 예제 (2)
2008.01.09   ASP.NET 탐색 컨트롤


LINQ to SQL을 사용하는 Application의 성능향상을 위한 10가지 제안

LINQ to SQL을 이용하면 Data Access작업에서 (과거에 비해) 놀라울 정도의 생산성 향상을 가져옵니다. 하지만, 그만큼 성늠이 우수한가에 대한 의문을 가질 수 밖에 없는 것은 사실입니다. 하지만 몇 가지 Benchmark들을 확인하면, LINQ to SQL을 제대로 사용하면, ADO.NET SQL DataReader의 93%의 성능까지 낼 수 있다고 합니다.

따라서 여기에서는 LINQ to SQL을 이용하여 데이터를 조회하고 수정하는데 있어서 성능을 향상시킬 수 있는 10가지 중요한 Tunning Point를 정리해드립니다.

  1. DataContext의 ObjectTrackingEnabled 속성이 필요하지 않다면, Off로 설정하십시요.
    만약 당신이 데이터를 조회만 하고, 데이터를 수정하지 않는다면 DataTracking 기능은 필요치 않습니다. DataTracking는 Server Memory에 올려진 LINQ데이터의 변화를 추적하여 DataContext.SubmitChage()되는 순간 그 변화를 반영하는 기능을 합니다. 만약 데이터를 조회만 한다면 아래와 같이 사용하십시요.
    using (DataClassesDataContext db = new DataClassesDataContext())
    {
         db.ObjectTrackingEnabled = false;
    }
  2. 전체 DB 개체들을 하나의 DataContext에 포함하지 마십시요.
    DataContext는 하나의 작업 단위를 표현해야지, 전체 DB를 표현해서는 안됩니다. 만약 당신의 DB개체 중에서 다른 개체와 연결되지 않고 독립적으로 동작하거나, 전혀 사용되지 않는 개체가 있다면, 그 개체들은 다른 DataContext로 분리하십시요. 만약 하나의 DataContext에 포함되어 있다면, 이러한 개체들은 DataContext를 선언할 때 불필요하게 메모리를 차지하며, DataConText의 CUD엔진이 사용하는 관리, 추적, 식별 비용을 증가시킬 뿐입니다.
    대신, 각 작업단위로 DataContext를 분리하는 것을 고려하십시요. 물론, Connection Pooling의 장점을 잃지 않기위해, 생성자를 이용하여 같은 Connection을 사용하도록 설정할 수 있습니다.
  3. 어디서든지 필요하다면 CompiledQuery를 이용하십시요.
    LINQ to SQL을 이용하여 표현식을 만들고 실행하기 위해서는 몇가지 단계가 존재합니다. 몇 가지 나열한다면 다음과 같습니다.
    1. Expression Tree의 생성
    2. Expression Tree를 SQL로 변환
    3. 생성된 SQL Query 실행
    4. 데이터 조회
    5. 조회된 데이터를 객체로 변환
    만약 당신이 같은 LINQ to SQL Query를 반복해서 사용한다고 할 때, 위의 과정 역시 반복된다고 한다면 그것은 불필요한 자원 낭비가 아닐 수 없습니다. 이 것이 바로 작은 System.Data.Linq 네임스페이스가 많은 자원을 소모하는 주 이유가 될 것입니다(같은 작업을 불필요하게 반복하는 것). CompiledQuery는 표현식을 Compile한 다음 이 것을 어딘가에 저장해둡니다. 그리고 같은 작업이 호출 되면 저장된 것을 통해 불필요한 Compile작업이 반복되는 것을 피하게 해줍니다. 이 기능은 정적 CompiledQuery.Compile메서드에 의해 실현할 수 있습니다. 예제는 다음과 같습니다.
    /*
     아래 NameSpance 선언 필요
     using System.Collections.Generic;
     using System.Data.Linq;
    */
    Func<DataClassesDataContext, IEnumerable<People>> func =
    	CompiledQuery.Compile<DataClassesDataContext, IEnumerable<People>> ((DataClassesDataContext db) => db.Peoples.Where<People>(t => t.PeopleName == "손대관"));
    이제 "func"는 Compiled Query로서 첫 실행시 단 한번만 Compile되게 됩니다. 다음 코드는 Compiled Query를 생성해서 Static Utility Class에 저장하는 예제입니다.
    /*
     아래 NameSpance 선언 필요
     using System.Collections.Generic;
     using System.Data.Linq;
    */
    public static class QueriesUtility
    {
    	public static Func<DataClassesDataContext, IEnumerable<People>> GetActivePeoples 
     	{
    		get
    		{
    			Func<DataClassesDataContext,IEnumerable<People>> func = 
    				CompiledQuery.Compile<DataClassesDataContext, IEnumerable<People>> ((DataClassesDataContext db)
    					=> db.Peoples.Where<People>(t => t.ActiveCheck = false));
    			return func;
    		}
    	}
    }
    이제 우리는 언제든지 위의 Compiled Query를 호출해서 사용할 수 있습니다.
    using (DataClassesDataContext db = new DataClassesDataContext())
    {
    	IEnumerable<People> p = QueriesUtility.GetActivePeoples(db);
    	lblTest.Text = p.Count().ToString();
    }
    이렇게 저장하고 실행하는 것은 반복적인 호출 비용을 단 한 1번의 호출 비용으로 감소시켜줍니다. 위와 같은 Compiled Query를 많이 만들어 둔다고 성능이 저하되지 않는 가 걱정하실 필요도 없습니다. 모든 Compiled Query는 처음 실행 될 때 단 한번만 Compile됩니다.
  4. DataLoadOptions.AssociateWith를 사용하여 필요한 데이터만 조회하세요.
    우리는 Primary Key로 연결된 관련된 데이터들을 한번에 읽어들여야 할 때, Load 또는 LoadWith를 사용합니다. 하지만 대부분의 경우 추가적인 필터링을 하게 되는데요, 이 경우 DataLoadOption.AssociateWith라는 Geniric Method는 매우 유용합니다. 이 뿐만 아니라 데이터를 조회할 때 필요한 데이터만 조회하는 것은 성능향상을 위한 첫걸음 입니다.
  5. 필요하지 않다면 Optimistic Concurrency을 끄세요.
  6. DataContext에 의해서 생성되는 데이터 조회 Query를 지속적으로 확인하세요.
    데이터를 조회할 때, DataContext는 Query를 자동으로 생성하는데요, 실제로 사용되지 않는 불필요한 코드가 생성될 수 있습니다. 성능개선을 위해서는 생성되는 Query를 지속적으로 감시하고, 불필요한 코드가 생성되지 않도록 LINQ to SQL 표현식을 수정해야 할 것입니다. 우리는 DataContext의 Log 속성을 이용해서 생성된느 SQL문을 볼 수 있습니다.
    using (DataClassesDataContext db = new DataClassesDataContext())
    {
    	System.IO.StreamWriter httpResponseStreamWriter = 
    		new StreamWriter(HttpContext.Current.Response.OutputStream);
    	db.Log = httpResponseStreamWriter;
    }
    위 코드는 생성된느 SQL문을 화면에 출력하는 코드입니다. Response개체 대신에 대상을 파일로 지정하는 것도 좋은 방법입니다.

    다른 방법은 'LINQ to SQL Debug Visualizer'를 사용하는 방법입니다. Debug 모드에서 손쉽게 생성된 SQL을 확인하고 실행할 수 있습니다. 'LINQ to SQL Debug Visualizer'에 대한 정보와 설치는 여기를 참조하세요.

  7. Attach()가 불필요한 Entity를 Context에 Attach하지 않도록 하세요
    조회된 Entity는 보통 DataContext에 연결되어 있으며, 내부적인 데이터 변화가 하나하나 추적되는 상태입니다. 이 상태에서는 Entity의 Update, Delete가 매우 쉽습니다. 하지만 Entity를 Serialize한 경우 처럼 DataContext와 Entity의 연결이 끊어진 상태도 존재합니다. 이럴 때 Attach를 통해 DataContext와 Entity를 연결하게 되는데, Entity를 Update 또는 Delete 할 경우에 Attach를 하는 것은 크게 문제가 되지 않습니다. 하지만 Update나 Delete하지 않음에도 Attach를 하는 경우가 있습니다. 이런 실수가 가장 많이 발생하는 경우가 바로 AttachAll()메서드로 Entity Collection을 DataContext로 연결하는 경우입니다.
    Object Tracking는 DataContext에 연결된 모든 개체의 Update, Delete를 추정하고 반영해주는 매우 멋진 기능이긴 하지만, 그만큼 많은 자원을 소모합니다. 따라서 위와 같이 Update, Delete가 되지 않는 Entity를 Attach하여 불필요하게 Entity가 추적되도록 하는 일은 최대한 피해야합니다.
  8. 불필요하게 Object Tracking가 작동하지 않는지 확인하세요
    다음과 같은 두 코드가 있을 때, 어느 쪽이 성능이 더 빠른지 생각해보라.
    예1)
    using (DataClassesDataContext db = new DataClassesDataContext())
    {
    	IQueryable<People> peopleList = db.Peoples
    		.Select(t => t);
    }
    
  9. 예2)
    using (DataClassesDataContext db = new DataClassesDataContext())
    {
    	var peopleList = db.Peoples
    		.Select(t => new
    		{
    			activeCheck = t.ActiveCheck,
    			deleteCheck = t.DeleteCheck
    		});
    }
    두 번째 표현식은 필요한 데이터를 걸러서 조회하고 있으며, 데이터 타입도 기존의 개체를 사용하는 것이 아닌 Var 타입을 사용하고 있기에, 첫번째 표현식이 더 빠를 것이라 생각할 수 있습니다. 하지만 실제로는 두번째 표현식이 더 자원을 적게 소모합니다. 첫 번째 표현식은 아직까지 Update, Delete 기능이 모두 지원하는 상태로 조회가 되므로 자원을 많이 소모합니다. 즉 첫번째 표현식은 Object Tracking가 동작하는 상태이며, 따라서 내부적으로는 데이터의 변화가 모두 일일이 추적되고 있는 상태입니다. 하지만 두번째 표현식 처럼 필요한 데이터를 걸러서 조회를 하게 되면, 조회된 List는 ReadOnly로 변하게 되며, 자연스럽게 보다 빠르게 동작합니다.
  10. 필요한 행만 걸러서 조회하세요.
    ListView에 데이터를 바인딩하고 Paging기능을 사용한다고 할 때, 우리는 Take와 Skip를 통해 필요한 페이지의 행만 조회할 수 있습니다. Skip, Take를 사용하지 않고 조회된 LINQ to SQL 결과를 바로 바인딩할 수 있지만, 그럴 경우 DB의 모든 데이터를 불러오기 때문에 행의 수에 비래하여 ListView의 속도도 느려집니다.
    아래는 해당페이지에 필요한 데이터만 조회하는 구문입니다.
    int intPageSize = 10;
    int intPageNum = 2;
    using (DataClassesDataContext context = new DataClassesDataContext())
    {
    	listView.DataSource = context.Peoples.Skip(intPageNum * intPageSize).Take(intPageSize);
    	listView.DataBind();
    }
    
  11. CompiledQuery를 오용하지 마세요.
    '어떻게 COmpiledQuery를 오용할 수 있는거지?'라는 생각을 하고 계신건 아닌지 모르겠네요. 여기서 하고자하는 말은 불필요한 최적화는 없어야 한다는 것입니다. CompiledQuery는 최소한 한번 이상 사용될 때에만 사용해야합니다.
    일반적인 LINQ to SQL 문장이 CompiledQuery 문장보다 더 빠릅니다. 왜냐하하면 CompiledQuery는 SQL Expression을 유지하고, 재사용하는 등의 모든 고려사항을 반영하기 위한 특별한 처리를 내부적으로 담고있기 때문입니다. 따라서 단순히 조회를 하는 일반적인 LINQ to SQL Expression 보다 무거울 수 밖에 없습니다.


신고
Tag : ASP.NET

name    password    homepage
 hidden


[ASP.NET] Calendar Extender의 줄바꿈 문제 해결하기

Calendar Extender를 사용할 때 발생하는 문제 하나 있는데요, 다음 그림을 통해 설명 드리도록 하겠습니다.

<asp:TextBox ID="date" runat="server" />
<AC:CalendarExtender ID="ce" runat="server" TargetControlID="date" />
<asp:RadioButton ID="am" runat="server" GroupName="rbtSendAmOrPm" Text="오전" />
<asp:RadioButton ID="pm" runat="server" GroupName="rbtSendAmOrPm" Text="오후" />
<asp:TextBox ID="tbxSendHour" runat="server" /> 시
<asp:TextBox ID="tbxSendMinute" runat="server" /> 분

위 코드를 작성한 다음 실행하면 다음 화면이 나타납니다.

before

CalendarExtender의 Target Control을 선택하면 다음과 같은 화면으로 Line이 먹히는 것을 볼 수 있습니다.

calendar

아래는 Calendar Extender를 닫은 화면입니다.

after

이와 같은 문제를 해결하기 위해서는 다음과 같은 간단한 StyleSheet Code를 추가하시면 됩니다.

.ajax__calendar { display: inline; }

 

아래는 Style가 적용된 후 화면입니다.

calendarAfter

 

감사합니다.

신고
Tag : ASP.NET

name    password    homepage
 hidden


ASP.NET VisualStudio의 localhost에서 FireFox 속도 저하현상 해결

VisualStudio(2005 또는 2008)를 사용하여, 웹어플리케이션을 실행하면 localhost로 실행이 되는데요. 이 때, firefox에서 속도가 상당히 저하되는 현상을 보이기도 합니다. 이 문제는 IPv6와 DNS에 관련되어 발생하는 문제입니다.

따라서 이문제를 해결하는 방법은 간단합니다. Firefox에서 IPv6 DNS를 꺼버리면됩니다.

  1. firefox 주소창에 about:config를 입력합니다.
  2. network.dns.disableIPv6를 찾습니다.
  3. 더블클릭하여 값을 true로 만듭니다.
  4. 문제가 해결되었는지 확인해봅시다.

또 다른 방법으로는 다음이 있다고 합니다. 문제가 되는 Windows파일을 삭제해버리는 방법으로서 문제의 원인을 없애버리는 것입니다.

  1. C:\WINDOWS\system32\drivers\etc 폴더로 이동합니다.
  2. hosts 파일을 삭제합니다.
  3. 문제가 해결되었는지 확인해봅시다.
신고
Tag : ASP.NET
Commented by at 2011.08.13 00:12 신고  r x
오~ 실행하고 한참뒤에 켜지던게... 첫번째 방법그대로 하니.. 바로 뜨네요!

name    password    homepage
 hidden


ASP.NET 중첩 마스터 페이지의 FindControl

중첩 마스터 페이지의 경우, 마스터페이지의 컨트롤을 찾기위해서는 다음과 같이 최상단의 Master Page로 이동 후, 단계적으로 찾아 내려오는 과정이 필요합니다.

예를들어 마스터페이지가 2개 중첩된 경우, Master.Master을 이용하여 최상단 MasterPage로 이동하는 과정이 필요하며, 최상단에서 ContentPlaceHolder을 찾아서 단계적으로 하위로 이동하여 자신이 원하는 컨트롤을 찾아야합니다.

MasterPage : firstContentPlaceHolder
MasterPage : secontPlaceHolder
<asp:Label id="targetLabel" />
ASPX Page : ContentPage
 

위의 페이지 구조를 가지는 경우, ContentPage에서  targetLabel을 컨트롤 해야하는 경우, 먼저 다음과 같은 코드로 Label을 찾아야합니다.

- ASPX Content Page에서 targetLabel을 컨트를 하는 방법
Label
targetLabel = this.Page.Master.Master
    .FindControl("firstContentPlaceHolder")
    .FindControl("secondContentPlaceHolder")
    .FindControl("targetLabel")as Label;

targetLabel.Text = "Hello ASP.NET";

신고
Tag : ASP.NET

name    password    homepage
 hidden


ASP.NET $get(), $find의 차이점

ASP.NET에서 ScriptManager가 페이지에 위치했을 때 자바스크립트에서는 $get()과 $find()를 사용할 수 있게 됩니다.

1.$GET()

$get는 docuemnt.getElementById와 element.getElementById 함수를 간단하게 사용할 수 있게 합니다. $get함수는 ASP.NET AJAX client sidle librarySys.UI.DomElement.getElementById와 관련이 있으며, 따라서 페이지에 ScriptManager을 위치시켰을 때에 비로소 사용할 수 있습니다. $get함수는 두가지 매개변수를 받습니다. 첫번째는 찾을 컨트롤의 id이며, 두번째는 선택적으로 사용가능한 '찾을 컨트롤이 포함된 부모 Element'입니다.

$get(id, element);

만약 디버깅 모드에서 $get함수를 찾아보면 다음과 같은 코드로 이루어져 있음을 알 수 있습니다.

function get(id, element)
{
        //  validation code that was removed

        if (!element) return document.getElementById(id);
        if (element.getElementById) return element.getElementById(id);

        //  manual DOM walk that was removed ...
    }

* 주의 : $get은 getElementById와 동일합니다. 따라서 서버컨트롤의 경우 ClientID를 $get()의 매개변수로 사용해야합니다. 한가지 더 참고할 점은, 특정 id를 가진 컨트롤을 찾을 필요없이, 해당 id를 적어주는 것만으로도 자바스크립트에서 해당 id를 갖는 컨트롤을 매핑시켜준다는 점입니다.
<span id="spanid">span text</span>
위의 코드에서는 아래의 코드가 작동합니다.(IE6, 7, FF 모두 가능)
alert(spanid.innerHTML);

2. $FIND() 

ASP.NET AJAX 컨트롤의 ID또는 BehaviorID로 해당 컨트롤을 찾을 수 있게합니다. 마찬가지로 2가지 매개변수를 받는데 첫번째는 찾을 ASP.NET AJAX 컨트롤의 id, 두번째는 선택적으로 사용가능한 '찾을 컨트롤을 포함하는 ASP.NET AJAX 컨트롤 또는 부모 Element'입니다.

$find(id, parent);

* BehaviorID : 모든 ASP.NET AJAX Control Toolkit의 컨트롤은 BehaviorID를 가집니다. 이는 ExtenderControlBase에 기초하고 있으며, 모든 Ajax Toolkit Control은 이를 상속하고 있습니다. 아무튼, 개발자는 BehaviorID를 지정할수도 그렇지 않을 수 도 있습니다. 지정하지 않을 경우 해당 컨트롤의 ClientID와 동일한 값이 Behavior값으로 자동 지정됩니다. 반대로 BehaviorID를 지정한다면 Client에서 해당 컨트롤의 ID는 BehaviorID로 지정됩니다. 즉 JavaScript에서 해당 컨트롤의 ClientID로 해당 컨트롤을 찾을 수 없게 됩니다. 따라서 BehaviorID를 지정했다면, 해당 컨트롤의 ClientID는 무의미 해집니다.

신고
Tag : ASP.NET
Commented by 고맙습니다. at 2009.10.21 16:30 신고  r x
$find(펑션명(),parent); 로 깔끔하고 간단하게 페어런츠의 펑션을 실행시켰습니다.

name    password    homepage
 hidden


ASP.NET Ajax Accordion Control

AJAX Control Toolkit의 Accordion, AccordionPane 컨트롤에 대한 설명입니다. 이 컨트롤에 대한 자세한 설명(영문)은 http://www.asp.net/AJAX/AjaxControlToolkit/Samples/Accordion/Accordion.aspx에서 확인하실 수 있습니다. 이 정보는 해당 웹사이트의 내용을 참조하여 작성되었습니다.

  1. 코드 구조 : 각 Accordion의 내용을 직접 입력하실 것이라면 <Panes>태그 내부에 <AccordionPane>을 생성해서 작성해주시면 되고, 만약 Data를 Binding하실 것이라면 <HeaderTemplate>, <ContentTemplate>를 작성하시면됩니다.
    <ajaxToolkit:Accordion ID="accordionID" runat="Server">
        <Panes>
            <ajaxToolkit:AccordionPane ID="accodionPane1" runat="server">
                <Header>제목1</Header>
                <Content>내용1</Content>
            </ajaxToolkit:AccordionPane>
            <ajaxToolkit:AccordionPane ID="accodionPane2" runat="server">
                <Header>제목2</Header>
                <Content>내용2</Content>
            </ajaxToolkit:AccordionPane>
            <ajaxToolkit:AccordionPane ID="accodionPane3" runat="server">
                <Header>제목3</Header>
                <Content>내용3</Content>
            </ajaxToolkit:AccordionPane>
        </Panes>
        <HeaderTemplate>DataBinding으로 Accordion을 사용할 때 구성해야할 제목부분</HeaderTemplate>
        <ContentTemplate>DataBinding으로 Accordion을 사용할 때 구성해야할 내용부분</ContentTemplate>
    </ajaxToolkit:Accordion>
  2. Property 설명
    • SelectedIndex – 시작시 기본적으로 펼쳐보일 패널의 Index번호
    • HeaderCssClass – Header 부분에 적용될 CSS
    • HeaderSelectedCssClass – 선택된 Header에 적용될 CSS
    • ContentCssClass – 내용에 적용될 CSS
    • FadeTransitions – Accordion의 내용이 전환될 때, Fade의 적용여부. IE6에서 테이블내부에 위치한 Accordion에 이 속성을 True로 설정하면 AccordionPane 사이의 공간에 영향을 미칠 수 있습니다. 또한 고해상도를 사용하는 시스템의 IE6에서 속도 저하 현상이 발견될 수 있습니다.
    • TransitionDuration – 전환 시간(millisecond)
    • FramesPerSecond – 전환 애니매이션의 초당 프레임수
    • AutoSize – Accordion 컨트롤의 크기
      • None – 제한없이 Accordion 컨트롤의 크기가 확장되거나 축소됩니다. 같은 페이지의 다른 컨트롤의 위치에 영향을 미칠 수 있습니다. 기본값으로 사용됩니다.
      • Limit – Height 속성에 지정된 높이보다 커지지 않습니다. 이 높이보다 큰 내용이 위치한다면 스크롤이 생깁니다.
      • Fill – Height 속성의 높이로 항상 고정합니다.
        * IE6과 7에서는 CSS에서 Max-height 속성을 지원하지 않기 때문에 Limit와 Fill은 동일하게 나타납니다.
    • RequireOpenedPane – 모든 패널이 닫히지 않고, 반드시 하나의 패널은 열려있도록 합니다.
    • SuppressHeaderPostbacks – True로 설정하면 Header내부에 위치한 모든 링크가 작동하는 것을 막습니다.
    • Panes - AccordionPane의 컬렉션입니다.
    • HeaderTemplate – Databinding로 Accordio Control을 사용할 때, Header의 내용을 위치하는 곳입니다.
    • ContentTemplate - Databinding로 Accordio Control을 사용할 때, Header의 내용을 위치하는 곳입니다.
    • DataSource - DataSource입니다.
    • DataSourceID - DataSourceControl의 ID를 지정합니다. DataSource Property와 동시에 사용될 수 없습니다..
    • DataMember - DataSourceID를 사용할 때 DataMember를 지정합니다. DataSourceID에 있는 List나 Table명이 지정됩니다.
신고
Tag : ajax, ASP.NET

name    password    homepage
 hidden


ASP.NET 3.5 GridView에서 Ajax Pop-up을 이용한 상세정보 표시

이 정보는 Visual Studio 2008(.NET Framework 3.5)에서 실행한 예제입니다. 또한 GridView의 기본과 <%# Eval() %>를 이용한 바인딩, ASP.NET의 기본적인 동작을 아시는 분들을 목적으로 제작된 글입니다.
image

GridView의 특정 행에 대한 상세정보를 팝업으로 표시하기 위해서 ASP.NET Ajax Control Toolkit의 PopupControlExtender를 이용할 것입니다.

먼저 ASP.NET Ajax Control Toolkit를 사용하기 위해선 ASP.NET Ajax Control Toolkit의 설치가 필요합니다. (여기에서는 .NET Framework 3.5 SP1에서 AjaxControlToolkit-Framework3.5SP1을 설치하였습니다.

  1. .NET Framework 3.5 SP1을 설치합니다. 파일을 다운로드 하신 후에 실행하시면 됩니다. 모든 프로그램이 실행되지 않은 상태에서 설치하실 것을 권하며, 설치 중 다른 프로그램으로 인해 설치를 진행할 수 없다고 한다면 일단 '무시'를 통해 설치를 강행해보시길 바랍니다.
  2. AjaxControlToolkit-Framework3.5SP1을 다운로드 하여 압축을 풉니다.
    image 
  3. Solution Explorer에서 마우스 오른쪽 버튼을 클릭 후, Add Existing Item...을 선택합니다.
    clip_image002
  4. Open 창이 나타나면 AjaxControlToolkit-Framework3.5SP1.zip의 압축을 푼 폴더에 가서 AjaxControlToolkit-Framework3.5SP1\SampleWebSite\Bin\AjaxControlToolkit.dll 파일을 선택하여 dll파일을 프로젝트에 추가합니다.
    image
  5. 새로운 웹 사이트를 생성하신 다음에, Toolbox에 새 탭을 추가합니다.
    image
  6. 추가된 새탭에 마우스 오른쪽 버튼을 누르신후 'Choose Items...'를 선택하여, Choose Toolbox Items 창이 나타나면 'Browse...' 버튼을 선택합니다.
    image
  7. Open창이 뜨면, 현재 솔루션에 추가된 AjaxControlToolkit.dll파일을 선택한 후, Choose Toolbox Items창에서 확인 버튼을 클립합니다.
  8. 다음과 같이 Ajax Control들이 추가된 것을 확인하실 수 있습니다.
    image

이제 Ajax 컨트롤들을 사용하실 준비가 끝이 났습니다. 이제 GridView를 추가하고 Popup창을 띄어보겠습니다.

먼저 화면에 GridView를 하나 그리고, DataSource를 원하는 것으로 연결하여 그리드 뷰로 데이터들이 출력되게 합니다.
image

먼저 페이지의 상단에 Ajax Control Toolkit의 ToolkitScriptManager과 Panel 컨트롤을 하나씩 추가합니다. ToolkitScriptManager은 Ajax Control Toolkit를 사용하기 위해 필요한 컨트롤이며, Panel컨트롤은 추후에 팝업될 컨트롤입니다.

이제 GridView에 TemplateField를 추가합니다. 다음과 같이 템플릿 편집 모드로 와서 ItemTemplage의 공간에 Image를 하나 추가하시고, SmartTag에서 Add Extender를 클릭합니다.
 image

나타나는 Extender Wizard창에서 Popup Control Toolkit를 선택합니다.

 image

다시 Image의 SmartTag에서 Add Dynamic Populate page method를 선택하면 자동으로 해당 메서드가 .cs파일에 추가가 됩니다. 이 메서드는 string를 반환하는데, 이 반환 값에 Popup창에 나타날 HTML을 작성할 것입니다.

image 

추가된 메서드
[System.Web.Services.WebMethodAttribute(), System.Web.Script.Services.ScriptMethodAttribute()]
public static string GetDynamicContent2(string contextKey)
{
    return default(string);
}

메서드를 작성하기 전에 다시 디자인 페이지로 돌아와서, 페이지 소스에서 cc1:PopupControlExtender태그를 찾아 다음과 같이 수정을 합니다.

<cc1:PopupControlExtender
                  ID="Image1_PopupControlExtender"
                  runat="server"
                  DynamicServiceMethod="GetDynamicContent2"
                  DynamicServicePath=""
                  DynamicContextKey='<%# Eval("CategoryID") %>'
                  DynamicControlID="Panel1"
                  PopupControlID="Panel1"
                  Enabled="True"
                  ExtenderControlID=""
                  TargetControlID="Image1">
</cc1:PopupControlExtender>

PopupControlExtender의 각 속성들의 의미는 다음과 같습니다.

  • DynamicServiceMethod : 팝업창이 나타나야 할 때, 서버측에서 실행될 메서드의 이름을 지정합니다. 이 속성의 값은 위에서 Add Dynamic Populate page method를 클릭했을 때 자동으로 추가된 것입니다.
  • DynamicControlID : 함수의 리턴값을 받아 출력될 개체의 ID를 지정합니다.
  • PopupControlID : 팝업될 컨트롤의 ID입니다.
  • DynamicContextKey : DynamicServiceMethod에 지정된 함수로 전달될 매개변수를 지정합니다.
  • TargetControlID : 팝업 창이 나타나게 하는 컨트롤을 지정합니다.
  • Position : TargetcontrolID의 어느 부분에 팝업이 나타날지 결정합니다.
  • DynamicServicePath : DynamicServiceMethod로 지정한 메서드가 다른 페이지에 존재할 경우, 이 속성 값으로 해당 페이지를 지정해 줍니다.

이제 DynamicServiceMethod에 지정한 함수를 구현합니다. 매개변수를 받아서, 적절한 데이터를 조회하고 그에 따른 HTML을 StringBuilder를 통해 작성합니다.
(String들을 '+'연산자로 합치는 것은 상당한 리소스를 사용하게 됩니다. 따라서 StringBuilder를 통해서 문자열을 결합 시킬 수 있는데, String와 비교했을 때 리소스 소모의 차이가 어마어마하기 때문에 StringBuilder을 사용하실 것을 권장합니다.)

참고할 만한 추가적인 작업

GridView에 의해서 여러 행들이 생성되면 각 PoputControlExtender과 Image들은 모두 같은 ID와 속성 값을 가지게 됩니다. 만약, 각 행마다 컨트롤들의 ID나 속성값을 다르게 하기 위해서는 다음과 같은 추가적인 작업이 필요합니다.

먼저 Grdiview의 RowCreated이벤트를 구현해야 합니다. 그리드 뷰를 선택하고 속성창에서 Events버튼(번개 아이콘)을 클릭합니다.
image 

RowCreated를 선택하여 해당 이벤트를 생성합니다. 각 행마다 생성되는 PoputControlExtender와 Image의 ID와 BehaviorID의 중복을 없에기 위해서는 다음과 같은 작업이 필요합니다. 아래 소스는 위에서 구현한 Popup이 MouseOver, MouseOut 이벤트에 따라 나타나거나 사라지는 기능을 부여합니다.

protected void GridView1_RowCreated(object sender, GridViewRowEventArgs e)
{
   if (e.Row.RowType == DataControlRowType.DataRow)
   {
     //현재 행에서 컨트롤을 찾습니다. 
      AjaxControlToolkit.PopupControlExtender pce = 
                                             e.Row.FindControl("PopupControlExtender1")  
                                             as AjaxControlToolkit.PopupControlExtender;
      Image image = (Image)e.Row.Cells[1].FindControl("Image1");

      // BehaviorID를 지정합니다. 이 값은 클라이언트에서 각각의
      //PoputControlExtender의 동작을 구분하기 위한 값입니다.
      string behaviorID = string.Concat("pce", e.Row.RowIndex);
      if(pce != null)
            pce.BehaviorID = behaviorID; 

      //Image에 적절한 이벤트를 넣어줍니다. $find()는 Jquery로 구현된 Ajax구문입니다.
      // hidePopup()과 showPopup()의 호출을 통해서 사용자가 팝업을 제어할 수 있습니다.
      string strOnMouseOver = string.Format("$find('{0}').showPopup();", behaviorID);
      string strOnMouseOut = string.Format("$find('{0}').hidePopup();", behaviorID);  
      if(image != null)
      {
            image.Attributes.Add("onmouseover", strOnMouseOver); 
            image.Attributes.Add("onmouseout", strOnMouseOut);
      }
   }
}

신고
Tag : ajax, ASP.NET
Commented by Favicon of http://www.mobilepro.pe.kr BlogIcon 몽중인 at 2009.01.14 21:22 신고  r x
좋은 정보 감사합니다.
퍼가면.. 문제가 될까요??....
Replied by Favicon of http://thankee.tistory.com BlogIcon thankee at 2009.01.23 13:33 신고 x
상관없습니다. 다만 출처는 표시해야겠지요..^^

name    password    homepage
 hidden


ASP.NET 잠재적 위험이 있는 Request.Form 값을 발견했습니다.
Form의 데이터를 Request할때, Form값에 태그가 포함 되어 있을 경우 다음과 같은 에러를 발생시킵니다.

클라이언트 (txtContent="<STRONG>Content</STRONG>...")에서 잠재적 위험이 있는 Request.Form 값을 발견했습니다.

Form의 값으로 태그와 몇몇 특수문자들을 그대로 전송받아 처리하게되면 XSS나 SQL Injection과 같은 공격을 회피하지 못하거나, 공격자에 의해 사이트가 변조 당하는 등의 문제가 발생할 수 있습니다.

따라서 ASP.NET에서는 Request한 값을 validate, 즉 유효성을 검사하여 사용자에게 알림으로서 보다 견고한 웹 어플리케이션을 구축할 수 있도록 하고 있습니다. 이 에러를 처리하는 방법으로는 다음과 같이 세가지 방법이 있으며, 첫 번째 방법이 가장 안전하고 권장되는 방법입니다.

1. Client에서 Form값을 전송하기 전 또는 Request한 값을 사용하기 전에, 특정 문자들을 제거하거나 HTML Encoding 등을 사용하여 특수문자들을 다른문자로 치환하는 방법입니다. Javascript 또는 Server Side Script 에서 제거할 수 있으며 개발자가 필요에 따라 선택하면 됩니다.

2. 특정페이지에서만 에러 발생을 무시하는 방법입니다. 에러가 발생하는 페이지의 Page 지시자에 validateRequest="false" 를 추가하면 해당 페이지에서는 이 에러가 발생하지 않게 됩니다.

<%@ Page
     language
="C#" Codebehind="...." AutoEventWireup="true" Inherits="..."
     validateRequest="false" %>

3. 전체 웹 어플리케이션에 해당 에러가 나타자니 않게 하는 방법입니다. web.config에서 <system.web>엘리먼트 내부에 <pages validateRequest="false" />를 넣어두면 모든 페이지에서 해당 에러는 발생하지 않게 됩니다.
<?xml version="1.0"?>
<configuration>
    <appSettings/>
    <system.web>
        <pages validateRequest="false" />
    </system.web>
    ....
</configuration>
신고
Tag : ASP.NET
Commented by 한국인 at 2008.10.16 12:00 신고  r x
2, 3번 방법은 폼값에 스크립트 입력을 허용함으로써 XSS에 노출되게 됩니다. 따라서 1번 방법을 선행한 후 2, 3번 방법을 사용해야 보안에 취약해지지 않습니다.

name    password    homepage
 hidden


ASP.NET 다중 파일 저장 예제
여기서 다중 파일이라 함은 클라이언트에서 여러 파일을 선택해놓고,
한번에 서버에 모두 업로드하는 것을 말합니다.

다음 이미지와 같습니다.
사용자 삽입 이미지
자바스크립트를 이용하여, 파일의 개수를 선택하고, 해당한 파일 모두를 한번에 서버로 업로드합니다.

 이 프로그램의 소스코드는 다음과 같습니다.



By thankee from tistory.com
신고
Tag : ASP.NET
Commented by 방문객 at 2010.01.15 15:31 신고  r x
정말 훌륭합니다.
조금 빌려써도 되겠지요^^ 감사합니다.
Commented by 지나가던 at 2010.09.27 11:21 신고  r x
와우.... 감사합니다.

name    password    homepage
 hidden


ASP.NET 탐색 컨트롤
ASP.NET에서 제공하는 탐색 컨트롤은 다음과 같습니다.
- SiteMapPath : 현재 페이지의 경로를 출력합니다.(예 : >>내용1>>현재페이지)
- Menu : 일반적인 메뉴를 출력합니다.
- TreeView : Tree구조로 메뉴를 출력합니다.

* 탐색 컨트롤을 사용하기 위해서 '새항목추가-사이트맵'을 추가하여 Web.sitemap파일을 작성해야합니다. 해당 웹 Application의 전체 페이지 구성을 모두 기술하도록 합니다. 보통 페이지들은 계층형 구조(Tree)를 가지는데, <siteMapNode>태그를 중첩함으로서 구현이 가능합니다.
<?xml version="1.0" encoding="utf-8" ?><!--붉은색까지는 기본태그입니다.-->
<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >
    <siteMapNode url="index.aspx" title="UMS홈페이지"  description="환영합니다.">
        <!--여기서부터 트리형식으로 자식 구현이 가능합니다.-->

        <siteMapNode url="introduction.aspx" title="UMS소개"  description="UMS를 소개합니다.">
            <siteMapNode url="AboutUMS.aspx" title="동아리 규칙"  description="동아리 규칙은?" />
            <siteMapNode url="UMSHistory.aspx" title="UMS연혁"  description="UMS의 역사" />
            <siteMapNode url="AboutProfessor.aspx" title="교수님"  description="교수님 한마디" />
            <siteMapNode url="AboutMembers.aspx" title="멤버소개"  description="멤버를 소개합니다." >
                <siteMapNode url="MembersNow.aspx" title="현 멤버 소개"  description="현재멤버" />
                <siteMapNode url="MembersOld.aspx" title="역대 멤버 소개"  description="선배님" />
            </siteMapNode>
        </siteMapNode>
        <siteMapNode url="photo.aspx" title="UMS사진첩"  description="UMS 추억" />
        <siteMapNode url="board.aspx" title="UMS게시판"  description="UMS 왁자지껄." >
            <siteMapNode url="UmsBoard.aspx" title="Ums전용"  description="UMS사설 게시판" />
            <siteMapNode url="guestBook.aspx" title="방명록"  description="한마디 남기기" />
        </siteMapNode>
    </siteMapNode>
</siteMap>
<!--url은 고유해야합니다. 중복된 Url이 있으면 에러가 나타납니다.-->
<!--현재 page의 Url을 보고 자동으로 탐색컨트롤의 내용이 구성되게 됩니다.-->


1. SiteMapPath : 현재 페이지의 경로를 표시하는 기능입니다.(예 : >>내용1>>현재페이지) 자동으로 Web.sitemap파일을 참조해서 경로를 표시하게 됩니다.
  • ParentLevelsDisplayed : 기본값은 -1로서 모든 부모를 표시합니다. 이 속성 값을 설정하면, 그 값 만큼 부모페이지가 표시됩니다.
  • PathDirection : RootToCurrent는 부모부터 현재 페이지까지 왼쪽에서 오른쪽으로 출력합니다. CurrentToRoot는 반대입니다.
  • ShowToolTips : description의 내용을 ToolTips로 보여줄지 여부를 결정합니다.
2. Menu : 손쉽게 메뉴를 구축할 수 있도록 제공되는 컨트롤입니다. 데이터소스로 부터 메뉴의 아이템값을 얻기 때문에, DB는 물론이고 데이터소스가 될 수 있는 모든 것으로부터 메뉴를 구성할 수 있습니다. 위에서 제작한 Web.sitemap를 데이터소스로 사용하기 위해서 SiteMapDataSource컨트롤이 필요합니다. 데이터소스를 활용하지 않고 수동으로 메뉴를 구성 할 수 도 있습니다. 템플릿 편집기능 역시 지원합니다.
  • Selectable : 메뉴를 수동으로 구성할 때 사용되는 메뉴항목 편집기 내의 속성입니다. 이 속성을 false로 하면 해당 아이템으로 Url이동을 비활성화하지만, 자식 메뉴를 나타낼 수는 있습니다.
  • DataSourceID : 사용 할 DataSource를 지정하는 속성입니다.
  • StaticDisplayLevels : 처음 출력될 경우 몇 단계의 리스트가 Root메뉴로서 펼쳐져 있을지 결정하는 속성입니다. 2로 설정하면 1단계에서 2단계까지 모든 메뉴가 기본적으로 펼쳐져 나타나게 됩니다. 이렇게 펼쳐져있는 메뉴를 정적메뉴(Static Menu)라 하며, 마우스로 하위메뉴를 나타나게 하는 방법이 동적메뉴(Dynamic Menu)라고 합니다.
  • Orientation : 메뉴의 출력형태를 설정합니다. 가로, 또는 세로 형식으로 지정할 수 있습니다.
  • LevelMenuItemStyles : 각 단계 메뉴 텍스트의 Style을 설정합니다.
  • LevelSelectedStyles : 이전에 방문한 적이 있는 메뉴의 Style을 설정합니다.
  • LevelSubMenuStyles : 하위 메뉴의 Style을 설정합니다.
  • MaximumDynamicDisplayLevels : 몇 단계까지 하위 메뉴로 표현할지 설정할 수 있습니다. 2면 하위 2단계 메뉴까지 표현가능합니다.
  • PathSeparator : 특정 메뉴를 선택했을 때, Root메뉴에서 해당 메뉴까지 경로를 표시한다고 할 때, 사용되는 문자입니다. 기본은 '/'입니다. 만일 메뉴의 텍스트에 '/'가 포함된 경우, 이 속성을 다른 문자로 바꾸어서 String.split()을 통해 각 메뉴를 잘라낼수 있도록 할 수 있습니다. PathSeparator가 '/'일 경우 'Menu컨트롤명.SelectedNode.ValuePath.Split('/');'로서 현재 선택된 메뉴까지의 경로 정보를 얻을 수 있게 됩니다.

3. TreeView : Menu와 대체적으로 같지만, 메뉴를 트리형태로 표시합니다. 데이터소스로부터 메뉴 구성 정보를 얻을 수 도 있으며, 수동으로 메뉴를 구성할 수 도있습니다.
  • ShowCheckBoxes : 각 아이템에 체크박스를 표시할 지 결정합니다.
  • ImageSet : 트리뷰를 구성하는 ImageSet을 변경합니다. 탐색기모양, 단순+- 모양 등 여러 ImageSet을 제공합니다.
  • LevelStyles : 각 레벨 별로 Style을 설정합니다.
  • NodeIdent : 들여쓰기 간격(Pixel)을 설정합니다.
  • Nodes : 메뉴의 각 아이템을 설정할 수 있습니다.
  • ShowExpandCollapse : 확장/축소 아이콘 표시여부를 설정할 수 있습니다.
  • ShowLines : Tree메뉴 각 항목 간에 연결하는 라인이미지를 출력할 지 설정할 수 있습니다.

by thankee from tistory.com
신고
Tag : ASP.NET

name    password    homepage
 hidden


 Category
분류 전체보기 (95)
Netwrok & Security (6)
Web Development (61)
Database (5)
Framework (6)
Others (17)
About (0)
 TAGS
ajax WCF XML c#.net 영국 학원 특수문자 data tier class id 차이 exception MS SQL Server SourceSafe2005 ASP.NET RFC 4180 smarty linux php LiveMail 리눅스 Blog API 영국 인턴쉽 UpdateProgress 오라클 구조 ebnf ATRIX 오라클 DTD id name 차이 ASP maxRecievedMessageSize mantis bug tracker Silverlight application error #401 mantis 자바스크립트 It's me SourceSafe Internet 영국 홈스테이 web tier PHP 강좌 ie6 자바스크립트 버그
 Calendar
«   2017/10   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31        
 Visitor Statistics
Total : 248,436
Today : 10
Yesterday : 73
rss
 

티스토리 툴바