ASP.NET MVC のRouteConfig以外でのRouteの指定方法

# RouteConfigを使用してみて

* 率直な感想からいうと慣れていないせいか、優先順位を含めて非常にわかりにくい感じがした
* 一つのアプリケーションで複数のコントローラーに対してのルーティングを書いて行くとRouteConfigが肥大化しそうだったため、後々の修正や改修を考えた際に非常にわかりにくいと思ったため別な方法を検討してみました。

# RouteAttributeを使用してみて

* メリットとして、コントローラーやアクション単位でルーティングを記述できるためシンプルになりました。
* コントローラーに属性として記述するため、RouteConfig.csと各Controller.csを見ながら記述する必要がないので楽
* 基本的に<a target="_blank" href="http://blogs.msdn.com/b/webdev/archive/2013/10/17/attribute-routing-in-asp-net-mvc-5.aspx">こちらのページ</a>を参考に実験しました。
* 
# 使用方法

* RouteConfig.csに追加

```csharp
public static void RegisterRoutes(RouteCollection routes)
{
　　// リソースデータに直接アクセスされない為の記述
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    
　　// この一行を追加
    // 意味：属性が定義されたアプリケーションのルートをマップします。
    routes.MapMvcAttributeRoutes();

    // デフォルトのルーティング
　　// この記述は、Controller側で[Route("~/")]を指定した場合、不要になる
    routes.MapRoute(
　　　　　　name: "Default",
　　　　　　url: "{controller}/{action}/{id}",
　　　　　　defaults: new 
　　　　　　　　{controller = "コントローラー名", 
　　　　　　　　 action = "アクション名", 
　　　　　　　　 id = UrlParameter.Optional
　　　　　　}
　　);
}
```

* コントローラーに実際に使用するルールを記述

```csharp
using System.Web;
using System.Web.Mvc;

namespace WebApplication1.Controllers
{
    [RoutePrefix("Home")]　// ← 【1】
    public class HomeController : Controller
    {
        [Route("~/")]　// ← 【2】
        [Route("I")]　 // ← 【3】
        public ActionResult Index()
        {
            return View();
        }

        /// <summary>
        /// 【4】
        /// id という引数を受け取る場合、Route属性に{id}を追加
　　　　 /// idがNull許容の場合、文字列でも{id?}のように「?」が必要
        /// </summary>
        [Route("A/{id}")]　
        public ActionResult About(string id)
        {
            ViewBag.Message = "Your application description page.";

            return View();
        }

        /// <summary>
        /// 【5】
        /// id という引数を受け取る場合、Route属性に{id}を追加
　　　　 /// idに「:int」とつけることで、int型しか受け付けないように制約がかけられる
        /// </summary>
        [Route("C/{id:int}")]
        public ActionResult Contact(int id)
        {
            ViewBag.Message = "Your contact page.";

            return View();
        }
    }
}
```

---
- 【1】RoutePrefixについて
 - コントローラーで使用する「接頭辞(接頭語)」
 - コントローラー名や全く別の名称でも使用できる。
     - 本来なら、HomeController　→ Home と設定するけど、test 等の名称に設定することも可能。<br>
※ あくまで一例であり、推奨はしません

---
- 【2】Route ・・・Defaltのルーティング設定
 - RouteConfig.cs内のDefaltの記述を削除したい場合に [Route("~/")]と指定することで、ルートアクションにすることができます。
     - Indexアクションを記述しなくて済むが、そもそも存在しなくても問題ないのであればエラーを表示してもいい。

---
- 【3】Route ・・・アクションに対しての設定
 - [Route("I")] とすることで、今まで Index というアクション指定をしていた部分が、「I」でアクセス可能になる。
 - View側でHtmlヘルパーのActionLinkを使用して出力されるリンクも【~/Home/I】という形式になる。
     - RoutePrefixで「test」と指定した場合・・・【~/test/I】という形式になる。

---
- 【4】Route ・・・ パラメーターの受け取り
 - [Route("A/{id}")] と指定することで、URLパラメーターを受け取ることが可能。
     - id は、アクションで受け取る変数名と同一の名称を指定しないと受け取れない。
     - id を Null許容に指定したい場合は たとえstring型であっても{id?}のように「?」をつけなければエラーとなる

---
- 【5】Route ・・・ パラメーターの受け取り時の型指定
 - [Route("C/{id:int}")]とすることで、受け取るURLパラメーターに制約をつけられるようになる。
     - エラーの場合は404エラーとなる。

# サポートされている型指定(2015/12/26 現在)

* x は変数を表します
* アクションに指定された引数「x」の型と一致しない場合は、エラーとなるため注意

|指定する値|説明|使用方法|
|:--:|:--|:--|
|alpha|アルファベットの指定。大文字/小文字の区別はしない。<br>(a-z, A-Z)まで判定してくれる。|{x:alpha}|
|bool|成否の指定。true or falseのみ受け付ける。0 or 1 はIntとして認識されエラーとなる。|{x:bool}|
|datetime|日付の指定。フォーマット<br>「2015-12-26」：OK<br>「2015/12/26」：NG|{x:datetime}|
|decimal|あれ・・・小数点入ると動作しない？<br>decimal型の変数は受け取れる。<br>小数点は、「.」がURL的にまずいのでそもそもNGな可能性がこれあり。|{x:decimal}|
|double|あれ・・・小数点入ると動作しない？|{x:double}|
|float|あれ・・・小数点入ると動作しない？|{x:float}|
|guil|「8桁-4桁-4桁-4桁-12桁」の形式指定。|{x:guid}|
|int|数値(-2,147,483,648 ～ 2,147,483,647)の指定。|{x:int}|
|length|指定された長さ。or 指定された範囲内の文字列<br>桁指定したい場合・・・1つ指定。<br>範囲指定したい場合・・・2つ指定。|{x:length(6)} <br>{x:length(1,20)}|
|long|数値(-9,223,372,036,854,775,808 ～ 9,223,372,036,854,775,807)の指定|{x:long}|
|max|値の最大値の指定。桁数ではないので注意。<br>{x:max(10)}と指定した場合・・・1～10までOK<br>アクションの引数が、string型の場合でも動作する。<br>URLで指定する値が数字の場合・・・OK<br>文字列の場合・・・NG|{x:max(10)}|
|min|値の最小値。|{x:min(1)}|
|range|値の最小値と最大値の指定。|{x:range(10，15)}|
|maxlength|値の最大桁数の指定。|{x:maxlength}|
|minlength|値の最小桁数の指定。|{x:minlength}|
|x:regex|正規表現を利用した指定。|{x:regex(^\\d{3}-\\d{4}$)}|

# 組み合わせで使える型指定

|指定例|意味|
|:--|:--|
|{x:int:min(1)}|数値で、最小値が1。つまり値が数値以外で0の場合エラーですよ。という指定。|
|{x:maxlength(3)?}|最大の桁数は3桁だけど、入ってない(null)でもOKですよ。という指定。|


# Areas

* アプリケーションで、Areasを使用してエリア分けをしてる際に今までなら、「AreaRegistration」にルーティングを記載していましたが
これもRouteAttributeを使用してすっきりと記述できたので時間があるときにでも記載します。