老赵前日的这篇博文讲的是有关ASPNET WebForm页面内容输出方式的内容尽管这个话题很老不过在ASPNET MVC中同样适用而且适用的情况有增无减因此十分重要希望这篇文章能够帮助你更好的理解ASPNET WebForm页面内容输出的细节
这次我们谈的话题是WebForm页面上输出内容的方式这其实是一个非常旧的话题了因为本文的内容甚至可以运用于ASPNET 之上不过这个话题的适用范围很广因为即使是目前最新的ASPNET MVC框架它的默认视图引擎依旧是基于ASPNET WebForm的(如PageControlMasterPage)甚至说由于ASPNET MVC框架的特性我们会遇到更多在页面上直接输出内容的情况因此这个话题在ASPNET MVC应用中可能由为重要
那么就拿ASPNET MVC举例吧假如我们在页面上生成一个Partial View我们可以这么做
< % HtmlRenderPartial(MyPartialView); %> 然而在前一篇文章中我们提出了一个新的方法Partial它返回一个字符串它可以在页面上这样使用
< %= HtmlPartial(MyPartialView) %> 一个aspx页面会被编译成Page类的一个子类这个子类的主要功能是覆盖了基类的Render方法
public class MyPage : Page
{
protected override void Render(HtmlTextWriter writer)
{
}
} 我们平时在aspx页面中编写的大量内容其实都会变成操作writer的代码例如使用writerWrite方法输出内容或者把writer交给子控件的Render方法用于生成内容那么以上两种页面上的标记分别又是如何操作writer的呢?
< %= expression %> 首先是< %= %>标记< %= %>标记内包含的是一个表达式因此它不能以分号结尾表达式内部的数据就会直接写入writer例如这样的标记
< %= DateTimeNow %> 在编译过后就成为
writerWrite(DateTimeNow) 与< %= %>标记不同< % %>标记中间其实包含的是语句语句自然可以有多行自然每行最后需要有分号这就像我们平时写C#代码那样不过实际上语句的功能其实并不是为了输出内容而是用来控制逻辑例如您在页面上写了这样的代码
< % Func< int bool> odd = i => i % != ; %> 这样就相当于您在Render方法内部声明了一个局部变量odd它的类型是一个Func< int bool>委托而如果您编写这样的代码
< % for (int i = ; i < ; i++)
{
%> < span> < %= i + %> < /span> < %
}
%>
则生成的Render方法中就会包含
for (int i = ; i < ; i++)
{
writerWrite(< span>);
writerWrite(i + );
writerWrite(< /span>);
}
如果是写在页面上的普通HTML标记编译后就被当作普通字符串来处理了有些朋友一直谈客户端控件等等其实如果一个元素上没有runat=server标记ASPNET只是把它们当作普通字符串处理并不会有任何HTML元素的概念当然上面的代码表现的是意图事实上在编译过后aspx页面中的空格和换行等字符也会包含在输出的内容中
那么既然< % %>中包含的是用来控制逻辑的语句本身不是用来表示输出的那么为什么刚才代码中的HtmlRenderPartial方法也会生成页面内容呢?那是因为RenderPartial方法直接向当前HttpContextResponseOutput里写入字符了很多朋友经常使用ResponseWrite来输出内容其实在Write方法内部就是输出到Output中
事实上即使我们的页面中使用了HtmlTextWriter来输出内容但它内部也是封装了Output所暴露出的TextWriter中为了验证您可以在代码中设置断点并观察Render方法的writer参数在正常情况下可以发现writerInnerWriter属性是一个HttpWriter对象这是个TextWriter的子类也是ASPNET中定义的内部类型
这便是ASPNET WebForm页面内容输出的细节那么请问以下两种输出方式的区别是什么呢?
< %= Hello World %> < % ResponseWrite(Hello World); %> 从效果上看两者没有任何区别但是实际上前者是使用页面的HtmlTextWriter对象输出的而后者则直接向ResponseOutput里输出内容这个区别看似不重要但其实它会涉及到我们很多开发过程中可用的实践方式在今后的文章中我会提出生成页面内容的一些准则解释这些准则的原因并指出ASPNET MVC本身是如何破坏这些设计准则的