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、JavaPHPフレームワークを持っているんだけど*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^)/

*1:手段の為には目的を選ばない駄目技術者なので(´・ω・`)

*2:他のIHttpModule拡張というと、Tokenによるダブルサブミット対策だとかとかフロー制御なんかにも使いますが(・ω・)

*3:JavaPHPはafter Railsを意識していたり、データアクセス部はLINQを意識しているのだけれど、作りかけだったり。.NETのものはASP.NET MVCはまだ時期尚早なので、ページベース。その他、フレームワークというかDBをはじめ他のプロダクトとのインテグレーション層はちょっとしたサポート機能がメイン。