しばやん雑記

Azure とメイドさんが大好きなフリーランスのプログラマーのブログ

ASP.NET MVC で Razor の基本クラスを変更する

ASP.NET MVC の場合は Razor で書かれたビューは System.Web.Mvc.WebViewPage クラスを基本クラスとしてコンパイルされます。

例えば以下のようなシンプルな Razor ビューがあるとします。

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

これをコンパイラが C# コードに変換すると以下のような形になります。Razor は結局のところ ASPX と同じく、クラスとしてコンパイルされるわけです。

namespace ASP
{
    public class _Page_Views_Home_Index_cshtml : System.Web.Mvc.WebViewPage<dynamic>
    {
        public override void Execute()
        {
            ViewBag.Title = "Index";

            WriteLiteral("\r\n\r\n<h2>Index</h2>");
        }
    }
}

ちなみに @model を使うと WebViewPage の型引数が @model で指定した型になるという仕組みです。

しかし、開発しているとビューのプロパティとして持たせたい情報とかが出てきます。そういった時にはビューの基本クラスを入れ替えてしまうことで対応しましょう。

実は Razor の基本クラスは Views ディレクトリ内にある Web.config に記述されているので、それを変更することで簡単に入れ替えることが出来ます。

<system.web.webPages.razor>
  <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
  <pages pageBaseType="MvcApplication1.CustomWebViewPage">
    <namespaces>
      <add namespace="System.Web.Mvc" />
      <add namespace="System.Web.Mvc.Ajax" />
      <add namespace="System.Web.Mvc.Html" />
      <add namespace="System.Web.Routing" />
    </namespaces>
  </pages>
</system.web.webPages.razor>

この例では MvcApplication1 名前空間の CustomWebViewPage クラスに入れ替えています。そして肝心の CustomWebViewPage クラスの実装は WebViewPage を継承するだけで非常に簡単。

public abstract class CustomWebViewPage<TModel> : WebViewPage<TModel>
{
    // プロパティ追加したりとか何でも出来る!
}

// 型引数なしの WebViewPage は既に使われていないが、R# が警告を出すので仕方なく用意する
public abstract class CustomWebViewPage : CustomWebViewPage<dynamic>
{
}

型引数付きのクラスだけで Razor は問題なくコンパイルと実行されるんですが、ReSharper を使っていると警告が出るので型引数なしのクラスも用意しておきます。

たったこれだけの作業で Razor 内で使えるプロパティを増やしたりできるので、覚えておいて損は無さそうです。