WCF Data Servicesの新機能 – リクエストパイプライン


WCF Data Servicesの新機能、リクエストパイプラインをご紹介します。(2/24に実施されたTechDaysセッションのフォローアップも兼ねています)

このシリーズの目次は以下になります。
1) WCF Data Servicesの新機能 – 射影
2) WCF Data Servicesの新機能 – カウント
3) WCF Data Servicesの新機能 – Server Driven Paging(SDP)
4) WCF Data Servicesの新機能 – Feed Customization
5) WCF Data Servicesの新機能 – データバインド
6) WCF Data Servicesの新機能 – カスタムプロバイダ1
7) WCF Data Servicesの新機能 – カスタムプロバイダ2
8) WCF Data Servicesの新機能 – リクエストパイプライン
9)Open Data Protocolの実装 – Share Point Server 2010のデータを操作する

また以下のトピックに関しては1)の記事を参照してください。
■名称の変更
■新バージョン
■更新モジュール(開発環境)

■リクエストパイプライン
データサービスのパイプライン処理のイベントが解放されました。例えば、サービスのリクエスト処理の直前などに処理を挟むことが可能です。開発チームのBlogにはこの機能の目的について以下のように書いてあります。

The goal of exposing our processing pipeline is to allow services further transparency into a data service such that a service author can do things such as setting HTTP response cache headers, wrapping interceptor processing and data service request processing in a single transaction, etc.

(超意訳)
サービスの作者が、HTTPレスポンスのキャッシュヘッダーのセッティングとかとか、出来るようにしたいんだよね。

では、実際に処理を記述してみたいと思います。

まず、典型的な使用方法としては、以下のように、カスタムプロバイダ作成の中で、処理を挟む形になるはずです。(Boldの部分)

public object GetService(Type serviceType)
{
    if (serviceType == typeof(IDataServiceMetadataProvider))
        return metadata;
    else if (serviceType == typeof(IDataServiceQueryProvider))
    {
        this.ProcessingPipeline.ProcessingRequest +=
new EventHandler<DataServiceProcessingPipelineEventArgs>
(ProcessingPipeline_ProcessingRequest);
        return query;
    }
    else
        return null;
}

void ProcessingPipeline_ProcessingRequest(object sender, DataServiceProcessingPipelineEventArgs e)
{
    throw new NotImplementedException();
}

ここでは、イベントハンドラになにも書いてありませんので、エラーが発生するだけですが、ここに何らかの処理(開発チームのゴールならキャッシュ関係など)を書きます。
また、指定できるイベントの種類は以下になります。
http://msdn.microsoft.com/en-us/library/system.data.services.dataserviceprocessingpipeline_events.aspx

カスタムプロバイダだけで使用するだけではなく、Entity Providerでも似たようなことをするための手軽な手法の一つとして、DataService<T>のOnStartProcessingRequestがあります。リクエスト処理前にコールされるメソッドです。純粋なリクエストパイプライン処理とは異なりますが、これで実装をしてみます。

public class pubsService : DataService< pubsEntities >
{
    public static void InitializeService(DataServiceConfiguration config)
    {
        config.SetEntitySetAccessRule("*", EntitySetRights.All);
        config.DataServiceBehavior.MaxProtocolVersion =
DataServiceProtocolVersion.V2;
    }

    protected override void OnStartProcessingRequest
(ProcessRequestArgs args)
    {
        base.OnStartProcessingRequest(args); 
        string method = HttpContext.Current.Request.HttpMethod.ToUpper();
        if (method == "GET")
        {
            HttpContext context = HttpContext.Current;
            HttpCachePolicy c = HttpContext.Current.Response.Cache;
            c.SetExpires(HttpContext.Current.Timestamp.AddSeconds(20));
            c.SetCacheability(HttpCacheability.Public);
            c.SetValidUntilExpires(true);
            c.VaryByHeaders["Accept-Language"] = true; 
           }
    }
}

普通に作成したDataServiceにBold部分を追加しただけです。
開発チームがいうようにキャッシュヘッダーに手を加えています。ここでは、Languageの設定ごとに20秒キャッシュを保つような設定です。

ちなみに、この方法は以下を参考にしています。(こんなのもCodeRecipeの逆引きにあるといいですよね・・・)
方法 - HTTP ヘッダーを使用してページのバージョンをキャッシュする

では、実行してみます。以下のように、適当ににクエリーしてみます。

http://localhost:3049/pubsService.svc/jobs

そうすると、赤枠あたりに時間が表示されていると思いますが、 F5キーなどで再リクエストしても20秒はキャッシュが使用されて時刻が変化しないのがわかります。( 上記のBoldを除いた通常のリクエストで確認すれば、この時刻は毎回変更されています。)

image


Skip to main content