ASP.NETでもFlash(ASP.NET MVCのTempData)を使いたい時
ページ駆動な設計でも(むしろページ駆動な設計でこそ?)Flashを使いたい時もあるので、Flashの機構を用意してみたり(・∀・)
まあ、半分遊びで作った感もありますが。*1
Flashっていうのはつまり1リクエスト間だけ生きているデータなわけですが。
データ自体はセッション上なんかに格納して、ページの処理前にそのデータを取得、ページの処理後にデータを保存すれば良いわけで。
ASP.NETでこれをやる場合、IHttpModule派生のモジュールを作ってWeb.configに登録するわけですが。*2
っで、今回作った処理の登場人物はこんなカンジ(・∀・)
- FlashModule(IHttpModule拡張)
- FlashData(IDictionary
を実装して、データと変更内容の管理) - Flash(FlashDataのThreadStaticでの保持)
上記がコアモジュール。
FlashDataの保持方法については、プロバイダモデルを用いて以下を用意。
- IFlashDataProvider & SessionFlashDataProvider(FlashDataのセッションへの保持)
あと、各PageでFlash機能を使いやすいように下記の様なAttributeも用意して。
- FlashAttribute(Page内で属性を付加したメンバをFlash対象に設定)
- FlashPageSupport(FlashAttributeの処理)
っで、FlashModuleからの処理抜粋はこんな感じです(・ω・)
public class FlashModule : IHttpModule { ... public void Init(HttpApplication context) { context.PreRequestHandlerExecute += OnPreRequestHandlerExecute; } private void OnPreRequestHandlerExecute(object sender, EventArgs e) { HttpApplication application = sender as HttpApplication; // 対象はページのみ Page page = application.Context.Handler as Page; if ( page != null ) { page.Unload += OnPageUnload; // 復元 Flash.Data.Load( FlashDataProvider ); // ページへ設定 FlashPageSupport.PopulatePage( page ); } } private void OnPageUnload(object sender, EventArgs e) { Page page = sender as Page; // ページへから取得 FlashPageSupport.ExportPage( page ); // 保存 Flash.Data.Save( FlashDataProvider ); } }
前処理でFlashDataの復元を行い、後処理(PageのUnload時)にFlashDataの保存をしています。
なお、処理対象にしているのはPage派生のみ。
FlashDataの実装については、結局ASP.NET MVCのTempDataDictionaryと同じようなカンジにしますた。
前にJava用に作ったFlash機能だと、前画面からのDictionaryと、次画面へのDictionaryを個別に管理していたんですが。
それを使ってみて、別に別管理する必要もあまり無いと思ったので、今回はデータDictionary、前画面からのキーSet、次画面へのキーSetな形で実装。
ちなみに、今、.NET、Java、PHPのフレームワークを持っているんだけど*3、それぞれに機能差があったり、同じ機能でも微妙に違う部分があったりしてちと嫌なカンジ(´・ω・`)
改善していきたいんだけどね(´д`)
閑話休題。
Flashクラスは、FlashDataをThreadStaticで保持しているだけ。
ASP.NET MVCのTempDataはControllerのベースが保持しているけど、この実装ではTLSに保存…っというか、別にTLSでなくてHttpRequestのItemに放り込んでおけば良かったかな(゜Д゜)
っで、SessionFlashDataProviderはHttpContext.Current.Sessionを使って、FlashDataが保持するDictionary
FlashAttributeはこんな風に使うために用意したもの(・∀・)
public partial class Page1 : Page { [Flash] protected string message; protected void Button1_Click(object sender, EventArgs e) { message = "うさうさだよもん"; Response.Redirect( "Page2.aspx" ); } }
public partial class Page2 : System.Web.UI.Page { [Flash] protected string message; protected void Page_Load(object sender, EventArgs e) { Label1.Text = message; } }
Page1でメンバ変数に設定した内容を、Page2に簡単に引き継げるように。
なお、FlashAttributeのメンバにはNameとTypeが用意してあって。
Nameが指定されている場合、その値をFlashのキーとして使用するためのもので、指定されていなければ変数名をキーとして使用。
TypeはImport、Export、Bothなenumで、それぞれFlashのデータを前画面から取得するか、次の画面へ引き渡すか、両方を行うかの指定。
デフォルトだとBothなので、同じ画面をF5した場合なんかには値は保持され続けるようになっています。
この、フレームワークが前画面の情報を取得して、次の画面のメンバにその値をインジェクションするというのは、ボクちんはよくやるパターンだったり。
クライアント用の画面遷移フレームワークでも同じ様な仕組みを用意していたり(・∀・)
で、今日はアプリケーション固有のMembershipProviderとRoleProviderを実装して今週も終わり。
余裕のある進行なので、4連休はデフォ\(^o^)/