快速业务通道

ASP.NET中aspx页面runat="server"的本质

作者 佚名技术 来源 NET编程 浏览 发布时间 2012-04-12
我们页面上的html应该如何解释的。准确地说,aspx页面的生成原理是,aspx页面会被读入分析器,当一个HTML标签内不包含runat=”server”的时候,它将被当作字符串输出或者编译成new LiteralControl(“具体的文本”);

当遇到runat=”server”的时候,如果标签可以被转换为一个HtmlControl,则转换成HtmlControl,否则将会被解释为一个HtmlGenericControl对象,因为要转换成对象,所以会多出一些规则检查,假设没有runat="server",则你的所有字符都将被当作文本进行输出,但是如果加上runat="server",则所有的属性如果有对应的则转换成“属性=value”的模式,如果没有,则转换成SetAttribute("name", "value");的形式,因此如果id="",则会变成XXX.ID="",而此处的ID则需要满足一般的命名规范,以满足在别的地方直接以ID进行对象引用,也就是说必须是字母/下划线打头。对其他属性则没有过多严格的要求,但是对应的<%=str%>将只以文本进行输出,而不会替换为其值。

下面的类继承图展示了所有继承自HtmlControls的控件。

 


比如一个<head runat=”server”></head> 将被解析为:
HtmlHead head = new HtmlHead(“head”);
HtmlTitle title = this.__BuildControl__control3();
IParserAccessor accessor = head;
accessor.AddParsedSubObject(title);
这里的AddParsedSubObject大致是如下代码:

public class Control
{
        protected virtual void AddParsedSubObject(object obj)
        {
            Control child = obj as Control;
            if (child != null)
            {
                this.Controls.Add(child);
            }
        }
}

 
 
也就是Controls.Add方法。 这里用增加输出委托的方式来进行一些HTML呈现的逻辑:

private HtmlTitle __BuildControl__control3()
{
    HtmlTitle title = new HtmlTitle();
    title.SetRenderMethodDelegate(new RenderMethod(this.__Render__control3));
    return title;
}
private void __Render__control3(HtmlTextWriter __w, Control parameterContainer)
{
    __w.Write("\r\n        ");
    __w.Write("My title");
}

 
 
4、那为何link的href会出错,而script则不会呢? // 生成script   private void __Render__control2(HtmlTextWriter __w, Control parameterContainer)
{
    parameterContainer.Controls[0].RenderControl(__w);
    parameterContainer.Controls[1].RenderControl(__w);
    __w.Write("\r\n\r\n    <script language=\"javascript\" type=\"text/javascript\" src=\"");
    __w.Write(this.str);
    __w.Write("/a.js\"></script>\r\n\r\n    ");
    parameterContainer.Controls[2].RenderControl(__w);
}

 

  // 生成HtmlLink
private HtmlLink __BuildControl__control4()
{
    HtmlLink link = new HtmlLink();
    ((IAttributeAccessor) link).SetAttribute("rel", "Stylesheet");
    link.Href = "<%= str %>/a.css";
    return link;
}
 
  很显然,link的Href是直接将页面上的文本进行赋值的,因此最终并没有使用str中的值去替代文本,而script中,str则是被直接输出的,因此script是可以的,而link则会出现问题。 5、去掉runat=”server”则解决问题,为什么? 因为去掉runat=”server”后,link标签将不再转换成HtmlLink,因此就不会调用link.Href属性去赋值,因此就不会出错了。  

6、有什么特征?(结论)

private void __Render__control1(HtmlTextWriter __w, Control parameterContainer)
{
    __w.Write("\r\n\r\n<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd%5C%22>\r\n<html xmlns=\"http://www.w3.org/1999/xhtml%5C%22>\r\n\r\n");
    __w.Write("\r\n\r\n<head>\r\n    <title>\r\n        ");
    __w.Write("My title");
    __w.Write("</title>\r\n    <link rel=\"Stylesheet\" href=\"");
    __w.Write(this.str);
    __w.Write("/a.css\" />\r\n\r\n    <script language=\"javascript\" type=\"text/javascript\" src=\"");
    __w.Write(this.str);
    __w.Write("/a.js\"></script>\r\n\r\n    ");
    parameterContainer.Controls[0].RenderControl(__w);
    __w.Write("\r\n</head>\r\n<body>\r\n    ");
    parameterContainer.Controls[1].RenderControl(__w);
    __w.Write("\r\n</body>\r\n</html>\r\n");
}

 

准确地说,因为在runat=”server”下,编译器会将其中的所有属性的xxxx=yyyy的部分都首先转换成其Attribute,设置的方式通常有以下两种 a、通过SetAttribute("xxxx", "yyyy"); b、如果该HtmlControl含有该属性,则由其属性来设置,如head.Href=”yyyy”; 注意,这里不管yyyy是否是<%=mmm%>,一样会被直接当作文本输出。 但是,在正文中出现的将以__w.Write(this.str);的方式输出。
    <form id="form1" runat="server" accept="<%=str %>">
<div>
<%=str %>
</div>
</form>
结论:在runat=”server”下的标签,如果可以转换成HtmlControl,那么它的Attribute将不能使用<%=str%>的方式输出,如果不能转换成HtmlControl,则没有具体要求。如果一定要使用<%=str%>的方式,则需要将其以及它的祖先节点上的runat=”server”去掉即可。但是,关于一个嵌套的结构是否会被自动提升为runat=”server”则是根据标准来制定的。比如将link标签放在head中,设置head为runat=”server”,则link会被转换成HtmlLink,但是将其放在<form runat=”server”>下则只会被当作文本输出。而在form下的控件则不会进行自动提升,如<form runat=”server”><input type=”button” /></form>则button将继续以文本的方式输出,遇到<%=str%>将被转换成__w.Write(str);。如果需要将其提升为HtmlInputButton控件,将显示指定其为<input runat=”server” type=”button” />。

编译下面的代码,并打开“C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\”路径下的对应的程序集,用reflector反编译查看源代码,并验证以上规律。

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebAppHeadRunatServer._Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

<script runat="server">
    string str = "mypath";   
</script>

<head runat="server">
    <title>
        <%="My title" %></title>
    <link rel="Stylesheet<%= str %>" href="<%= str %>/a.css" />
    <input id="Button1" type="button" value="<%=str %>" />

    <script language="javascript" type="text/javascript" src="<%=str %>/a.js"><%=str %><link rel="Stylesheet<%= str %>" href="<%= str %>/a.css" /></script>

    <meta content="volnet.cnblogs.com" name="<%=str %>-blog" runat="server" />
</head>
<body>
    <form id="form1" runat="server" accept="<%=str %>">
    <link rel="Stylesheet<%= str %>" href="<%= str %>/a.css" />
    <div id="<%=str %>x">
        accept="<%=str %>"
    </div>
    <input type="button" value="<%=str %>" />
    <input type="button" runat="server" value="<%=str %>" />
    </form>
</body>
</html>
 

 

凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

分享到: 更多

Copyright ©1999-2011 厦门凌众科技有限公司 厦门优通互联科技开发有限公司 All rights reserved

地址(ADD):厦门软件园二期望海路63号701E(东南融通旁) 邮编(ZIP):361008

电话:0592-5908028 传真:0592-5908039 咨询信箱:web@lingzhong.cn 咨询OICQ:173723134

《中华人民共和国增值电信业务经营许可证》闽B2-20100024  ICP备案:闽ICP备05037997号