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 追記
動作するサンプルがほしいという方がいたので、ソリューションを公開します。ここからダウンロードしてください。