Slow web pages - updating some bits after the page has loaded
On one of my websites, I was finding that a particular database operation was taking a long time to execute. This in turn meant that the web pages were loading slowly as the user's browser was waiting for my server to return all of the data to display. Firstly, I created a new Ajax enabled website. I won't go into the details here, but this can be done through Visual Studio. Next, I created a web service (WebService.asmx) which returned the data string - this can be seen below. The really important line is the <System.Web.Script.Services.ScriptService()> entry, as this indicates it can be called from Ajax. Note I've added an artifical 2 second sleep in the HelloWorld web method, so you can see the delay when you run this. <%@ WebService Imports System.Web Imports System.Web.Services Imports System.Web.Services.Protocols <System.Web.Script.Services.ScriptService()> _ <WebService(Namespace:="http://blah.blah.com/")> _ <WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _ Public Class WebService <WebMethod()> _ System.Threading.Thread.Sleep(2000) End Function End Class A default page (default.aspx) was made, as shown below. Note there is a call to some JavaScript in the page header and some changes to the ScriptManager tag. This page will be run and shows the results of the webservice call. <%@ <!DOCTYPE html PUBLIC <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> </head> <body> </body> </html> You could include the JavaScript in the header programmatically if you don't want it in the header. In my website, it's done as below as the service only needs to be called for some of the pages. If (Not Page.ClientScript.IsClientScriptIncludeRegistered("jsfile")) Then Page.ClientScript.RegisterClientScriptInclude(Me.GetType(), "jsfile", ResolveClientUrl("~/jsfile.js")) End The ServiceReference indicates the location of the WebService (which happens to be in the root of the web site) Finally, the JavaScript file is used to call the webservice and write the output to the 'div1' tag: <!-- function pageLoad() { ret = WebService.HelloWorld(OnCompleteOne, OnError, OnTimeOut); } function OnCompleteOne(result) { document.getElementById("div1").innerHTML = result; } function OnTimeOut(result) { document.getElementById("div1").innerHTML = 'TimeOut!'; } function OnError(result) { document.getElementById("div1").innerHTML = 'Error!'; } // --> The JavaScript above includes functions for error and timeout situations, so I could return different information in these two instances. Believe it or not, that was it – I was very surprised it was so easy! I then started to adapt it to my situation, which included the slow database call in the web service.
Some of this data was not needed to be on the page straightaway, so I needed to investigate if I could make a JavaScript update to the page after it had loaded.
I'm not that into JavaScript, but I found this wasn't as hard as I feared. Long running service
Language="VB" Class="WebService" %>
Inherits System.Web.Services.WebService
Public Function HelloWorld() As String
Return "Hello World"Calling Page
Page Language="VB" AutoEventWireup="false"
%>
"-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<title>Untitled Page</title>
<script
language="javascript"
type="text/javascript"
src="JScript.js">
</script>
<form id="form1"
runat="server">
<asp:ScriptManager
ID="ScriptManager1"
runat="server">
<Services>
<asp:ServiceReference
Path="~/WebService.asmx"
/>
</Services>
</asp:ScriptManager>
<div id="div1">
</div>
</form>
IfJavaScript File
Last words