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(); } |
ここでは、イベントハンドラになにも書いてありませんので、エラーが発生するだけですが、ここに何らかの処理(開発チームのゴールならキャッシュ関係など)を書きます。
また、指定できるイベントの種類は以下になります。
https://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 ヘッダーを使用してページのバージョンをキャッシュする
では、実行してみます。以下のように、適当ににクエリーしてみます。
https://localhost:3049/pubsService.svc/jobs
そうすると、赤枠あたりに時間が表示されていると思いますが、 F5キーなどで再リクエストしても20秒はキャッシュが使用されて時刻が変化しないのがわかります。( 上記のBoldを除いた通常のリクエストで確認すれば、この時刻は毎回変更されています。)