WebForm页面内容输出的细节分析
创始人
2024-06-07 07:31:50
0

老赵前日的这篇博文讲的是有关ASP.NET WebForm页面内容输出方式的内容。尽管这个话题很老,不过在ASP.NET MVC中同样适用,而且适用的情况有增无减,因此十分重要。希望这篇文章能够帮助你更好的理解ASP.NET WebForm页面内容输出的细节。

这次我们谈的话题是“WebForm页面上输出内容的方式”。这其实是一个非常旧的话题了,因为本文的内容甚至可以运用于ASP.NET 1.1之上。不过这个话题的适用范围很广,因为即使是目前***的ASP.NET MVC框架,它的默认视图引擎依旧是基于ASP.NET WebForm的(如Page,Control,MasterPage)。甚至说,由于ASP.NET MVC框架的特性,我们会遇到更多在页面上“直接输出”内容的情况。因此,这个话题在ASP.NET MVC应用中可能由为重要。

那么就拿ASP.NET MVC举例吧。假如,我们在页面上生成一个Partial View,我们可以这么做:

  1. < % Html.RenderPartial("MyPartialView"); %> 

然而,在前一篇文章中我们提出了一个新的方法Partial,它返回一个字符串,它可以在页面上这样使用:

  1. < %= Html.Partial("MyPartialView") %> 

一个aspx页面会被编译成Page类的一个子类,这个子类的主要“功能”是覆盖了基类的Render方法:

  1. public class MyPage : Page  
  2. {  
  3.     protected override void Render(HtmlTextWriter writer)  
  4.     {  
  5.         ...  
  6.     }  
  7. }  
  8.  

我们平时在aspx页面中编写的大量内容,其实都会变成操作writer的代码。例如使用writer.Write方法输出内容,或者把writer交给子控件的Render方法用于生成内容。那么,以上两种页面上的标记分别又是如何操作writer的呢?

  1. < %= expression %> 

首先是< %= %>标记。< %= %>标记内包含的是一个“表达式”,因此它不能以分号结尾。表达式内部的数据就会直接写入writer。例如这样的标记:

  1. < %= DateTime.Now %> 

在编译过后就成为:

  1. writer.Write(DateTime.Now) 

与< %= %>标记不同,< % %>标记中间其实包含的是“语句”。语句自然可以有多行,自然每行***需要有分号,这就像我们平时写C#代码那样。不过实际上,语句的功能其实并不是为了“输出内容”,而是用来“控制逻辑”。例如,您在页面上写了这样的代码:

  1. < % Func< int, bool> odd = i => i % 2 != 0; %> 

这样就相当于您在Render方法内部声明了一个局部变量odd,它的类型是一个Func< int, bool>委托。而如果您编写这样的代码:

  1. < % for (int i = 0; i <  10; i++) { %> 
  2.     < span> 
  3.         < %= i + 1 %> 
  4.     < /span> 
  5. < % } %> 

则生成的Render方法中就会包含:

  1. for (int i = 0; i <  10; i++)  
  2. {  
  3.     writer.Write("< span>");  
  4.     writer.Write(i + 1);  
  5.     writer.Write("< /span>");  

如果是写在页面上的普通HTML标记,编译后就被当作普通字符串来处理了。有些朋友一直谈“客户端控件”等等,其实如果一个元素上没有runat="server"标记,ASP.NET只是把它们当作普通字符串处理,并不会有任何“HTML元素”的概念。当然,上面的代码表现的是“意图”,事实上在编译过后aspx页面中的空格和换行等字符也会包含在输出的内容中1。

那么,既然< % %>中包含的是用来控制逻辑的语句,本身不是用来表示输出的,那么为什么刚才代码中的Html.RenderPartial方法也会生成页面内容呢?那是因为RenderPartial方法直接向当前HttpContext.Response.Output里写入字符了。很多朋友经常使用Response.Write来输出内容,其实在Write方法内部就是输出到Output中。

事实上,即使我们的页面中使用了HtmlTextWriter来输出内容,但它内部也是封装了Output所暴露出的TextWriter中。为了验证,您可以在代码中设置断点并观察Render方法的writer参数,在“正常情况下”可以发现writer.InnerWriter属性是一个HttpWriter对象,这是个TextWriter的子类,也是ASP.NET中定义的内部类型。

这便是ASP.NET WebForm页面内容输出的细节。那么请问,以下两种输出方式的区别是什么呢?

  1. < %= "Hello World" %> 
  2. < % Response.Write("Hello World"); %> 

从效果上看,两者没有任何区别。但是实际上前者是使用页面的HtmlTextWriter对象输出的,而后者则直接向Response.Output里输出内容。这个区别看似不重要,但其实它会涉及到我们很多开发过程中可用的实践方式。在今后的文章中,我会提出生成页面内容的一些准则,解释这些准则的原因,并指出ASP.NET MVC本身是如何破坏这些设计准则的。

自然,修改版本的ASP.NET MVC会发布在MvcPatch项目中。

【编辑推荐】

  1. 解决WebForm未定义的原因及方法
  2. WebForm中的ListBox组件编程
  3. ASP.NET MVC与WebForm区别谈
  4. ASP.NET Routing之“解析URL”功能详解
  5. 为ASP.NET MVC应用添加自定义路由

相关内容

热门资讯

如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
施耐德电气数据中心整体解决方案... 近日,全球能效管理专家施耐德电气正式启动大型体验活动“能效中国行——2012卡车巡展”,作为该活动的...
Windows恶意软件20年“... 在Windows的早期年代,病毒游走于系统之间,偶尔删除文件(但被删除的文件几乎都是可恢复的),并弹...
20个非常棒的扁平设计免费资源 Apple设备的平面图标PSD免费平板UI 平板UI套件24平图标Freen平板UI套件PSD径向平...
德国电信门户网站可实时显示全球... 德国电信周三推出一个门户网站,直观地实时提供其安装在全球各地的传感器网络检测到的网络攻击状况。该网站...
着眼MAC地址,解救无法享受D... 在安装了DHCP服务器的局域网环境中,每一台工作站在上网之前,都要先从DHCP服务器那里享受到地址动...
为啥国人偏爱 Mybatis,... 关于 SQL 和 ORM 的争论,永远都不会终止,我也一直在思考这个问题。昨天又跟群里的小伙伴进行...