WCFサービスではwebHttpBindingの構成を変更することでJSON形式で結果をシリアライズして、AJAXのクライアントに結果を返せるようになります。
確認環境は次の通り
- Windows Vista Enterprise(WCFサービス,WCFクライアント同一マシン)
- 開発環境 Visual Studio 2008 Professional (英語版)
- .NET 3.5
1. ソリューションの作成
Visual Studioを起動して空のプロジェクトを作成します。プロジェクト名はWCFSample017としました。
2. WCFサービスプロジェクトの作成
ソリューションを右クリック→[Add]→[New Project]でプロジェクトを新規作成します。WCF Service Libraryテンプレートを選択して、プロジェクト名をWCFSample.PersonServiceとしてプロジェクトを新規作成します。プロジェクト作成後、自動で作成されたIService.cs,Service.cs,App.configを削除します。プロジェクトの参照にSystem.ServiceModel.Webを追加して、サービスクラス、データコントラクトを作成します。
2.1 データコントラクトクラスの作成
プロジェクトを右クリック→[Add]→[New Item]でファイルタイプにClassを選択、ファイル名をPerson.csとして作成する。
Person.csを次のように編集します。PersonクラスはID,ファーストネーム、ラストネームを持つデータコントラクトクラスです。
using System; using System.ServiceModel; using System.ServiceModel.Web; using System.Runtime.Serialization; namespace WCFSample.PersonService { [DataContract] public class Person { public Person(int id, string firstName, string lastName) { this.ID = id; this.FirstName = firstName; this.LastName = lastName; } [DataMember] public int ID; [DataMember] public string FirstName = ""; [DataMember] public string LastName = ""; } }
2.2 サービスコントラクト,サービスクラスの作成
プロジェクトで新規項目を作成します。ファイルタイプのWCF Serviceを選択。ファイル名をPersonSearchと入力して、サービスコントラクト、サービスクラスを新規作成します。
サービスコントラクトクラスIPersonSearch.csは次のように編集します。ServiceContract.Namespaceに設定した値WCFSample.AjaxScriptは、AJAX用のクライアントスクリプトのネームスペースになります。
using System; using System.Collections.Generic; using System.Runtime.Serialization; using System.ServiceModel; using System.ServiceModel.Web; namespace WCFSample.PersonService { [ServiceContract(Namespace="WCFSample.AjaxScript")] interface IPersonSearch { [OperationContract] [WebGet] IList<Person> GetPersons(); [OperationContract] [WebGet] Person GetPersonByID(int id); } }
サービスクラスは次のように編集します。
using System; using System.Collections.Generic; using System.Runtime.Serialization; using System.ServiceModel; namespace WCFSample.PersonService { public class PersonSearch : IPersonSearch { #region IPersonSearch Members public IList<Person> GetPersons() { return persons; } // idに該当する情報を返す。 public Person GetPersonByID(int id) { Person result = (from p in persons where p.ID == id select p).Single(); return result; // 非LINQバージョン //foreach (Person p in persons) //{ // if (p.ID == id) return p; //} //throw new FaultException("Not Found"); } #endregion private static IList<Person> persons = new List<Person>(); static PersonSearch() { persons.Add(new Person(1, "aiueo", "AIUEO")); persons.Add(new Person(2, "kakikukeko", "KAKIKUKEKO")); persons.Add(new Person(3, "sashisuseso", "SASHISUSESO")); } } }
App.configが作成されている場合、使用しないので削除しておいて下さい。
3.ASP.NET サイトの作成
ソリューションを右クリック→[Add]→[New Web Site..]を選択して新規にWebサイトを作成します。ソリューション直下にWebSiteフォルダにプロジェクトを作成しました。ウェブサイトプロジェクトを右クリックして、プロジェクトの参照にWCFSample.PersonServiceを追加します。
3.1 サービスファイルの作成
ウェブサイトプロジェクトを右クリック→[Add New Item]をクリックします。表示されたAdd New Itemダイアログでファイルタイプにテキストを選択し、ファイル名service.svcとしてファイルを新規作成します。
作成されたsvcファイルでWCFSample.PersonService.PersonSearchサービスをホストできるように下のように編集します。
<%@ServiceHost language=c# Debug="true" Service="WCFSample.PersonService.PersonSearch" %>
Web.configを開いて次のようにwebHttpBindingを編集します。(system.serviceModelタグはconfigurationタグ直下に記述します。)endpoinBehaviorの設定でenableWebScriptを追加することで、WCFサービスで返されるデータがJSON形式でシリアライズされるようになります。バインディングはwebHttpBindingを使用します。
<system.serviceModel> <behaviors> <endpointBehaviors> <behavior name="WCFAjaxBehavior"> <enableWebScript /> </behavior> </endpointBehaviors> <serviceBehaviors> <behavior name="ServiceBahavior"> <serviceDebug includeExceptionDetailInFaults="true" /> </behavior> </serviceBehaviors> </behaviors> <services> <service name="WCFSample.PersonService.PersonSearch" behaviorConfiguration="ServiceBahavior"> <endpoint address="" behaviorConfiguration="WCFAjaxBehavior" binding="webHttpBinding" bindingConfiguration="" name="WCFAjaxEndpoint" contract="WCFSample.PersonService.IPersonSearch"/> </service> </services> </system.serviceModel>
3.2 ASP.NETテストページの作成
ウェブサイトプロジェクトを右クリック→[Add New Item]をクリックします。新規アイテムの追加でファイルタイプにAjax Web Fromを選択し、ファイル名をShowPerson.aspxとしてASP.NETのページを作成します。作成した画面をソースビューで開いて次のように編集します。ScriptManagerタグでサービスの参照を設定することで、PersonService用のAJAXクライアントのプロキシクラスが作成されるようになります。
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="ShowPerson.aspx.cs" Inherits="ShowPerson" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title>Test Page</title> <script type="text/javascript"> function pageLoad() { } function ShowPersons(){ var proxy = new WCFSample.AjaxScript.IPersonSearch(); proxy.GetPersons(onSuccess, onFail, null); } function ShowPersonByID(){ var idx = document.getElementById("searchID").selectedIndex; var option = document.getElementById("searchID")[idx].text; var proxy = new WCFSample.AjaxScript.IPersonSearch(); proxy.GetPersonByID(parseInt(option), onSuccess2, onFail, null); } function onSuccess(result){ var tbdy = document.getElementById("searchresult"); while(tbdy.childNodes.length > 0){ tbdy.deleteRow(0); } var i; for(i=0;i<result.length;++i){ var row = document.createElement("tr"); var cell = document.createElement("td"); row.appendChild(cell); cell.appendChild(document.createTextNode(result[i].ID)); cell = document.createElement("td"); row.appendChild(cell); cell.appendChild(document.createTextNode(result[i].FirstName)); cell = document.createElement("td"); row.appendChild(cell); cell.appendChild(document.createTextNode(result[i].LastName)); tbdy.appendChild(row); } //alert(tbdy.innerHTML); // debug } function onFail(err){ alert("ERROR"); } function onSuccess2(result){ var tbdy = document.getElementById("searchresult"); while(tbdy.childNodes.length > 0){ tbdy.deleteRow(0); } var row = document.createElement("tr"); var cell = document.createElement("td"); row.appendChild(cell); cell.appendChild(document.createTextNode(result.ID)); cell = document.createElement("td"); row.appendChild(cell); cell.appendChild(document.createTextNode(result.FirstName)); cell = document.createElement("td"); row.appendChild(cell); cell.appendChild(document.createTextNode(result.LastName)); tbdy.appendChild(row); //alert(tbdy.innerHTML); // debug } </script> </head> <body> <form id="form1" runat="server"> <div> <asp:ScriptManager ID="ScriptManager1" runat="server"> <Services> <asp:ServiceReference Path="~/service.svc" /> </Services> </asp:ScriptManager> </div> <table> <thead> <tr> <td> ID </td> <td> FirstName </td> <td> LastName </td> </tr> </thead> <tbody id="searchresult"> </tbody> </table> <input type="button" onclick="javascript:ShowPersons()" value="Search All" /> <select id="searchID"> <option>1</option> <option>2</option> <option>3</option> </select> <input type="button" onclick="javascript:ShowPersonByID()" value="Search By ID" /> </form> </body> </html>
色が青色の文字が追加した部分です。javascriptでWebフォームのボタンがクリックしたときにAJAX用のプロキシクラスWCFSample.AjaxScriptを使用して、Personデータを取得するスクリプトを記述しています。Webフォームのページ部分の追加内容はデータ取得イベント用のボタンと取得結果表示用のtableです。WCFSample.AjaxScriptはサービスコントラクトで設定したNameSpaceに一致します。(JavaScriptの稚拙さはご容赦ください。あまり得意ではないのです。)
4.動作確認
プロジェクトを保存してデバッグ実行してみます。[Search All]ボタンを押すと次のように表示されます。

[Search By ID]ボタンを押すと、次のようになります。

IPersonServiceサービスコントラクトの定義でサービスオペレーションにWebGetAttributeを付与しているので、次のようにURLに打ち込むとJSON形式のデータを直接取得できます。ホスト名,ポート番号はよって変換して下さい。
http://localhost:49397/WebSite/service.svc/GetPersonByID?id=1
URLに直接入力すると、ファイルダウンロードダイアログが表示されるので、保存すると次のようにJSON形式でシリアライズされているデータを確認できます。
{"d":{"__type":"Person:#WCFSample.PersonService","FirstName":"aiueo","ID":1,"LastName":"AIUEO"}}
説明は以上です。間違い、指摘事項がありましたら連絡ください。
2011/6/14 追記
動作するサンプルがほしいという方がいたので、ソリューションを公開します。ここからダウンロードしてください。