WCFを利用して RESTインターフェイスのWebサービスを作成する - ASP.NET

WCFを利用して RestインターフェイスのWebサービスを作成する手順とコードを紹介します。

概要

こちらの記事ではWCFを利用してWebサービスを作成する手順を紹介しました。作成したサービスはWSDL(SOAPのインターフェイス)に対応していますが、最近のWebサービスではよりシンプルなREST形式のインターフェイス(RESTful Web サービス)を利用したい場合があります。この記事ではRESTインターフェイスを持つWebサービスをWCFで作成する手順を紹介します。

実装する手順

実装する手順の概要は以下になります。
  1. WCFサービスの作成 (通常のWCFサービスの実装と同様です。(参考))
  2. インターフェイス部分の修正 (インターフェイス部分に WebGet属性、Invoke属性を追記し、UriTemplateを設定します)
  3. WCFサービスの動作確認 (WCFサービスが正しく動作するか確認します)
  4. ルーティングの設定 (設定したUriTemplateが実行されるよう、ルーティングを設定し指定されたURLでオブジェクトが呼び出される動作を実装します)
  5. REST呼び出しでの動作確認 (RESTの呼び出しで正常に動作するか、レスポンスが戻るかを確認します。)

プログラム例

WCFサービスのプロジェクトを作成します。プロジェクトが作成された状態が下図です。

ファイル名の変更

ファイル名を変更します。デフォルトで作成された"Service1.svc"の名称を変更します。


ソリューションエクスプローラでファイルの項目を半クリックすると名前の変更ができます。今回は "RestService.svc" に変更します。


同様の手順で、"IService.cs" ファイルを "IRestService.cs" ファイルに名前を変更します。


コードの記述

下記のコードを記述します。
IRestService.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;

namespace SimpleRestWcfService
{
  // メモ: [リファクター] メニューの [名前の変更] コマンドを使用すると、コードと config ファイルの両方で同時にインターフェイス名 "IService1" を変更できます。
  [ServiceContract]
  public interface IRestService
  {

    [OperationContract]
    string GetData(int value);

    [OperationContract]
    CompositeType GetDataUsingDataContract(CompositeType composite);

    // TODO: ここにサービス操作を追加します。
    [OperationContract]
    [WebGet(ResponseFormat = WebMessageFormat.Json, UriTemplate = "add/{value1}/{value2}")]
    string AddString (string value1, string value2);

    [OperationContract]
    [WebInvoke(Method = "POST",
            RequestFormat = WebMessageFormat.Json,
            ResponseFormat = WebMessageFormat.Json,
            UriTemplate = "addi")]
    AddStrResponse AddStringInvert(AddStrRequest req);
  }


  // サービス操作に複合型を追加するには、以下のサンプルに示すようにデータ コントラクトを使用します。
  [DataContract]
  public class CompositeType
  {
    bool boolValue = true;
    string stringValue = "Hello ";

    [DataMember]
    public bool BoolValue
    {
      get { return boolValue; }
      set { boolValue = value; }
    }

    [DataMember]
    public string StringValue
    {
      get { return stringValue; }
      set { stringValue = value; }
    }
  }

  [DataContract]
  public class AddStrRequest
  {
    [DataMember(Name = "value1")]
    public string Value1 { get; set; }

    [DataMember(Name = "value2")]
    public string Value2 { get; set; }
  }

  [DataContract]
  public class AddStrResponse
  {
    [DataMember(Name = "result")]
    public string result { get; set; }

    [DataMember(Name = "resultid")]
    public int resultid { get; set; } 
  }
}
RestService.svc.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;

namespace SimpleRestWcfService
{
  // メモ: [リファクター] メニューの [名前の変更] コマンドを使用すると、コード、svc、および config ファイルで同時にクラス名 "Service1" を変更できます。
  // 注意: このサービスをテストするために WCF テスト クライアントを起動するには、ソリューション エクスプローラーで Service1.svc または Service1.svc.cs を選択し、デバッグを開始してください。
  public class RestService : IRestService
  {
    public string GetData(int value)
    {
      return string.Format("You entered: {0}", value);
    }

    public CompositeType GetDataUsingDataContract(CompositeType composite)
    {
      if (composite == null) {
        throw new ArgumentNullException("composite");
      }
      if (composite.BoolValue) {
        composite.StringValue += "Suffix";
      }
      return composite;
    }

    public string AddString (string value1, string value2)
    {
      return value1 + value2;
    }

    public AddStrResponse AddStringInvert(AddStrRequest req)
    {
      AddStrResponse resp = new AddStrResponse();
      resp.result = req.Value2 + req.Value1;
      resp.resultid = (new Random().Next(10000));
      return resp;
    }
   
  }
}

解説

IRestService.cs

サービス操作のセクションには下記のコードを記述します。2つのWebメソッドを定義しています。
今回はREST形式(JSONフォーマットでの入出力)のWebAPIを作成しますので、Webメソッドの引数や戻り値はstring型(文字列型)とします。
AddStringはHTTPのGetのアクションで呼び出されるWebメソッドです。value1, value2の2つの引数を持つメソッドになります。

"UriTemplate"の値がこのメソッドを呼び出すURIになります。今回の記述では"add/{value1}/{value2}"と記述していますので、
http://WebサービスのURL/add/パラメーター1の値/パラメーター2の値
のURLにアクセスすると、AddStringメソッドが実行され、value1 に "パラメーター1の値"、value2 に "パラメーター2の値"が代入されてメソッドが呼び出される動作となります。

AddStringInvertはHTTPのPostのアクションで呼び出されるWebメソッドです。Postで渡されるパラメーターをSubRequestのクラスとして定義します。また、メソッドの戻り値はSubResponse のクラスとして定義します。UriTemplateがメソッドを呼び出すURIになります。今回の記述では"addi"と記述していますので
http://WebサービスのURL/addi
のURLに対してPOSTするとWebメソッドが呼び出されます。
    [OperationContract]
    [WebGet(ResponseFormat = WebMessageFormat.Json, UriTemplate = "add/{value1}/{value2}")]
    string AddString (string value1, string value2);

    [OperationContract]
    [WebInvoke(Method = "POST",
            RequestFormat = WebMessageFormat.Json,
            ResponseFormat = WebMessageFormat.Json,
            UriTemplate = "addi")]
    AddStrResponse AddStringInvert(AddStrRequest req);

サービス操作の複合型を定義する部分には下記のコードを記述します。AddStringInvert() メソッドのパラメータとなるAddStrRequest クラスと戻り値となるAddStrResponse を定義します。
  [DataContract]
  public class AddStrRequest 
  {
    [DataMember(Name = "value1")]
    public string Value1 { get; set; }

    [DataMember(Name = "value2")]
    public string Value2 { get; set; }
  }

  [DataContract]
  public class AddStrResponse
  {
    [DataMember(Name = "result")]
    public string result { get; set; }

    [DataMember(Name = "resultid")]
    public int resultid { get; set; } 
  }

AddStrRequest はvalue1, value2 の2つの引数をとるメソッドとなります。JSON形式での定義としているため、下記のJSONをPOSTする仕様となります。
{
  "value1":"ABC",
  "value2":"XYZ"
}

AddStrResponse はresultの1つの値を返すオブジェクトとなります。JSON形式での定義としているため、下記のJSONで結果が返ります。
{
  "result":"ABCXYZ"
}

RestService.svc.cs

RestService.svc.cs には IRestService.cs で定義したメソッドの実装ロジックを記述します。RestService は IRestService インターフェイスからの継承であるため、IRestService で定義されている抽象メソッドをすべて実装している必要があります。
今回定義する2つのメソッド、AddString は2つの引数の文字列連結した文字列を返します。AddStringInvert も動作は同じですが、2つ目の引数を先にして2つに引数を結合する動作になります。また、AddStringInvertメソッドのほうはresultidプロパティに乱数を設定して返します。
  public string AddString (string value1, string value2)
  {
    return value1 + value2;
  }

  public AddStrResponse AddStringInvert(AddStrRequest req)
  {
    AddStrResponse resp = new AddStrResponse();
    resp.result = req.Value2 + req.Value1;
    resp.resultid = (new Random().Next(10000));
    return resp;
  }

グローバル アプリケーション クラスの追加

ソリューションエクスプローラーで右クリックし、ポップアップメニューの[追加]メニューの[新しい項目]をクリックします。

下図の[新しい項目の追加]ダイアログが表示されます。左側のツリービューで[Web]のノードをクリックして選択します。下図の画面が表示されます。右側のファイルの種類のリストから[グローバル アプリケーション クラス]をクリックして選択します。ファイル名はデフォルトの "Global.asax"とします。ウィンドウ右下の[追加]ボタンをクリックします。


作成された Global.asax ファイルに下記のコードを記述します。
Global.asax
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.SessionState;
using System.Web.Routing;
using System.ServiceModel.Activation;

namespace SimpleRestWcfService
{
  public class Global : System.Web.HttpApplication
  {

    protected void Application_Start(object sender, EventArgs e)
    {
      ServiceRoute sroute = new ServiceRoute("RestService", new WebServiceHostFactory(), typeof(RestService));
      RouteTable.Routes.Add(sroute);
    }

    protected void Session_Start(object sender, EventArgs e)
    {

    }

    protected void Application_BeginRequest(object sender, EventArgs e)
    {
      //他のドメインからアクセスする場合
      Response.AddHeader("Access-Control-Allow-Origin", "*");
    }

    protected void Application_AuthenticateRequest(object sender, EventArgs e)
    {

    }

    protected void Application_Error(object sender, EventArgs e)
    {

    }

    protected void Session_End(object sender, EventArgs e)
    {

    }

    protected void Application_End(object sender, EventArgs e)
    {

    }
  }
}

解説

Application_Start メソッドに下記のコードを記述します。ASP.NETのURLルーティングの機能を利用して、URLルーティングをします。下記のコードでは、"RestService"にアクセスした場合、RestServiceクラスへのアクセスとします。
第二引数の ServiceHostFactoryBase クラスは、ServiceHostFactoryBase の派生となる、ServiceHostFactory クラスがあり、その派生クラスとして、DataServiceHostFactory, WebScriptServiceHostFactory, WebServiceHostFactory, AplicationServicesHostFactory クラスがあります。
今回はWebのアクセスにより、受信メッセージに応答してホスト インスタンスが動的に作成される動作のため、WebServiceHostFactory を利用します。作成されたServiceRouteオブジェクトはRouteTableのRoutesに追加します。
  ServiceRoute sroute = new ServiceRoute("RestService", new WebServiceHostFactory(), typeof(RestService));
  RouteTable.Routes.Add(sroute);

上記のコードにより http://WCFウェブサービスのURL/RestService にアクセスすると、RestService オブジェクトが実行される動作になります。

また、他のドメインのWebページからJavaScriptでAPIを呼び出す場合には、Access-Control-Allow-Originの設定が必要です。 Access-Control-Allow-Origin のヘッダへの追加は Global.asax ファイルの Application_BeginRequest() メソッドに記述します。
Access-Control-Allow-Origin の詳細についてはこちらのページを参照してください。
  protected void Application_BeginRequest(object sender, EventArgs e)
  {
    Response.AddHeader("Access-Control-Allow-Origin", "*");
  }

WCFサービスの動作確認

RestService.svc をアクティブにした状態でプロジェクトを実行します。下図の[WCFテスト クライアント]のウィンドウが表示されます。


左側のツリービューで[AddString]ノードをダブルクリックします。下図の画面に切り替わります。


[value1][value2]の[値]のフィールドに入力値を設定します。今回はvalue1には「ぺんぎん」の文字列をvalue2には「ジャンプ」の文字列を設定します。


ウィンドウ右側の[起動]ボタンをクリックします。下図の[セキュリティ警告]ダイアログが表示されます。[OK]ボタンをクリックして続行します。


[応答]エリアにメソッドの戻り値が表示されます。入力の2つの文字列が連結された「ぺんぎんジャンプ」の値が表示されます。


もう一つのメソッド、AddStringInver() も動作確認します。左側のツリービューで[AddStringInveert]のノードをダブルクリックします。下図の画面が表示されます。


入力パラメーターを設定します。value1を「あひる」、value2を「泳ぐ」に設定します。設定後[起動]ボタンをクリックします。

[応答]セクションにメソッドの戻り値が表示されます。resultに入力文字列が結合された「泳ぐあひる」が resultid に乱数が表示されます。

サービス名の変更

サービス名称を変更します。RestService.svc.cs ファイルの Service1 クラスの宣言部分の "Service1" の文字列を選択し右クリックします。


下図のポップアップメニューが表示されますので、メニューの[名前の変更]をクリックします。


名称変更モードに切り替わります。


"Service1" を "RestService" に今回は変更します。変更ができたら、名前変更ポップアップウィンドウの[適用]ボタンをクリックします。


プロジェクトを起動して、Webブラウザで svcファイルのURLにアクセスします。下図の画面が表示され、サービス名が "ReseService"に変更できていることが確認できます。

動作確認(Webブラウザから)

RestService.svc ではないファイルをアクティブにした状態でプロジェクトを実行します。Webブラウザが起動しますので、http://ドキュメントルートURL/RestService/ のURLにアクセスします。下図の画面が表示されます。


REST API のURL http://ドキュメントルートURL/RestService/add/Penguin/Jump URLにアクセスします、入力パラメーターが "Penguin"と"Jump" の文字列となります。


Webメソッドの結果が画面に表示されます。"PenguinJump" の文字列が表示され、Webメソッドで文字列が結合されたことが確認できます。

プログラムからアクセスする

C#

C#のプログラムからアクセスする場合の手順とコードはこちらの記事を参照してください。

JavScript

JavScriptからアクセスする場合の手順とコードはこちらの記事を参照してください。
著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
最終更新日: 2022-01-23
作成日: 2018-05-30
iPentec all rights reserverd.