在由ASP.NET所谓前台调用后台、后台调用前台想到HTTP——理论篇中描述了一下ASP.NET新手的三个问题及相关的HTTP协议内容,在由ASP.NET所谓前台调用后台、后台调用前台想到HTTP——实践篇(一)中已经解答了关于服务器怎么改变页面元素或“调用”JavaScript的问题,为了不上篇啰啰嗦嗦一大推,此次直奔主题——ASP.NET前台如何调用后台方法javascript
所谓前台调用后台这种问题的提出无非是由于不少新手受了ASP.NET服务器端控件的“误导”,你不是说前台没有把JavaScript语句、页面元素什么的传到后台,因此前台调用后台,或者后台监视页面变化是扯淡嘛!那ASP.NET中为何服务器端控件一点击就能调用后台制定方法呢?按照你前面的理论即便用了服务器端控件,那么到了浏览器页面也变成最普通不过的HTML文本了,怎么还可以调用服务器端方法呢?!css
确实,浏览器呈现的是HTML文本,咱们先不用拘泥于ASP.NET怎么作到的前台“调用”后台,咱们能够本身实现一下,不过在此以前咱们得明白一些过于Post的问题html
咱们在看不少网页的时候都会看到这样的内容java
<form id="form1" method="post" action="Default.aspx"> <input type="text" name="wd" /> <input type="submit" name="test" value="test" /> </form>
这段HTML文本同窗们都能看懂,页面上有一个form,form内有两个input,点击submit的时候,页面form内容会以post方式被提交到Default.aspx这个页面。程序员
HTTP协议中的Post方法会将所处的form提交到form指定页面,若是form指定的方法为post(还多是get等),那么form内有些数据会一并被提交。浏览器
既然不是整个form被提交,那么哪些数据会被提交呢?服务器
1.input的name和valueide
2.input type=”submit” 只有被点击的时候才将其自己name与value提交函数
3.对于多个name相同的input type=”checkbox”,只有选中项的值会被提交(多个value以,链接)post
4.对于多个name相同的input type=”radio”,只有选中项的value会被提交(同名的radio只能单选)
5.select的name和被选中的option的vaue(不是option的text)
6.textarea 的name与value
这样被提交的数据能够在提交的页面的后台中以Request.Form[“name”]的方式查到其值
知道了form和post的最基本知识,咱们就能够模拟ASP.NET的button调用后台方法了,首先准备这样一个页面
<form id="form1" method="post" action="Default.aspx"> <input type="submit" name="test" value="test"/> </form>
在后台添加想调用的方法
protected void test_Click(object sender, EventArgs e) { Response.Write("Button Click!"); }
很简单的内容,后台方法的两个参数彻底能够不用(和事件有关),填上只是为了增长其逼真性,代码中有几个须要注意的地方
1.form的方法须要设为post,这个很明显。。。
2.form的action设为页面自己,也就是让页面提交给本身
3.input要有name
准备工做作好后就能够模拟JavaScript调用后台方法了,在页面的 OnLoad方法中写入代码
protected override void OnLoad(EventArgs e) { if (Request.Form["test"]!=null) { test_Click(this, new EventArgs()); } base.OnLoad(e); }
聪明的同窗确定能够看出端倪了,在点击test的时候会提交表单,页面的OnLoad会自动执行,这时候会判断提交过来的表单中是否包含test(submit被点击后会被提交,不点击不提交,因此能够根据name能够判断出哪一个按钮被按了),就这么简单,点击submit的时候,预约义的方法就被调用了,要是页面上有不少submit,这时候就须要if-else或者switch或者for这样的东西来判断究竟是哪一个submit被点击了,而后调用对应方法。
对比一下,ASP.NET正好用,首先人家的from是这样的
<form id="form1" runat="server"> </form>
人家自动就给render成这样了
咱们也不须要本身在OnLoad中添加if-else,只要在control的属性中添加OnClick=”XXX”就能够了,我没看过.NET源码,可是我大胆的揣测,虽然不用再OnLoad里if-else了,但应该也是相似的方式处理。
细心的同窗可能要问了,你这么作是能够,可是依赖于表单提交,咱们知道并非全部的页面元素都会点一下就提交表单,像控件asp: DropDownList的OnSelectIndexChanged事件,人家也会调用回台方法,那是怎么作的?
其实很是简单,对于这种需求,仍然能够用表单提交的方式处理,不能自动提交表单,那么咱们能够用JavaScript帮助其提交,看个select change “调用”后台函数的例子,首先像这样修改页面,添加一个select
<form id="form1" method="post" action="Default.aspx"> <input type="hidden" id="__param" name="__param" /> <input id="test" name="test" type="submit" value="test" /> <select id="select1" name="select1"> <option value="0">0</option> <option value="1">1</option> <option value="2">2</option> </select> <script type="text/javascript"> document.getElementById('select1').onchange = function () { document.getElementById('__param').value = this.name; document.getElementById('form1').submit(); }; </script> </form>
咱们除了select元素还添加了两个内容,一个input type=”hidden”的隐藏元素,一段JavaScript脚本,在JavaScript脚本中对select的onchange绑定了一个方法,当select选择项变化的时候,把其name赋值给隐藏域的value,而后提交表单,因为隐藏域可定会被提交,这样咱们能够一样在页面的Onload中判断谁的onchange触发了,而后调用预约义方法,后台代码是这样的
protected override void OnLoad(EventArgs e) { string param= Request.Form["__param"]; if (Request.Form["test"]!=null) { test_Click(this, new EventArgs()); } else if (param == "select1") { select_Change(this, new EventArgs()); } base.OnLoad(e); } protected void test_Click(object sender, EventArgs e) { Response.Write("Button Click!"); } protected void select_Change(object sender, EventArgs e) { string newValue = Request.Form["select1"]; Response.Write("Seclect value chaned to " + newValue); }
是否是很简单呢?先判断是否是submit,不是的话判断隐藏域,命中后调用预约义方法。
细心的同窗仍然会发现问题,要是一个元素上同时又两个事件怎么办?好比还想对这个select添加cilck事件怎么办,这时候咱们能够修改隐藏域的值,不只记录name,还记上事件类型,相似这样
document.getElementById('select1').onchange = function () { document.getElementById('__param').value = this.name+"$ onchange"; document.getElementById('form1').submit(); }; document.getElementById('select1').onclick = function () { document.getElementById('__param').value = this.name+"$ onclick"; document.getElementById('form1').submit(); };
而后在后台判断的时候,咱们能够先把参数按$分割为两个字符串,分别判断元素与事件类型,固然咱们也能够再添加一个隐藏域,用来记事件类型,大同小异。
还有同窗回问,若是我在客户端一样写了select的onclick,不就把你的代码覆盖了吗?这样我就不能post了,对于这个问题咱们大能够换种方式绑定事件处理程序,用addEventListener(attachEven)的方式,这样post的代码和本身写的客户端的就能够同时存在了,这样
var select = document.getElementById('select1'); select.onclick = function () { // // // }; select.addEventListener('clcik', function () {//浏览器兼容性问题要处理,这里就不演示了 document.getElementById('__param').value = this.name + "$ onclick"; document.getElementById('form1').submit(); }, false);
咱们能够看看ASP.NET是怎么处理的,在页面上写一个DropDownList,设起AutoPostBack属性为true
<form id="form1" runat="server"> <asp:DropDownList ID="ddlTest" runat="server" AutoPostBack="true"> <asp:ListItem>1</asp:ListItem> <asp:ListItem>2</asp:ListItem> <asp:ListItem>3</asp:ListItem> </asp:DropDownList> </form>
生成的页面源码是这样的
<html xmlns="http://www.w3.org/1999/xhtml"><head><title> </title><style type="text/css"></style></head> <body cz-shortcut-listen="true"> <form method="post" action="Default.aspx" id="form1"> <div class="aspNetHidden"> <input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value=""> <input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value=""> </div> <script type="text/javascript"> //<![CDATA[ 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> <div class="aspNetHidden"> <input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/wEdAAWUpg6MZl3t8/pBYubwqWOJqSwDGOXu15HYfC2efhAyHc1gIfz8erLrnvHjMLCTGHuRsEl8lEzJ1SVLtM7lgCLfggLVPRtDk70yN7TcfPOwwBRLeEs10HSMSLT9zq5aYmmjMFX5QrdQAuJDrw+EXFTJ"> </div> <select name="ddlTest" onchange="javascript:setTimeout('__doPostBack(\'ddlTest\',\'\')', 0)" id="ddlTest"> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> </select> </form> </body></html>
主要是这个方法,认真读读是否是和咱们刚才写的相似呢,人家传了两个隐藏域,一个用来是Target,一个用来及参数
onchange="javascript:setTimeout('__doPostBack(\'ddlTest\',\'\')', 0)"
function __doPostBack(eventTarget, eventArgument) { if (!theForm.onsubmit || (theForm.onsubmit() != false)) { theForm.__EVENTTARGET.value = eventTarget; theForm.__EVENTARGUMENT.value = eventArgument; theForm.submit(); } }
经过上面例子分析能够看得出来,JavaScript根本没有调用后台函数,只是提交了含有预设参数的表单,服务器根据参数调用后台方法,生成特定HTML,所谓前台调用后台也就这么回事儿。
有一个问题值得思考,为何这种很想固然的作法PHP程序员能够轻松想到,不少.NET初级程序员却不行,甚至有时候咱们都已经在使用了,好比根据Url的QueryString来调用不一样方法,或进行不一样处理,却没有进一步想到更经常使用的Button、DropDownList是怎么作到的?仍是那句话,.NET程序员当自勉,不要被.NET的易用性惯坏,多学习原理知识,不要过度知足于作出来,而要多追求为何,这样才能不断进步。