方法 : AJAX 対応 ASP.NET Web サービスを WCF に移行する
ここでは、基本的な ASP.NET AJAX サービスを同等の AJAX 対応 Windows Communication Foundation (WCF) サービスに移行する手順の概要を説明します。ここでは、ASP.NET AJAX サービスの、機能的に同等の WCF バージョンを作成する方法を示します。この 2 つのサービスを並行して使用することも、WCF サービスを ASP.NET AJAX サービスと置き換えて使用することもできます。
既存の ASP.NET AJAX サービスを WCF AJAX サービスに移行すると、次のような利点が得られます。
- 最小限の追加構成で、AJAX サービスを SOAP サービスとして公開できます。
- トレースなどの WCF の機能の利点が得られます。
次の手順では、Visual Studio 2008 が使用されていることを前提としています。
手順に続く例で、ここで説明する手順によって作成されるコードを示します。
AJAX 対応のエンドポイントを通じて WCF サービスを公開する方法詳細については、 、「方法 : 構成を使用して ASP.NET AJAX エンドポイントを追加する」を参照してください。
ASP.NET Web サービス アプリケーションを作成してテストする
Visual Studio 2008 を開きます。
[ファイル] メニューの [新規作成] をクリックし、[プロジェクト]、[Web] の順にクリックして、[ASP.NET Web サービス アプリケーション] をクリックします。
プロジェクトに「ASPHello」という名前を付け、[OK] をクリックます。
Service1.asmx.cs ファイルで、
System.Web.Script.Services.ScriptService]
が含まれた行のコメントを解除し、このサービスに対して AJAX を有効にします。[ビルド] メニューの [ソリューションのビルド] をクリックします。
[デバッグ] メニューの [デバッグなしで開始] をクリックします。
生成された Web ページで、
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 を返します。
このサービスへのアクセス方法詳細については、 、「Using Web Services in ASP.NET AJAX」を参照してください。
これで、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 操作に追加し、Xml を返すように RequestFormat プロパティを設定します。この設定を行わない場合、既定の戻り値の型は Json です。
[OperationContract] [WebInvoke(ResponseFormat=WebMessageFormat.Xml)] public string HelloWorld() { return "Hello World"; }
[ビルド] メニューの [ソリューションのビルド] をクリックします。
WCFHello.svc ファイルを開き、[デバッグ] メニューの [デバッグなしで開始] をクリックします。
現在、サービスは、WCFHello.svc/HelloWorld でエンドポイントを公開しています。このエンドポイントが HTTP POST 要求に応答します。HTTP POST 要求をブラウザからテストすることはできませんが、エンドポイントは次の XML を返します。
<string xmlns="https://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 型は、XmlSerializer によってシリアル化できないため、DataContractJsonSerializer ではサポートされていません。XDocument 型を使用するか、DocumentElement をシリアル化します。
ASMX Web サービスが WCF サービスと並行してアップグレードおおび移行される場合は、クライアントで 2 つの型を同じ名前に割り当てないようにします。同じ名前が割り当てられていると、WebMethodAttribute と ServiceContractAttribute で同じ型が使用されている場合に、シリアライザで次のような例外が発生します。
- WCF サービスが先に追加された場合は、ASMX Web サービスでメソッドを呼び出すと、ConvertValue で例外が発生します。これは、プロキシでの順序の定義で WCF スタイル定義が優先されるためです。
- ASMX Web サービスが先に追加された場合は、WCF サービスでメソッドを呼び出すと、DataContractJsonSerializer で例外が発生します。これは、プロキシでの順序の定義で Web サービス スタイル定義が優先されるためです。
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 で使いやすいと言えます。
これらのシリアライザの主な違いを次の表に示します。
相違点のカテゴリ | DataContractJsonSerializer | ASP.NET AJAX JavaScriptSerializer |
---|---|---|
空きバッファ (新しい byte[0]) の Object (または Uri、あるいは他の一部のクラス) への逆シリアル化 |
SerializationException |
null |
Value のシリアル化 |
{} (or {"__type":"#System"}) |
null |
[Serializable] 型のプライベート メンバのシリアル化 |
シリアル化できます |
シリアル化できません |
ISerializable 型のパブリック プロパティのシリアル化 |
シリアル化できません |
シリアル化できます |
JSON の「拡張機能」 |
オブジェクト メンバ名で引用符を必要とする ({"a":"hello"}) JSON 仕様に準拠しています。 |
引用符のないオブジェクト メンバ名 ({a:"hello"}) をサポートします。 |
DateTime 協定世界時刻 (UTC) |
"\/Date(123456789U)\/" 形式または "\/Date\(\d+(U|(\+\-[\d{4}]))?\)\\/)" 形式をサポートしません。 |
DateTime 値として、"\/Date(123456789U)\/" 形式と "\/Date\(\d+(U|(\+\-[\d{4}]))?\)\\/)" 形式をサポートします。 |
ディクショナリの表現 |
KeyValuePair<K,V> の配列。文字列以外の種類のキーを処理します。 |
実際の JSON オブジェクトですが、文字列の種類のキーのみ処理します。 |
エスケープ文字 |
必ず、エスケープ文字であるスラッシュ (/) を付けます。"\n" などのエスケープされない無効な JSON 文字は使用できません。 |
DateTime 値には、エスケープ文字スラッシュ (/) を付けます。 |