讲下ASP.NET MVC把WebForm页面内容输出方式
下面例子以ASP.NET MVC为基础讲解WebForm页面内容输出方式:
我们在页面上生成一个Partial View,我们可以这么做:
<% Html.RenderPartial("MyPartialView"); %>
然而,在前一篇文章中我们提出了一个新的方法Partial,它返回一个字符串,它可以在页面上这样使用:
<%= Html.Partial("MyPartialView") %>
一个aspx页面会被编译成Page类的一个子类,这个子类的主要“功能”是覆盖了基类的Render方法:
public class MyPage : Page
{
protected override void Render(HtmlTextWriter writer)
{
...
}
}
我们平时在aspx页面中编写的大量内容,其实都会变成操作writer的代码。例如使用writer.Write方法输出内容,或者把writer交给子控件的Render方法用于生成内容。那么,以上两种页面上的标记分别又是如何操作writer的呢?
<%= expression %> 首先是<%= %>标记。<%= %>标记内包含的是一个“表达式”,因此它不能以分号结尾。表达式内部的数据就会直接写入writer。例如这样的标记:
<%= DateTime.Now %> 在编译过后就成为:
writer.Write(DateTime.Now) 与<%= %>标记不同,<% %>标记中间其实包含的是“语句”。语句自然可以有多行,自然每行最后需要有分号,这就像我们平时写C#代码那样。不过实际上,语句的功能其实并不是为了“输出内容”,而是用来“控制逻辑”。例如,您在页面上写了这样的代码:
<% Func<int, bool> odd = i => i % 2 != 0; %> 这样就相当于您在Render方法内部声明了一个局部变量odd,它的类型是一个Func<int, bool>委托。而如果您编写这样的代码:
<% for (int i = 0; i < 10; i++) { %>
<span>
<%= i + 1 %>
</span>
<% } %>
则生成的Render方法中就会包含:
for (int i = 0; i < 10; i++)
{
writer.Write("<span>");
writer.Write(i + 1);
writer.Write("</span>");
}
如果是写在页面上的普通HTML标记,编译后就被当作普通字符串来处理了。有些朋友一直谈“客户端控件”等等,其实如果一个元素上没有runat="server"标记,ASP.NET只是把它们当作普通字符串处理,并不会有任何“HTML元素”的概念。当然,上面的代码表现的是“意图”,事实上在编译过后aspx页面中的空格和换行等字符也会包含在输出的内容中1。
那么,既然<% %>中包含的是用来控制逻辑的语句,本身不是用来表示输出的,那么为什么刚才代码中的Html.RenderPartial方法也会生成页面内容呢?那是因为RenderPartial方法直接向当前HttpContext.Response.Output里写入字符了。很多朋友经常使用Response.Write来输出内容,其实在Write方法内部就是输出到Output中。