<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 495,comments - 227,trackbacks - 0
    轉(zhuǎn)自msdn
    AJAX依靠代理(broker)指派和處理往返服務(wù)器的請(qǐng)求。對(duì)此,.NET包裝器依靠客戶端XmlHttpRequest對(duì)象。多數(shù)瀏覽器都支持XmlHttpRequest對(duì)象,這就是選擇它的原因。因?yàn)榘b器的目的是隱藏XmlHttpRequest的實(shí)現(xiàn),我們就不再詳細(xì)討論它了。
    包裝器本身通過將.NET函數(shù)標(biāo)記為AJAX方法來工作。標(biāo)記之后,AJAX就創(chuàng)建對(duì)應(yīng)的JavaScript函數(shù),這些函數(shù)(和任何JavaScript函數(shù)一樣)作為代理可以在客戶端使用XmlHttpRequest調(diào)用。這些代理再映射回服務(wù)器端函數(shù)。
    復(fù)雜嗎?并不復(fù)雜。我們來看一個(gè)例子。假設(shè)有一個(gè).NET函數(shù):
    ublic int Add(int firstNumber, int secondNumber)
    {
    return firstNumber + secondNumber;
    }
    AJAX .NET包裝器將自動(dòng)創(chuàng)建名為“Add”、帶有兩個(gè)參數(shù)的JavaScript函數(shù)。使用JavaScript(在客戶機(jī)上)調(diào)用該函數(shù)時(shí),請(qǐng)求將傳遞給服務(wù)器并把結(jié)果返回給客戶機(jī)。
    ?
    初始設(shè)置
    我們首先介紹“安裝”項(xiàng)目中使用的.dll的步驟。如果您很清楚如何添加.dll文件引用,可以跳過這一節(jié)。
    首先,如果還沒有的話,請(qǐng)下載最新的AJAX版本。解壓下載的文件并把a(bǔ)jax.dll放到項(xiàng)目的引用文件夾中。在Visual Studio.NET中有機(jī)Solution Explorer的“References(引用)”節(jié)點(diǎn)并選擇Add Reference(添加引用)。在打開的對(duì)話框中,單擊Browse(瀏覽)并找到ref/ajax.dll文件。依次單擊Open(打開)和Ok(確認(rèn))。這樣就可以用AJAX .NET包裝器編程了。
    建立HttpHandler
    為了保證正常工作,第一步是在web.config中設(shè)置包裝器的HttpHandler。不需要詳細(xì)解釋HttpHandlers是什么及其如何工作,只要知道它們用于處理ASP.NET請(qǐng)求就足夠了。比如,所有*.aspx頁面請(qǐng)求都由System.Web.UI.PageHandlerFactory類處理。類似的,我們讓所有對(duì)ajax/*.ashx的請(qǐng)求由Ajax.PageHandlerFactory處理:
    <configuration>
    ? <system.web>
    ? ? <httpHandlers>
    ? ? ? <add verb="POST,GET" path="ajax/*.ashx"
    ? ? ? ? ? type="Ajax.PageHandlerFactory, Ajax" />
    ? ? </httpHandlers>?
    ? ? ...
    ? <system.web>
    </configuration>
    簡(jiǎn)言之,上面的代碼告訴ASP.NET,和指定路徑(ajax/*.ashx)匹配的任何請(qǐng)求都由Ajax.PageHandlerFactory而不是默認(rèn)處理程序工廠來處理。不需要?jiǎng)?chuàng)建ajax子目錄,使用這個(gè)神秘的目錄只是為了讓其他HttpHandlers能夠在自己建立的子目錄中使用.ashx擴(kuò)展。
    ?
    建立頁面
    現(xiàn)在我們可以開始編碼了。創(chuàng)建一個(gè)新頁面或者打開已有的頁面,在file后的代碼中,為Page_Load事件添加以下代碼:
    public class Index : System.Web.UI.Page{
    ? private void Page_Load(object sender, EventArgs e){
    ? ? ? Ajax.Utility.RegisterTypeForAjax(typeof(Index));? ? ?
    ? ? ? //...? ?
    ? }
    ? //...?
    }
    調(diào)用RegisterTypeForAjax將在頁面上引發(fā)后面的JavaScript(或者在頁面中手工加入以下兩行代碼):
    <script language="javascript" src="ajax/common.ashx"></script>
    <script language="javascript"
    src="ajax/Namespace.PageClass,AssemblyName.ashx"></script>
    其中最后一行的含義是:
    下面是AjaxPlay項(xiàng)目中sample.aspx頁面的結(jié)果例子:
    <%@ Page Inherits="AjaxPlay.Sample" Codebehind="sample.aspx.cs" ... %>
    <html>
    <head>
    ? <script language="javascript" src="ajax/common.ashx"></script>
    ? <script language="javascript"
    ? ? ? ? ? src="ajax/AjaxPlay.Sample,AjaxPlay.ashx"></script>
    </head>
    ? <body>? ?
    ? ? <form id="Form1" method="post" runat="server">
    ? ? ? ...
    ? ? </form>? ?
    ? </body>
    </html>
    可以在瀏覽器中手工導(dǎo)航到src路徑(查看源代碼,復(fù)制粘貼路徑)檢查是否一切正常。如果兩個(gè)路徑都輸出一些(似乎)毫無意義的文本,就萬事大吉了。如果什么也沒輸出或者出現(xiàn)ASP.NET錯(cuò)誤,則表明有些地方出現(xiàn)問題。
    即便不知道HttpHandlers如何工作,上面的例子也很容易理解。通過web.config,我們已經(jīng)保證所有對(duì)ajax/*.ashx的請(qǐng)求都由自定義的處理程序處理。顯然,這里的兩個(gè)腳本標(biāo)簽將由自定義的處理程序處理。
    ?
    創(chuàng)建服務(wù)器端函數(shù)
    現(xiàn)在來創(chuàng)建可從客戶端調(diào)用中異步訪問的服務(wù)器端函數(shù)。因?yàn)槟壳斑€不支持所有的返回類型(不用擔(dān)心,將在目前的基礎(chǔ)上開發(fā)新的版本),我們繼續(xù)使用簡(jiǎn)單的ServerSideAdd函數(shù)吧。在file后的代碼中,向頁面添加下列代碼:
    [Ajax.AjaxMethod()]
    public int ServerSideAdd(int firstNumber, int secondNumber)
    {
    ? return firstNumber + secondNumber;
    }
    要注意,這些函數(shù)具有Ajax.AjaxMethod屬性集。該屬性告訴包裝器這些方法創(chuàng)建javaScript代理,以便在客戶端調(diào)用。
    ?
    客戶端調(diào)用
    最后一步是用JavaScript調(diào)用該函數(shù)。AJAX包裝器負(fù)責(zé)創(chuàng)建帶有兩個(gè)參數(shù)的JavaScript函數(shù)Sample.ServerSideAdd。對(duì)這種最簡(jiǎn)單的函數(shù),只需要調(diào)用該方法并傳遞兩個(gè)數(shù)字:
    <%@ Page Inherits="AjaxPlay.Sample" Codebehind="sample.aspx.cs" ... %>
    <html>
    <head>
    ? <script language="javascript" src="ajax/common.ashx"></script>
    ? <script language="javascript"
    ? ? ? ? ? src="ajax/AjaxPlay.Sample,AjaxPlay.ashx"></script>
    </head>
    ? <body>? ?
    ? ? <form id="Form1" method="post" runat="server">
    ? ? ? <script language="javascript">
    ? ? ? ? var response = Sample.ServerSideAdd(100,99);
    ? ? ? ? alert(response.value);
    ? ? ? </script>
    ? ? </form>? ?
    ? </body>
    </html>
    當(dāng)然,我們不希望僅僅用這種強(qiáng)大的能力來警告用戶。這就是所有客戶端代理(如JavaScript Sample.ServerSideAd函數(shù))還接受其他特性的原因。這種特性就是為了處理響應(yīng)而調(diào)用的回調(diào)函數(shù):
    Sample.ServerSideAdd(100,99, ServerSideAdd_CallBack);

    function ServerSideAdd_CallBack(response){
    ?if (response.error != null){
    ? alert(response.error);
    ? return;
    ?}
    ?alert(response.value);
    }
    從上述代碼中可以看到我們指定了另外一個(gè)參數(shù)。ServerSideAdd_CallBack(同樣參見上述代碼)是用于處理服務(wù)器響應(yīng)的客戶端函數(shù)。這個(gè)回調(diào)函數(shù)接收一個(gè)響應(yīng)對(duì)象,該對(duì)象公開了三個(gè)主要性質(zhì)
    • Value——服務(wù)器端函數(shù)實(shí)際返回的值(無論是字符串、自定義對(duì)象還是數(shù)據(jù)集)。
    • Error——錯(cuò)誤消息,如果有的話。
    • Request——xml http請(qǐng)求的原始響應(yīng)。
    • Context——上下文對(duì)象。
    首先我們檢查error只看看是否出現(xiàn)了錯(cuò)誤。通過在服務(wù)器端函數(shù)中拋出異常,可以很容易處理error特性。在這個(gè)簡(jiǎn)化的例子中,然后用這個(gè)值警告用戶。Request特性可用于獲得更多信息(參見下一節(jié))。
    ?
    處理類型
    ?
    返回復(fù)雜類型
    Ajax包裝器不僅能處理ServerSideAdd函數(shù)所返回的整數(shù)。它目前還支持integers、strings、double、booleans、DateTime、DataSets和DataTables,以及自定義類和數(shù)組等基本類型。其他所有類型都返回它們的ToString值。
    返回的DataSets和真正的.NET DataSet差不多。假設(shè)一個(gè)服務(wù)器端函數(shù)返回DataSet,我們可以通過下面的代碼在客戶端顯示其中的內(nèi)容:
    <script language="JavaScript">
    //Asynchronous call to the mythical "GetDataSet" server-side function
    function getDataSet(){
    ? AjaxFunctions.GetDataSet(GetDataSet_callback);? ?
    }
    function GetDataSet_callback(response){
    ? var ds = response.value;
    ? if(ds != null && typeof(ds) == "object" && ds.Tables != null){
    ? ? var s = new Array();
    ? ? s[s.length] = "<table border=1>";
    ? ? for(var i=0; i<ds.Tables[0].Rows.length; i++){
    ? ? ? s[s.length] = "<tr>";
    ? ? ? s[s.length] = "<td>" + ds.Tables[0].Rows[i].FirstName + "</td>";
    ? ? ? s[s.length] = "<td>" + ds.Tables[0].Rows[i].Birthday + "</td>";
    ? ? ? s[s.length] = "</tr>";
    ? ? }
    ? ? s[s.length] = "</table>";
    ? ? tableDisplay.innerHTML = s.join("");
    ? }
    ? else {
    ? ? alert("Error. [3001] " + response.request.responseText);
    ? }
    }
    </script>
    Ajax還可以返回自定義類,唯一的要求是必須用Serializable屬性標(biāo)記。假設(shè)有如下的類:
    [Serializable()]
    public class User{
    ? private int _userId;
    ? private string _firstName;
    ? private string _lastName;

    ? public int userId{
    ? ? get { return _userId; }
    ? }
    ? public string FirstName{
    ? ? get { return _firstName; }
    ? }
    ? public string LastName{
    ? ? get { return _lastName; }
    ? }
    ? public User(int _userId, string _firstName, string _lastName){
    ? ? this._userId = _userId;
    ? ? this._firstName = _firstName;
    ? ? this._lastName = _lastName;
    ? }
    ? public User(){}
    ? [AjaxMethod()]
    ? public static User GetUser(int userId){
    ? ? //Replace this with a DB hit or something :)
    ? ? return new User(userId,"Michael", "Schwarz");
    ? }
    }
    我們可以通過調(diào)用RegisterTypeForAjax注冊(cè)GetUser代理:
    private void Page_Load(object sender, EventArgs e){
    ? Utility.RegisterTypeForAjax(typeof(User));
    }
    這樣就可以在客戶端異步調(diào)用GetUser:
    <script language="javascript">
    function getUser(userId){
    ? User.GetUser(GetUser_callback);
    }
    function GetUser_callback(response){
    ? if (response != null && response.value != null){
    ? ? var user = response.value;
    ? ? if (typeof(user) == "object"){? ? ? ? ?
    ? ? ? alert(user.FirstName + " " + user.LastName);
    ? ? }
    ? }
    }
    getUser(1);
    </script>
    響應(yīng)中返回的值實(shí)際上是一個(gè)對(duì)象,公開了和服務(wù)器端對(duì)象相同的屬性(FirstName、LastName和UserId)。
    ?
    自定義轉(zhuǎn)換器
    我們已經(jīng)看到,Ajax .NET包裝器能夠處理很多不同的.NET類型。但是除了大量.NET類和內(nèi)建類型以外,包裝器對(duì)不能正確返回的其他類型僅僅調(diào)用ToString()。為了避免這種情況,Ajax .NET包裝器允許開發(fā)人員創(chuàng)建對(duì)象轉(zhuǎn)換器,用于在服務(wù)器和客戶機(jī)之間平滑傳遞復(fù)雜對(duì)象。
    ?
    其他事項(xiàng)
    ?
    在其他類中注冊(cè)函數(shù)
    ?
    上面的例子中,我們的服務(wù)器端函數(shù)都放在執(zhí)行頁面背后的代碼中。但是,沒有理由不能把這些函數(shù)放在單獨(dú)的類文件中。要記住,包裝器的工作方式是在指定類中發(fā)現(xiàn)所有帶Ajax.AjaxMethod的方法。需要的類通過第二個(gè)腳本標(biāo)簽指定。使用Ajax.Utility.RegisterTypeForAjax,我們可以指定需要的任何類。比如,將我們的服務(wù)器端函數(shù)作為單獨(dú)的類是合情合理的:
    Public Class AjaxFunctions
    ? <Ajax.AjaxMethod()> _
    ? Public Function Validate(username As String, password As String) As Boolean
    ? ? 'do something
    ? ? 'Return something
    ? End Function
    End Class
    通過指定類的類型而不是頁面就可以讓Ajax包裝器創(chuàng)建代理:
    private void Page_Load(object sender, EventArgs e){
    ? Ajax.Utility.RegisterTypeForAjax(typeof(AjaxFunctions));
    ? //...
    }
    要記住,客戶端代理的名稱是<ClassName>.<ServerSideFunctionName>。因此,如果ServerSideAdd函數(shù)放在上面虛構(gòu)的AjaxFunctions類中,客戶端調(diào)用就應(yīng)該是: AjaxFunctions.ServerSideAdd(1,2)。
    ?
    代理到底是如何工作的
    ?
    Ajax工具生成的第二個(gè)腳本標(biāo)簽(也可以手工插入)傳遞了頁面的名稱空間、類名和程序集。根據(jù)這些信息,Ajax.PageHandlerFactory就能夠使用反射得到具有特定屬性的任何函數(shù)的詳細(xì)信息。顯然,處理函數(shù)查找具有AjaxMethod屬性的函數(shù)并得到它們的簽名(返回類型、名稱和參數(shù)),從能夠創(chuàng)建必要的客戶端代理。具體而言,包裝器創(chuàng)建一個(gè)和類同名的JavaScript對(duì)象,該對(duì)象提供代理。換句話說,給定一個(gè)帶有Ajax ServerSideAdd方法的服務(wù)器端類AjaxFunctions,我們就會(huì)得到公開ServerSideAdd函數(shù)的AjaxFunction JavaScript對(duì)象。如果將瀏覽器指向第二個(gè)腳本標(biāo)簽的路徑就會(huì)看到這種動(dòng)作。
    ?
    返回Unicode字符
    ?
    Ajax .NET包裝器能夠從服務(wù)器向客戶機(jī)返回Unicode字符。為此,數(shù)據(jù)在返回之前必須在服務(wù)器上用html編碼。比如:
    [Ajax.AjaxMethod]
    public string Test1(string name, string email, string comment){
    ? string html = "";
    ? html += "Hello " + name + "<br>";
    ? html += "Thank you for your comment <b>";
    ? html += System.Web.HttpUtility.HtmlEncode(comment);
    ? html += "</b>.";
    ? return html;
    }
    SessionState
    ?
    服務(wù)器端函數(shù)中很可能需要訪問會(huì)話信息。為此,只需要通過傳遞給Ajax.AjaxMethod屬性的一個(gè)參數(shù)告訴Ajax啟用這種功能。
    在考察包裝器會(huì)話能力的同時(shí),我們來看看其他幾個(gè)特性。這個(gè)例子中我們有一個(gè)文檔管理系統(tǒng),用戶編輯的時(shí)候會(huì)對(duì)文檔加鎖。其他用戶可以請(qǐng)求在文檔可用的時(shí)候得到通知。如果沒有AJAX,我們就只能等待該用戶再次返回來檢查請(qǐng)求的文檔是否可用。顯然不夠理想。使用支持會(huì)話狀態(tài)的Ajax就非常簡(jiǎn)單了。
    首先來編寫服務(wù)器端函數(shù),目標(biāo)是循環(huán)遍歷用戶希望編輯的documentId(保存在會(huì)話中)并返回所有已釋放的文檔。
    [Ajax.AjaxMethod(HttpSessionStateRequirement.Read)]
    public ArrayList DocumentReleased(){
    ? if (HttpContext.Current.Session["DocumentsWaiting"] == null){
    ? ? return null;
    ? }
    ? ArrayList readyDocuments = new ArrayList();
    ? int[] documents = (int[])HttpContext.Current.Session["DocumentsWaiting"];
    ? for (int i = 0; i < documents.Length; ++i){
    ? ? Document document = Document.GetDocumentById(documents[i]);
    ? ? if (document != null && document.Status == DocumentStatus.Ready){
    ? ? ? readyDocuments.Add(document);
    ? ? }? ? ? ?
    ? }
    ? return readyDocuments;
    ? }
    }
    要注意,我們指定了HttpSessionStateRequirement.Read值(還可以用Write和ReadWrite)。
    現(xiàn)在編寫使用該方法的JavaScript:
    <script language="javascript">
    function DocumentsReady_CallBack(response){
    ? if (response.error != null){
    ? ? alert(response.error);
    ? ? return;
    ? }
    ? if (response.value != null && response.value.length > 0){
    ? ? var div = document.getElementById("status");
    ? ? div.innerHTML = "The following documents are ready!<br />";
    ? ? for (var i = 0; i < response.value.length; ++i){
    ? ? ? div.innerHTML += "<a href=\"edit.aspx?documentId=" + response.value[i].DocumentId + "\">" + response.value[i].Name + "</a><br />";
    ? ? }? ? ?
    ? }
    ? setTimeout('page.DocumentReleased(DocumentsReady_CallBack)', 10000);
    }
    </script>?
    <body onload="setTimeout('Document.DocumentReleased(DocumentsReady_CallBack)', 10000);">
    我們的服務(wù)器端函數(shù)在頁面加載時(shí)調(diào)用一次,然后每隔10秒鐘調(diào)用一次?;卣{(diào)函數(shù)檢查響應(yīng)看看是否有返回值,有的話則在div標(biāo)簽中顯示該用戶可使用的新文檔。
    結(jié)束語
    AJAX技術(shù)已經(jīng)催生了原來只有桌面開發(fā)才具備的健壯而豐富的Web界面。Ajax .NET包裝器讓您很容易就能利用這種新的強(qiáng)大技術(shù)。請(qǐng)注意,Ajax .NET包裝器和文檔仍在開發(fā)之中。


    posted on 2007-01-25 17:05 SIMONE 閱讀(1257) 評(píng)論(0)  編輯  收藏 所屬分類: .NET
    主站蜘蛛池模板: 成人亚洲国产va天堂| 亚洲第一福利网站在线观看| 久久久99精品免费观看| 国产无限免费观看黄网站| 免费无码国产在线观国内自拍中文字幕 | 国产美女视频免费观看的网站| 亚洲国产无线乱码在线观看| youjizz亚洲| 精品丝袜国产自在线拍亚洲| 亚洲精品国产成人中文| 久久亚洲精品无码VA大香大香| 亚洲av永久无码精品网站| 亚洲国产精品无码专区影院 | 一本久久综合亚洲鲁鲁五月天| 免费高清资源黄网站在线观看| 成年女人18级毛片毛片免费| 97免费人妻无码视频| 久久久久久国产a免费观看黄色大片 | 亚洲av无码有乱码在线观看| 麻豆亚洲AV成人无码久久精品 | 久久久久亚洲av无码专区| 亚洲精品中文字幕麻豆| 亚洲国产成a人v在线观看| 亚洲狠狠婷婷综合久久蜜芽| 国产亚洲精品2021自在线| 一级做a毛片免费视频 | 亚洲Av无码专区国产乱码DVD| 无码欧精品亚洲日韩一区| 亚洲精品国产成人专区| 亚洲午夜久久久久久尤物| 亚洲熟妇无码一区二区三区| 日韩毛片一区视频免费| 精品在线免费观看| 久久精品网站免费观看| 伊人久久亚洲综合影院| 久久夜色精品国产亚洲| 亚洲成AV人综合在线观看| 亚洲国产综合精品中文第一| 亚洲精品国产综合久久久久紧| 黄页网站在线视频免费| 久久免费视频观看|