【茶包射手日記】ReportViewer 陷入無窮迴圈
0 |
最近溫習到 ReportViewer,參考網路教學寫 WebForm 顯示 RDLC 報表當伸展操。
【延伸閱讀】
- ReportViewer! RDLC!
- 使用 Visual Studio 2017 開發 RDLC 報表
- Set ReportPath of Local SSRS Report from Code Behind in ASP.Net
- 同場加映:如果要在 MVC 中整合 ReportViewer,有個套件 ReportViewerForMVC 可以省點事(但骨子裡還是靠 WebForm + ReportViewer Web Control 實現),參考:MVC 使用 rdlc 報表 by 尼克人生
先寫了一個雛型,將整個資料表丟到報表顯示,運作正常:
public partial class RptViewerLoop : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
SetReportViewer();
}
private void SetReportViewer()
{
ReportViewer1.ProcessingMode = ProcessingMode.Local;
ReportViewer1.LocalReport.ReportPath =
Server.MapPath("~/Reports/PlayerReport.rdlc");
ReportDataSource ds = DataService.QueryData();
ReportViewer1.LocalReport.DataSources.Clear();
ReportViewer1.LocalReport.DataSources.Add(ds);
//傳入參數在報表顯示查詢範圍
ReportViewer1.LocalReport.SetParameters(new ReportParameter("Range", "All Data"));
}
}
接著我加入查詢條件,在網頁新增欄位 <input type="text" name="rangeSt" >、<input type="text" name="rangeEd" > ,按 <button type="submit"> PostBack 傳回 rangeSt 跟 rangeEd 限定報表查詢區間。另一方面,我希望也能用 QueryString ?rangeSt=...&rangeEd=... 輸入參數,做到 GET/POST 兩吃。於是我移除 Page_Load() 的 if (!IsPostBack) 判斷,並由 Request["rangeSt"]、Request["rangeEd"] 接入 QueryString 或 POST 送回參數當成查詢條件:
(資安提醒:若參數與安全有關,宜寫成 Request.QueryString[paramName] 及 Request.Form[paramName] 明確指定來源,以免被惡意偷渡參數)
protected void Page_Load(object sender, EventArgs e)
{
SetReportViewer(Request["rangeSt"], Request["rangeEd"]);
}
private void SetReportViewer(string rangeSt, string ragneEd)
{
ReportViewer1.ProcessingMode = ProcessingMode.Local;
ReportViewer1.LocalReport.ReportPath =
Server.MapPath("~/Reports/PlayerReport.rdlc");
ReportDataSource ds = DataService.QueryData(rangeSt, rangeEd);
ReportViewer1.LocalReport.DataSources.Clear();
ReportViewer1.LocalReport.DataSources.Add(ds);
ReportViewer1.LocalReport.SetParameters(new ReportParameter("Range", rangeSt + "~" + rangeEd));
}
結果悲劇了!
如上圖所示,網頁陷入無窮迴圈,停留在 Loading... 幾秒後閃一下。又出現 Loading...,下方則觀察到每隔兩秒多瀏覽器會使用 XHR 呼叫自己(RptViewerLoop.aspx)一次,周而復始。
爬文發現這是個經典問題,在微軟部落格 Reports Never Stop Loading With VS 2010 有詳細解釋 - ReportViewer 2010 起不使用 IFrame,改用 AsyncRendering/UpdatePanel 產生報表內容,意思是第一次 GET 傳回的 HTML 包含 Script 觸發 AJAX 呼叫自己取得報表內容,由於我拿掉 if (!IsPostBack),故 AJAX 呼叫時也會執行 SetReportViewer(),因為我在其中呼叫了 SetParameters(),會觸發傳回指令要求瀏覽器重新產生報表,於是一切從頭,陷入無窮迴圈。
微軟部落格建議的解法是只有在 GET 時才設定 SetParameters(),我們最早加入的 if (!IsPostBack) 即有此效果,但我的情境需要在 Form POST 時也做查詢,想到兩種解法:
- 另外宣告一個 <input name="mode" type="hidden" value="form-post" > 額外參數,用 if (!IsPostBack || Request.Form["mode"] == "form-post") 判斷 GET 及 Form POST。
- ReportViewer 透過 ScriptManager 發出 AJAX 呼叫,故可偵測 ScriptManager.IsInAsyncPostBack 避開來自 ReportViewer XHR 的呼叫。
最後,我新增一行判斷,搞定收工。
protected void Page_Load(object sender, EventArgs e)
{
if (ScriptManager1.IsInAsyncPostBack) return;
SetReportViewer(Request["rangeSt"], Request["rangeEd"]);
}
Case of infinite loop of Report Viewer during loading and how to avoid it.
Comments
Be the first to post a comment