ICallbackEventHandler (Client Callback)
ASP.NET에서 AJAX(Asynchronous JAvaScript Xml)는 어떻게 구현하나요?
뭐라고 쫑알대는것보다는, 간단한 예제 하나 만들어보면서 느껴보는게 가장 빠르지 않을까요?
어쨌든 들어갑니다 !
준비물 :
Microsoft Visual Studio 2005 (이하 VS2005) (또는 Microsoft Visual Web Developer 2005 Express)
Microsoft SQL Server 2005 (이하 SQL) (또는 SQL Server 2005 Express)
(참, 실습을 위해서 SQL Server에 AdventureWorksDB 라는 예제 데이터베이스가 있어야 합니다)
①
VS2005를 실행하고 메뉴에서 [파일] - [새 웹 사이트] 를 클릭한 다음
템플릿에 (ASP.NET 웹 사이트) - 언어는 당연히 (Visual C#)이구요 - 위치는 적당히 맨 마지막에 "ClientCallback" 이라고 적습니다.
②
기본으로 웹 사이트의 골격이 생성되고, Default.aspx가 생성됨과 동시에 열립니다.
Default.aspx에서 [디자인]보기를 클릭하고 "도구상자"에서 "HTML"의 요소로 다음과 같이 디자인합니다.
③
그리고 [소스]보기를 클릭하고 나오는 Default.aspx의 HTML소스를 다음과 같이 고칩니다.
|
④
Default.aspx를 저장하고 (무슨 일이 생길지 모르니, 항상 저장하는 습관을 기릅시다!)
"솔루션 탐색기"에서 Default.aspx 밑에 있는 Default.aspx.cs 파일을 더블클릭해서 열도록 합니다.
⑤
그리고 소스를 다음과 같이 고칩니다.
|
"이 페이지 클래스는 ICallbackEventHandler 라는 인터페이스를 상속해서 구현합니다"
ASP.NET 2.0 에서는 새로 ICallbackEventHandler 인터페이스를 소개하면서
이 인터페이스를 통해 서버페이지(이하 서버)와 비동기적으로 통신할 수 있도록 했습니다.
정보를 한번 서버에 전송하는데 페이지를 "깜빡"하고 날려버리는 포스트백(PostBack)과는 다르게,
개발자가 정의한 "내용"만을 서버에 전송할 수 있다는 "그냥 듣기만해도 좋아보이는 말"입니다.
|
어쨌든, 이런일을 하려면 먼저 서버에 제대로된 값이나 보내고 응답을 받을 생각을 해야겠죠?
일단은 서버에 "나 이거 보낼테니, 다 되면 알려줘" 라고 콜백을 보내야 합니다.
이를 위해, 클라이언트측에서 콜백을 보내도록 하는
자바스크립트 함수인 WebForm_DoCallback()를 호출하는 내용의 함수를 만들어야 합니다.
근데 그걸 어떻게 만드냐구요? 모든 건 준비되어 있으니까 걱정하지 마시라구요!
|
⑥
Default.aspx.cs 파일을 열고 Page_Load()를 다음과 같이 고칩니다.
protected void Page_Load(object sender, EventArgs e) // 페이지가 처음 시작할때 페이지에 등록한다
|
ClientScript 는 이전 ASP.NET 2.0 에서 새로이 추가된 Page 클래스의 속성으로
클라이언트측 스크립트를 등록하거나 하는 등의 스크립트에 관한 모든 메소드를 담고 있습니다.
마법의 코드는 그냥 ClientScript.GetCallbackEventReference()로 간단히 얻을 수 있습니다.
정말 싱겁죠? GetCallbackEventReference()의
첫번째 인자에는 클라이언트 콜백을 처리할 컨트롤로,
ICallbackEventHandler 인터페이스를 구현하는 페이지 자체에 대한 참조를 넘깁니다.
두번째 인자에는 클라이언트측에서 서버쪽으로 전달되는 값을 넘깁니다.
그러니까 여기에 서버에 보내고자 하는 값을 넘기면 되는거죠... 바로는 안되고... 어떻게 넘기냐?
@"function callback(argument, context){ " +
그렇죠, 클라이언트측 자바스크립트 함수(이하 클라이언트측 함수)에서 만들어진 callback() 을
호출할때, callback() 의 매개변수인 argument 부분에 보내고자 하는 값을 넘기면 된다는거죠.
(뭐 이건 조금있다가 다시 살펴보겠습니다)
세번째 인자에는 "서버가 나 할일 다 끝났으니, 이제 니가 알아서 해"라고 하며
호출할 클라이언트측 함수의 이름을 넘깁니다. 이건 잠시후에 만들테니 조금만 기다려주시구요.
네번째 매개변수에 대한 설명은 도움말에서 가져왔습니다. 귀찮아서 ...
* context
콜백을 시작하기 전에 클라이언트에서 계산되는 클라이언트측 스크립트입니다.
스크립트 결과는 클라이언트측 이벤트 처리기로 다시 전달됩니다.
콜백을 서버로 보냈으니, 서버는 이를 처리해서 결과를 클라이언트측에 넘기도록 해야겠죠?
이를 위해서 상속받은 ICallbackEventHandler 인터페이스의 2개의 메소드 -
RaiseCallbackEventReference()와 GetCallbackEvent()를 구현합니다.
근데, 사실 별 것 없습니다.
말 그대로 "콜백이 왔어-콜백이 일어났어"에 대한 일을 처리하는
RaiseCallbackEvent() 는 클라이언트에게 받아온 (callback () 메소드를 통해서 들어온) 를 넘겨받고
"처리가 끝났어, 난 늬들이 원하는 값을 줄테니까, 이제 늬들이 알아서 해"에 대한 일을 처리하는
GetCallbackResult()는 처리한 내용을 문자열에 담아서 다시 클라이언트에 넘깁니다.
별것없기 때문에 바로 구현을 해보도록 하겠습니다.
⑦
Default.aspx.cs 파일을 열고 Page 클래스 선언의 ICallbackEventReference 인터페이스를
상속받는 부분에 마우스를 대고 오른쪽 버튼을 눌러 [인터페이스]-[인터페이스 구현]을 클릭합니다.
그러면 인터페이스를 상속받는 코드가 자동으로 생성되어 나오는데
그 코드들을 다음과 같이 고칩니다.
#region ICallbackEventHandler 멤버
// RaiseCallbackEvent에서 얻어온 클라이언트 파라미터의 값을 가지는 변수
public string GetCallbackResult() public void RaiseCallbackEvent(string eventArgument)
#endregion
|
여기에서 보고 있으면 GetCallbackEvent()에서 클라이언트로 결과값을 보내는데
결과값을 GetPersonAddress()에서 만들어 보냈는데요.
GetPersonAddress()는 AdventureWorks의 Person.Address 테이블에서
AddressLine1, City, StateProvinceID를 얻어와서 하나의 문자열로 조합하는 메소드입니다.
별건 아니므로 이것도 간단하게 구현해보도록 하겠습니다.
// System.Data.SqlClient; 네임스페이스를 추가시켜야 합니다. using System.Data.SqlClient;
...
// 1개의 AddressID를 받아 using(SqlConnection sc = new SqlConnection("Data Source=localhost; Initial Catalog=AdventureWorks;Integrated Security=SSPI")) FROM Person.Address WHERE AddressID = @AddressID"; { sd.Read(); + sd.GetInt32(2).ToString(); } { } // DataReader를 닫는다 return address;
|
이제 이런 값들을 클라이언트에게 넘겨주고 GetCallbackEventReference() 의 세번째 인자로 주었던
클라이언트측의 함수를 호출합니다. 내가 할일은 끝났으니까, 이제 알아서 해봐" 하면서 되부르는 ...말 그대로 콜백(Callback)이죠?
맞다! 서버로부터 콜백을 받을 클라이언트측 함수를 만들어야 겠군요!
GetCallbackEventReference() 의 세번째 인자로 주었던 "이름"과 같은
클라이언트측 함수를 호출한다고 했었으니까
반드시 함수의 이름은 GetCallbackEventReference()의 세번째 인자로 준 것과 같아야겠죠?
예제에서는 콜백을 받을 함수의 이름을 "receive"로 정했으니
우리가 작성해야하는 클라이언트측 함수의 이름 역시 "receive"로 해야할 것입니다.
콜백을 받을 함수는 서버로부터 처리된 값을 받아오므로 이 값을 얻어올 매개변수를 가지게 됩니다.
보통 2개의 매개변수를 선언하는데, 하나는 서버에서 보내오는 값을 받아오는 매개변수와
나머지 하나는 서버에서 다시 전달하는 컨텍스트 값을 받아오는 매개변수입니다.
(여기에서 컨텍스트 값의 선언은 선택적이므로 선언을 생략해도 됩니다)
말만 복잡하게 했는데요.
실제 코드는 아래에서 보는것 처럼 너무 단순합니다.
⑧
Default.aspx를 열고 [소스]보기를 클릭하고 나오는 HTML 소스의 맨끝에 다음의 코드를 추가합니다.
|
위에 추가한 document.getElementById(ID)는 주어진 ID에 해당되는
HTML 요소를 가져오라는 DOM(Document Object Model) API 함수입니다.
그리고 가져온 HTML 요소의 innerHTML 속성에 rValue 즉, 서버가 반환한 값을 넣으라는 뜻입니다.
예제에서는 "divAddress"라는 ID를 가지는 <div> 부분에 서버가 처리한 주소값을 넣도록 했습니다.
이제 나머지 하나만 남았습니다.
콜백을 보내는 클라이언트측 함수는 만들었지만
(GetCallbackEventReference() 로 만들고, RegisterStartupScriptBlock() 으로 추가한 callback())
이를 정식으로 호출하는 함수는 아직 만들지 않았죠?
방금 추가한 receive() 끝에 다음의 코드를 추가합니다.
|
서버에 보낼 값을 "txtAddressID"라는 ID를 가지는 HTML 요소로부터 (즉, INPUT 텍스트박스에서)
값을 얻어와서 이를 서버에 콜백을 보내는 함수를 호출하며 인자로 넘겨줍니다.
이제 텍스트박스에 글을 쓰고 엔터를 누르면 이 함수를 호출할 수 있도록
Default.aspx 의 [소스]보기에서 다음과 같이 INPUT 텍스트박스의 속성을 고칩니다.
|
자 여기까지 따라오시느라 수고하셨습니다.
이렇게 수고스럽게 만들었는데 구경하지 않는다면 이제까지 버린 시간에 대한 죄라고 할 수 있겠죠?
아래는 이를 실행한 화면입니다.
INPUT 텍스트박스에 숫자를 입력한 다음에 엔터는 누르지 마시고 마우스로 아무곳이나 클릭하거나 탭 버튼을 한 번 눌러 INPUT 텍스트박스에 값이 바뀌었다는 이벤트가 발생하도록 해줘서 send()가
호출되도록 해줍니다. 와, 화면이 바뀌었습니다! (뒤로가기) 버튼도 비활성화가 되있구요!
여러분은 해내셨습니다!