Progress Indicator when using Ajax Service Methods

I have to say, that sometimes I really feel the infancy of the Ajax controls.  I love them, don't get me wrong, but some of this stuff seems like it should have been thought of.  Needless to say, recently I found myself needing to use Service Methods for a project, and on several occasions when data was being pumped in from my webservice to my proxy I was left thinking - what's it doing?  The solution of course was easy, since Service Methods run on a JavaScript backbone already there wasn't much work to do at all.  On to the code!

Initial Setup:

To get going, I've got a "website" in Visual Studios 2005, it could be an WAP, but for now a website will work just fine.  I've put a webservice into my site and named it cleverly "Webservice".  Inside webservice, I've left the HelloWorld function in place and declared a new function ReturnData() and wired it up with some example code.

 

<WebMethod()> _
Public Function ReturnData() As String
    'Used as an example.  Sleeping the thread would
    'never be used in production.
    System.Threading.Thread.Sleep(5000)
    Return "Freakyuno's Blog Rox!"
End Function

 

Nothing crazy here.  There's one last thing to do in our webservice.  It needs a special class attribute before we can call it with our JavaScript proxy method.

<System.Web.Script.Services.ScriptService()> _

 

That line will enable us to call this webservice through Script Manager Proxy call, from our .NET pages.  Cool right!  Calling managed code directly from JavaScript.  Ok - on with the example.

Next, we are going to setup our page to allow all this to happen.

I'm just using the default.aspx page in this example, but you wouldn't have to of course.  We need to rewrite our ScriptManager a little bit so that we have a reference to the Webservice method we'd like to call referenced.  Keep in mind this is a path to the webservice - this is not a call to the class yet.

<asp:ScriptManager ID="ScriptManager1" runat="server">
    <Services>
        <asp:ServiceReference Path="WebService.asmx" />
    </Services>
</asp:ScriptManager>

 

When we have that done, we can set up our page to receive our data.  Again, nothing special about this part.  I'm going to demonstrate this using a single Div for content, and a Div for our progress indicator (which I sagged from this site: http://www.napyfab.com/ajax-indicators/ ).  We'll get to that in a moment.

 

<div id="progress" style="display:none; width:0px; height:0px; text-align:center">
    <img src="progressbar_microsoft[1].gif" alt="Progress" />
</div>
<div id="showdata">
    Your Data is:<br />       
</div>

 

Nothing hard yet right? Ok, on to the JavaScript

When you call a webservice using this methodology, there is a special way to handle the events as they are returned from an Asynchronous JavaScript service call.  Namely 3 delegates that must be present in the call.  You can name them anything you want, but they must be present on the call.  OnComplete, OnTimeout, and OnError.  If you wish to pass Data to your webservice, you can preface your JavaScript call with a variable.  It wont hinder these methods.

We are going to make this happen in the JavaScript pageLoad event, but you could do this on a button, or control load, or anything that can call a JavaScript method.

<script type="text/javascript" language="javascript">
function pageLoad(){
ret = WebService.ReturnData(OnComplete,OnTimeout,OnError);
}
function OnTimeout(result){
alert("Timeout");
}
function OnError(result){
alert("Error")
}
function OnComplete(result){
    document.getElementById("showdata").innerHTML += result;
}
</script>
 
Great right?  You bet.  But if you're asking about our progress indicator, that is sitting there doing nothing, you'd be a keen observer.  We need to wire that puppy up!  You could render your page, and test this method as it sits if you'd like - it should work if you've followed the example correctly.
 
Make way for Progress!
 
The completed example, using the progress div to give the user visual indication that something is happening. 
 
<script type="text/javascript" language="javascript">
function pageLoad(){
    ret = WebService.ReturnData(OnComplete,OnTimeout,OnError);
    var newX = document.getElementById("showdata").style.left;
    var newY = document.getElementById("showdata").style.top;
    var newH = document.getElementById("showdata").style.height;
    var newW = document.getElementById("showdata").style.width;

    var progress = document.getElementById("progress");
    progress.style.display = "block";
    progress.style.position = "absolute";
    progress.style.width = newW;
    progress.style.height = newH;
    progress.style.left = newX;
    progress.style.top = newY + 30;

}
function OnTimeout(result){
    alert("Timeout");
    hideDiv();
}
function OnError(result){
    alert("Error")
    hideDiv();
}
function OnComplete(result){
    document.getElementById("showdata").innerHTML += result;
    hideDiv();
}
function hideDiv(){
    document.getElementById("progress").style.display = "none";
}
</script>

 

Happy coding!

Bryan Sampica ( Freakyuno )

No Comments