訳あって調べ物。REST(Representative State Transfer)と呼ばれる方式の処理呼び出し/応答を行うWebサービスを作成する必要があるので、作り方の基礎の基礎を実際にやってみることに。細かい定義やらなにやらはさておき、とりあえず手を動かす路線で。
参考にしたサイト
30分程度しか時間が無いので、とりあえずこれ。
- 10 行でズバリ!! REST サービスの作成 (C#)
- http://code.msdn.microsoft.com/windowsdesktop/10-REST-C-f2ea1965
やってみた
手順は
- 新規プロジェクトでWCFサービスを選択。
- サービスコントラクト(ServiceContract)属性を持つインターフェースを作成。
- データコントラクト(DataContract)属性を持つデータ保持用クラスを作成。各プロパティにはデータメンバー(DataMember)属性をつける。
- サービス本体のクラスを作成。拡張子はsvc.cs。クラスは上記1のインターフェースを実装し、メインメソッドには後述するWebGet属性を設定しておく。
- svcファイルを作成。デフォルト記述の末尾にFactoryとしてSystem.ServiceModel.ACtivation.WebServiceHostFactoryを指定。
- web.configからServiceModelに関する記述を削除。
サービスの処理本体となるクラスにつける属性は以下の通り。
[WebGet(UriTemplate="orders/{id}",ResponseFormat=WebMessageFormat.Xml)]
動かしてみた
Visual Studioのソリューションエクスプローラー上で、svc.csファイルを右クリック。「ブラウザで表示」を選択。その後、URL部分の末尾(~.svcの後ろ)に「orders/3」のように書けば、以下のような応答が返ってくる(ブラウザに表示される)。
なるほど。ここではURLのパス指定でパラメータを渡したけれど、書式を「UriTemplate」で指定すればどうとでもなるのかな?。
これ、.NETのライブラリが受け答えをやってくれているけれど、自力で全部作れと言われたら結構大変なんだろうな(かつて、まだ新人に毛が生えた程度の頃に、VB6.0でSOAPを使ったWebサービスを組もうとしたのを思い出した……)。
インターフェースを使ったやりかたは必須なのだろうか?
必須では無いようです。実際、インターフェースを実装せずに
- 実処理を実装するクラスにServiceContract属性をつける(冒頭のサンプルではインターフェースに属性をつけていた)。
- 実際のメソッドにOperationContract属性をつける(冒頭のサンプルではインターフェースのメソッド宣言につけていた)。
で同じことができました。ただ、インターフェースについていれば実装部分でつける必要が無いのであれば、実処理の実装者にややこしい属性指定をさせず、インターフェースを実装するという宣言だけすればコントラクトの適用ができる、という点ではインターフェースを使った方がいいのかもしれません。
JSONで返答を返したい
今回、やらないといけないのはJSON(JavaScript Object Notation)での応答なのだけど……もしかして、実際の処理実装を行うクラスにつけた属性「WebMessageFormat」を「WebMessageFormat.Json」に変えると……なるほど。できた。これがJSON形式か。
このときの実処理クラスソースはこんな。あ、これ、インターフェース使わないバージョンです。
using System.ServiceModel.Web; namespace RestTest1 { //public class OrderService : IOrderService [ServiceContract] public class OrderService { //[WebGet(UriTemplate="orders/{id}",ResponseFormat=WebMessageFormat.Xml), OperationContract] [WebGet(UriTemplate = "orders/{id}", ResponseFormat = WebMessageFormat.Json), OperationContract] public OrderItem GetOrderInfo(string id) { return new OrderItem(id, "サンプル商品" + id); } } } ||<< 実際の呼び出しは、これをJavascriptとかから呼ぶ感じなんだろうか。その辺は別途、呼び出しサンプルを作ってみないといけないですね……