WCF Web API を使用した REST サービスの作成と起動


2012/02 追記 : 本投稿の 「WCF Web Api」 (Preview) は、2012 年末に終了予定です。この機能は、現在、「ASP.NET Web API」 としてリリースされています。(ASP.NET Web API は、ASP.NET MVC 4 Beta 以降に含まれています。)

環境 : Visual Studio 2010, WCF Web API Preview 5

こんにちは。

WCF Web API は、現在 プレビュー版として提供されている新しい Web API の開発フレームワークです。

この WCF Web API を使うと、要求や応答の細かな制御 (StatusCode, Headers, さまざまな Content-Type への対応, など)、クエリーや OData のサポート、より高度なシナリオへの対応など (非同期実行など)、REST 固有の細かなカスタマイズが大変容易になっています。(以前 こちら でも紹介しましたが、HttpClient クラスを使用したクライアント用の API や、JsonValue クラスなどを使用した動的な Json シリアライズなど、クライアント側も含め、より柔軟な開発が可能です。既に、NuGet からも取得できます。)

この WCF Web API を使った利点 (メリット) や特徴については、時間を見つけて、いずれ説明しますが、まずは、そのための準備として、基本的な起動方法について以下に説明しておきます。

 

HttpServiceHostFactory を使用した起動

この方法は、従来の WCF 開発者にとって馴染みのある手法です。ServiceHost クラスから継承された Factory クラスを使って、WCF Web API を使った REST サービスを起動することができます。

さっそく、手順を見てみましょう。

Visual Studio を起動し、[WCF サービス アプリケーション] を新規作成します。

プロジェクトに、下記の 4 つの dll を参照追加します。

WCF Web API のインストール ディレクトリー\WCFWebApi\Http\prototypes\Microsoft.ApplicationServer.HttpEnhancements\bin\Debug\ の下の
Microsoft.Net.Http.dll
Microsoft.Net.Http.Formatting.dll
Microsoft.ApplicationServer.Http.dll

補足 : Preview 6 では、Microsoft.Net.Http.dll の代わりに System.Net.Http.dll を使用してください。

10 行でズバリ!! REST サービスの作成」ではインターフェイス (IService1.cs) を使用しましたが、今回は、面倒なので、インターフェイスは使用せず構築します。このため、IService1.cs をプロジェクトから削除します。

Service1.svc をマウスで右クリックして、[マークアップの表示] を選択すると、.svc ファイルのソースが表示されます。
このソースに、下記太字の通り、Factory として HttpServiceHostFactory を設定します。(「10 行でズバリ!! REST サービスの作成」で使用した WebServiceHostFactory ではありませんので、注意してください。)

<%@ ServiceHost Language="C#"
  Debug="true"
  Service="WcfService1.Service1"
  CodeBehind="Service1.svc.cs"
  Factory="Microsoft.ApplicationServer.Http.Activation.HttpServiceHostFactory" %>

補足 : ここでは HttpServiceHostFactory クラスを使用して、内部で HttpServiceHost インスタンスを作成 (および、Open) していますが、もちろん、HttpServiceHost クラスを使ってプログラミング (new と Open) しても構いません。

Web.config を開き、  <system.serviceModel /> 要素全体をすべて削除します。(上記の Factory を使えば、必要に応じ、構成を追加するだけで OK です。)

Service1.svc.cs を開き、今回は、下記の通り実装しましょう。

. . .

using System.Net;
using System.Net.Http;
. . .

[ServiceContract]
public class Service1
{
    [OperationContract]
    [WebGet(UriTemplate = "Orders/{id}")]
    public HttpResponseMessage GetOne(string id)
    {
        // 下記は、new HttpResponseMessage<OrderItem>(resObj) としても OK です
        HttpResponseMessage resMsg = new HttpResponseMessage();
        resMsg.StatusCode = HttpStatusCode.OK;
        OrderItem resObj = new OrderItem
        {
            Id = int.Parse(id),
            Time = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(
                DateTime.UtcNow, "Tokyo Standard Time")
        };
        resMsg.Content = new ObjectContent<OrderItem>(resObj);
        return resMsg;
    }
}

[DataContract(Namespace = "", Name = "OrderItem")]
public class OrderItem
{
    [DataMember]
    public int Id;
    [DataMember]
    public DateTime Time;
}
. . .

以上で完了です。
このサービスでは、ブラウザーなどを使って http://[アプリケーション URL]/Service1.svc/Orders/[番号] の URI フォーマットで接続すると、オブジェクト (OrderItem) を Plain XML で返します。

ここでは、単に、オブジェクト (OrderItem) を Plain XML で返すだけのサンプルであるため WCF Web API のメリット (これまでの WCF REST サービス開発との違い) が伝わらないかもしれませんが、上記の HttpRequestMessage / HttpResponseMessage などを使って、上記の StatusCode の設定 (201, 304 など) のように、細かな制御が可能です。
なお、ここでは詳述しませんが、上記の ObjectContent は、WCF Web API の HttpContnt クラスから継承されたクラスで、上記のようにオブジェクトをラッピングできます。(この他にも、HttpContnt クラスから継承されたクラスとして StringContent、ByteArrayContent、MultipartContent などがあり、さまざまなコンテンツを REST サービスの返り値として設定できます。)
こうしたメリットは、いづれ、このブログでも紹介したいと思います。

 

ASP.NET MapRoute テーブルを使用した起動

WCF Web API は、上述からわかる通り WCF をベースとしていますが、つぎの起動方法を見ていただくとわかる通り、ASP.NET (および、ASP.NET MVC) とも、より親和性 高く利用できるようになっています。

今回は、Visual Studio で、[ASP.NET MVC 3] のプロジェクトを新規作成します。

下記の 7 つの dll を参照追加します。(今度は、WCF 関連の dll も追加しておきます。また、Microsoft.ApplicationServer.HttpEnhancements.dll は、後述する MapServiceRoute 拡張メソッドで使用します。)

System.ServiceModel.dll
System.ServiceModel.Web.dll
System.Runtime.Serialization.dll
WCF Web API のインストール ディレクトリー\WCFWebApi\Http\prototypes\Microsoft.ApplicationServer.HttpEnhancements\bin\Debug\ の下の
Microsoft.Net.Http.dll
Microsoft.Net.Http.Formatting.dll
Microsoft.ApplicationServer.Http.dll
Microsoft.ApplicationServer.HttpEnhancements.dll

補足 : Preview 6 では、Microsoft.Net.Http.dll の代わりに System.Net.Http.dll を使用してください。

プロジェクトの [追加] - [新しい項目] で、[クラス] を追加します。(今回、追加したクラスを OrderService.cs とします。)

Global.asax.cs を開き、下記 太字の通りコードを追加し、上記のクラス (サービス, Api) をパスとしてマップします。

. . .

using Microsoft.ApplicationServer.Http.Activation;
. . .

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapServiceRoute<OrderService>("Orders");
    routes.MapRoute(
        "Default", // Route name
        "{controller}/{action}/{id}", // URL with parameters
        new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
    );
}

また、WCF サービスで上記のルーティングを可能にするため、Web.config を開いて、下記の通り、ASP.NET Compatibility Mode に設定します。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  . . .

  <system.serviceModel>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
  </system.serviceModel>
</configuration>

つぎに、上記で追加した OrderService.cs (クラス) に、下記の通りコードを記述します。

. . .

using System.ServiceModel;
using System.ServiceModel.Web;
using System.Runtime.Serialization;
using System.Net;
using System.Net.Http;
. . .

[ServiceContract]
public class OrderService
{
    [OperationContract]
    [WebGet(UriTemplate = "{id}")]
    public HttpResponseMessage GetOne(string id)
    {
        // 下記は、new HttpResponseMessage<OrderItem>(resObj) としても OK です
        HttpResponseMessage resMsg = new HttpResponseMessage();
        resMsg.StatusCode = HttpStatusCode.OK;
        OrderItem resObj = new OrderItem
        {
            Id = int.Parse(id),
            Time = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(
                DateTime.UtcNow, "Tokyo Standard Time")
        };
        resMsg.Content = new ObjectContent<OrderItem>(resObj);
        return resMsg;
    }
}

[DataContract(Namespace = "", Name = "OrderItem")]
public class OrderItem
{
    [DataMember]
    public int Id;
    [DataMember]
    public DateTime Time;
}
. . .

以上で完了です。

ブラウザーなどを使って、http://[アプリケーション URL]/Orders/[番号] の URI フォーマットで接続すると、同様に、オブジェクト (OrderItem) を Plain XML で返します。MVC らしく、URI では Service1.svc という余計なアドレスも取れて、きれいに統合されています。

「よーし、WCF を作るぞー!」ではなく、このように、普通に ASP.NET MVC のプロジェクトを構築し、API 部分 (サービス部分) を WCF Web API を使って部分的に構築できます。(無論、MVC の JsonResult なども使えますが、より専門的、かつ、より柔軟に、Api 部分を実装できます。)

 

なお、WCF Web API は、上述の通り、プレビュー版であり、これらの dll は現時点 (2011/09) の Windows Azure には入っていません。
このため、Windows Azure に配置する場合は、Visual Studio のプロジェクトで、挿入された上記の WCF Web API の dll (4 つ) のそれぞれを選択して、下図の通り、プロパティ画面の [ローカル コピー] を True、[特定バージョン] を False に設定しておきます。(Windows Azure のプロジェクトで作成すると、自動的にこれらのプロパティが設定されるとは思いますが . . .)

 

WCF Web API は、今後の .NET による REST 開発のメインストリームとなる可能性もあるので、今から Watch しておいても損はないでしょう。
この WCF Web API を使用した応用例 (フォーマットの変更方法、OData 対応の方法、など) については、下記に記載しましたので参考にしてください。

 

Comments (0)

Skip to main content