ASP.NET MVC的Razor引擎:View编译原理2012-09-07 博客园 Artech通过.cshtml或者.vbhtml文件定义的View能够被执行,必须先被编译成存在于某个程序集的类型,ASP.NET MVC采用动态编译的方式对View文件实施编译。当我们在对ASP.NET MVC进行部署的时候,需要对.cshtml或者.vbhtml文件进行打包。针对某个View的第一次访问会触发针对它的编译,一个View对应着一个类型。我们可以对.cshtml或者.vbhtml进行修改,View文件修改后的第一次访问将会导致View的再一次编译。和ASP.NET 传统的编译方式一样,针对View的编译默认是基于目录的,也就是说同一个目录下的多个View文件被编译到同一个程序集中。为了让读者对ASP.NET MVC对View文件的编译机制具有一个深刻的认识,我们通过一个简单的实例来确定View文件最终都被编译成什么类型,所在的程序集又是哪一个。我们在一个ASP.NET MVC应用中为HtmlHelper定义了如下一个扩展方法ListViewAssemblies,该方法用于获取当前被加载的包含View类型的程序集(程序集名称以“App_Web_”为前缀)。
 1: public static class HtmlHelperExtensions
 2: {
 3: public static MvcHtmlString ListViewAssemblies(this HtmlHelper helper)
 4: {
 5: TagBuilder ul = new TagBuilder("ul");
 6: foreach(var assembly in AppDomain.CurrentDomain.GetAssemblies().Where(a=>a.FullName.StartsWith("App_Web_")))
 7: {
 8: TagBuilder li = new TagBuilder("li");
 9: li.InnerHtml = assembly.FullName;
10: ul.InnerHtml+= li.ToString();
11: }
12: return new MvcHtmlString(ul.ToString());
13: }
14: }
然后我们定义了如下两个Controller类型(FooController和BarController),它们之中各自定义了两个Action方法Action1和Action2。
 1: public class FooController : Controller
 2: {
 3: public ActionResult Action1()
 4: {
 5: return View();
 6: }
 7: public ActionResult Action2()
 8: {
 9: return View();
10: }
11: }
12: 
13: public class BarController : Controller
14: {
15: public ActionResult Action1()
16: {
17: return View();
18: }
19: public ActionResult Action2()
20: {
21: return View();
22: }
23: }
接下来我们为定义在FooController和BarController的四个Action创建对应的View(对应文件路为:“~/Views/Foo/Action1.cshtml”、“~/Views/Foo/Action2.cshtml”、“~/Views/Bar/Action1.cshtml”和“~/Views/Bar/Action2.cshtml”)。它们具有如下相同的定义,我们在View中显示自身的类型和当前加载的基于View的程序集。
 1: <div>当前View类型:@this.GetType().AssemblyQualifiedName</div>
 2: <div>当前加载的View程序集:</div>
 3: @Html.ListViewAssemblies()
现在运行我们的程序并在浏览器中通过输入相应的地址“依次”(“Foo/Action1”、“Foo/Action2”、“Bar/Action1”和“Bar/Action2”)访问定义在FooController和BarController的四个Action,四次访问得到的输出结果下图所示。
