프로젝트 생성
Visual Studio.NET을 구동시키고 [File]-[New]-[Project..] 메뉴를 선택한다. 프로젝트 위저드 화면이 나타나면 아래 그림과 같이 "Visual C# Projects" 프로젝트 타입 중에서 "ASP.NET Web Service" 템플릿을 선택하고 "WebSvcSample"이라는 이름을 준 다음 [확인] 버튼을 누른다.
프로젝트가 생성되고 Visual Studio.NET이 FrontPage 2000 서버 확장 모듈을 사용하여 프로젝트명과 동일한 가상 디렉터리까지 만들어줄 것이다. 프로젝트 생성이 제대로 되면 아래와 같은 화면이 나온다.
코드 작성
폼 디자이너에 올라온 Service1.asmx.cs 파일을 마우스 오른쪽 버튼으로 클릭하고 [View Code] 메뉴를 선택하면 아래와 같이 C#으로 짜여진 Service1.asmx.cs의 소스 코드가 나타날 것이다.
소스의 아래 부분에 보면 커멘트로 막혀있는 부분이 있다.
//public string HelloWorld() //{ // return "Hello World"; //} |
위저드가 생성해준 부분으로서, 웹 메서드를 생성할 때에는 이러한 방식으로 하라는 예제 코드이다. 이 부분의 커멘트를 모두 풀어주고 프로젝트를 빌드한다.
실행
웹 브라우져를 띄워 Service1.asmx에 대한 URL을 입력한다. 본서의 예제대로 따라했다면 URL은 "http://localhost/WebSvcSample/Service1.asmx"가 된다. 또는 솔루션 탐색기에서 Service1.asmx 항목을 마우스 오른쪽 버튼으로 클릭하고 [View in Browser] 메뉴를 선택하면 다음과 같은 화면이 나올 것이다.
내부적으로 진행된 프로세스를 살펴보자.
1) 웹 서비스는 클라이언트가 사용할 수 있는 웹 메서드를 노출시킨다.
2) 웹 브라우저가 웹 서비스의 기본 URL에 request를 보내면 웹 서비스는 discovery document를 웹 브라우저에게 보낸다(Discovery).
3) 웹 브라우저는 discovery document를 해석하여 웹 서비스에게 service description을 요청한다(Description).
4) 웹 서비스는 WSDL을 사용하여 service description을 담고 있는 XML을 클라이언트에 보낸다.
5) 웹 브라우저는 service description을 해석하여 이 웹 서비스가 제공하는 메서드를 화면에 출력한다.
2) 웹 브라우저가 웹 서비스의 기본 URL에 request를 보내면 웹 서비스는 discovery document를 웹 브라우저에게 보낸다(Discovery).
3) 웹 브라우저는 discovery document를 해석하여 웹 서비스에게 service description을 요청한다(Description).
4) 웹 서비스는 WSDL을 사용하여 service description을 담고 있는 XML을 클라이언트에 보낸다.
5) 웹 브라우저는 service description을 해석하여 이 웹 서비스가 제공하는 메서드를 화면에 출력한다.
Service1 웹 서비스가 보내준 service description을 보고 싶지 않은가? 어떻게 생겼나 호기심이 생길 것이다. 위 화면 상단의 "Service Description" 링크를 클릭하면 아래와 같이 XML로 작성된 service description이 나타난다. URL을 보면 웹 서비스를 요청하는 기본 URL에 "WSDL"이라는 매개 변수를 전달하고 있다. 이것은 웹 서비스 모듈과 클라이언트의 약속이다. 위 화면에서도 내부적으로 "http://localhost/WebSvcSample/Service1.asmx?WSDL"이라는 request를 던졌기 때문에 이 웹 서비스가 제공하는 메서드를 표시할 수 있었던 것이다.
위 화면에서 service description을 살펴보자.
첫 번째 라인에서 이 service description 파일이 XML 문법에 따르고 있음과 utf-8 문자체계를 따름을 명시하고 있다.
첫 번째 라인에서 이 service description 파일이 XML 문법에 따르고 있음과 utf-8 문자체계를 따름을 명시하고 있다.
service description에서 사용하는 네임스페이스를 정의한다.
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:s0="http://tempuri.org/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" targetNamespace="http://tempuri.org/" xmlns="http://schemas.xmlsoap.org/wsdl/"> |
"HelloWorld", "HelloWorldResponse", "HelloWorldResult" 엘리먼트를 정의한다. HelloWorldResponse 엘리먼트는 HelloWorldResult 엘리먼트를 내포하며 HelloWorldResult 엘리먼트는 string 형이고 null 값이 될 수 있음을 명시하고 있다.
<s:complexType /> </s:element> <s:element name="HelloWorldResponse"> <s:complexType> <s:sequence> <s:element minOccurs="0" maxOccurs="1" name="HelloWorldResult" type="s:string" /> </s:sequence> </s:complexType> </s:element> <s:element name="string" nillable="true" type="s:string" /> |
SOAP 방식의 메시징 입출력에 대해 정의한다.
<part name="parameters" element="s0:HelloWorld" /> </message> <message name="HelloWorldSoapOut"> <part name="parameters" element="s0:HelloWorldResponse" /> </message> |
HTTP GET 방식의 메시징 입출력에 대해 정의한다.
<message name="HelloWorldHttpGetOut"> <part name="Body" element="s0:string" /> </message> |
HTTP POST 방식의 메시징 입출력에 대해 정의한다.
<message name="HelloWorldHttpPostOut"> <part name="Body" element="s0:string" /> </message> |
SOAP 방식의 메시징에 대해 정의한다. 입력시에는 위에서 정의했던 HelloWorldSoapIn 엘리먼트를, 출력시에는 HelloWorldSoapOut 엘리먼트를 사용한다.
<operation name="HelloWorld"> <input message="s0:HelloWorldSoapIn" /> <output message="s0:HelloWorldSoapOut" /> </operation> </portType> |
HTTP GET 방식의 메시징에 대해 정의한다. 입력시에는 위에서 정의했던 HelloWorldHttpGetIn 엘리먼트를, 출력시에는 HelloWorldHttpGetOut 엘리먼트를 사용한다.
<operation name="HelloWorld"> <input message="s0:HelloWorldHttpGetIn" /> <output message="s0:HelloWorldHttpGetOut" /> </operation> </portType> |
HTTP POST 방식의 메시징에 대해 정의한다. 입력시에는 위에서 정의했던 HelloWorldHttpPostIn 엘리먼트를, 출력시에는 HelloWorldHttpPostOut 엘리먼트를 사용한다.
<operation name="HelloWorld"> <input message="s0:HelloWorldHttpPostIn" /> <output message="s0:HelloWorldHttpPostOut" /> </operation> </portType> |
SOAP 방식의 메시징이 HTTP 프로토콜을 사용하여 전송됨을 명시하고, "HelloWorld"라는 메서드가 사용하는 입출력 방식을 정의한다.
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" /> <operation name="HelloWorld"> <soap:operation soapAction="http://tempuri.org/HelloWorld" style="document" /> <input> <soap:body use="literal" /> </input> <output> <soap:body use="literal" /> </output> </operation> </binding> |
HTTP GET 방식의 메시징에 있어서 "HelloWorld"라는 메서드가 사용하는 입출력 방식을 정의한다.
<http:binding verb="GET" /> <operation name="HelloWorld"> <http:operation location="/HelloWorld" /> <input> <http:urlEncoded /> </input> <output> <mime:mimeXml part="Body" /> </output> </operation> </binding> |
HTTP POST 방식의 메시징에 있어서 "HelloWorld"라는 메서드가 사용하는 입출력 방식을 정의한다.
<http:binding verb="POST" /> <operation name="HelloWorld"> <http:operation location="/HelloWorld" /> <input> <mime:content type="application/x-www-form-urlencoded" /> </input> <output> <mime:mimeXml part="Body" /> </output> </operation> </binding> |
"Service1" 서비스가 노출시키는 메시징 방식을 정의하고 각각의 메시징을 사용하기 위한 기본 URL을 정의한다.
<port name="Service1Soap" binding="s0:Service1Soap"> <soap:address location="http://localhost/WebSvcSample/Service1.asmx" /> </port> <port name="Service1HttpGet" binding="s0:Service1HttpGet"> <http:address location="http://localhost/WebSvcSample/Service1.asmx" /> </port> <port name="Service1HttpPost" binding="s0:Service1HttpPost"> <http:address location="http://localhost/WebSvcSample/Service1.asmx" /> </port> </service> |
웹 브라우저는 이 service description을 해석하여 어떤 형식으로 request를 보내야 하는지, 어떤 형식의 결과 값이 넘어오는지 알아낸다. 이 웹 서비스는 "HelloWorld"라는 웹 메서드를 지원하고 있으며, 화면 상단의 "HelloWorld" 링크를 클릭하면 아래와 같이 이 메서드를 호출하기 위한 세 가지 방법, 즉 SOAP, HTTP GET, HTTP POST에 대한 샘플이 나온다.
화면 상단의 "Invoke" 버튼을 눌러 HelloWorld 메서드를 호출해보자. 위 화면의 HTML 소스를 보면 GET 방식으로 요청했음을 알 수 있다(Wire Format). 아래 그림에서 볼 수 있듯이 메서드가 반환하는 결과 값 역시 XML 형식으로 넘어온다.
소스 분석
탐색기를 띄우고 Service1.asmx 파일을 텍스트로 열어보자.
단 한 줄로 이루어져 있으며, 이 웹 서비스는 Service1.asmx.cs 파일에서 C# 언어를 사용하여 WebSvcSample.Service1 클래스로 구현했음을 나타낸다.
Service1.asmx.cs 소스를 보자.
using System.Collections; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Web; using System.Web.Services; namespace WebSvcSample { /// <summary> /// Summary description for Service1. /// </summary> public class Service1 : System.Web.Services.WebService { public Service1() { //CODEGEN: This call is required by the ASP.NET Web Services Designer InitializeComponent(); } #region Component Designer generated code //Required by the Web Services Designer private IContainer components = null; /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { } /// <summary> /// Clean up any resources being used. /// </summary> protected override void Dispose( bool disposing ) { if(disposing && components != null) { components.Dispose(); } base.Dispose(disposing); } #endregion // WEB SERVICE EXAMPLE // The HelloWorld() example service returns the string Hello World // To build, uncomment the following lines then save and build the project // To test this web service, press F5 [WebMethod] public string HelloWorld() { return "Hello World"; } } } |
"WebSvcSample"이라는 네임스페이스가 선언되고 그 안에 "Service1"이라는 클래스가 선언되었다. 공통적인 초기화 작업이 필요한 경우 InitializeComponent() 멤버 함수에서 처리하면 된다. 반대로 작업 수행 후 마무리해야 하는 작업이 있으면 Dispose() 멤버 함수에서 처리한다. 예를 들어 모든 웹 메서드가 데이터베이스에 연결되어야 한다면 InitializeComponent()에서 그 과정을 처리하고 Dispose()에서 데이터베이스 연결을 해지하면 될 것이다. 이러한 방식은 반복적인 코딩을 줄임으로써 개발 시간을 단축시키고 개발자의 실수로 리소스가 낭비되는 현상을 방지하는 데에 도움을 준다.
가장 중요한 부분이라 할 수 있는 웹 메서드에 대해 좀더 알아보자. 소스에서 볼 수 있듯이 클라이언트가 사용하기 위해서는 반드시 "[WebMethod]" 지시자가 멤버 함수 앞에 위치해야 한다. 만약 이 지시자가 없으면 멤버 함수가 public형으로 선언되었다고 해도 클라이언트는 이 메서드를 사용할 수 없다.
웹 메서드에는 몇 가지 속성을 적용시킬 수 있는데 예를 들어 이 웹 메서드가 트랜잭션을 사용할 것인지, 혹은 세션을 사용할 것인지, response 버퍼링을 사용할 것인지 등을 지정할 수 있다. 각 속성에 대한 자세한 설명은 MSDN을 참조하기 바란다.
다음은 웹 메서드 속성의 사용예이다.
{ [ WebMethod (Description="세션을 사용하는 카운터",EnableSession=true)] public int SessionCounter() { // "Counter" 세션 변수가 존재하지 않으면 세션변수를 만들고 1로 초기화한다 if (null == Session("Counter")) Session("Counter") = 1; else // "Counter" 세션 변수가 존재하면 그 값을 1만큼 증가시킨다 Session("Counter") = Session("Counter") + 1; // "Counter" 세션 변수의 값을 반환한다 int nRet = Session("Counter"); return nRet; } } |
웹 서비스 모듈 역어셈블링
Service1.asmx.cs가 컴파일된 실질적인 웹 서비스 모듈을 IL Disassembler에서 열어보자. 탐색기에서 웹 서비스 프로젝트가 저장된 디렉터리로 이동한다.
프로젝트 파일이 저장된 WebSvcSample 디렉터리를 보면 bin이라는 서브 디렉터리가 있다. 이 곳이 웹 서비스의 바이너리 모듈이 위치하는 장소이다. "WebSvcSample.dll" 파일이 보이는데, 이것이 컴파일된 웹 서비스 모듈이다.
탐색기를 사용하여 Program FilesMicrosoft.NETFrameworkSDKBinildasm.exe 파일을 실행시키고 IL Disassembler의 [File]-[Open] 메뉴를 선택하여 WebSvcSample.dll 파일을 지정한다.
프로젝트 파일이 저장된 WebSvcSample 디렉터리를 보면 bin이라는 서브 디렉터리가 있다. 이 곳이 웹 서비스의 바이너리 모듈이 위치하는 장소이다. "WebSvcSample.dll" 파일이 보이는데, 이것이 컴파일된 웹 서비스 모듈이다.
탐색기를 사용하여 Program FilesMicrosoft.NETFrameworkSDKBinildasm.exe 파일을 실행시키고 IL Disassembler의 [File]-[Open] 메뉴를 선택하여 WebSvcSample.dll 파일을 지정한다.
트리를 펼치면 아래 그림과 같은 화면을 볼 수 있을 것이다. WebSvcSample.dll 파일이 IL, 즉 CLR을 대상으로 하는 Intermediate Language로 만들어졌다는 사실을 알 수 있으며 우리가 사용한 HelloWorld 메서드를 포함한 여러 함수들의 리턴형과 매개 변수가 나온다.
WebSvcSample.dll은 IL 형태이기 때문에 이것이 웹 서버에서 돌아가기 위해서는 프로세서가 이해할 수 있도록 컴파일이 수행되어야 한다. WebSvcSample.dll이 만들어지고 Service1.asmx에 대한 첫 번째 request가 들어왔을 때 이 작업이 수행된다. 플랫폼에 적합한 컴파일된 모듈이 메모리상에 만들어지고 곧바로 캐시 상태로 남아있게 된다. 그 다음 request부터는 재컴파일 작업이 필요없으며 캐시된 모듈이 request를 처리를 담당하게 되어 처리 속도가 빨라진다.
웹 어플리케이션과 마찬가지로 메모리에 캐시되는 것은 웹 서비스 모듈의 사본이다. 웹 서비스 모듈의 사본을 인터넷 정보 서비스가 사용하기 때문에 인터넷 정보 서비스를 멈추지 않고도 웹 서비스 모듈을 덮어쓸 수 있다. 파일을 덮어쓰게 되면 운영체제가 .NET 프레임워크에 그 사실을 알려주고 .NET 프레임워크는 현재 메모리에 캐시되어 있는 웹 서비스 모듈의 사본이 현재 처리중인 프로세스를 모두 마칠 때까지 기다린다. 작업이 끝나면 메모리에서 그 모듈을 언로드하고 새로운 웹 서비스 모듈의 사본을 적재한다.
세션 변수와 어플리케이션 변수의 사용
ASP나 웹 어플리케이션과 마찬가지로 웹 서비스에서도 세션 변수와 어플리케이션 변수를 사용할 수 있다. IL Disassembler에서 Global 서브 트리를 보면 세션과 어플리케이션에 관련된 메서드들을 볼 수 있는데, 이 부분은 Visual Studio.NET이 자동으로 생성해준 것이다. 이것과 관련된 소스는 우리가 작성한 프로젝트의 소스와 같은 디렉터리에 존재하는 Global.asax와 Global.asax.cs이다. 이것은 각각의 웹 서비스 모듈마다 개별적인 어플리케이션 변수와 세션 변수를 사용할 수 있음을 의미한다.
Global.asax의 소스를 보자.
using System.Collections; using System.ComponentModel; using System.Web; using System.Web.SessionState; namespace WebSvcSample { /// <summary> /// Summary description for Global. /// </summary> public class Global : System.Web.HttpApplication { public Global() { InitializeComponent(); } protected void Application_Start(Object sender, EventArgs e) { } protected void Session_Start(Object sender, EventArgs e) { } protected void Application_BeginRequest(Object sender, EventArgs e) { } protected void Application_EndRequest(Object sender, EventArgs e) { } protected void Application_AuthenticateRequest(Object sender, EventArgs e) { } protected void Application_Error(Object sender, EventArgs e) { } protected void Session_End(Object sender, EventArgs e) { } protected void Application_End(Object sender, EventArgs e) { } #region Web Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { } #endregion } } |
WebSvcSample 네임스페이스의 Global 클래스가 보인다. System.Web.HttpApplication 클래스에서 상속받고 있고 Application과 Session은 System.Web.HttpApplication의 public 멤버 변수이다. 결국 Global 클래스는 Application과 Session이라는 public 멤버 변수를 상속받으며, Global 클래스에서 Application과 Session에 관련된 메서드들은 protected로 선언되어 있기 때문에 이 클래스를 상속받는 Global.asax는 부모 클래스에 속한 이 메서드들을 사용할 수 있다. Application이나 Session에 관련된 처리를 하려면 Global.asax.cs 파일의 해당 메서드에 코드를 넣어주면 된다. Visual Studio.NET은 WebSvcSample이라는 동일한 네임스페이스를 사용하는 Service1.asmx.cs와 Global.asax.cs 파일을 함께 컴파일하여 하나의 웹 서비스 모듈로 생성한다.
설정 파일
웹 서비스에서도 웹 어플리케이션처럼 web.config 파일을 사용하여 서비스의 속성을 지정한다. 우리가 예제로 만들었던 Service1.asmx 파일이 위치하는 디렉터리에 가보면 web.config이라는 파일이 있다. web.config 파일에 대해서는 웹 어플리케이션에서 설명한 부분을 참조하기 바란다.
가상 디렉터리 설정
이번에는 Visual Studio.NET이 FrontPage 2000 서버 확장 모듈을 사용하여 만들어준 가상 디렉터리를 살펴보겠다.
[시작]-[프로그램]-[관리도구]-[인터넷 서비스 관리자]를 실행한다. 트리를 펼치면 아래와 같은 화면을 볼 수 있을 것이다. 예제로 작성했던 WebSvcSample 프로젝트가 동일명의 가상 디렉터리로 만들어져 있다. 소스 파일과 여러 개의 서브 디렉터리가 보이는데 실제 서비스에 필요한 파일은 Global.asax, Service1.asmx, WebSvcSample.vsdisco, Web.config, 그리고 bin 서브 디렉터리의 WebSvcSample.dll이다.
ASPNET_ISAPI.DLL
.asmx 파일에 대한 request를 보냈을 때 그와 관련된 웹 서비스 모듈이 호출되는 과정 역시 웹 어플리케이션과 동일하다.
[시작]-[프로그램]-[관리도구]-[인터넷 서비스 관리자]를 실행하고 예제로 작성한 /WebSvcSample 가상 디렉터리를 마우스 오른쪽 버튼으로 클릭하여 [등록 정보] 메뉴를 선택한다. 아래 등록 정보 창의 [디렉터리] 탭 화면에서 하단의 [구성...] 버튼을 누른다.
아래의 [응용 프로그램 매핑] 탭 화면에서 볼 수 있듯이 .asmx 확장자는 aspnet_isapi.dll 파일에 매핑되어 있는데, /WebSvcSample이라는 가상 디렉터리에 확장자가 .asmx인 파일에 대한 request가 들어오면 aspnet_isapi.dll 파일에 제어권을 넘긴다는 의미이다. 제어권을 넘겨받은 aspnet_isapi.dll은 CLR에게 해당 웹 어플리케이션 모듈을 동작시키게끔 한다. 만약 여러분이 .asmx에 대한 매핑을 제거한다면 .asmx 파일에 대한 request를 보냈을 때 response가 돌아오지 않는 공백 화면을 보게 되며 이 사항은 ASP.NET과 관련된 모든 확장자 매핑(.aspx, .asax, .ascx, .asmx, .config, .vsdisco 등)에 대하여 동일하게 적용된다.
웹 메서드 추가
웹 메서드를 하나 추가하여 여러 개의 웹 메서드를 가지는 웹 서비스를 만들어보자. Service1.asmx.cs 소스를 열고 HelloWorld() 웹 메서드 아래에 다음과 같이 string 형의 매개 변수를 하나 받아서 string 형의 결과 값을 반환하는 "ByeWorld"라는 웹 메서드를 추가한다. 이 때 웹 메서드임을 알려주는 [WebMethod] 속성 지시자를 빠뜨리지 말자. 프로젝트를 저장하고 빌드한다.
public string ByeWorld(string strName) { return (strName + "! Hello World"); } |
클라이언트 프로젝트 작성
간단한 웹 어플리케이션을 작성하여 이 서비스를 사용해보자. 솔루션 탐색기에서 "WebSvcSample" 솔루션 항목을 마우스 오른쪽 버튼으로 클릭하고 [추가]-[새 프로젝트..] 메뉴를 실행하여 다음 그림과 같이 "Visual C# 프로젝트" 형식의 "ASP.NET 웹 응용 프로그램" 템플릿을 선택한다. "WebSvcSampleClient"라는 이름을 주고 [확인] 버튼을 눌러 프로젝트를 생성한다.
클라이언트 웹 폼 디자인
폼 디자이너에 올라온 WebForm1.aspx에 아래 그림과 같이 HelloWorld() 웹 메서드를 호출할 버튼(id: BtnHello), ByeWorld() 웹 메서드를 호출할 버튼(id: BtnBye), 결과를 표시할 레이블(id: Label1)을 올린다.
웹 참조 추가
솔루션 탐색기에서 "WebSvcSampleClient" 프로젝트를 마우스 오른쪽 버튼으로 클릭하고 [웹 참조 추가…] 메뉴를 선택한다. 다음 그림과 같이 주소란에 웹 서비스의 service description에 대한 URL을 입력하고 엔터키를 누른다. 본서의 예제를 그대로 따라했다면 URL은 "http://localhost/WebSvcSample/Service1.asmx?WSDL"가 된다.
아래와 같이 service description의 내용이 출력되면 [참조 추가] 버튼을 눌러 WebSvcSample 웹 서비스를 WebSvcSampleClient의 웹 참조 항목으로 추가한다.
솔루션 탐색기에서 보면 WebSvcSampleClient 프로젝트의 "웹 참조" 항목 밑에 "localhost"라는 이름으로 웹 참조가 추가되었을 것이다. 코드에서 구분하기 쉽도록 이 항목의 이름을 "WebSvcSample"로 변경한다.
HelloWorld() 웹 메서드 호출
폼 디자이너에서 WebForm1.aspx의 "HelloWorld" 버튼을 더블 클릭하여 WebForm1.aspx.cs를 소스 에디터로 열고 BtnHello_Click() 이벤트 핸들러에 코드를 작성한다.
웹 참조 항목으로 포함한 WebSvcSample 네임스페이스의 Service1 객체를 생성한다.
생성된 객체를 사용하여 HelloWorld() 메서드를 호출하고 결과 값을 받는다.
결과 값을 Label1 레이블에 뿌린다.
ByeWorld() 웹 메서드 호출
WebForm1.aspx의 "GoodBye" 버튼을 더블 클릭하고 ByeWorld() 웹 메서드를 호출하는 코드를 작성한다.
{ // WebSvcSample 네임스페이스의 Service1 객체를 생성한다 WebSvcSample.Service1 obj = new WebSvcSample.Service1(); // 웹 메서드 호출 string strRet = obj.ByeWorld("dizzi"); // 리턴값 표시 Label1.Text = strRet; } |
실행
프로젝트를 빌드하고 웹 브라우저에서 클라이언트 WebForm1.aspx 페이지를 호출한다. 필자는 WebForm1.aspx가 존재하는 디렉터리를 "/WebSvcSampleClient"라는 가상 디렉터리로 지정하여 실행하였다.
위 화면에서 HelloWorld 버튼을 클릭하면 아래와 같이 HelloWorld() 웹 메서드의 호출 결과 페이지가 나타난다.
GoodBye 버튼을 눌러 ByeWorld() 웹 메서드를 호출하였을 때의 결과 화면은 아래와 같다.
'.net' 카테고리의 다른 글
ASP.NET 파일 업로드 하기 (2) | 2007.05.03 |
---|---|
비동기식 통신(Asynchronous communication) (0) | 2007.05.03 |
성공적인 데이터 액세스를 위한 팁 (0) | 2007.05.03 |
WebClient를 이용하여 웹 페이지 실행하기 (0) | 2007.05.03 |
웹에서의 비동기 호출 : Ajax와 Ajax.NET (3) | 2007.05.03 |