방법: AJAX 사용 ASP.NET 웹 서비스를 WCF로 마이그레이션
이 항목에서는 기본 ASP.NET AJAX 서비스를 해당 AJAX 사용 WCF(Windows Communication Foundation) 서비스로 마이그레이션하는 절차에 대해 간략하게 설명합니다. 동일한 기능의 WCF 버전 ASP.NET AJAX 서비스를 만드는 방법을 보여 줍니다. 그런 다음, 두 서비스를 병행하여 사용하거나 ASP.NET AJAX 서비스를 WCF 서비스로 대체하여 사용할 수 있습니다.
기존 ASP.NET AJAX 서비스를 WCF AJAX 서비스로 마이그레이션하면 다음과 같은 이점이 있습니다.
최소의 추가 구성만으로 AJAX 서비스를 SOAP 서비스로 노출할 수 있습니다.
추적 기능 등 WCF 기능의 이점을 활용할 수 있습니다.
다음 절차에서는 Visual Studio 2012를 사용하고 있다고 가정합니다.
이 항목에서 간략히 설명된 절차에서 얻어진 코드는 다음 예제에 나와 있습니다.
AJAX 사용 엔드포인트를 통해 WCF 서비스를 노출하는 방법에 대한 자세한 내용은 방법: 구성을 사용하여 ASP.NET AJAX 엔드포인트 추가 항목을 참조하세요.
ASP.NET 웹 서비스 애플리케이션을 만들고 테스트하려면
Visual Studio 2012를 엽니다.
파일 메뉴에서 새로 만들기, 프로젝트, 웹, ASP.NET 웹 서비스 애플리케이션을 차례로 선택합니다.
프로젝트 이름을
ASPHello
로 지정한 다음, 확인을 클릭합니다.이 서비스에서 AJAX를 사용하려면 Service1.asmx.cs 파일에서
System.Web.Script.Services.ScriptService]
가 포함된 행의 주석 처리를 제거합니다.빌드 메뉴에서 솔루션 빌드를 선택합니다.
‘디버그’ 메뉴에서 ‘디버그하지 않고 시작’을 선택합니다.
생성된 웹 페이지에서
HelloWorld
작업을 선택합니다.HelloWorld
테스트 페이지에서 호출 단추를 클릭합니다. 다음과 같은 XML 응답을 받게 됩니다.<?xml version="1.0" encoding="utf-8" ?> <string xmlns="http://tempuri.org/">Hello World</string>
이 응답을 통해 현재 ASP.NET AJAX 서비스가 작동 중임을 확인할 수 있으며, 특히 해당 서비스가 Service1.asmx/HelloWorld에서 HTTP POST 요청에 응답하는 엔드포인트를 노출하고 XML을 반환함을 확인할 수 있습니다.
이제 이 서비스를 변환하여 WCF AJAX 서비스를 사용할 준비가 되었습니다.
동등한 WCF AJAX 서비스 애플리케이션을 만들려면
ASPHello 프로젝트를 마우스 오른쪽 단추로 클릭하고 추가, 새 항목, AJAX 사용 WCF 서비스를 차례로 선택합니다.
서비스 이름을
WCFHello
로 지정하고 추가를 클릭합니다.WCFHello.svc.cs 파일을 엽니다.
Service1.asmx.cs에서 다음과 같은
HelloWorld
작업의 구현을 복사합니다.public string HelloWorld() { return "Hello World"; }
복사한
HelloWorld
작업의 구현을 WCFHello.svc.cs 파일에 다음 코드 대신 붙여 넣습니다.public void DoWork() { // Add your operation implementation here return; }
ServiceContractAttribute의
Namespace
특성을WCFHello
로 지정합니다.[ServiceContract(Namespace="WCFHello")] [AspNetCompatibilityRequirements(RequirementsMode=AspNetCompatibilityRequirementsMode.Required)] public class WCFHello { … }
WebInvokeAttribute를
HelloWorld
작업에 추가하고 ResponseFormat 속성을 설정하여 Xml를 반환합니다. 이 속성을 설정하지 않은 경우 기본 반환 형식은 Json입니다.[OperationContract] [WebInvoke(ResponseFormat=WebMessageFormat.Xml)] public string HelloWorld() { return "Hello World"; }
빌드 메뉴에서 솔루션 빌드를 선택합니다.
WCFHello.svc 파일을 열고 디버그 메뉴에서 디버깅하지 않고 시작을 선택합니다.
이제 서비스가
WCFHello.svc/HelloWorld
에서 HTTP POST 요청에 응답하는 엔드포인트를 노출합니다. HTTP POST 요청은 브라우저에서 테스트할 수 없지만 엔드포인트는 다음과 같은 XML을 반환합니다.<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">Hello World</string>
WCFHello.svc/HelloWorld
및Service1.aspx/HelloWorld
엔드포인트는 이제 기능적으로 동일합니다.
예시
이 항목에서 간략히 설명된 절차에서 얻어진 코드는 다음 예제에 나와 있습니다.
//This is the ASP.NET code in the Service1.asmx.cs file.
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml.Linq;
using System.Web.Script.Services;
namespace ASPHello
{
/// <summary>
/// Summary description for Service1.
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ToolboxItem(false)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
[System.Web.Script.Services.ScriptService]
public class Service1 : System.Web.Services.WebService
{
[WebMethod]
public string HelloWorld()
{
return "Hello World";
}
}
}
//This is the WCF code in the WCFHello.svc.cs file.
using System;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
namespace ASPHello
{
[ServiceContract(Namespace = "WCFHello")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class WCFHello
{
// Add [WebInvoke] attribute to use HTTP GET.
[OperationContract]
[WebInvoke(ResponseFormat=WebMessageFormat.Xml)]
public string HelloWorld()
{
return "Hello World";
}
// Add more operations here and mark them with [OperationContract].
}
}
XmlDocument 형식은 DataContractJsonSerializer를 통해 serialize할 수 없으므로 XmlSerializer에서 지원하지 않습니다. 대신 XDocument 형식을 사용하거나 DocumentElement를 serialize할 수 있습니다.
ASMX 웹 서비스를 WCF 서비스로 업그레이드하고 동시에 마이그레이션하는 경우 클라이언트에서 두 형식을 같은 이름으로 매핑해서는 안 됩니다. 이 경우 같은 형식을 WebMethodAttribute 및 ServiceContractAttribute에서 사용하면 serializer에 예외가 발생합니다.
WCF 서비스가 먼저 추가되는 경우 프록시의 WCF 스타일 정의 순서가 우선하므로 .ASMX 웹 서비스에서 메서드를 호출하면 ConvertValue(Object, Type, String)에 예외가 발생합니다.
ASMX 웹 서비스가 먼저 추가되는 경우 프록시의 웹 서비스 스타일 정의 순서가 우선하므로 WCF 서비스에서 메서드를 호출하면 DataContractJsonSerializer에서 예외가 발생합니다.
DataContractJsonSerializer와 ASP.NET AJAX JavaScriptSerializer의 동작에는 상당한 차이점이 있습니다. 예를 들어, DataContractJsonSerializer는 키/값 쌍의 배열로 사전을 나타내고, ASP.NET AJAX JavaScriptSerializer는 실제 JSON 개체로 사전을 나타냅니다. 따라서 ASP.NET AJAX에서 사전은 다음과 같이 나타납니다.
Dictionary<string, int> d = new Dictionary<string, int>();
d.Add("one", 1);
d.Add("two", 2);
이 사전은 다음 목록에 표시된 것처럼 JSON 개체로 표현됩니다.
DataContractJsonSerializer에 의한 [{"Key":"one","Value":1},{"Key":"two","Value":2}]
ASP.NET AJAX JavaScriptSerializer에 의한 {"one":1,"two":2}
DataContractJsonSerializer는 키 유형이 문자열이 아닌 사전을 처리할 수 있다는 점에서 훨씬 강력합니다. 반면 JavaScriptSerializer는 키 유형이 문자열이 아닌 사전을 처리할 수 없습니다. 그러나 후자가 JSON에 더 적합합니다.
이 두 serializer의 중요한 차이점이 다음 표에 요약되어 있습니다.
차이의 범주 | DataContractJsonSerializer | ASP.NET AJAX JavaScriptSerializer |
---|---|---|
빈 버퍼(새 바이트[0])를 Object 또는 Uri 또는 다른 클래스로 역직렬화함 | SerializationException | null |
Value의 serialization | {}(또는 {"__type":"#System"}) | Null |
[Serializable] 형식의 private 멤버 serialization | serialize됨 | serialize되지 않음 |
ISerializable 형식의 .public 속성 serialization | serialize되지 않음 | serialize됨 |
JSON "확장명" | 개체 멤버 이름({"a":"hello"})에 따옴표를 사용해야 하는 JSON 사양 준수 | 따옴표가 없는 개체 멤버 이름({a:"hello"}) 지원 |
DateTime UTC(협정 세계시) | "\/Date(123456789U)\/" 또는 "\/Date\(\d+(U|(\+\-[\d{4}]))?\)\\/)" 형식을 지원하지 않습니다. | "\/Date(123456789U)\/" 및 "\/Date\(\d+(U|(\+\-[\d{4}]))?\)\\/)" 형식을 DateTime 값으로 지원합니다. |
사전의 표현 | KeyValuePair<K,V>의 배열은 문자열이 아닌 키 유형을 처리합니다. | 실제 JSON 개체로 문자열인 키 유형만 처리합니다. |
이스케이프된 문자 | 항상 이스케이프 슬래시(/)가 포함되고, "\n"과 같이 이스케이프되지 않은 잘못된 JSON 문자는 사용할 수 없습니다. | DateTime 값에 이스케이프 슬래시(/)가 포함됩니다. |