ASP.NET AJAXのWCFサポート
VS2008では「AJAX 対応 WCF サービス」テンプレートが用意されています。これとScriptManagerコントロールを利用すると、WCFサービスをJSON形式でASP.NET AJAXと共に使用できます。WCFに関する基礎知識は「WCF(Windows Communication Foundation)チュートリアル 前編」と「WCF(Windows Communication Foundation)チュートリアル 後編」を参考にしてください。また、「Visual Studio 2008徹底入門」の第7回でもWCFについて扱う予定です。
web.config(構成ファイル)を使用したエンドポイント追加方法
ここでのサンプルはシンプルにテキストに入力された数字に3をかけた値を返すWCFサービスを作成します(図1~2)。
[新しい項目の追加]で「AJAX 対応 WCF サービス」を選択すると(図3)AJAX対応のWCFサービスが作成されます。その時web.configやendpointは自動的に記述されます。
<system.serviceModel> <behaviors> <endpointBehaviors> <behavior name="AJAXAspNetAjaxBehavior"> <enableWebScript /> </behavior> </endpointBehaviors> </behaviors> <serviceHostingEnvironment aspNetCompatibilityEnabled="true" /> <services> <service name="AJAX"> <endpoint address=""
behaviorConfiguration="AJAXAspNetAjaxBehavior"
binding="webHttpBinding" contract="AJAX" /> </service> </services> </system.serviceModel>
Service name属性とcontract属性にサービス名が、binding属性にはwebHttpBindingが設定されています。webHttpBindingはwebプログラミングでWCFを利用する場合のバインディングです。
自動追記されたweb.configには、エンドポイントの作成、コントラクトの設定がされているので、このWCFサービスを利用するにはサービスメソッドを記述するだけでOKです。
<ServiceContract(Namespace:="AJAXIAN")> _ <AspNetCompatibilityRequirements(RequirementsMode:= AspNetCompatibilityRequirementsMode.Allowed)> Public Class AJAX <OperationContract()> _ Public Function Math(ByVal item As Integer) As Integer Return item * 3 End Function End Class
続いて、ASP.NET AJAX(Webフォーム)側での設定ですが、こちらも簡単でScriptManagerコントロールのServicesプロパティを設定すると、WCFサービスとアクセスすることが可能になります。
<asp:ScriptManager ID="ScriptManager1" runat="server"> <Services> <asp:ServiceReference Path="サービス名.svc" /> </Services> </asp:ScriptManager>
WCFサービスにアクセスできるようになったので、後はASP.NET AJAX(Webフォーム)側でそれを利用するコードを記述するだけです。
function Click(){ var txt = $get("TextBox1").value; var service = new AJAXIAN.AJAX(); service.Math(txt,Finish); return false; } function Finish(res){ $get("Label1").innerHTML=res; }
web.config(構成ファイル)を使用しないエンドポイント追加方法
web.configにエンドポイントの追記を行うことなく、WCFを利用する方法もあります。この方法はWCFサービスがIISに配置されていることが必要です。
また、この方法のメリットは、web.configへの追記を行うことなくWCFを利用できるという点になります(前項の方法を利用すれば、web.configへの自動記述がされるのでなおさら利用機会が少ないかもしれません。個人的見解としては、ASP.NETを使用しない場合にエンドポイント作成を簡略化させるために存在しているという認識です)。
前項で作成したWebサイトから、web.configのsystem.serviceModel要素の記述をコメントアウトしてIISにWebサイトを配置します。そして、web.configの代わりに@ServiceHostディレクティブのFactory属性に WebScriptServiceHostFactory を指定します。手順はこれだけです。
<%@ ServiceHost Language="VB" _ Debug="true" Service="名前空間.クラス" _ CodeBehind="~/App_Code/Service.cs" _ Factory=System.ServiceModel.Activation.WebScriptServiceHostFactory %>
このFactory属性を指定することで、本来必要なweb.configに対する設定をFactory属性で指定されたファクトリクラスの中で実施します。これによって、クライアントサイドのJavaScriptからWCFサービスを呼び出すことができます。
ASP.NETを使用しないAJAXエンドポイント追加方法
WCFは使いたいけど、ASP.NETは使用していないAJAX対応のページを作成する事も考えられます。WCFはこのシナリオにも対応しています。手順は以下のようになっています。
- AJAXエンドポイントの作成
- AJAX対応コントラクトの作成
- WCFへのアクセス
このうち、「AJAXエンドポイントの作成」については、既に述べている構成ファイルを使用するパターンと、しないパターンの2種類ですので解説は割愛します。
AJAX対応コントラクトの作成
JSON形式でデータのやり取りをするにはWCFサービス側で、対応のコントラクトを作成する必要があります。クライアントサイドではJSON形式でのデータを送信し、WCFサービス側はJSON形式のデータを受け取るためのコントラクトと、WebGetAttribute属性かWebInvokeAttribute属性を設定する必要があります。GETを使用する場合はWebGetAttribute属性を、POST、PUTなどを利用するときはWebInvokeAttribute属性を使用します。
サンプルでは、苗字と名前を入力してもらい、結合して返すシンプルなサービスにしています。
var name = '{"FirstName":'; name = name + '"' + firstname + '"' + ',"LastName":'; name = name + '"' + lastname + '"' + '}';
<ServiceContract()> _ Public Interface IService <OperationContract()> _ <WebInvoke(ResponseFormat:=WebMessageFormat.Json, bodystyle:=WebMessageBodyStyle.WrappedRequest)> _ Function NameCombine(ByVal FirstName As String, ByVal LastName As String) As String End Interface Public Class Service Implements IService Public Function NameCombine(ByVal FirstName As String, ByVal LastName As String) As String _ Implements IService.NameCombine Return "こんにちは " + LastName + " " + FirstName + " さん" End Function End Class
WCFへのアクセス
WCF AJAXエンドポイントは、JSON/XMLどちらの形式の要求も受け取り可能です。
ただし、JSONで利用したい場合はXMLHttpRequestのsetRequestHeaderのContent-typeをapplication/jsonに設定する必要はあります。もちろんポストするデータはJSON形式で処理したい場合はJSONシリアライズする必要があります。Content-typeがtext/xmlの場合のPOST要求はXML として処理されます。
function nameCombine() { var firstname = document.getElementById("firstname").value; var lastname = document.getElementById("lastname").value; var xmlHttp = new XMLHttpRequest(); // WCFサービスへのURL var url = "Service.svc/jsonEndpoint/NameCombine"; //JSON形式へシリアライズ var name = '{"FirstName":'; name = name + '"' + firstname + '"' + ',"LastName":'; name = name + '"' + lastname + '"' + '}'; // WCFサービスへJSON形式でのリクエスト xmlHttp.open("POST", url, true); xmlHttp.setRequestHeader("Content-type", "application/json"); xmlHttp.send(name); // サービスからの応答処理 xmlHttp.onreadystatechange = function Status(){ if (xmlHttp.readyState == 4){ document.getElementById("combinename").innerHTML = xmlHttp.responseText; } } }