Contents

How many times have you been on a web page and you selected a value in a drop down box, only to suddenly see the whole page refresh so that it can fetch values for another drop down box? I see it all the time in car web sites. You select the Make of the car and the whole page is reloaded to bring back all the corresponding Models. Then you select the Model and the whole page is reloaded again to bring back all the corresponding Trims. Annoying, isn't it?

Some sites avoid this problem by preloading all the possible alternatives in memory. This works, but there are times when the amount of data is just too overwhelming for all the possible combinations.

Remote Scripting offers a better alternative. Instead of the whole page refreshing, a hidden request is made to the server to execute a method which returns back just the data that needs to be changed on the page. The result is a smoother user experience. Indeed, Remote Scripting brings some of the benefits of a traditional fat-client application to a web application. It can be used to refresh individual controls, to validate controls, or even to process a form without having to post the whole page to the server. It's cool stuff and it works on all major browsers!

Over the years, I've seen two popular remote scripting implementations. Back in the days of Visual InterDev 6.0, Microsoft provided client and server-side include files inside its _ScriptLibrary directory. I used it in a few projects and it worked quite well. The only problem I found was that it used a Java applet to handle the communications, so it tended to be sluggish at times. Then I started doing JSP and I found a better alternative called JSRS. Depending on the browser, it created a hidden element on the page that submitted the request to the server which then responded back to it. It was more efficient, but it only allowed the remote calls to be asynchronous.

Now with ASP.NET, I've once again needed to use Remote Scripting. I initially wrote a small class library in C# that provided support for both Microsoft's and JSRS's clients. But then I decided to see if I could come up with a better client implementation, and I believe I did. I came up with a hybrid solution based on both of the existing implementations, which I believe looks and works better. This article presents my Remote Scripting client and server side implementation for ASP.NET. Enjoy!

The downloadables include a file called rsDemo.aspx which has a fully working example of this code. It also demonstrates how to populate the drop downs using data from an XML file (rsDemo.xml). The link below goes to the demo page. When you change the Type, the Amount is repopulated using Remote Scripting.

I've strived to make my Remote Scripting implementation as simple and easy to use as possible. There are just a few simple steps to take on the client and server side to get it working. Be sure to look at the rsDemo.aspx file to get the complete picture.

Client-side

Include rs.js in your .aspx page, like this:

<scriptlanguage="'JavaScript'"src='/scripts/rs.js'></script>

Use RS.Execute to invoke the remote method using JavaScript, like this:

The page.aspx file is where the RemoteMethod will be executed. The RemoteMethod's parameters are optional, so don't pass anything if they're not needed. The callback function (which is not a string parameter) is also optional and if passed will be called when the server's response is received. Its first parameter will be the value returned by the RemoteMethod, converted to a string. If there's a chance for error, you can also pass a second callback method that will receive the error description. If it's not passed, an alert box will be shown in case of error. If you pass optionalCallbackParam2, optionalCallbackParam3, or optionalCallbackParam4, they will also be passed to the callbacks. Keep in mind that RS.Execute is asynchronous, so the callbacks are the only way to know when and what was returned from the server.

If you care about the RemoteMethod's result, add a callback method to get it, and optionally do the same for error messages:

Server-side

This accomplishes several things. First, it checks if the client is making a remote request on the page. If not, this method returns false (and Page_Load proceeds). If there is a client request, the remote method is invoked, its return value is written to the response, and it is then sent back to the client immediately.

If your page does not have a Page_Load method (and you don't want to add one), you can just place those two lines at the top of your page inside <% %> tags.

Add the remote method as a public instance or static member of your Page class:

If you just need to read a field's value, you can use a property instead of a method:

publicstringRemoteProperty
{
get { return m_someField; };
}

The return type does not need to be a string but it will be converted to a string before going back to the client. The parameters must all be of type string, and the method (or property) must be public or you'll receive a System.MissingMethodException error.

As an alternative to remotely executing a public method or property of the Page, you may also directly execute a public method or property of a control on the page. For example, if you want to retrieve the Text property of a TextBox control called "txtAmount", you can pass "txtAmount.Text" as the name of the remote method in RS.Execute.

RS.ReplaceOptions2 takes the same parameters as RS.ReplaceOptions but in the opposite order so that it can be used as a callback. This allows you to do everything in one call!

The RS object also has a member called debug that you can set to true (RS.debug = true;) to show the hidden elements used for communicating with the server.

On the server side, you'll see that the RemoteScripting class is designed to handle any of three possible clients: Mine (RS), JSRS, and Microsoft's (MSRS). The type of client is determined based on the parameters passed into the request. If you have your own client implementation, my architecture makes it easy to add an implementation for it by deriving from the RemoteScriptingClient class.

Microsoft is the only remote client implementation that supports synchronous calls to the server, so if you absolutely need that, you can use it. All you need on the client is the rs.htm and RSProxy.class files from the _ScriptLibrary directory. I personally don't recommend it since it ties up the browser until the response is sent back and it requires the browser to support Java. Nevertheless, I added support for it inside the RemoteScriptingClient class.

Something else to point out: for drop downs that are populated and repopulated based on remote scripting calls, I recommend you remove them from the ViewState (EnableViewState=false), since you'll need to populate them on every trip back to the server. In other words, regardless of whether IsPostBack is true or not, you'll need to populate these drop downs, so it will be a waste to save them to the ViewState.

History

Version 1.0 - Mar 12, 2004.

Initial release.

Version 2.0 - Sept 3, 2004.

Enhanced RS.Execute to allow passing of up to three additional parameters to the callbacks (aside from the result of the remote method).

Enhanced RemoteScriptingClient.InvokeMethod to allow execution of a method or property of a control of the page. Thanks to Jonathan Marbutt for the idea and his implementation.

Fixed bug that didn't allow remote scripting to work with the Opera browser. Thanks to Christoph Weber for reporting it.

Fixed bug that prevented remote scripting from working in SSL sites. Thanks to Peter for reporting it and providing the solution.

Fixed bug that was filling the call pool when remote methods were executed over 100 times. Thanks to emadns and Anonymous for reporting it.

Fixed bug that was taking the result string and replacing any slashes (/) with \/.

Version 2.1 - Feb 7, 2005.

Fixed small problem in RemoteScriptingCall.setResult of rs.js when simultaneous calls were made to RS.Execute. Thanks to Eddy A for reporting it and providing the solution.

Updated the rsDemo.aspx page to demonstrate how to make it work with a Submit button.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

Share

About the Author

I've done extensive work with C++, MFC, COM, and ATL on the Windows side. On the Web side, I've worked with VB, ASP, JavaScript, and COM+. I've also been involved with server-side Java, which includes JSP, Servlets, and EJB, and more recently with ASP.NET/C#.

Comments and Discussions

Please clarify license :-
RemoteScripting.cs : "This file and the accompanying source code may not be hosted on a website or bulletin board without the author written permission."
rs.js : no license mentioned.

Hi, All,
I have seperated the reDemo.aspx to two files.
in reDemo.aspx:
RS.Execute("reDemoServer.aspx","UpdateAmounts", .............."

Inside reDemoServer.aspx file, declare the function UpdateAmounts(), I change the server side code from C# to VB.Net, everything works fine.

But if I include a file that create DB connection, when I return the connection string, it's empty.

Can anybody tell me what's wrong.

The codes in reDemoServer.aspx are as the following:

<![CDATA[<%@ Page Language="VB" %>]]>

<!-- #INCLUDE FILE="../../include/dbConnection.aspx" -->

Private Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
If AMS.Web.RemoteScripting.InvokeMethod(Page) Then
Return
End If
End Sub

Public Function UpdateAmounts(ByVal argu1 as string) As String
Return "Return String From Remote Scripting." 'Works fine
'Return myConn 'myConn is defined in above include file, it's a
'string , but when I return it, it's an empty.
End Function

Hi Alvaro,
I'm using your code in an ASP.net 2.0 application and it is really useful.
Recently I have following problem:
When I'm calling a server-side method from my javascript and pass a string as parameter which contains an "umlaut" like the word "eisbär", during the transfer it transforms to "eisbr". In the server-side method which is called only the wrong parameter arrives.
Is there a possibility to change the charset or text encoding (I'm not sure) so that I can use UTF-8 characters?

Hi Timothy,
On first sight I would say don't use quotes in this place:
instead of
RS.Execute('Default.aspx', 'Method1', 'value1', 'Method1CallBack');
use
RS.Execute('Default.aspx', 'Method1', value1, Method1CallBack);

You look like the one who gave the direction to Microsoft on how to make Callback in their 2005 .NET version.
I am a beginner programmer, and I want to know if I can use your code for one of my projects at work.

I recently (today) came across this article and thought that is exactly what I need to do as part of my Msc project.

So I downloaded you code, it worked fine.

I then created my own page, like yours, but I dont want a callback to the client, I simply want to call a server side method, and thats it. Which seems to be ok, with what you have implemented, as you state that the callback is optional.

OK, so what I need to do is, call the method from the client, then in the method at server side, I want to change some properties of another (more in the real project) of another server side web control, you know with the runat="server" attribute. The samll page I am trying it on has a TextBox, and I am trying to change the Text property in the remote method call, Like shown below

So thats what I am tring to do, but am totally not getting, if what you have done, even allows for this. It should, shouldnt it, or have I got it completely wrong.

I am new to the whole Ajax style of thing, I get the concept, I know this is not Ajax, but to me it is exactly what I wanted, An Ajax type of arrangement, where I could call a server method, without a callback, this is what I want to do.

PLEASE PLEASE PLEASE could you have a look at this simply example I am doing, and see what I am doing wrong.

I would be happy to email source if you like, my email, is sachabarber@hotmail.com

If you haven't already, I recommend you use an Ajax implementation, like Anthem.NET which will do what you want. However, to answer your particular question, you really didn't need Remote Scripting to change a textbox on the form. You could have done it with some simple Javascript on the client:

I have taken the RS source code and packed it into another assembly. I have also combined the client-side javascript into this assembly.

When the if(AMS.Web.RemoteScripting.InvokeMethod(Page))return; is called it writes the clientside javascript nicely into the head of the calling document. (this is so you do not have to worry about where the client side script resides etc.)

I have also written a new function / method that is a one-stop-shop remote scripting call: (see below). It allows you to define all the information and class in one easy-to-use function:

Well, not sure how to convey so many thanks for your library. Maybe a big THANKS... but well, still not big enough. I'd even bring some flowers but hmmm maybe better not . Anyway, thanks for such a great library; and your writing style is excellent.

You reported on an earlier comment[^] that you preferred not to use POST since there were some reports that the IE progress bar was unreliable. I ran into the same, and after making sure I was using GET and still experiencing the same issue (more or less randomly), I digged a little longer and deeper.

I found a report from MS which put me on the right track, as it explains that when a behavior is dynamically attached to a page, the progress bar, well, basically just loses it. I traced the execution and found that if I insert a "windows.status='Done';" at the end of the setResult call (just below this.busy=false;), the problem would be gone, and the progress bar come back to its senses; for the time being, at least.

Note that if you use "window.status='';" ", as I wanted to, the problem remains; you have to use an actual string... sucks for other language browsers, but well, what the heck.