由ASP.NET所謂前臺調用後臺、後臺調用前臺想到HTTP——實踐篇(二)

由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

簡單聊聊Post

咱們在看不少網頁的時候都會看到這樣的內容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」]的方式查到其值

input type=」submit」  「調用」後臺方法

知道了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: button

對比一下,ASP.NET正好用,首先人家的from是這樣的

<form id="form1" runat="server">
</form>

人家自動就給render成這樣了

image

咱們也不須要本身在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: DropDownList

咱們能夠看看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的易用性慣壞,多學習原理知識,不要過度知足於作出來,而要多追求爲何,這樣才能不斷進步。

相關文章
相關標籤/搜索