过完年, 大家都忙碌起来了, 我也不例外. 不过并不是忙碌于去面试找工作, 而是忙碌于现在手上的工作. 闲话不多说了, 进入今天的主题.
一、Index页面在哪里
很奇怪, 在目录bin下面的dll文件中, 都没有看见过视图的具体内容, 那么他们都去哪里了呢?
首先在Index页面中, 加入一句话: @this.GetType().Assembly.Location
当程序运行起来之后, 就可以在页面上看到运行的目录.
我的目录是这个:
C:UsersxxxxxAppDataLocalTempTemporary ASP.NET Filesvs31cf611379f9587cApp_Web_xwp5b05u.dll
后面我标黄的这一段, 是随机数, 不用去管它. 拿到他直接反编译, 来看一下效果:
[Dynamic(new bool[] { false, true })] public class _Page_Views_Home_Index_cshtml : WebViewPage<object> { // Methods public override void Execute() { ((dynamic) base.ViewBag).Title = "Index"; base.BeginContext("~/Views/Home/Index.cshtml", 0x23, 4, true); this.WriteLiteral(" "); base.EndContext("~/Views/Home/Index.cshtml", 0x23, 4, true); base.BeginContext("~/Views/Home/Index.cshtml", 40, 0x20, false); this.Write(base.GetType().Assembly.Location); base.EndContext("~/Views/Home/Index.cshtml", 40, 0x20, false); base.BeginContext("~/Views/Home/Index.cshtml", 0x48, 0x33, true); this.WriteLiteral(" <h2>Index</h2> <table> <tr> <td>"); base.EndContext("~/Views/Home/Index.cshtml", 0x48, 0x33, true); base.BeginContext("~/Views/Home/Index.cshtml", 0x7c, 10, false); this.Write(((dynamic) base.Model).Name); base.EndContext("~/Views/Home/Index.cshtml", 0x7c, 10, false); base.BeginContext("~/Views/Home/Index.cshtml", 0x86, 40, true); this.WriteLiteral("</td> </tr> <tr> <td>"); base.EndContext("~/Views/Home/Index.cshtml", 0x86, 40, true); base.BeginContext("~/Views/Home/Index.cshtml", 0xaf, 9, false); this.Write(((dynamic) base.Model).Age); base.EndContext("~/Views/Home/Index.cshtml", 0xaf, 9, false); base.BeginContext("~/Views/Home/Index.cshtml", 0xb8, 0x2c, true); this.WriteLiteral("</td> </tr> </table> <script> "); base.EndContext("~/Views/Home/Index.cshtml", 0xb8, 0x2c, true); base.BeginContext("~/Views/Home/Index.cshtml", 0x160, 11, true); this.WriteLiteral(" </script>"); base.EndContext("~/Views/Home/Index.cshtml", 0x160, 11, true); } // Properties protected global_asax ApplicationInstance { get { return (global_asax) this.Context.ApplicationInstance; } } }
从这里看, 页面上的那些普通的标签语句都通过 this.WriteLiteral() 方法, 解析成字符串了. 而@Model.Name也解析出来了.
这里注意到, 是将Model转成dynamic变量的. 那么, 我在View这里能不能传一个dynamic的值呢? 这个在后面会给出demo.
在上一篇的 System.Web.Mvc.RazorView.RenderView()方法中, 有一句:WebPageRenderingBase startPage = null;
这里的 _Page_Views_Home_Index_cshtml 类, 就是间接继承自 WebPageRenderingBase 类.
二、Razor的基本用法
在MVC中, 在前台页面, 可以借助Razor像后台那样编程. 然后通过 @变量 来输出. 如:
@if (true) { <table> <tr> <td>@Model.Name</td> </tr> <tr> <td>@Model.Age</td> </tr> </table> }
括号里面, 可以直接写html是因为编译器能识别标签, 知道该怎么去解析.
那么如果我在<script>标签里面也这么写, 如:
@if (true) { alert(1); }
这个是不行的, 因为没有明显的标志, 来让编译器识别, 里面的alert(1)是属于html里面的还是C#语句. 识别不出来的.
那么这时候, 就需要借助别的东西来帮助识别了. 两种方式 : 1. <text></text> 2. @:
<script> @if (true) { @: alert(1); <text>alert(2);</text> } else { @: alert('@DateTime.Now.ToString()'); } </script>
这两种方式都是可以的, 就看个人习惯吧. 在使用<text>的时候, vs缩进的让人看着难受. 就像下面这样:
<script> @if (true) { @: alert(1); <text> alert(2); </text> } else { @: alert('@DateTime.Now.ToString()'); } </script>
两种方式各有优缺点. <text></text>中间可以放很多内容. @:遇到多行时, 每一行都要加.
三、Model传值
在View(model)这里可以传递后台的变量, 那么这个model是存放在哪里的呢?
public TModel Model { get { return this.ViewData.Model; } }
看这里, 是存放在ViewData里面的. 那么也就是说, 我可以在后台通过 ViewData.Model的方式来替换View(model)的方式来传值. 事实上也是可以的.
那么一般类型的值, 肯定都是可以传递的. 上面也说到, 能不能传递dynamic的值呢?
答案是不可以直接传递的, 也就是说我不能这么传递: return View(dynamic), 那能不能传递匿名类型呢:return View(new {name="haha"}) ?
答案也是不可以直接传递.
那么有没有办法来传递这些值呢? 当然可以, 不然我也不会这么问了.
Demo1:
public ActionResult Index() { dynamic model1 = new ExpandoObject(); model1.Name = "ExpandoObject"; model1.Age = 12; var res = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(model1)); return View(res); }
Index页面还是上面的那个. 看一下结果:
这里我一遍序列化与反序列化, 就可以了. 这里的model1当然也可以是匿名类型.
不过这种方式并不推荐使用吧, 也挺麻烦的, 多了一道序列化与反序列化.