【Web開発】【ASP.NET】URLルーティングでリクエストをシンプルにしてみる。

ASP.NETで、URLルーティングを導入する方法をまとめたいと思います。

URLルーティングは、ASP.NET 3.5からサポートされた機能ですが、クエリなどを含む動的なURLを、静的なURLにマップする機能です。

Googleなどの検索エンジンのクローラは、クエリを含むURLに対して冷たい(内容が変化するとして検索インデックスを下げるか、スキップする)ので、静的なURLに見せかけて検索インデックスを向上させよう、というのがそもそもの狙いです。

また、クエリを含むURLはあまりフレンドリーではないので、フレンドリーなものに見せかけるというのもありますね。

例えば、www.example.com/index.aspx?a=tako&b=namakoというURLはフレンドリーではなく、また検索エンジンからも冷たくあしらわれるので、www.example.com/tako/namako/のようなURLにマップしてやれば、フレンドリーになって検索エンジンからも覚えよく扱われる、という次第です。

普通はこのように使うのですが、私の場合はプログラミングの手間を低減するために導入しました。

例えば、「新館」の「森と公園めぐり」のページでは、こんなURLで各公園のページにアクセスします。

www.naosan.jp/park/shikinomori.aspx

単純に考えれば、shikinomori.aspxというASP.NETページを作成して、ということになるのですが、公園のページはたくさんあり、それぞれにページを作っていてはたいへんです。デザインの統一もたいへんです。

そこで、park.ascxというユーザコントロールを作成し、それをshikiomori.aspxに組み込みます。共通機能はpark.ascxに実装し、park.ascxでは自らの組み込まれたページのURLを判断し、同名のテキストファイル(たとえばshikinomori.txt)を読み込み、ページごとに異なった振る舞いをさせる、というよくある方法を採用しています。

もちろん、テキストファイルを用いているのはデータが軽くプログラミングが単純だからで、データ量が大きいか複雑な場合はXMLやRDBを使うのがベターです。

この方法の面倒くささは、中身のまったく同じ.aspxファイルを公園ページごとに作らなければならない点です。面倒というか、美しくないですね。メンテナンス的にも問題がありそうです。

そこで、URLルーティングを用い、リクエストを受け付けるURLをwww.naosan.jp/park/default.aspxに一本化します。そして、公園の名前をクエリで受け取ることにします。

www.naosan.jp/park/default.aspx?place=shikinomori

これを、以下のURLになるようにglobal.asaxの Application_Startメソッド内に、マッピングルールを書き加えます(コードはC#です)。

            RouteTable.Routes.MapPageRoute(
                "parkRouting", //ルーティング名
                "park/{place}.aspx", //ルーティング元のURL定義。{}内はパラメータ
                "~/park/default.aspx");  //ルーティング先のURL

あ、System.Web.Routing名前空間をインポートするのを忘れずに。

using System.Web.Routing;

これで、park/xxxx.aspxにマッチするURLがリクエストされたら、park/default.aspxにplace=xxxxをクエリ引数として渡してリクエストを転送します。

default.aspxでは、Page_Loadイベントハンドラ内で、Page.RouteData.Values["place"]としてクエリを取り出せばOKです。

さて、この方式には実は問題がありまして、ルーティングもとのURLパターンが普通のASP.NETページを表しているため、すでに物理リソースが存在していれば、そちらが優先される、という点です。

つまり、shikinomori.aspxが存在していれば、default.aspx?place=shikinomoriというリクエストに置き換わりません。これはこれで問題ないのでは?とも思えますが、デバッグ中などでは、ついついshikinomori.aspxの存在を忘れて、クエリが空だ〜などとパニックになります。

こういうときには、先ほどのマッピングルールを追加する前に、物理的リソースを無視する、という指定を入れればOKです。

            RouteTable.Routes.RouteExistingFiles = true;

これで、いつでもURLルーティングが可能になり、いちいち.aspxをダミーで作る必要もなく、メンテナンスが快適になりました。が、本来の使い方とはちょっと違うな、と思うので、次の機会にはもっと意味のある使い方をしてみたいと思います。

コメント