'2017/01'에 해당되는 글 4건

Programming/.NET

 1. UpdatePanel

 

일반적으로 웹 환경은 클라이언트가 서버에 어떠한 처리를 요청하면 서버는 요청을 받아들이고 해당 작업을 수행한 뒤 페이지에 대한 전체적인 데이터를 클라이언트에게 넘겨줍니다. 그러면 클라이언트(웹브라우저)는 수신된 페이지 내용을 표시하게 되는 것입니다.

 

이는 페이지 전체가 아닌 일부분만을 갱신할때 매우 비효휼적인 처리방식입니다. 그래서 AJAX는 클라이언트의 Javascrpt를 통해 페이지 전체중 필요한 특정 부분만을 갱신하기 위한 비동기 처리를 요청합니다. 이 후 서버로의 응답을 수신해 필요한 정보만을 화면에 재표시하게 됩니다.

 

<form id="form1" runat="server">

<div>

    <asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>

    <asp:UpdatePanel ID="UpdatePanel1" runat="server">

        <ContentTemplate>

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

            <asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />

        </ContentTemplate>

    </asp:UpdatePanel>

</div>

</form>

 

protected void Button1_Click(object sender, EventArgs e)

{

    Label1.Text = DateTime.Now.ToString();

}

 

위 예제는 ASP.NET에서 구현가능한 AJAX의 간단한 기능을 보여주고 있습니다. 페이지에서 사용된 ScriptManager는 AJAX를 위한 서버컨트롤로서 AJAX구현에 필요한 자바스크립트(Javascript)를 알아서 로딩하여 관리하고 서버에서 응답해 오는 데이터를 마샬링(SOAP, JSON등을 활용)하여 클라이언트에서 필요한 처리를 수행할 수 있도록 해주는 역활을 수행합니다.

 

특정 웹 사이트가 마스터페이지를 사용하는 형태라면 ScriptManager는 마스터페이지에 배치해 둘 수 있습니다. 그러면 마스터페이지안에 포함되는 하위페이지의 경우 개별적으로 ScriptManager를 둘 필요없이 마스터페이지의 ScriptManager를 대체하여 사용할 수 있습니다. 만약 마스터페이지안에 ScriptManager가 존재하는데 하위페이지에서 또 다시 ScriptManager를 포함시키려 하면 오류가 발생할 것입니다. 왜냐하면 ScriptManager는 페이지당 하나의 ScriptManager컨트롤만 가질 수 있기 때문입니다.

 

하지만 하위페이지에서 해당 페이지에만 필요한 스크립트 처리를 위해 ScriptManager의 형태를 변경해야 한다면 ScriptManager대신 ScriptManagerProxy컨트롤을 사용할 수 있습니다. 아래 예제는 마스터페이지의 ScriptManager에 스크립트참조를 추가하도록 합니다.

<asp:ScriptManagerProxy ID="ScriptManagerProxy1" runat="server">
    <Scripts>
        <asp:ScriptReference Path="aaa.js" />
    </Scripts>
</asp:ScriptManagerProxy>

UpdatePanel은 ContentTemplate내부에서 부분 PostBack을 발생시키기 위한 필요한 영역을 정의합니다. 이 안에 웹페이지의 작동에 필요한 컨트롤을 배치하고 해당 컨트롤에서 PostBack을 발생시키면 페이지 전체가 아닌 UpdatePanel로 둘러진 영역만 부분 PostBack이 발생하게 되는 것입니다.

 

 2. Triggers

 

그런데 여기서는 한가지 문제가 있습니다. UpdatePanel의 ContentTemplate안에는 버튼도 있는데 실제 갱신이 필요한것은 Label이지 Button이 아닙니다. 버튼은 그저 클릭에 대한 이벤트만 발생시킬뿐 AJAX처리 대상이 아닌데 불필요 하게 서버측 전송데이터에 포함되는 것입니다. 따라서 Label과 Button을 분리시켜야할 필요가 있습니다.

 

<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
    <ContentTemplate>
        <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
    </ContentTemplate>
    <Triggers>
        <asp:AsyncPostBackTrigger ControlID="Button1" />
    </Triggers>
</asp:UpdatePanel>

<asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />

 

이럴 경우 UpdatePanel의 ContentTemplate요소에는 PostBack전송에 필요한 요소만 추가하고 이벤트를 발생시키는 요소는 UpdatePanel 밖에서 정의합니다. 그리고 Triggers섹션 하위에 AsyncPostBackTrigger로 이벤트를 발생시키는 컨트롤을 ControlID를 통해 지정하면 됩니다.

 

AsyncPostBackTrigger에는 ControlID외에 EventName속성도 지정할 수 있는데 EventName은 이벤트를 발생시키는 요소가 비동기포스트백 호출을 위해 호출하는 이벤트이름입니다.

 

참고로 만약 UpdatePanel을 2개 이상 사용하고 있는 경우 Triggers로 잡혀있는 컨트롤에서 이벤트를 발생시키면 모든 UpdatePanel이 포스트백을 일으키게 됩니다.

 

<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
    <ContentTemplate>
        <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
    </ContentTemplate>
    <Triggers>
        <asp:AsyncPostBackTrigger ControlID="Button1" EventName="Click" />
    </Triggers>
</asp:UpdatePanel>

<asp:UpdatePanel ID="UpdatePanel2" runat="server">
    <ContentTemplate>
        <asp:Label ID="Label2" runat="server" Text="Label"></asp:Label>
    </ContentTemplate>
</asp:UpdatePanel>

<asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />

 

예를 들어 위와 같이 구성된 페이지에서 Button1_Click 이벤트에 다음과 같이 코드를 작성하고

 

protected void Button1_Click(object sender, EventArgs e)
{
    Label1.Text = DateTime.Now.ToString();
    Label2.Text = DateTime.Now.ToString();
}

 

페이지를 실행한뒤 버튼을 클릭하면 각 Panel에 있는 모든 Label의 Text값이 변경됩니다. Button컨트롤은 분명 UpdatePanel1에 묶어 있지만 이벤트를 발생시키면 모든 UpdatePanel의 요소가 포스트백 대상이 되기 때문입니다.

 

따라서 Trigger로 연결되어 있는 컨트롤의 UpdatePanel만 포스트백을 처리하려면 해당 UpdatePanel에서 UpdateMode속성을 Conditional로 설정해야 합니다.

 

<asp:ScriptManager ID="ScriptManager1" runat="server" ></asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
    <ContentTemplate>
        <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
    </ContentTemplate>
    <Triggers>
        <asp:AsyncPostBackTrigger ControlID="Button1" EventName="Click" />
    </Triggers>
</asp:UpdatePanel>

<asp:UpdatePanel ID="UpdatePanel2" runat="server" UpdateMode="Conditional">
    <ContentTemplate>
        <asp:Label ID="Label2" runat="server" Text="Label"></asp:Label>
    </ContentTemplate>
</asp:UpdatePanel>

<asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />

 

그러면 이벤트 발생시 연결되어 있는 UpdatePanel의 요소만 포스트백 처리될것입니다.

 

 3. UpdateProgress

 

페이지에서 포스트백이 발생할때 이에 대한 처리시간이 오래걸리는 경우 사용자에게 어떤 식으로는 처리중이라는 메세지를 표시해야하는 경우가 있습니다. UpdateProgress는 이런 경우를 위한 컨트롤입니다.

 

<asp:UpdateProgress ID="UpdateProgress1" runat="server">
    <ProgressTemplate>
        처리중...
    </ProgressTemplate>
</asp:UpdateProgress>

 

UpdateProgress 컨트롤을 원하는 위치에 배치하고 ProgressTemplate안에 적당한 내용을 넣어둡니다. ASP.NET의 대부분의 Template이 그러하듯이 여기에도 단순텍스트나 HTML요소, 컨트롤등이 들어갈 수 있습니다.

 

protected void Button1_Click(object sender, EventArgs e)
{
    Thread.Sleep(10000);
    Label1.Text = DateTime.Now.ToString();
}

 

클릭이벤트에는 일부로 시간을 지연시키기 위해 Sleep를 주었습니다.

 

실제 버튼을 클릭하면 UpdateProgress가 배치된 위치에 '처리중...'이라는 메세지가 뜨고 Sleep시간이 지나면 시간이 표시될 것입니다. 참고로 DisplayAfter속성을 이용하면 지정된 시간 이후에 메세지를 표시합니다. 이 기능은 처리시간이 빠르게 진행될때 메세지를 굳이 표시할 필요가 없는 경우 유용하게 사용될 수 있습니다.

 

 4. Script combining (스크립트 결함)

 

ASP.NET의 AJAX처리는 필요에 따라 여러 스크립트를 다운로드하도록 합니다. 문제는 수많은 스크립트의 다운로드를 위한 요청이 너무 많으면 성능상 좋지 못하기 때문에 이들 스크립트를 하나로 묶어주는 방법을 써야 합니다.

 

이 방법은 현재 페이지에 AJAX처리를 위해 필요한 스크립트를 ScriptManager에 모두 명시함으로서 가능한 것인데 이때 무슨 스크립트가 얼마나 필요한지를 어떻게 알아낼까 하는 의문이 생길 수 있습니다. 이 문제는 ScriptReferenceProfiler 라는 서버컨트롤을 사용하면 아주 간단히 해결될 수 있습니다.

 

해당 컨트롤은 Visual Studio의 도구모음에 포함되어 있지 않습니다. 아래 사이트에 접속해 내려받으시기 바랍니다.

 

http://aspnet.codeplex.com/releases/view/13356

 

파일(Binary)을 내려받고 압축을 풀면 dll파일 하나만 있는데 이 파일을 도구모음에 포함시키면 다음과 같이 ScriptReferenceProfiler컨트롤이 생성되는 것을 볼 수 있습니다.

 

 

 

이 컨트롤을 aspx디자인모드에서 원하는 곳에 끌어다 놓으십시오.

 

<%@ Register Assembly="ScriptReferenceProfiler" Namespace="ScriptReferenceProfiler" TagPrefix="cc1" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
        <asp:UpdatePanel ID="UpdatePanel1" runat="server">
            <ContentTemplate>
                <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
                <asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />
            </ContentTemplate>
        </asp:UpdatePanel>
        <cc1:scriptreferenceprofiler runat="server">
        </cc1:scriptreferenceprofiler>
    </div>
    </form>
</body>
</html>

 

그러면 Register 지시자와 함께 컨트롤이 배치될 것입니다. 이 상태에서 그대로 페이지를 실행시켜 보면

 

위와 같이 필요한 스크립트를 표시하게 됩니다. 필요한 경우 별도로 스크립트를 다운받을 수도 있군요.

 

어쨌건 위에 표시된 목록을 그대로 복사해서 ScriptManager에 CompositeScript로 추가시키면 스크립트 결합이 완료됩니다.

 

<asp:ScriptManager ID="ScriptManager1" runat="server">
    <CompositeScript>
        <Scripts>
            <asp:ScriptReference name="MicrosoftAjax.js"/>
            <asp:ScriptReference name="MicrosoftAjaxWebForms.js"/>
        </Scripts>
    </CompositeScript>
</asp:ScriptManager>

 

예제에서는 어차피 필요한 스크립트가 2개밖에 안되므로 별 차이가 없지만 많은 수의 스크립트를 필요로 하는 경우 해당 스크립트에 대한 서버요청수를 획기적으로 줄일 수 있으므로 성능에 분명 도움이 될것입니다.

'Programming > .NET' 카테고리의 다른 글

[ASP.NET] 서버 컨트롤 - 6 (컨트롤)  (0) 2017.02.08
[ASP.NET] HttpModule, HttpHandler  (0) 2017.02.02
[ASP.NET] AJAX  (0) 2017.01.24
[ASP.NET] 캐시 - 2  (0) 2017.01.17
[ASP.NET] ExecuteXmlReader  (0) 2017.01.13
[ASP.NET] SiteMapDataSource  (0) 2017.01.03
0 0
Programming/.NET

캐시는 페이지나 컨트롤의 전체 혹은 부분을 캐시하는것 뿐만 아니라 개발자가 원하는 특정 데이터를 캐시할 수도 있습니다.

 

Cache["tmp"] = "cliel";
Response.Write((Cache["tmp"] as string).ToString());

 

위 예제는 아주 간단한 캐시개체의 활용방법을 보여주고 있습니다. Cache에 특정 키와 값을 부여하고 같은 키를 통해 원하는 값을 다시 가져올 수 있습니다. Cache개체에는 거의 모든 타입의 데이터저장이 가능합니다.

 

Cache.Insert("tmp", "cliel", null, DateTime.Now.AddSeconds(600), System.Web.Caching.Cache.NoSlidingExpiration);

 

캐시 만료시간을 600초로 지정하지만 슬라이딩만료방식을 사용하지 않습니다.

 

Cache.Insert("tmp", "cliel", new System.Web.Caching.CacheDependency(Server.MapPath("tmp.xml")));

 

위 예제는 Dependency를 설정하는 경우입니다. Dependency에 tmp.xml을 지정함으로서 만일 tmp.xml파일내용이 변경되면 캐시가 만료되도록 하였습니다.

 

Cache.Insert("tmp", "cliel", new System.Web.Caching.CacheDependency(new string[] { Server.MapPath("tmp1.xml"), Server.MapPath("tmp2.xml") } ));

 

Dependency가 필요한 파일이 여러개라면 위와 같이 설정할 수도 있습니다.

 

AggregateCacheDependency acd = new AggregateCacheDependency();
acd.Add(new CacheDependency(Server.MapPath("tmp.xml")));
acd.Add(new SqlCacheDependency(new SqlCommand("Select samplecolumn From sampleTable;")));
Cache.Insert("tmp", "cliel", acd);

 

다른 타입의 Dependency를 설정해야 한다면 AggregateCacheDependency 클래스를 사용해야 합니다. 이 클래스의 인스턴스에 필요한 Dependency를 추가하고 Cache에 인스턴스를 포함시킵니다.

 

Dependency 타입은 CacheDependency를 상속함으로서 사용자 정의 캐시 종속성을 구현할 수 있습니다.

 

public class customer_dependency : CacheDependency
{

}

 

customer_dependency cd = new customer_dependency();
Cache.Insert("tmp", "cliel", cd);

'Programming > .NET' 카테고리의 다른 글

[ASP.NET] HttpModule, HttpHandler  (0) 2017.02.02
[ASP.NET] AJAX  (0) 2017.01.24
[ASP.NET] 캐시 - 2  (0) 2017.01.17
[ASP.NET] ExecuteXmlReader  (0) 2017.01.13
[ASP.NET] SiteMapDataSource  (0) 2017.01.03
[ASP.NET] 캐시 - 1  (0) 2016.12.26
0 0
Programming/.NET

Microsoft SQL Server에서는 데이터를 XML로 처리할 수 있는 기능을 제공하는데 아래 글에서 쿼리를 통해 XML을 다루는 기본적인 방법을 알 수 있습니다.

 

2010/10/01 - [Programming/Microsoft SQL Server] - [SQL] For Xml을 이용해 Table을 XML형태로 조회하기

 

위 내용을 토대로 특정 Table의 내용을 XML형식으로 가져와 표시해 보고자 합니다.

 

XmlDocument xd = new XmlDocument();

using (SqlConnection conn = new SqlConnection(con))
{
    SqlCommand cmd = new SqlCommand("Select * From BOOK for xml auto, elements;", conn);
    conn.Open();

    XPathNavigator xn = xd.CreateNavigator();

    using (XmlWriter xw = xn.PrependChild()) {
        xw.WriteStartElement("books");
        using (XmlReader xr = cmd.ExecuteXmlReader()) {
            xw.WriteNode(xr, true);
        }
        xw.WriteEndElement();
    }
}

Response.ContentType = "text/xml";
xd.Save(Response.Output);

 

방법상으로는 일반적인 DB처리방식과 크게 다르지 않지만 ExecuteXmlReader 메소드를 호출함으로써 DB데이터자체를 XML형식으로 가져오며 또한 그에 맞게 XmlDocument 클래스를 사용해 각 요소를 출력하고 있습니다.

 

참고로 쿼리에서 직접 Select * From BOOK for xml auto, elements, Root('books'); 처럼 루트요소를 지정하면 코드안에서 루트요소를 지정한 WriteStartElement 메소드와 WriteEndElement메소드는 더이상 필요하지 않습니다.

'Programming > .NET' 카테고리의 다른 글

[ASP.NET] AJAX  (0) 2017.01.24
[ASP.NET] 캐시 - 2  (0) 2017.01.17
[ASP.NET] ExecuteXmlReader  (0) 2017.01.13
[ASP.NET] SiteMapDataSource  (0) 2017.01.03
[ASP.NET] 캐시 - 1  (0) 2016.12.26
[ASP.NET] 서버 컨트롤 - 5 (포스트백처리)  (0) 2016.12.21
0 0
Programming/.NET

사이트맵데이터소스 컨트롤은 사이트맵을 바인딩하고 조작하는데 사용되는 데이터 소스컨트롤입니다. 사이트맵에 관해서는 아래글을 참고해 주시기 바랍니다.

 

2016/02/19 - [Programming/ASP.NET] - [ASP.NET] 사이트 네비게이션

 

일부 사이트맵에 관련된 컨트롤, 이를테면 SiteMapPath와 같은 컨트롤은 별도의 데이터소스컨트롤 없이도 자체적으로 사이트맵데이터를 바인딩하지만 사이트맵에 많이 사용되는 Menu, Treeview와 같은 컨트롤에서는 사이트맵 바인딩을 위해 사이트맵데이터소스컨트롤이 필요합니다.

 

따라서 사이트맵데이터소스컨트롤은 자체적으로 어떤 역활을 수행한다기 보다 사이맵데이터를 필요로 하는 다른 컨트롤의 데이터공급자로서의 역활을 주로 수행하는 것입니다. 하지만 이 경우에도 자체적인 몇가지 속성을 통해 사이트맵데이터를 어느정도 조작할 수 있습니다.

 

 1. ShowStartingNode

 

이 속성은 사이맵에서 최상위 요소(가장 상위 페이지)를 나타낼지 지정합니다.

 

 2. StartFromCurrentNode

 

일반적으로 사이트맵은 '처음페이지 > A > B' 식으로 사이트맵을 표시하지만 이 속성을 true로 하면 항상 현재페이지를 루트노드로 하여 하위노드를 표시합니다. 예를 들어 현재 A페이지에 머물고 있다면 사이트맵은 처음페이지를 제외하고 'A > B'식으로 표시하게 됩니다.

 

 3. StartingNodeOffset

 

이 속성의 기본값은 0입니다. 0은 최상위 노드부터 사이트맵을 표시한다는 의미입니다. 만약 이 값을 1로 한다면 최상위 페이지에서 한단계 하위페이지부터 사이트맵을 표시할 것입니다.

예를 들어 'A > B > C'형태로 사이트맵을 표시한다면 이 값이 1일때 B페이지에 접속하면 'B > C'와 같은 형식으로 사이트맵을 표시하는 것입니다.

 

 4. StartingNodeUrl

 

'A.aspx > B.aspx > C.aspx'와 같은 구조의 사이트맵에서는 일반적으로 최상위 페이지를 A로 하게 됩니다. 하지만 이 속성에 'B.aspx'와 같이 특정한 페이지를 설정하면 이 페이지를 최상위 페이지로 표시하게 됩니다.

'Programming > .NET' 카테고리의 다른 글

[ASP.NET] 캐시 - 2  (0) 2017.01.17
[ASP.NET] ExecuteXmlReader  (0) 2017.01.13
[ASP.NET] SiteMapDataSource  (0) 2017.01.03
[ASP.NET] 캐시 - 1  (0) 2016.12.26
[ASP.NET] 서버 컨트롤 - 5 (포스트백처리)  (0) 2016.12.21
[ASP.NET] 서버 컨트롤 - 4 (ControlState)  (0) 2016.12.13
0 0
1
블로그 이미지

클리엘