同事問到,如何以 Ajax 的方式取得 UserControl 的內容。
問題
由於 UserControl 是無法單獨被客戶端所呼叫(Request),因此我們必須想個辦法將 UserControl 加到一個 Page內。
解決步驟
1 Web Service 回傳 UserControl 的內容
使用 Visual Studio (我使用 2010) 建立一個 Web Application,並加入一個 WebService。程式碼如下
[WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] [System.Web.Script.Services.ScriptService] public class WebService1 : System.Web.Services.WebService { [WebMethod(EnableSession = true)] public string GetUserControlHtml(string location) { var webServiceString = string.Format("Thread Id={0}, Time={1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now.ToString("HHmmss fffffff")); var page = new Page(); var userControl = (UserControl)page.LoadControl(location); userControl.EnableViewState = false; var form = new HtmlForm(); form.Controls.Add(userControl); page.Controls.Add(form); var writer = new StringWriter(); HttpContext.Current.Server.Execute(page, writer, false); return webServiceString + "<br /> " + RemoveFormTagFromHtml(writer.ToString()); } /// <summary> /// 移掉 Form Tag /// </summary> /// <param name="html"></param> /// <returns></returns> private static string RemoveFormTagFromHtml(string html) { return Regex.Replace(html, @"<[/]?(form)[^>]*?>", "", RegexOptions.IgnoreCase); } }
過程大略是:手動建立一個 Page,Page 內加入一個 Form,Form 動態載入指定的 UserControl。使用 Server.Execute 取得 html 內容後,將 <form tag 移除,避免避免原 asp.net 網頁失敗。
2 寫 UserControl
今天的配角是 UserControl。UserControl並不難實作。我簡單的寫了兩個 UserControl,分別 Thread.Sleep 了2秒,3秒。
3 於呼叫網頁使用 Ajax 方式呼叫 ASP.NET Web Service
我再入成兩種方式來呼叫。一個是 ASP.NET AJAX,一個則是 jQuery。3.1 使用 ASP.NET AJAX 呼叫 Web Service
加入一個 ScriptManager,並加入一個 ScriptReference 參考到剛剛建立的 WebService。利用動態產生的 javascript file (可使用 http://…/WebService1.asmx/jsdebug 取得內容)協助呼叫 ASP.NET Web Service3.2 使用jQuery 的 .ajax 呼叫 Web Service
使用jQuery 大概是近來 Web 技術的顯學吧。為了方便未來的 ASP.NET MVC的使用,還是乖乖的學一下吧。
<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication3._Default" %> <asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent"> <script src="Scripts/jquery-1.4.1.js" type="text/javascript"></script> <script type="text/javascript"> $(document).ready(function () { var datestring = getNow(); $("#div1").html("at client, " + datestring + "<br/>"); getData("WebUserControl1.ascx", $("#div1")); datestring = getNow(); $("#div2").html("at client, " + datestring + "<br/>"); getDataByJquery("WebUserControl2.ascx", $("#div2")); }); function getNow() { var today = new Date(); return today.format("HHmmss ffffff"); } function getData(controlLocation, container) { WebApplication3.WebService1.GetUserControlHtml(controlLocation, function (result) { $(container).append(result); }, function () { alert(error.get_message()); } ); } function getDataByJquery(controlLocation, container) { var datestring = getNow(); $.ajax({ type: "POST", contentType: "application/json; charset=utf-8", url: "WebService1.asmx/GetUserControlHtml", data: "{'location': '" + controlLocation + "'}", dataType: "json", success: function (result) { $(container).append(result.d); }, error: function (error) { alert(error.responseText); } }); } </script> </asp:Content> <asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent"> <asp:ScriptManager ID="ScriptManager1" runat="server"> <Services> <asp:ServiceReference Path="~/WebService1.asmx" /> </Services> </asp:ScriptManager> <h2> Welcome to ASP.NET! </h2> <div style="border: 2px solid red"> <h1> User Controll 1</h1> <div id="div1"> </div> </div> <div style="border: 2px solid red"> <h1> User Controll 2</h1> <div id="div2"> </div> </div> <div id="result"> </div> </asp:Content>
4 測試
測試時發現狀況還不錯。雖然同時發出 Request, 約2秒後得到UserControl1 的內容,但 UserControl2卻在約略在 5.5 秒後才得到內容,而非3秒。為什麼?
5 Session 造成 lock,因而 Delay
原來是步驟1中,[WebMethod(EnableSession = true)] 這個 true 所造成的。改成 EnableSessioin = false後,網頁測試結果如下
沒事最好還是不要用 Session。
範例下載
沒有留言:
張貼留言