Spring.NET Web Frameworkをさわってみる

Spring.NET 1.1がリリースされたので、さっそく気になる機能をさわってみる。
まずはSpring.NET Web Frameworkから。これはASP.NETMVCパターンを使った開発をできるようにするもの。具体的には画面遷移の部分、いわゆるコントローラの部分が抽象化されている。*1

通常、ASP.NETで画面遷移を行う場合

Response.Redirect("Hoge.aspx");
// 又は
Server.Transfer("Hoge.aspx");

とやる。非常に簡単に遷移することができるが、この方法にはいくつか問題がある。

例えば、

  1. ページ名がハードコーディングされるため、ページ名が変更されたりするとコードを変更して、リコンパイルする必要がある。
  2. 遷移先のページに対してGET(Response.Redirect)するのかPOST(Server.Transfer)するのかがハードコーディングされているため、HTTPメソッドを変更しようと思うと (ry
  3. HTTPメソッドを変更すればもちろんパラメータの渡し方(クエリかPOSTデータか)が変わるので、それらを切り替えようと思うと (ry

など。

Spring.NET Web Framework はページ間の遷移方法を抽象化することで、これらの問題を解決する。

単純な画面遷移

Default.aspxとNext.aspxというページがあり、Default.aspxのボタンをクリックするとNext.aspxというページに遷移する。

まずは、VS2005で「ASP.NET Web アプリケーション」プロジェクトを作る。
Spring.Core.dllとSpring.Web.dllを参照設定する。
Web.configを開いて、以下の設定を追加する。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <configSections>
        <sectionGroup name="spring">
            <section name="context" type="Spring.Context.Support.WebContextHandler, Spring.Web"/>
        </sectionGroup>
    </configSections>

    <spring>
        <context>
            <resource uri="~/App_Data/spring/objects.config" />
        </context>
    </spring>

    <system.web>

        <httpHandlers>
            <add verb="*" path="*.aspx" type="Spring.Web.Support.PageHandlerFactory, Spring.Web" />
        </httpHandlers>
        <httpModules>
            <add name="Spring" type="Spring.Context.Support.WebSupportModule, Spring.Web" />
        </httpModules>

    </system.web>

</configuration>

Default.aspx、Next.aspxというWeb フォームを作っておき、それぞれのベースクラスをSpring.Web.UI.Pageクラスに変更しておく。

App_Data/spring/objects.configというXMLファイル(オブジェクト定義ファイル)を作成して、まずはページをobjectタグで定義する。

<?xml version="1.0" encoding="utf-8" ?>
<objects xmlns="http://www.springframework.net">

    <object type="Default.aspx">
    </object>

    <object type="Next.aspx"></object>

</objects>

type属性でページのURLを指定する。id属性などは必要ない。ちなみにここでpropertyタグを使えば、Webフォームのプロパティに値をインジェクションする事ができたりする。

次に遷移方法ルールを定義するオブジェクトを定義する。ここではNext.aspxにリダイレクトすることにする。

    <object id="next" type="Spring.Web.Support.Result, Spring.Web">
        <property name="TargetPage" value="Next.aspx" />
        <property name="Mode" value="Redirect" />
    </object>

TargetPageプロパティで遷移先のURLを、Modeプロパティで遷移方法を指定する。

そしてこれをDefault.aspxに関連付ける。

    <object type="Default.aspx">
        <property name="Results">
            <dictionary>
                <entry key="next" value-ref="next" />
            </dictionary>
        </property>
    </object>

Resultsプロパティにディクショナリで指定する。

次に実際に遷移させるコードをDefault.aspxに追加する。Webフォームにボタン(btnNext)を追加して、イベントハンドラを定義する。

public partial class _Default : Spring.Web.UI.Page {
    protected void btnNext_Click(object sender, EventArgs e) {
        SetResult("next");
    }
}

やることは、Resultsプロパティで定義したキー名を引数にして、SetResultメソッドを呼び出すだけ。

これで一回ビルドして、Default.aspxにアクセスしてボタンをクリックするとNext.aspxに無事遷移された。

ちなみに遷移ルールはオブジェクトとして定義しないで以下のように記述する事もできる。

<?xml version="1.0" encoding="utf-8" ?>
<objects xmlns="http://www.springframework.net">

    <object type="Default.aspx">
        <property name="Results">
            <dictionary>
                <!-- 直接遷移ルールを記述 -->
                <entry key="next" value="redirect:Next.aspx" />
            </dictionary>
        </property>
    </object>

    <object type="Next.aspx"></object>

</objects>

他で利用しない遷移ルールの場合はこの方法で記述すればいいだろう。

あと、遷移ルールのModeプロパティにはRedirect以外にTransferと指定することもできるけど、こちらはなぜか例外が表示されてうまく動かなかった。ソースを追っかけてみるとPOSTデータを送信するところでエラーが出ていた。(バグか?)

パラメータを渡す

Default.aspxにテキストボックス(txtName)を追加して、このテキストボックスの値をNext.aspxにクエリパラメータとして渡す場合。

まず、Default.aspxにテキストボックスの値を外部から取得するためのプロパティを定義する。

public partial class _Default : Spring.Web.UI.Page {
    public string Name {
        get { return txtName.Text; }
    }
    // 省略...
}

そして、このプロパティの値をクエリとして渡すための定義を遷移ルールに追加する。

    <object id="next" type="Spring.Web.Support.Result, Spring.Web">
        <property name="TargetPage" value="Next.aspx" />
        <property name="Mode" value="Redirect" />
        <!-- パラメータ -->
        <property name="Parameters">
            <dictionary>
                <entry key="name" value="${Name}" />
            </dictionary>
        </property>
    </object>

${}でプロパティ名を囲む事で、遷移元のページの該当するプロパティから値を取得してくれる。

あとは、Next.aspxにラベル(lblName)を追加して、そのラベルにクエリから渡された値を表示するようにする。

public partial class Next : System.Web.UI.Page {
    protected void Page_Load(object sender, EventArgs e) {
        lblName.Text = Request.QueryString["name"];
    }
}

これでビルドして、Default.aspxにアクセスして、テキストボックスに適当な値を入力して、ボタンをクリックすると、その値が表示される。

う〜ん、使い物になるかなぁ?

*1:元々ASP.NETではビューとモデルがコードビハインドによって分離されている