Click here to Skip to main content
Click here to Skip to main content

Synchronous JavaScript call using Scriptable XML Webservice (S-AJAX)

By , 4 Nov 2008
 

Introduction

This article shows how to consume a Microsoft AJAX web service (System.Web.Script.Services.ScriptService) to call synchronously at the client side using the XMLHttpRequest object and JavaScript.

Using a synchronous call, we can get rid of the problems of validating duplicate names in a custom validator without changing the code-behind. Many developers like me face this problem and have to find alternate solutions.

Using the Code

Here is the JavaScript code following the function GetSynchronousJSONResponse that calls the URL and posts the POST data synchronously using an XMLHttpRequest.

function GetSynchronousJSONResponse(url, postData) {
    var xmlhttp = null;
    if (window.XMLHttpRequest)
        xmlhttp = new XMLHttpRequest();
    else if (window.ActiveXObject) {
        if (new ActiveXObject("Microsoft.XMLHTTP"))
            xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
        else
            xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
    }
        // to be ensure non-cached version of response
    url = url + "?rnd=" + Math.random(); 
    
    xmlhttp.open("POST", url, false);//false means synchronous
    xmlhttp.setRequestHeader("Content-Type", "application/json; charset=utf-8");
    xmlhttp.send(postData);
    var responseText = xmlhttp.responseText;
    return responseText;
}

How to call GetSynchronousJSONResponse()

First, lets do a simple server call to get a single constant string. To understand the following code snippets, you need a bit of knowledge of JSON and how JSON represents an object. "HelloWorld" is the method name in the code-behind of the web service.

function HelloWorld() {
    var result = GetSynchronousJSONResponse(
                        '<%= Page.ResolveUrl("~/WebService.asmx/HelloWorld") %>', null);
                        //second argument is null as there is no argument in web method
    result = eval('(' + result + ')'); 
    alert(result.d); //process your result at client side
}

Code-behind:

[WebMethod]
public string HelloWorld()
{
    return "Hello World";
}

In the above code, the eval() function parses the JSON string in to the JavaScript object.

Let's move to a bit more complex situation. If you want to pass data to the server and get the server to return processed data back to display to the user:

function HelloMe() {
    var result = GetSynchronousJSONResponse('<%= Page.ResolveUrl(
                            "~/WebService.asmx/HelloMe") %>',
                          '{"Name":"' + document.getElementById('txtName').value + '"}');
    result = eval('(' + result + ')');
    alert(result.d); //process your result at client side
}

Code-behind:

[WebMethod]
public string HelloMe(string Name)
{
    return "Hello " + Name + " !";
}

In the above code, if the input contains the name "Sandip", then the JSON string to post will be {"Name":"Sandip"}. Here, "Name" is an argument of the web method which is defined in the code-behind of the web service file. We can only use primitive data types like string, int, decimal, etc. We can also pass multiple arguments, for example, {"Name":"Sandip","Age":"23"}, to pass both the name and age.

Finally, let us use it in a custom validator. Here, the return type of the web method is bool according to the condition.

function CheckForDuplicateInDB(sender, arg) {
    var result = GetSynchronousJSONResponse('<%= Page.ResolveUrl(
                          "~/WebService.asmx/CheckName") %>',
                       '{"Name":"' + arg.Value + '"}');
    result = eval('(' + result + ')');
    arg.IsValid = !result.d;
}

ASPX markup:

<asp:TextBox ID="txtCheckName" runat="server" Text="Validator"></asp:TextBox>
<asp:CustomValidator ID="cvName" ControlToValidate="txtCheckName"
                  ClientValidationFunction="CheckForDuplicateInDB" 
        EnableClientScript="true" runat="server" Display="Static"
                  ToolTip="Name is Duplicate." Text="*">
                           </asp:CustomValidator>
<asp:Button ID="btnClickMe" runat="server" Text="ClickMe!" />

Code-behind:

//code behind
[WebMethod]
public bool CheckName(string Name)
{
    // Checking for db records can be done here.
    return (Name == "Validator");
}

Additionally, here is the code to handle/display server side errors:

function CallError() {
    var result = GetSynchronousJSONResponse('<%= Page.ResolveUrl(
             "~/WebService.asmx/CallError") %>', null);
    result = eval('(' + result + ')');
    if (typeof (result.d) == 'undefined')
        alert(result.Message);//you can also have StackTrace and ExceptionType
    else
        alert(result.d); //process your result at client side
}

Code-behind:

[WebMethod]
public string CallError()
{
    int i = 0;
    int j = 5 / i; //Devide by Zero Error
    return "Call Error";
}

References

History

  • 22 Oct 2008: Posted to The Code Project.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Sandip R Patel
Web Developer Gateway Technolabs
India India
Member
ASP.net C#, Microsoft Dynamics CRM 4.0

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralWonderful Article - Minor Suggestionmembercjbarth10 May '11 - 8:28 
This is wonderful code and a nice compliment to the built-in functions that MS provides for AJAX to webservices. However, I would suggest that you replace return responseText; with return eval('(' + responseText + ')');. That would make it so that the conversion doesn't have to be done after the call. Even better might be to return eval('(' + responseText + ')').d, perhaps after a check to see if it is defined.;
GeneralMy vote of 5memberChristian Del Bianco19 Apr '11 - 23:14 
Good article!
GeneralWeb Service Return List<>memberSSL SSL29 Nov '10 - 17:04 
Hi,
 
I have created a web service that will return List<> object.
 
When I return it to javascript that always display "undefined" of the result object.
 
How can I handle it?
 
Thank you!
GeneralThank's a lotmemberandibaden29 Jan '10 - 9:39 
Great Stuff, you saved my day!!!!!
QuestionHow do I make a progress bar show when there is a synchronous ws callmemberTravelthrprog11 Dec '09 - 11:26 
Your worked great. But how do show a progress bar when the web service is called?
Questionhow to call webservice using ajax from another machinemembergargprabhat20109 Oct '09 - 1:16 
hi,
 
i had develop a project is which i am calling webservice from client side of asp.net page using ajax control and xml. this webservice is working fine on single machine. but i am unable to call this from another machine. please help me
 
please find below the code which is using to call webservice.
 
function XmlhttpCall(objXML,serviceName)
{
try
{


var xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
var xmlHttpGo = xmlHttp;
var WebServicePath = "http://192.168.0.1/PerkWebService/WebServiceLeave/WebServiceLeave.asmx/" ;
var str = WebServicePath + serviceName;
xmlHttpGo.open("POST", str, false);
xmlHttpGo.SetRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlHttpGo.send('xmlreceive=' + objXML.xml);
var xmlString1 = xmlHttpGo.responseXML.text;
return xmlString1;
}
catch(e)
{
return (e.Message + "--> XmlhttpCall");
}
}
 
no comment

GeneralAsynchronous alternative for WebService-based validationmemberMember 46241952 May '09 - 2:45 
Maybe I've found an asynchronous alternative for this.
Give a look at my blog entry:
http://www.codegolem.com/post.aspx?id=7edcaa9d-4476-4a81-b72d-c7edc616f7a6[^]
 
Any feedback is appreciated. Bye!
NewsASP.NET Synchronous Page MethodsmemberEric Carter29 Oct '08 - 4:55 
For the many out there like myself interested in executing a PageMethod synchronously, here is an example using Sandip's GetSynchronousJSONResponse function above. Many thanks to Sandip for supplying the GetSynchronousJSONResponse code!
 
function ExecutePageMethodSync(methodName, jsonArgs) {
    var url = PageMethods.get_path() + "/" + methodName;
    var resp = GetSynchronousJSONResponse(url, jsonArgs);
 
    //result is a json expression, so we eval it to return the object
    var result = eval("(" + resp + ")");
 
    return result;
}
 
Here is an example of the usage. In my case, I needed to validate that a mnemonic was not yet used. The CheckMnemonic Page Method takes the mnemonic as an argument and returns true if the mnemonic is in use, otherwise false.
 
function uwgResponses_BeforeRowTemplateClose(gridId, rowId, saved) {
    if (saved) {
        var mnc = $get("igtbl_TextBox_0_2");
        var desc = $get("igtbl_TextBox_0_3");
 
        if (mnc.value.length == 0) {
            alert("Mnemonic is required.  Please enter a valid mnemonic for this field.");
            return true;
        }
        else if (desc.value.length == 0) {
            alert("Description is required.   Please enter an appropriate description for this field.");
            return true;
        }
        else {
            var result = ExecutePageMethodSync("CheckMnemonic", '{"mnc":"' + mnc.value + '"}');
 
            if (typeof (result.d) == 'undefined') {
                alert("Error validating mnemonic:  " + result.Message);
                return true;
            }
            else if (result.d) {
                alert("The mnemonic \"" + mnc.value + "\" is already in use.  Please select a different mnemonic.");
                return true;
            }
        }
    }
 
    return false;
}

GeneralRe: ASP.NET Synchronous Page MethodsmemberSandip R Patel31 Oct '08 - 21:01 
that means you want to call page method instead of webservice? yes you can call page method logic is that GET or POST like http://localhost/MyPage.aspx?method=CheckMnemonic with some post data. and in Page_Load you can get Request["method"] and other post data and you can return appropriate result by Response.Write("") and Response.End().
GeneralRe: ASP.NET Synchronous Page MethodsmemberEric Carter1 Nov '08 - 18:44 
Hi Sandip,
 
I actually had the ASP.NET AJAX Page Method already defined on the page. I didn't need to do any work in the codebehind to make the script work the way I wanted it to. I just passed in the JSON args and it worked like a charm. ASP.NET AJAX handled all of the other stuff behind the scenes without any further intervention from me in the codebehind.
GeneralRe: ASP.NET Synchronous Page MethodsmemberSandip R Patel4 Nov '08 - 17:34 
yes, i got it, thanks
GeneralRe: ASP.NET Synchronous Page MethodsmemberGeoffMci16 Apr '09 - 0:47 
Thumbs Up | :thumbsup: Thanks to both of you! This article and page method post saved me a HEAP of stress.
Geoff Mc
Generalone important thing...memberMOMTeB127 Oct '08 - 22:31 
If you want to use this kind of WS call you must enable the POST and/or GET method in web.conig file.
 






GeneralRe: one important thing...memberSandip R Patel31 Oct '08 - 20:53 
yes this is correct, but this settings is by default on when you start AJAX website project.
GeneralVery NicememberSam Shiles23 Oct '08 - 3:26 
Just what I was looking for, worked perfectly

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130516.1 | Last Updated 4 Nov 2008
Article Copyright 2008 by Sandip R Patel
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid