日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

现存问题以及解决方案:在ASP.NET AJAX中从客户端向服务器端传送DataTable

發布時間:2025/5/22 asp.net 57 豆豆
生活随笔 收集整理的這篇文章主要介紹了 现存问题以及解决方案:在ASP.NET AJAX中从客户端向服务器端传送DataTable 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

摘要

在《現存問題以及解決方案:在ASP.NET AJAX客戶端得到服務器端的DataTable》這篇文章中,我給出了一個在ASP.NET AJAX中從服務器端得到客戶端DataTable的方法,以及相應的示例程序。Jeffrey Zhao更加聰明地對此進行了改進,從根本上解決了從服務器到客戶端傳送DataTable的問題。

然而,這也僅僅解決了這個問題的一半而已。從客戶端向服務器端發送DataTable仍然無法實現,這部分的問題要比前一部分更加嚴重。本文就將分析其中的原因,并給出解決方案。

本文包括如下內容:

  • 異常重現——第一個異常:客戶端JSON序列化時發生循環引用造成堆棧溢出
  • 解決第一個異常——破壞循環引用
  • 異常重現——第二個異常:服務器端Deserialize()方法拋出異常
  • 解決第二個異?!唵螌崿FDeserialize()方法
  • 完成后的示例程序
  • 示例代碼下載
  • 參考文獻
  • ?

    異常重現——第一個異常:客戶端JSON序列化時發生循環引用造成堆棧溢出

    本文的將接著《現存問題以及解決方案:在ASP.NET AJAX客戶端得到服務器端的DataTable》這篇文章中的示例程序繼續開發。如果你還沒有閱讀過,那么請先至少熟悉其中的示例程序。在這篇文章中,我們已經能夠在客戶端得到一個DataTable,其中客戶端的回調函數如下:

    function cb_getDataTable(result) { result = parseBetaDataTable(result); var contentBuilder = new Sys.StringBuilder(); for (var i = 0; i < result.get_length(); ++i) { contentBuilder.append("<strong>Id</strong>: "); contentBuilder.append(result.getRow(i).getProperty("Id")); contentBuilder.append(" <strong>Name</strong>: "); contentBuilder.append(result.getRow(i).getProperty("Name")); contentBuilder.append("<br />"); } $get("result").innerHTML = contentBuilder.toString(); }

    其中result就是這個客戶端DataTable,讓我們在該函數外定義一個全局的DataTable,將這個DataTable先保留起來:

    var m_myDataTable = null;

    修改一下上述回調函數,將result保留在m_myDataTable中:

    function cb_getDataTable(result) { result = parseBetaDataTable(result); m_myDataTable = result; var contentBuilder = new Sys.StringBuilder(); //...... }

    然后在頁面中再添加一個按鈕:

    <input id="btnSendDataTable" type="button" value="Send DataTable" onclick="return btnSendDataTable_onclick()" />

    onclick中指定的事件處理函數定義如下:

    function btnSendDataTable_onclick() { PageMethods.SendDataTable(m_myDataTable, cb_sendDataTable); }

    可以看到,PageMethods.SendDataTable()即為服務器端名為SendDataTable()的Web Method的客戶端代理,我們就通過這個代理將前面保存起來的DataTable(m_myDataTable)發送回了服務器。服務器端SendDataTable()方法的定義如下,注意該方法必須為靜態(static),且被 [System.Web.Services.WebMethod]和 [Microsoft.Web.Script.Services.ScriptMethod]兩個屬性所修飾:

    [System.Web.Services.WebMethod] [Microsoft.Web.Script.Services.ScriptMethod] public static void SendDataTable(DataTable myDataTable) { // do anything you like. save it to database or xml file, etc. }

    示例程序中我們什么都沒做,具體應用中各位朋友可以隨心所欲地發揮。我們只要保證DataTable能夠發送過去就行了。

    返回到客戶端JavaScript部分,注意到在調用PageMethods.SendDataTable()時候我們為其指定了一個回調函數,名為cb_sendDataTable(),該JavaScript函數的定義如下:

    function cb_sendDataTable(result) { debugger; }

    沒什么講的,只要能夠順利執行到回調函數,也就是其中的debugger被hit,那么我們就算是成功了!

    這樣就完成了本示例程序,運行并點擊“Get DataTable”,將順利得到如下圖所示的界面。若出現了異常,請先參考《現存問題以及解決方案:在ASP.NET AJAX客戶端得到服務器端的DataTable》這篇文章進行修正。

    然后點擊“Send DataTable”按鈕,將這個DataTable發送回服務器…………………………………………在經歷過長時間的等待以及瀏覽器無響應之后,拋出了Out of stack space異常:

    上圖右上角的Call Stack中可以看到,同一個函數被調用了無數次——顯然發生了循環引用問題。

    讓我們在btnSendDataTable_onclick() 中加上一個斷點,看看這個客戶端DataTable到底是怎么回事。關于調試JavaScript,請參考我的這篇文章。

    在上圖中可以看到,Immediate Window中測試m_myDataTable._rows[0]._owner == m_myDataTable,返回為true。說明確實存在著循環引用:客戶端DataTable的每一個Row對象的_owner屬性都引用回了該DataTable自身,這也就造成了客戶端序列化時無止無休的進行,直至堆棧溢出。

    ?

    解決第一個異?!茐难h引用

    客戶端DataTable的Row對象的_owner屬性在傳回服務器時似乎沒什么用。所以解決這個循環引用問題最好的方式就是,在將客戶端DataTable傳回服務器之前,清空其每一個Row對象的_owner屬性。

    編寫一個輔助函數prepareSendingDataTable(),接受一個客戶端DataTable,返回一個破壞掉循環引用的DataTable:

    function prepareSendingDataTable(dataTable) { for (var i = 0; i < dataTable.get_length(); ++i) { dataTable._rows[i]._owner = null; } return dataTable; }

    然后修改一下btnSendDataTable_onclick() ,首先調用該輔助函數,然后再發送:

    function btnSendDataTable_onclick() { var myDataTable = prepareSendingDataTable(m_myDataTable); PageMethods.SendDataTable(myDataTable, cb_sendDataTable); }

    這樣以后,第一個異?!蛻舳薐SON序列化時發生循環引用造成堆棧溢出就被搞定了!

    ?

    異常重現——第二個異常:服務器端Deserialize()方法拋出異常

    別高興得太早了——再次運行示例程序,依次點擊“Get DataTable”和“Send?DataTable”兩個按鈕。又出現了如下錯誤:

    打開Fiddler,可以看到如下異常的詳細信息:

    仍舊是“System.NotSupportedException”異?!?/p>

    通過某些手段,我們可以知道ASP.NET AJAX中自帶的Microsoft.Web.Preview.Script.Serialization.Converters.DataTableConverter中根本沒有實現Deserialize()方法,該方法中僅僅是拋出了System.NotSupportedException異常而已……

    似乎覺得無語,是么?不過ASP.NET AJAX也有它自己的考慮,畢竟DataTable是一個非常復雜的對象。其中Row、Column、數據類型、更新、刪除等各種關系信息非常復雜。實現這個Deserialize()方法確實將是一個非常浩大的工程。

    ?

    解決第二個異?!唵螌崿FDeserialize()方法

    有了問題不能逃避。我這里就簡單地實現了一個DataTable的Deserialize()方法,其中忽略了太多太多的復雜東西。僅僅是創建出了最最最最最最最基本的一個DataTable而已,朋友們可以基于這個進行改進:

    using System; using System.Data; using System.Configuration; using System.Collections.Generic; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; namespace Dflying.Atlas { /// <summary> /// Simple implementation of DataTable Converter - Deserialize() method. /// </summary> public class DataTableConverter : Microsoft.Web.Preview.Script.Serialization.Converters.DataTableConverter { public override object Deserialize(IDictionary<string, object> dictionary, Type t, Microsoft.Web.Script.Serialization.JavaScriptSerializer serializer) { // there's no rows in the DataTable, return null object. Array rowDicts = (dictionary["_array"] as Array); if (rowDicts.Length == 0) { return null; } DataTable myDataTable = new DataTable(); // get column info foreach (string colKey in (rowDicts.GetValue(0) as IDictionary<string, object>).Keys) { myDataTable.Columns.Add(colKey); } // create and add rows to the DataTable foreach (object rowObj in rowDicts) { IDictionary<string, object> rowDict = rowObj as IDictionary<string, object>; DataRow newRow = myDataTable.NewRow(); foreach (DataColumn column in myDataTable.Columns) { newRow[column.ColumnName] = rowDict[column.ColumnName]; } myDataTable.Rows.Add(newRow); } // done! return myDataTable; } } }

    注釋非常詳細,這里不贅。若您不能完全理解,請參考Jeffrey Zhao的一系列非常精彩的深入文章。若您只想著使用的話,那么也無所謂理解了。

    將其放置于App_Code目錄下,并修改Web.config,使用我們自己的DataTableConverter:

    <jsonSerialization maxJsonLength="500000000"> <converters> <add name="DataTableConverter" type="Dflying.Atlas.DataTableConverter"/> </converters> </jsonSerialization>

    千辛萬苦之后,終于大功告成!

    ?

    完成后的示例程序

    在public static void SendDataTable(DataTable myDataTable)中加上個斷點,再次運行示例程序,依次點擊“Get DataTable”和“Send?DataTable”兩個按鈕。如我們所愿,服務器端得到了正確的DataTable:

    接下來,客戶端回調函數中的debugger也順利被hit。終于搞定……

    ?

    示例代碼下載

    本文的示例程序在此下載:ASPNETAJAXDataTable_Send.zip

    ?ASP.NET 2.0 AJAX Futures January CTP

    轉載于:https://www.cnblogs.com/Luoke365/archive/2007/10/08/917519.html

    總結

    以上是生活随笔為你收集整理的现存问题以及解决方案:在ASP.NET AJAX中从客户端向服务器端传送DataTable的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。