传统的WEB编程能引起页面表单提交的元素为:
INPUT type=submit 元素 | input type=submit 对象
创建一个按钮,该按钮单击后将提交表单。
INPUT type=image 元素 | input type=image 对象
创建一个图像控件,该控件单击后将导致表单立即被提交。
还有一个提交From的方法:
submit;
相信我不解释你也知道这个的方法的用法!!好的,看看Asp.Net生成的页面文件,是不是能逃脱这个宿运?随便Create一个工程,拖一个服务器控件button进来,运行,看生成的客户端代码:怎么样?看出来倪端吧?
其实所有的服务器控件都会生成类似这样的客户端代码,服务器控件是微软的一大创举,颠覆了传统的WEB的开发模式,创造性地应用了经典C/S事件驱动模式,天然的是Asp.Net模型符合MVC模式!
呵呵,Net如何把服务器控件Button解释成上述客户端的呈现哪?Good!请看微软实现Button的代码:
首先构造函数继承基类如下:
{
}
说明他首先在客户端生成一个<input>元素,再看:
{
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!
代码如下:
完成一系列其他的修饰后在调用基类的AddAttributesToRender(writer)!
呵呵,如果你是细心的人,你会注意到上面我们说过 useSubmitBehavior,它默认是True,你会说,如果我把他设成False,他生成的客户端元素<inpput>的代码属性不再会是submit,而是button,而这个属性点击后不会触发表单提交!看看微软如何解决这个问题的。好,还是先看客户端代码:
被解释(应该叫编译)成
注意到有什么变化吗?客户端多了οnclick="javascript:__doPostBack('btnTest','')",我塞,你真牛,这都被你看出来了!在看看服务器端多了什么?UseSubmitBehavior="False",呵呵,又被你看出来了!
那么这两者肯定有必然的联系!靠,这个你又猜到了!I Flow You!这个放后再说,先看下面:
既然客户端多了一个
οnclick="javascript:__doPostBack('btnTest','')",
那客户端肯定存在__doPostBack(Argumen1, object Argument1) ,仔细看下你生成的页面代码:
是不是有这段代码存在:
<!--
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的实现代码:
{
//…….省略其它代码
else if (!this.UseSubmitBehavior)
{
this.Page.RegisterPostBackScript();
}
}
}
注意 this.Page.RegisterPostBackScript();这个就是罪魁祸首了!
{
//……省略了其他代码:
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!然后合并积累和客户设置的客户端事件,然后再生成οnclick="javascript:__doPostBack('btnTest','')客户端属性,如下:
if ( base .EnableLegacyRendering)
{
writer.AddAttribute("language", "javascript", false);
}
好了,至此,你应该知道Asp.Net的如何和服务器交互了,别管怎么复杂的控件都是通过如上方法进行提交表单的!
PS:这个是我在出差南京路上写的,比较匆忙,通过我的这三篇文章,你应该知道Asp.Net向的数据项并知Asp.Net在豪华的外衣下和服务器交互的原始手段的对应得方法,其实服务器空间之所以强大,Asp.Net编程模型的成功还离不开一位功臣,那就是ViewState,呵呵,直到我的下篇随想是什么了吧!