misc.log

日常茶飯事とお仕事と

Visual Studio 2008 + C#でRESTサービスを作ってみる

訳あって調べ物。REST(Representative State Transfer)と呼ばれる方式の処理呼び出し/応答を行うWebサービスを作成する必要があるので、作り方の基礎の基礎を実際にやってみることに。細かい定義やらなにやらはさておき、とりあえず手を動かす路線で。

参考にしたサイト

30分程度しか時間が無いので、とりあえずこれ。

10 行でズバリ!! REST サービスの作成 (C#)
http://code.msdn.microsoft.com/windowsdesktop/10-REST-C-f2ea1965

やってみた

手順は

  1. 新規プロジェクトでWCFサービスを選択。
  2. サービスコントラクト(ServiceContract)属性を持つインターフェースを作成。
  3. データコントラクト(DataContract)属性を持つデータ保持用クラスを作成。各プロパティにはデータメンバー(DataMember)属性をつける。
  4. サービス本体のクラスを作成。拡張子svc.cs。クラスは上記1のインターフェースを実装し、メインメソッドには後述するWebGet属性を設定しておく。
  5. svcファイルを作成。デフォルト記述の末尾にFactoryとしてSystem.ServiceModel.ACtivation.WebServiceHostFactoryを指定。
  6. web.configからServiceModelに関する記述を削除。

サービスの処理本体となるクラスにつける属性は以下の通り。

[WebGet(UriTemplate="orders/{id}",ResponseFormat=WebMessageFormat.Xml)]

動かしてみた

Visual Studioのソリューションエクスプローラー上で、svc.csファイルを右クリック。「ブラウザで表示」を選択。その後、URL部分の末尾(~.svcの後ろ)に「orders/3」のように書けば、以下のような応答が返ってくる(ブラウザに表示される)。

f:id:frontline:20140205010845j:plain

なるほど。ここではURLのパス指定でパラメータを渡したけれど、書式を「UriTemplate」で指定すればどうとでもなるのかな?。

これ、.NETのライブラリが受け答えをやってくれているけれど、自力で全部作れと言われたら結構大変なんだろうな(かつて、まだ新人に毛が生えた程度の頃に、VB6.0でSOAPを使ったWebサービスを組もうとしたのを思い出した……)。

インターフェースを使ったやりかたは必須なのだろうか?

必須では無いようです。実際、インターフェースを実装せずに

  • 実処理を実装するクラスにServiceContract属性をつける(冒頭のサンプルではインターフェースに属性をつけていた)。
  • 実際のメソッドにOperationContract属性をつける(冒頭のサンプルではインターフェースのメソッド宣言につけていた)。

で同じことができました。ただ、インターフェースについていれば実装部分でつける必要が無いのであれば、実処理の実装者にややこしい属性指定をさせず、インターフェースを実装するという宣言だけすればコントラクトの適用ができる、という点ではインターフェースを使った方がいいのかもしれません。

JSONで返答を返したい

今回、やらないといけないのはJSONJavaScript Object Notation)での応答なのだけど……もしかして、実際の処理実装を行うクラスにつけた属性「WebMessageFormat」を「WebMessageFormat.Json」に変えると……なるほど。できた。これがJSON形式か。

f:id:frontline:20140205011809j:plainf:id:frontline:20140205011901j:plain

このときの実処理クラスソースはこんな。あ、これ、インターフェース使わないバージョンです。

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とかから呼ぶ感じなんだろうか。その辺は別途、呼び出しサンプルを作ってみないといけないですね……