ScriptTagProxy+XTemplate+WCF跨域取數據
小編:管理員 216閱讀 2022.09.07
ajax應用中跨域一直是一個非常麻煩的問題,目前也有一些解決辦法,但要么比較麻煩,要么就不具備通用性,幸好ExtJs里的ScriptTagProxy提供了跨域讀取數據的功能,而且在幾大瀏覽器上都可以正常運行,但在使用過程中要注意幾點:
1.服務端返回時,必須按以下格式返回:
stcCallback1001({...})
其中stcCallback1001中的1001是自動生成的,如果是分頁提交的話,每再請求一次1001會變成1002,1003...類推
2.ExtJs官方的示例中雖然ScriptTagProxy的例子并不少,但是就是沒有XTemplate+ScriptTagProxy跨域讀取的單一功能示例,下面給一個XTemplate跨域讀取數據的示例
a.服務端WCF的處理
Code [OperationContract] [WebInvoke(ResponseFormat = WebMessageFormat.Json, UriTemplate = "GetData3?start={start}&limit={limit}&callback={callback}", Method = "*")] public Stream GetData3(int start, int limit,string CallBack) { System.Threading.Thread.Sleep(1000);//為演示Ajax加載效果,停1秒 List<T_GuestBook> _List = new List<T_GuestBook>(); _List.Add(new T_GuestBook() { F_ID = 1, F_IP = "192.23.37.41", F_Date = DateTime.Now, F_Content = "這是第一條留言", F_Reply = "" }); _List.Add(new T_GuestBook() { F_ID = 2, F_IP = "192.168.0.1", F_Date = DateTime.Now, F_Content = "這是第二條留言", F_Reply = "" }); _List.Add(new T_GuestBook() { F_ID = 3, F_IP = "192.168.0.2", F_Date = DateTime.Now, F_Content = "這是第三條留言", F_Reply = "" }); _List.Add(new T_GuestBook() { F_ID = 4, F_IP = "172.168.235.1", F_Date = DateTime.Now, F_Content = "這是第四條留言", F_Reply = "" }); _List.Add(new T_GuestBook() { F_ID = 5, F_IP = "10.200.30.4", F_Date = DateTime.Now, F_Content = "這是第五條留言", F_Reply = "" }); _List.Add(new T_GuestBook() { F_ID = 6, F_IP = "10.200.30.5", F_Date = DateTime.Now, F_Content = "這是第六條留言", F_Reply = "" }); //以上操作也可以改為利用Linq直接從數據庫讀取 PageData<List<T_GuestBook>> _PageData = new PageData<List<T_GuestBook>>(); _PageData.RecordCount = _List.Count; int PageSize = limit; if (PageSize <= 0) { PageSize = 1; } if (PageSize > _PageData.RecordCount) { PageSize = _PageData.RecordCount; } _PageData.PageSize = PageSize; //計算總頁數 if (_PageData.RecordCount % _PageData.PageSize == 0) { _PageData.PageCount = (_PageData.RecordCount / _PageData.PageSize); } else { _PageData.PageCount = (_PageData.RecordCount / _PageData.PageSize) + 1; } int PageIndex = (start/limit) + 1; if (PageIndex <= 0) { PageIndex = 1; } if (PageIndex > _PageData.PageCount) { PageIndex = _PageData.PageCount; } _PageData.CurrentPageIndex = PageIndex; List<T_GuestBook> _List2 = _List.Skip(start).Take(limit).ToList();//取得當前頁數據 _PageData.Data = _List2; string returnStr = CallBack + "(" + JavaScriptConvert.SerializeObject(_PageData) +")"; MemoryStream ms = new MemoryStream(); StreamWriter sw = new StreamWriter(ms); sw.AutoFlush = true; sw.Write(returnStr); ms.Position = 0; WebOperationContext.Current.OutgoingResponse.ContentType = "text/plain"; return ms; }復制
這里與上一篇http://www.cnblogs.com/yjmyzz/archive/2008/09/10/1288399.html (ExtJs學習筆記(22)-XTemplate + WCF 打造無刷新數據分頁)相比,多了一個參數callBack,同時返回類型改為Stream,返回方法的處理參考了老張的(再說ExtJs與WCF之間的跨域訪問)一文
b.ExtJs的前端處理
Code <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> <link type="text/css" rel="Stylesheet" href="../resources/css/ext-all.css" /> <script type="text/javascript" src="../adapter/ext/ext-base.js"></script> <script type="text/javascript" src="../ext-all-debug.js"></script> <style type="text/css"> *{font-size: 9pt;line-height: 120%;} .red{color: Red;} h1{font-size:16px;} </style> </head> <body> <script type="text/javascript"> Ext.onReady(function() { var proxy = new Ext.data.ScriptTagProxy({ url: 'http://ext.cneds.net/WCF/MyService.svc/GetData3' //服務端的返回值類似: //stcCallback1001({"RecordCount":6,"PageSize":2,"PageCount":3,"CurrentPageIndex":2,"Data":[{"F_ID":3,"F_IP":"192.168.0.2","F_Date":new Date(1221399073843),"F_Content":"這是第三條留言","F_Reply":""},{"F_ID":4,"F_IP":"172.168.235.1","F_Date":new Date(1221399073843),"F_Content":"這是第四條留言","F_Reply":""}]}) //其中stcCallback1001中的1001是自動生成的,如果是分頁提交的話,每再請求一次1001會變成1002,1003類推 }); var reader = new Ext.data.JsonReader( { root: 'Data', totalProperty: 'RecordCount' }, [ { name: 'F_ID' }, { name: 'F_IP' }, { name: 'F_Date' }, { name: 'F_Content' } ] ); var tpl = new Ext.XTemplate( '<table width="100%">', '<tpl for="data">', //表明這里開始循環 '<tr><td style="font-weight:bold;color:#666">網友[{F_IP}] {F_Date} 說:</td></tr>', '<tr><td> {F_Content}</td></tr>', '<tr><td><hr style="height:1px"/></td></tr>', '</tpl>', //循環結束 '</table>' ); var oGrid = Ext.get("page-grid"); //回調函數 function callback(data, arg, success) { if (success) { var _returnStr = Ext.util.JSON.encode(data); //{"success":true,"records":[{"id":1001,"data":{"F_ID":3,"F_IP":"192.168.0.2","F_Date":"2008-09-14T21:28:28","F_Content":"這是第三條留言"},"json":{"F_ID":3,"F_IP":"192.168.0.2","F_Date":"2008-09-14T21:28:28","F_Content":"這是第三條留言","F_Reply":""}},{"id":1002,"data":{"F_ID":4,"F_IP":"172.168.235.1","F_Date":"2008-09-14T21:28:28","F_Content":"這是第四條留言"},"json":{"F_ID":4,"F_IP":"172.168.235.1","F_Date":"2008-09-14T21:28:28","F_Content":"這是第四條留言","F_Reply":""}}],"totalRecords":6} //服務端將返回類似上面的字符串,無法直接跟xTemplate綁定,需要轉換一下 var oReg = /\"json\":({.*?})/gi; var oResult = _returnStr.match(oReg); var s = ""; for (var i = 0; i < oResult.length; i++) { oResult[i].match(oReg); s += RegExp.$1 + ","; } if (s.length != 0) { s = s.substr(0, s.length - 1); } s = "{data:[" + s + "]}"; //最終將轉換成 //{data:[{"F_ID":3,"F_IP":"192.168.0.2","F_Date":"2008-09-14T21:29:55","F_Content":"這是第三條留言","F_Reply":""},{"F_ID":4,"F_IP":"172.168.235.1","F_Date":"2008-09-14T21:29:55","F_Content":"這是第四條留言","F_Reply":""}]} var data = eval("(" + s + ")"); tpl.overwrite("page-grid", data); } } oGrid.dom.innerHTML = "加載中"; proxy.load({ start: 2, limit: 2 }, reader, callback, this); }); </script> <div id="page-grid"></div> </body> </html>復制
這里要注意的是:
嘗試了多次,發現XTemplate不支持多層節點的綁定,即服務端返回的值類似:
stcCallback1001({"RecordCount":6,"PageSize":2,"PageCount":3,"CurrentPageIndex":2,"Data":[{"F_ID":3,"F_IP":"192.168.0.2","F_Date":new Date(1221399073843),"F_Content":"這是第三條留言","F_Reply":""},{"F_ID":4,"F_IP":"172.168.235.1","F_Date":new Date(1221399073843),"F_Content":"這是第四條留言","F_Reply":""}]})
在回調函數里經過Ext.util.JSON.encode(data)處理后,變成了
{"success":true,"records":[{"id":1001,"data":{"F_ID":3,"F_IP":"192.168.0.2","F_Date":"2008-09-14T21:28:28","F_Content":"這是第三條留言"},"json":
{"F_ID":3,"F_IP":"192.168.0.2","F_Date":"2008-09-14T21:28:28","F_Content":"這是第三條留言","F_Reply":""}},{"id":1002,"data":{"F_ID":4,"F_IP":"172.168.235.1","F_Date":"2008
-09-14T21:28:28","F_Content":"這是第四條留言"},"json":{"F_ID":4,"F_IP":"172.168.235.1","F_Date":"2008-09-14T21:28:28","F_Content":"這是第四條留
言","F_Reply":""}}],"totalRecords":6}
雖然也是標準的JSON字符串,但是數據節點是多層次的,XTemplate無法直接讀取。所以只能在客戶端用JS的正則表達式處理,手動重新組織成XTemplate所需的JSON對象,最終轉換成:
{data:[{"F_ID":3,"F_IP":"192.168.0.2","F_Date":"2008-09-14T21:29:55","F_Content":"這是第三條留言","F_Reply":""},{"F_ID":4,"F_IP":"172.168.235.1","F_Date":"2008-09-14T21:29:55","F_Content":"這是第四條留言","F_Reply":""}]}
相關推薦
- ExtJs七(ExtJs Mvc創建ViewPort) 前言在4.1的時候,要先創建一個擴展于Ext.app.Application的類,然后用create創建它的實例來開始應用程序的。而在4.1.1,則可直接調用application方法開始執行應用程序,簡化了。調用application方法,其參數是一個配置對象,主要配置項有以下三個:name:用來…
- Hibernate Criterion 在查詢方法設計上能夠靈活的依據Criteria的特點來方便地進行查詢條件的組裝.Hibernate設計了CriteriaSpecification作為Criteria的父接口,以下提供了Criteria和DetachedCriteria.Criteria和DetachedCriteria的主要差別在于創建的形式不一樣,Criteria是在線的,所…