ASP.NET Web Api の Custom HTTP Header (HTTP ヘッダー)

(2012/02 : サンプル コードを、WCF Web Api から ASP.NET Web Api に変更)

(2012/06 : サンプル コードを、ASP.NET Web API RC 版にあわせて変更)

環境 : Visual Studio 2010, ASP.NET Web API RC (ASP.NET MVC 4 RC)

REST サービス / Web Api の実践

ここでは、応用的なテーマをとりあげます。基本的な構築手順については、「Getting Started with ASP.NET Web Api」 (ASP.NET の場合)、または「REST サービスの作成」 (WCF の場合) を参照してください。

こんにちは。

今日は簡単な Tips ですが、Web Api (REST サービス) で HTTP ヘッダーをカスタマイズする方法について記載します。

下記の 3 つの方法があります。

 

方法 1 : カスタムの HTTP ハンドラー / HTTP モジュール (IHttpModule) を使う

IIS レベルで、カスタムの HTTP Handler / HTTP Module を使って、ヘッダーをカスタマイズできます。

この具体的な方法については、前回、「Web Api (REST サービス) で Custom Basic 認証を使用してクラウド (Windows Azure) に配置する」で簡単なサンプル コードを紹介していますので、ここでは、詳細の構築手順については省略します。

 

方法 2 (ASP.NET の場合) : ASP.NET Web API の HttpResponseMessage を使う

ASP.NET Web API を使うと、もっと容易にヘッダーをカスタマイズできます。(このあと紹介する WCF のサンプルと比較しても、非常に簡単です。)

以下 (太字) では、ASP.NET Web API を使って、Expires ヘッダーの設定をおこなっています。

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

public class OrderController : ApiController
{
  // GET /api/order/5
  public HttpResponseMessage Get(int id)
  {
    OrderItem resObj = new OrderItem
    {
      Id = id,
      Time = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(
        DateTime.UtcNow, "Tokyo Standard Time")
    };
    HttpResponseMessage resMsg = new HttpResponseMessage(
      HttpStatusCode.OK);     
    resMsg.Content = new ObjectContent<OrderItem>(
      resObj,
      new System.Net.Http.Formatting.JsonMediaTypeFormatter());
    resMsg.Headers.CacheControl =
      new System.Net.Http.Headers.CacheControlHeaderValue()
      {
        Private = true
      };
    resMsg.Content.Headers.Expires =
      DateTimeOffset.UtcNow.AddMinutes(1);
    return resMsg;
  }
}

public class OrderItem
{
  public int Id;
  public DateTime Time;
}
. . .

補足 : Windows Azure 上に配置した場合を考慮し、上記では、日付/時刻の処理をすべて UTC で処理し、必要に応じて日本時間に変換しています。

補足 : 今回は Plain XML で返していますが、返り値としてJson を使用する場合は、DateTime の扱いに注意してください。Json には Date 型はないため、上記のような書き方だと、独自な文字列形式でデータが返ってきます。(特に、Microsoft 以外のプラットフォームと組み合わせる場合は、注意してください。)

この Web Api をブラウザーを使って何度も参照した場合、1 分間は ブラウザー側のキャッシュが使用され、1 分後に サーバーからページを取得します。(なお、Internet Explorer をお使いの場合、ブラウザーの再表示ボタンを押すと、必ず最新の情報を取り直すので、アドレス欄に URL を入力して、リターン キーを何度も押してください。キーを押し続けると、ブラウザー上に表示される時刻が、1 分後に変更されるはずです。)

 

方法 3 (WCF の場合) : OutgoingMessageProperties を使う

WCF を使用する場合は、以前 このブログでも紹介したように、オペレーション制御のための専用のクラス (プロパティ) を使用して、Request ヘッダーと Response ヘッダーの細かなカスタマイズができます。

補足 : 以前記載した この投稿 を参照してください。この投稿では、クライアント側でこのクラスを使い、サーバー側は ASP.NET Compatibility Mode を使うことで 通常の HttpContext クラスを使っています。今回は、下記の通り、サーバー側でヘッダーをカスタマイズします。

下記のサンプル コードでは、この手法を使って、HTTP の Expires ヘッダーに、1 分後の時間を設定しています。
なお、WCF を使った REST サービスの基本的な構築手順については、ここでは省略しますので、「10 行でズバリ!! REST サービスの作成」を参照してください。(下記の通り、インターフェイス (IService1) を使用せず記述することもできます。)

. . .

using System.ServiceModel.Channels;
. . .

[ServiceContract]
public class Service1
{
    [OperationContract]
    [WebGet(UriTemplate = "orders/{id}",
        ResponseFormat = WebMessageFormat.Xml)]
    public OrderItem GetOne(string id)
    {
        var responseProp = new HttpResponseMessageProperty();
        responseProp.Headers.Add(
            System.Net.HttpResponseHeader.Expires,
            String.Format("{0:r}", DateTime.UtcNow.AddMinutes(1)));
        OperationContext.Current.OutgoingMessageProperties.Add(
            HttpResponseMessageProperty.Name, responseProp);

        return new OrderItem
        {
            Id = int.Parse(id),
            Time = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(
                DateTime.UtcNow, "Tokyo Standard Time")
        };
    }
}

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

 

前者の ASP.NET Web API を使用したサンプル コードと比べると、違いがおわかり頂けるでしょう。(ASP.NET Web API では、HttpResponseMessage オブジェクトを使用して、ヘッダーや StatusCode などの細かなカスタマイズがたった 1 行で実施できます。また、Expires ヘッダーの処理なども、わざわざ GMT に変換する必要はありません。)
ASP.NET Web API では、こうした Web API 独自の細やかなカスタマイズを容易するための仕組みを提供しています。

 

た、た、台風が。。。 (そろそろ、帰ります)

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s