圓梦

激情燃燒的歲月
  博客园  :: 首页  :: 新随笔  :: 订阅 订阅  :: 管理

ASP.Net随想_服务器控件的页面请求模型

Posted on 2007-04-27 12:22  szw104  阅读(257)  评论(0编辑  收藏  举报

ASP.Net随想_服务器控件的页面请求模型

[日期:2007-04-11] 来源:http://www.cnblogs.com/Roping/archive/2007/04/07/7  作者:Roping [字体: ]
  前两篇文章ASP.Net随想_了解下原始的东西HTTPASP.Net随想_实现WEB表单外部提交 分析了ASPX页面请求和回发时候的数据并在此基础上实现了一个WEB标单提交的方法!WEB页面基于HTTP协议进行和服务器交互,ASP.Net本质上也不例外!由于HTTP协议是无状态的,那么,aspx页面如何提交请求的哪?就是说如何触发请求事件?呵呵,也许你会说事件驱动,委托一大堆的理由来解释!你误解我说的意思了,我是说的在客户端如何执行上述问题的!asp.net在客户端就是纯HTML+JavaScitpt(也可能是VBScript,或者包含其它的Active,我不和你争论这个概念),不存在你说的那些服务器段概念!其实服务器控件在客户端都对应一个html元素的!asp.net也逃脱不了传统的WEB页面请求模型!
 
传统的WEB编程能引起页面表单提交的元素为:

INPUT type=submit 元素 | input type=submit 对象
创建一个按钮,该按钮单击后将提交表单。
INPUT type=image 元素 | input type=image 对象
创建一个图像控件,该控件单击后将导致表单立即被提交。

还有一个提交From的方法:
submit;

相信我不解释你也知道这个的方法的用法!!好的,看看Asp.Net生成的页面文件,是不是能逃脱这个宿运?随便Create一个工程,拖一个服务器控件button进来,运行,看生成的客户端代码:怎么样?看出来倪端吧?

<asp:Button ID="btnTest" runat="server" OnClick="btnTest_Click" Text=" 测 试 " />
被解释(应该叫编译)成
<input type="submit" name="btnTest" value=" 测 试 " id="btnTest" />

其实所有的服务器控件都会生成类似这样的客户端代码,服务器控件是微软的一大创举,颠覆了传统的WEB的开发模式,创造性地应用了经典C/S事件驱动模式,天然的是Asp.Net模型符合MVC模式!

呵呵,Net如何把服务器控件Button解释成上述客户端的呈现哪?Good!请看微软实现Button的代码:
首先构造函数继承基类如下:

public Button() : base(HtmlTextWriterTag.Input)

    
{

}

说明他首先在客户端生成一个<input>元素,再看:

protected override void AddAttributesToRender(HtmlTextWriter writer)

    
{

        
bool useSubmitBehavior = this
.UseSubmitBehavior;

        
if (this.Page != null
)

        
{

            
this.Page.VerifyRenderingInServerForm(this
);

        }


        
if (useSubmitBehavior)

        
{

            writer.AddAttribute(HtmlTextWriterAttribute.Type, 
"submit"
);

        }


        
else

        
{

            writer.AddAttribute(HtmlTextWriterAttribute.Type, 
"button"
);

        }


       
//省略了其他代码…………………………………………………….

        
base.AddAttributesToRender(writer);

}

注意useSubmitBehavior,这个是button属性:表示是否这个按钮呈现为提交按钮(说白了是否设定input

的type是否为sumbit)!默认情况下是TRUE!

代码如下:

sumbit writer.AddAttribute(HtmlTextWriterAttribute.Type, "submit");

完成一系列其他的修饰后在调用基类的AddAttributesToRender(writer)!

呵呵,如果你是细心的人,你会注意到上面我们说过 useSubmitBehavior,它默认是True,你会说,如果我把他设成False,他生成的客户端元素<inpput>的代码属性不再会是submit,而是button,而这个属性点击后不会触发表单提交!看看微软如何解决这个问题的。好,还是先看客户端代码:

<asp:Button ID="btnTest" runat="server" OnClick="btnTest_Click" Text=" 测 试 " UseSubmitBehavior="False" />

被解释(应该叫编译)成
<input type="button" name="btnTest" value=" 测 试 " onclick="javascript:__doPostBack('btnTest','')" id="btnTest" /> 

注意到有什么变化吗?客户端多了onclick="javascript:__doPostBack('btnTest','')",我塞,你真牛,这都被你看出来了!在看看服务器端多了什么?UseSubmitBehavior="False",呵呵,又被你看出来了!

那么这两者肯定有必然的联系!靠,这个你又猜到了!I Flow You!这个放后再说,先看下面:

既然客户端多了一个

onclick="javascript:__doPostBack('btnTest','')",

那客户端肯定存在__doPostBack(Argumen1, object Argument1) ,仔细看下你生成的页面代码:

是不是有这段代码存在:

<script type="text/javascript">

<!--

var theForm 
= document.forms['form1'];

if (!theForm) 
{

    theForm 
=
 document.form1;

}


function __doPostBack(eventTarget, eventArgument) 
{

    
if (!theForm.onsubmit || (theForm.onsubmit() != false)) 
{

        theForm.__EVENTTARGET.value 
=
 eventTarget;

        theForm.__EVENTARGUMENT.value 
=
 eventArgument;

        theForm.submit();

    }


}


// -->

</script>

 

先解释下,__doPostBack就是触发表单提交的客户端函数,参事一是触发事件的控件,参数二十事件的所带的参数!__EVENTTARGET和EVENTARGUMENT为隐藏的Input元素!!

这段代码如何生成的哪?回去再看Button的实现代码:

 protected internal override void OnPreRender(EventArgs e)

    
{

            
//…….省略其它代码


            
else if (!this.UseSubmitBehavior)

            
{

                
this
.Page.RegisterPostBackScript();

            }


        }


    }

注意 this.Page.RegisterPostBackScript();这个就是罪魁祸首了!

,还有一个问题没有解决:onclick="javascript:__doPostBack('btnTest','')"如何由UseSubmitBehavior="False"生成的过程哪?

protected override void AddAttributesToRender(HtmlTextWriter writer)

    
{

       

     
//……省略了其他代码:


        
if (isEnabled)

        


 firstScript 
= Util.EnsureEndWithSemiColon(this
.OnClientClick);

            
if (base
.HasAttributes)

            
{

                
string text3 = base.Attributes["onclick"
];

                
if (text3 != null
)

                
{

                    firstScript 
= firstScript +
 Util.EnsureEndWithSemiColon(text3);

                    
base.Attributes.Remove("onclick"
);

                }


            }


}


            
if (this.Page != null)

            
{

                
string secondScript = this.Page.ClientScript.GetPostBackEventReference(postBackOptions, false
);

                
if (secondScript != null
)

                
{

                    firstScript 
=
 Util.MergeScript(firstScript, secondScript);

                }


            }


        }


        
if (this.Page != null)

        
{

            
this
.Page.ClientScript.RegisterForEventValidation(postBackOptions);

        }


        
if (firstScript.Length > 0)

        
{

            writer.AddAttribute(HtmlTextWriterAttribute.Onclick, firstScript);

            
if (base
.EnableLegacyRendering)

            
{

                writer.AddAttribute(
"language""javascript"false
);

            }


        }


      

        
//…..省略了其他代码

    }

 首先检测如果启动控件,首先去掉基类的"click"的Attributes!然后合并积累和客户设置的客户端事件,然后再生成onclick="javascript:__doPostBack('btnTest','')客户端属性,如下:

writer.AddAttribute(HtmlTextWriterAttribute.Onclick, firstScript);

if (base
.EnableLegacyRendering)

            
{

                writer.AddAttribute(
"language""javascript"false
);

            }


好了,至此,你应该知道Asp.Net的如何和服务器交互了,别管怎么复杂的控件都是通过如上方法进行提交表单的!