ajaxed: Calling server side VBScript procedures from client side (equivalent to PHP xajax)

By | July 2

My last post (about an ASP RSS component) included a demonstration which made use of a cool ajax technique simply called “ajaxed”. See the demonstration here again. If you play around you will recognize that there is no conventional postback and AJAX is up in here ;) I have developed a small “library” which easily allows you to call server side ASP VBScrtipt procedures from the client side. No low-level Ajax knowledge is required…
Summarized it can be said that I have developed a bit similar thing for ASP like there is already for PHP (xajax - ). It is not the same as xajax but it also allows you to call server side procedures from client side. We are all tired of the conventional postbacks which refresh the whole page, thats why we want ajax. I was tired of hacking all the lowlevel stuff for ajax and thought of a way to call the ASP procedures directly. With this and some stuff of my existing gabLibrary I have built a small library called “ajaxed”. ajaxed just because it makes my pages ajaxed. Here is a very simple example which sums up two numbers (Try the demo here):

  1. <!--#include virtual="/ajaxed/ajaxed.asp"-->
  2. <%
  3. set page = new AjaxedPage
  4. page.draw()
  5.  
  6. sub init() : end sub
  7.  
  8. sub callback(action)
  9.     if action = "add" then page.return(add(page.RF("a"), page.RF("b")))
  10. end sub
  11.  
  12. function add(a, b)
  13.     if not isnumeric(a) then a = 0
  14.     if not isnumeric(b) then b = 0
  15.     add = cint(a) + cint(b)
  16. end function
  17.  
  18. sub main() %>
  19.  
  20.     <script>
  21.         function added(sum) {
  22.             $('c').value = sum;
  23.         }
  24.     </script>
  25.  
  26.     <form id="frm">
  27.         <input type="Text" name="a" id="a">+
  28.         <input type="Text" name="b" id="b">=
  29.         <input type="Text" name="c" id="c">
  30.         <button onclick="ajaxed.callback('add', added)" type="button">calculate</button>
  31.     </form>
  32.  
  33. <% end sub %>

At first sight you can see that the calculation is done on server side (“add” function) and there is no classical XHR and not much JavaScript. The calculation is invoked through the button and therefore the button includes a JavaScript call which defines the “gateway” to the server side. Before I explain how the execution works, it is necessary to look at the page structure. The structure of an ajaxed page (as shown in the example) is the following:

  1. Loading ajaxed.asp (include)
  2. Create an instance of the AjaxedPage class and execute draw()
  3. Provide 3 methods:
    1. init(): executed on every request (before main() or callback())
    2. main(): executed when the page is ordinary called by a user
    3. callback(): executed when the page calls itself again and requests a server side method (action)

The execution flow results as followed:

  1. init()
  2. main() or callback()

The whole trick here is that the page is able to make a request to itself. It has two states. One for the ordinary request of the user - which normally displays the user interface with (X)HTML. The other state is when the page requests itself again - which results in a JSON response. Ok lets forget the underlying technical details now…

The entry point in the example is the draw() method which draws the page and cares about everything for you. As already mentioned you need to provide the procedures init(), main() and a callback(action) in your page. Whereas init() is executed on every request the main() and callback() are never executed togehter. All the presentation should be put in the main() - you see the form in the example is in the main(). All security checks, preperations, initializations, etc should be put into the init() which is always executed before the main() and callback(action). When is the callback called? It is called if the ajaxed.callback JavaScript function is executed - which in this case is in the onclick event of the button. The ajaxed.callback requires an action (which is used as input for the server side callback function) and a JavaScript callback function which will be called after the server side process has been finished. This callback function (added) gets then the return of the server side function call. In this case with page.return(). The nice thing is that the page handles all conversions from the VBScript datatypes into the JavaScript equivalents (see Generate JSON from ASP datatypes if you are interested in the details). The page posts all form variables by default to the callback which means that the form fields are accessible via request.form within the callback. The AjaxedPage class offers several convenient utility methods to access the request collection. If you dont want to post the whole form or use your own parameters for the callback, you can use the third parameter of the ajaxed.callback function (with JSON). E.g.

javascript
< view plain text >
  1. ajaxed.callback('serversideAction', jsCallback, {param1:1, param2:'michal'});

With this technique its now possible to call all your server side procedures and then change the DOM according to the return value(s) from the server side. There is no need to care about any XHR or e.g. loading indication. Everything is handled. Another example?

Populating dropdown from the database

Lets assume we have a table called “table” which holds two columns named “id” and “name”. We want to fill a dropdown with those values. id as the value and name as the displayed text. I have created a form which holds dropdown and a button. The button invokes the database call on server side. The callback then returns an ADODB.recordset which is automatically converted into an equivalent JavaScript data structure. The “got” JavaScript function can directly access the recordsets data. (Note: the “getRecordset” function does not exist and is just for demonstration)

  1. <!--#include virtual="/ajaxed/ajaxed.asp"-->
  2. <%
  3. set page = new AjaxedPage
  4. page.draw()
  5.  
  6. sub init() : end sub
  7.  
  8. sub callback(action)
  9.     if action = "get" then page.return(getRecordset("SELECT * FROM table"))
  10. end sub
  11.  
  12. sub main() %>
  13.  
  14.     <script>
  15.         function got(recs) {
  16.             for (i = 0; i < recs.length; i++) {
  17.                 var o = new Option(recs[i].name, recs[i].id, false, false)
  18.                 $('dd').options[$('dd').options.length] = o;
  19.             }
  20.         }
  21.     </script>
  22.  
  23.     <form id="frm">
  24.         <select id="dd"></select>
  25.         <button onclick="ajaxed.callback('get', got)" type="button">load</button>
  26.     </form>
  27.  
  28. <% end sub %>

Returning more values with returnValue()

The following example demonstrates that it is also possible to return more values on the callback. returnValue() allows to return more values by specifying each value with a name. return() in comparision can only return one value.

Run the example

(It expects some value in the textbox. if no value is given then a “valid” flag is set to false and returned from server side. If some input is provided then an array additionally to the valid flag is returned. This example make not much sense but demonstrates the usage of more return values)

  1. <!--#include virtual="/ajaxed/ajaxed.asp"-->
  2. <%
  3. set page = new AjaxedPage
  4. page.draw()
  5.  
  6. sub init() : end sub
  7.  
  8. sub callback(action)
  9.     if action = "do" then
  10.         page.returnValue "valid", page.RFHas("code")
  11.         if page.RFHas("code") then
  12.             page.returnValue "even", array(2, 4, 6, 8)
  13.         end if
  14.     end if
  15. end sub
  16.  
  17. sub main() %>
  18.  
  19.     <script>
  20.         function done(r) {
  21.             if (r.valid) {
  22.                 for (i = 0; i < r.even.length; i++) {
  23.                     $('vals').innerHTML += r.even[i] + "<br />";
  24.                 }
  25.             } else {
  26.                 alert("type in something!")
  27.             }
  28.         }
  29.     </script>
  30.  
  31.     <form id="frm">
  32.         <div id="vals"></div>
  33.         <input type="Text" name="code" value=""> (type in something)
  34.         <button onclick="ajaxed.callback('do', done)" type="button">load</button>
  35.     </form>
  36.  
  37. <% end sub %>

The concept makes use of Prototype JavaScript Library and the JSON utility class.
The ajaxed library includes those and therefore they can be used when working with ajaxed e.g. all features of Prototype. Furthermore it offers other convenient built-in features to ease the work with ASP pages (e.g. RFHas() method in the example above - it checks if agiven field from the request.form collection exists). Some other features of the Ajaxed page …

  • AjaxedPage.isPostback() - equivalent to postback
  • AjaxedPage.throwError() - generates an ASP user error
  • AjaxedPage.RFT() - gets a field from the request collection already trimmed
  • AjaxedPage.RFE() - gets a field from the request collection HTMLEncoded
  • AjaxedPage.loadJSFile() - ensures that JavaScript file is loaded only once
  • AjaxedPage.iif() - an VBScript inline if
  • AjaxedPage.getLocation() - gets the location of the page in several formats

Download ajaxed 0.1
ajaxed 0.1 class reference

Installation

Download the zip archive and copy the whole “ajaxed” folder into your web root. Access the demo at and check if everything works fine. There is a config.asp which provides some configurations.

Tell me what you think about it. I will come up with some more sophisticated examples in the future. cheeers…

49 comments on “ajaxed: Calling server side VBScript procedures from client side (equivalent to PHP xajax)

  1. holy….! :-o

    this library is amazing!
    what can i say the sky is the limit now, so nice that I can make my asp apps ajaxed!

    thank you very much Michal!!!

  2. glad to hear that you like it. it brings new flair into working with classic ASP ;) spread the word and i happy about feedback … new tutorial coming soon..

  3. hi Michal,
    is there a way to contact you personaly via email?
    it’s not for annoying questions…
    - Uri

  4. Wonderfull framework. This is going to speed up ajax integration in asp apps.

    Great Job Michal! Keep up the good work

  5. Merci d’avoir pensé en ASP
    Super

  6. is this good for server-side javascript too?
    (sorry for not having the time to dwell into the details)

    thanks.

  7. Eyal what do mean by server side JavaScript.. i never heard about that ;)

  8. now seriously michael :),
    can i use your lib when writing javascript code on the server side instead of vbscript?

    thanks for the prompt reply btw.

  9. ah you mean JScript ;) I dont think that this is possible. I never accessed VBScript code from JScript within one page and so i am not sure if this is possible. I have set up a small example now but it didnt work. So i guess you cannot really use it with JScript.
    Maybe if there are some ASP JScript Pro’s around, they could help.

  10. thanks again for the quick reply and your time anyhow :)

  11. this is what i’ve been searching for, thanks michal i love this one

  12. Hi,

    Looks like u r inspired from callback mechanism,
    But avoided view state and page reconstruction at server side.

    Good, leaving aside heavy features of and using the valuable features of .

    BUT..
    Yes this BUT is very much important,
    Your scripts are vulnerable, can be easily exploited.

    If you could proceed further and do something on security front so that you could validate the client side requests, then it would be really nice,
    See to criticize u is not my motto, i find something can be improved, and i just pointed it out..!! that’s it.

    Otherwise, your code and library is conceptually very good..!!

  13. @Tanmay: thanks very much for your feedback. i am really interested in the vulnerability. could you explain it more detailed. I am not sure what you mean.
    If you mean that it is possible to call the callback state of the page directly. That is true but thats not a vulnerability because you should validate on server side what output you want to return and what not.
    Thanks for your participation…

  14. Pingback: OmgSaveMe » Blog Archive » Ajaxed: Ajax for classic ASP

  15. Eyal,
    It is (as far as I know) impossible to use a VBScript class inside of Jscript for two reasons. 1. JScript can not directly create a VBScript object, though it can call a VBScript function which could return an object. Calling a function does not work either, however, because of the order that the languages are processed. Try this:

    Response.write(“This is JScript”)

    When you see the output, the order is reversed. This is because all JScript is run first (not 100% true but that’s the simplified explanation) and the output sent to the browser before any VBScript is executed.

    I believe the reason that function definitions are available and class definitions are not has something to do with the Object Dispatch mechanism inside ASP, but I’m not enough of a fan of Microsoft to get into that mess too deeply. ;-)

  16. Pingback: Flxi.Org » Site Arşivi » Ajaxed: ASP İçin AJAX Kütüphanesi

  17. Hi Michal,

    Thanks for this framework. Like some of the others here, I think it’s great to finally have an easy to use Ajax framework for classic ASP ;)

    I’m sure we’ll all move over to .net some day soon but until we do this should provide a nice addition to our app’s. Thanks!

    Rich

  18. no, we won’t move :)

  19. Hi! This looks like a very nice addition to classic asp.
    I’ve placed it on a few pages, and notice that page.RF or Request.Form variables sometimes remain empty on a callback. I haven’t figured out what exactly drives this behaviour, but on some pages the elements are empty.
    At first I thought it may be the formid, and then noticed that the constant AJAXED_FORMID is not used anywhere.
    Could it be a matter of setting this?

  20. the AJAXED_FORMID is only used within the javascript … can you show me your code which is not working properly. thx

  21. I’ve noticed that some malformed html will cause trouble. The form I was submitting was not within a proper table structure (it had some extra trs and tds from previous code) and was thus causing trouble. Now all works well and I’m impressed and will impress others!
    thanks for the great addition!

  22. I am unable to get even the demo page to work on my server… Not sure what is going wrong because i can see the demo works fine here.. I wonder if its the version of IIS i’m running or something.

  23. HI Michal,

    I have not used it yet.. But it sounds good.

    And thanks for this good stuff. Can we do the same dropdown thing like Google autofill dropdown list?

  24. @adam: can you tell me what error you get .. or describe what happens

  25. Adam: you probably didn’t set the config.asp file right…

    lets say your virtual directory looks like this:

    you should have in your config.asp:

    const AJAXED_LOCATION = “/SH/ajaxed/”

  26. Great tool! exactly what I’m looking for. I’m having one problem though. I’m calling from within a longer validation script, and I need it to return true or false to the script that is calling it. Like this

    function validatePurchPage2(){
    if (document.forms.application.propertyStateCode.value == “”) {
    alert(“Please enter the Property State.”);
    document.forms.application.propertyStateCode.focus();
    return false;
    }
    if (document.forms.application.searchZip.value.length

  27. alert(“Please enter a full zip code”);
    document.forms.application.searchZip.focus();
    return false;
    }

    ajaxed.callback(‘CheckStateZip’, statezip, null, null, ‘ratequote2.asp’);
    return true;
    }

    I use the checkstatezip to access the database and do a check on whether the state matches the zip code. Then statezip returns the prompt to enter a valid prompt or not, and returns true or false. Problem is, that true or false is not bubbling up to validatePurchPage2. What am I doing wrong?

  28. I can’t get it to work on w2k3

    when accessed the test page, it printed 22 line of “true” output then followed by the adding input samples. It bounced JS error with “added” is undefined when hit “calculate” button.

    Thanks

  29. Hi Michal,

    Nice article, Every thing is ok, but problem is that I am unable to connect with MS SQL Server Database,

    sub callback(action)
    if action = “get” then page.return(getRecordset(“SELECT * FROM table”))
    end sub

    This subroutines used recordset but My question is that where I’ll have to put Connection Object,

    Please give the solution

    Regards,
    M sarfraz

  30. I am unable to get even the demo page to work on my server… Not sure what is going wrong because i can see the demo works fine here.. I wonder if its the version of IIS i’m running or something.

  31. I am unable to get even the demo page to work on my server… Not sure what is going wrong because i can see the demo works fine here.. I wonder if its the version of IIS i’m running or something.

  32. I stumbled across ajaxed, and what a good asp-script. Now there is even less reason to use .Net stuff. But there is a problem with the latest protoype 1.6.0. If I replaec the prototype.js with the latest, the callbacks stop working. Do you have a new version or patch going? Keep up your good work !

  33. Very good! Remote scripting has failed on me (it delays for 15 - 30 seconds) so this looks like a quick fix. Keep up the great work!

  34. hy adam, great framework, very useful.
    I’m trying to use it on my new job.
    It gives me this error on codePage

    Object doesn’t support this property or method: ‘codePage’

    I’ve comm /tools/ajaxed/ajaxedPage.asp at line 334, and it works.
    is there better solution?
    My conf is win2k with iis5.0

    tnx
    s

  35. How can i get the contents of another page using this library. e.g. i am on a default.asp and want to embed the results of specials.asp (with few parameters) on this page. At the moment, i am using the iframe. want to remove this and instead want to display the results in a div on default.asp

  36. humble ajaxed uses prototypejs as the javascript library … thus you can use al its ajax facilities.. in your case it would be the Ajax.Updater .. doc can be found here:
    basically you would use it like this:

    new Ajax.Updater(‘containerID’, ‘pageurl.asp’, {parameters: {someParam: 1}});

  37. Thanks Michael,

    Ajaxed Rocks

  38. I’ve installed the latest version of Ajaxed and am ver impressed. The samples are really great, but lacking in documentation and explanation.

    I really wnat to use the datagrid for an application of mine, but the example has little or no text to help me.

    Is there a tutorial or documentation as to how to use these features?

    many thanks
    Pete

  39. hey pete … i know the documentation sucks a lot but its getting better. there are no tutorials for the datatable yet because it is not in an official release … i will release the next version soon but i think the datatable wont make it into the next one … its not finished yet .. paging and filtering is still missing.
    if u have some specific question then post them on the google group … you will get answers quick as the documentation lacks ;)

  40. “If you dont want to post the whole form or use your own parameters for the callback, you can use the third parameter of the ajaxed.callback function (with JSON). E.g.”

    But how do I get the value of my parameters in my callback sub?

    Thx..

  41. jonas just the the request.form collection .. the values are being posted. a nicer way though is accessing it with the RF methods of the page e.g.

    page.RF(fieldname)

    but

    request.form(fieldname)

    is also possible…

  42. Michal,

    I am updating one of my pages and need to acces a large number of form variables. Previously I have always passed all the values I need to access as parameters. e.g.

    This allows me to use p.RF(“passedrecvalue”) to get the value of the changed field

    However I now want to use the values from about 6 other form fields. From reading I thought I could use r.RF(“Any other form element name”) to access their value. However they are always null. However if I stop passing parameters e.g.

    with the callback I can access all the form elements using e.g. p.RF(“City”) etc. As soon as I pass parameters I can’t.

    Is this the expected behaviour or should I be able to pass parameters and access form elements?

    Thanks

  43. Pingback: AJAX Kaynakları | SG - Webmaster Kaynakları | Teknoloji Dünyası

  44. Thank you, I have been searching for a nice AJAX toolkit to speed up my ASP development.

    Have a look at my free KudzuASP template engine to help you put HTML in one page and ASP code in another.

  45. I have read this a few times and realise that the biggest problem with the example is the lack of HTML to show the proper page markup. Not having the statement etc makes it harder to understand what is Server side and what is Client side.

  46. very, very nice. thanks! classic ASP lives!!!!

  47. Pingback: AJAX Kaynakları- Web Hizmetleri Sorunsuz ve Sonsuz Hizmet Webtc.İnfo

  48. Hey just wondering how I would use JSON data with this. Here’s the deal, it will be a flash site that requires a user to enter a participation code that validates against a JSON data file. The user goes through the site answering a few questions and the answers append the JSON data file. So I need some sort of asp processing layer.

  49. Good. Long live asp classic.