はじめに
今回から数回にわたって合わせて1つのスマホ×Azureなアプリケーションになるような簡単なサンプルアプリケーションを構築していきます。連載第3回の今回はWindows AzureでRESTアクセス可能なWebサービスを構築していきたいと思います。
プロジェクトの作成
それではWindows Azureアプリケーションの開発の基となる
次に、
- プロジェクト名:GihyoAzureSampleGame01
![図1 プロジェクトの作成 図1 プロジェクトの作成](/assets/images/dev/serial/01/azure_wp/0003/thumb/TH800_001.png)
OKボタンをクリックすると、
- プロジェクトのタイプ:ASP.
NET Web Role - プロジェクトの名前:GameWebRole
左のペインでASP.
![図2 ASP.NET Web Roleというプロジェクトタイプを選択 図2 ASP.NET Web Roleというプロジェクトタイプを選択](/assets/images/dev/serial/01/azure_wp/0003/thumb/TH800_002.png)
![図3 GameWebRoleという名前で作成 図3 GameWebRoleという名前で作成](/assets/images/dev/serial/01/azure_wp/0003/thumb/TH800_003.png)
2つのプロジェクトを作成しましたが、
RESTサービスの作成
次に、
- カードを引く
- カードの一覧を取得する
今回は上記を簡略化して、
参照の追加まずは開発に必要なアセンブリ(コードライブラリ)への参照を追加していきます。「参照設定」を右クリックし、「参照の追加」をクリックします。そこで下記4つの参照を追加します(図4)。
- System.
Runtime.Serialization
- System.
ServiceModel
- System.
ServiceModel.Activation
- System.
ServiceModel.Web
図4 参照の追加
System.ServiceModel名前空間のクラスはWebサービスを開発する際に必要なライブラリです。
エンティティクラスの作成
次に、Webサービスの通信インターフェースであるエンティティクラスを作成します。DTO(Data Transfer Object)とも呼ばれるクラスになります。2つのクラスを作成します。それぞれ一覧取得処理のインターフェースとして利用します。一覧取得時にリクエストパラメータがないのでリクエストDTOの中身は空、レスポンスDTOはカードの一覧(今回は乱数の一覧)を保持するリストを持っているものとします。また、クラスはGameWebRoleプロジェクト直下に「Model」フォルダを作成して、その下に作るものとします。Modelフォルダを右クリックし、追加>クラスで作成していってください。
GameServiceRequest.cs
using System.Runtime.Serialization;
namespace GameWebRole.Model
{
[DataContract]
public class GameServiceRequest
{
}
}
GameServiceResponse.cs
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace GameWebRole.Model
{
[DataContract]
public class GameServiceResponse
{
[DataMember(Name = "cardList")]
public List CardList { get; set; }
}
}
ポイントは[DataContract]属性をクラスに付加している部分です。これを付けておくと、通信時に適切にXMLやJSONフォーマットにデータが変換されるようになります。同様に[DataMember]属性は指定したプロパティがXMLやJSONに変換されるべきで、その際に指定した名前で変換するように指定しています。
サービスインターフェースの作成
次にサービスインターフェースを作成します。GameWebRoleプロジェクト直下にServiceフォルダを作成してその下に作成します。
IGameService.cs
using System.ServiceModel;
using System.ServiceModel.Web;
using GameWebRole.Model;
namespace GameWebRole.Service
{
[ServiceContract]
public interface IGameService
{
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Json, UriTemplate = "getcard")]
int GetCard();
[OperationContract]
[WebInvoke(Method = "POST",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "getcardlist")]
GameServiceResponse GetCardList(GameServiceRequest request);
}
}
今回はGETリクエストでGetCardメソッドを、POSTリクエストでGetCardListメソッドを実装する事にします。クラスには[ServiceContract]属性を、各サービスメソッドに対しては[OperationContract]属性を指定して、Webサービスとして呼び出せますよという事を宣言しています。それぞれのメソッドではWebGet属性、WebInvoke属性を指定する事によって、RESTプログラミングモデルに従ったサービスオペレーションである事を宣言しています。引数としてリクエスト、レスポンスのフォーマットをJSONとし、クライアントから呼び出される際のURLのフォーマットも同時に定義しています。GetCardListメソッドに関してはリクエストとレスポンスのインターフェースとして先ほど作成したDTOを利用しています。
サービスの実装
サービスの実装は以下のようになります。
GameService.cs
using System.Collections.Generic;
using System.ServiceModel.Activation;
using GameWebRole.Data;
using GameWebRole.Model;
namespace GameWebRole.Service
{
[AspNetCompatibilityRequirements(RequirementsMode =
AspNetCompatibilityRequirementsMode.Required)]
public class GameService:IGameService
{
public int GetCard()
{
int newCardNumber = DataHelper.GetCard();
DataHelper.SaveCard(newCardNumber);
return newCardNumber;
}
public GameServiceResponse GetCardList(GameServiceRequest request)
{
GameServiceResponse response = new GameServiceResponse();
List cardList = DataHelper.SelectCard();
response.CardList = cardList;
return response;
}
}
}
クラス宣言に付加されているAspNetCompatibilityRequirements属性はASP.NET互換性を宣言するものです。後述のASP.NETの機能を利用するために必要になります。実装はDataHelperクラスを介してカード(乱数)の取得、カード(乱数)の保存、カード一覧(乱数一覧)の取得を行っています。
データ処理周りは今回はDataHelperクラスにまとめてあります。DataHelperクラスはDataフォルダを作り、その直下に作成します。コードは下記のようになります。
DataHelper.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace GameWebRole.Data
{
public class DataHelper
{
private static List CardList;
public static int GetCard()
{
Random random = new Random();
int newCardNumber = random.Next(1, 10);
return newCardNumber;
}
public static void SaveCard(int newCardNumber)
{
if (CardList == null)
{
CardList = new List();
}
CardList.Add(newCardNumber);
}
public static List SelectCard()
{
List returnValue = new List();
if (CardList != null)
{
var orderdCardList = from card in CardList
orderby card ascending
select card;
returnValue = orderdCardList.ToList();
}
return returnValue;
}
}
}
今回はデータベース(KVSであるTableやRDBであるSQL Azure)を利用しないので、メモリ内で引いたカード(乱数)を保持する形にします。カード一覧を取得するSelectCardメソッドではLINQを用いてデータをソートしています。
設定
最後に作成したWebサービスをhttp://xxx.xxx.xxx/GameServiceというURLでアクセスできるように設定しておきます。Global.aspxファイルを開き、Application_Startメソッド内に下記コードを記述します。
Global.aspx.cs
void Application_Start(object sender, EventArgs e)
{
ServiceRoute gameServiceRoute = new ServiceRoute("GameService",
new WebServiceHostFactory(), typeof(GameService));
RouteTable.Routes.Add(gameServiceRoute);
}
ローカルでの実行
実装が終わったら、F5キーでデバッグ実行します。Windows Azure Compute Emulatorが起動し、作成したGihyoAzureSampleGame01のGameWebRoleがデプロイされ、アプリケーションが実行されます。また、ブラウザが起動し、ホームページが表示されます(図5)。
図5 デバッグ実行
今回作成したのはRESTアクセスが可能なWebサービスなので、ブラウザでGETリクエスト可能な処理の方を呼び出してみます。ブラウザでhttp://127.0.0.1:81/GameService/getcardにアクセスすると画面に数字が表示されます。再読み込みのたびに数字が変更されます。その都度サーバのメモリ上で乱数が保存されています。
POSTアクセスが必要なgetcardlistメソッドのテストに関しては、次回のWindows Phoneクライアント実装編で取り上げることにします。
今回紹介したサンプルコードはこちらからダウンロードできます。
最後に
今回はシンプルなWebサービスをWindows AzureのWebロール上に構築してみました。次回は今回作成したアプリケーションをAzureにデプロイ(アップロード)してみたいと思います。
※毎度のお勧め情報になりますが、Windows Azureプラットフォームは無料で試すことが可能です。また、MSDNサブスクリプション会員であれば、かなりの枠を無料で利用可能です。これを機に試してみてはいかがでしょうか。
- System.
Runtime. Serialization - System.
ServiceModel - System.
ServiceModel. Activation - System.
ServiceModel. Web
![図4 参照の追加 図4 参照の追加](/assets/images/dev/serial/01/azure_wp/0003/thumb/TH800_004r.png)
System.
エンティティクラスの作成
次に、
using System.Runtime.Serialization;
namespace GameWebRole.Model
{
[DataContract]
public class GameServiceRequest
{
}
}
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace GameWebRole.Model
{
[DataContract]
public class GameServiceResponse
{
[DataMember(Name = "cardList")]
public List CardList { get; set; }
}
}
ポイントは[DataContract]属性をクラスに付加している部分です。これを付けておくと、
サービスインターフェースの作成
次にサービスインターフェースを作成します。GameWebRoleプロジェクト直下にServiceフォルダを作成してその下に作成します。
using System.ServiceModel;
using System.ServiceModel.Web;
using GameWebRole.Model;
namespace GameWebRole.Service
{
[ServiceContract]
public interface IGameService
{
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Json, UriTemplate = "getcard")]
int GetCard();
[OperationContract]
[WebInvoke(Method = "POST",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "getcardlist")]
GameServiceResponse GetCardList(GameServiceRequest request);
}
}
今回はGETリクエストでGetCardメソッドを、
サービスの実装
サービスの実装は以下のようになります。
using System.Collections.Generic;
using System.ServiceModel.Activation;
using GameWebRole.Data;
using GameWebRole.Model;
namespace GameWebRole.Service
{
[AspNetCompatibilityRequirements(RequirementsMode =
AspNetCompatibilityRequirementsMode.Required)]
public class GameService:IGameService
{
public int GetCard()
{
int newCardNumber = DataHelper.GetCard();
DataHelper.SaveCard(newCardNumber);
return newCardNumber;
}
public GameServiceResponse GetCardList(GameServiceRequest request)
{
GameServiceResponse response = new GameServiceResponse();
List cardList = DataHelper.SelectCard();
response.CardList = cardList;
return response;
}
}
}
クラス宣言に付加されているAspNetCompatibilityRequirements属性はASP.
データ処理周りは今回はDataHelperクラスにまとめてあります。DataHelperクラスはDataフォルダを作り、
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace GameWebRole.Data
{
public class DataHelper
{
private static List CardList;
public static int GetCard()
{
Random random = new Random();
int newCardNumber = random.Next(1, 10);
return newCardNumber;
}
public static void SaveCard(int newCardNumber)
{
if (CardList == null)
{
CardList = new List();
}
CardList.Add(newCardNumber);
}
public static List SelectCard()
{
List returnValue = new List();
if (CardList != null)
{
var orderdCardList = from card in CardList
orderby card ascending
select card;
returnValue = orderdCardList.ToList();
}
return returnValue;
}
}
}
今回はデータベース
設定
最後に作成したWebサービスをhttp://
void Application_Start(object sender, EventArgs e)
{
ServiceRoute gameServiceRoute = new ServiceRoute("GameService",
new WebServiceHostFactory(), typeof(GameService));
RouteTable.Routes.Add(gameServiceRoute);
}
ローカルでの実行
実装が終わったら、
![図5 デバッグ実行 図5 デバッグ実行](/assets/images/dev/serial/01/azure_wp/0003/thumb/TH800_006.png)
今回作成したのはRESTアクセスが可能なWebサービスなので、
POSTアクセスが必要なgetcardlistメソッドのテストに関しては、
今回紹介したサンプルコードはこちらからダウンロードできます。
最後に
今回はシンプルなWebサービスをWindows AzureのWebロール上に構築してみました。次回は今回作成したアプリケーションをAzureにデプロイ
※毎度のお勧め情報になりますが、