Friday 15 July 2011

Call Web Services from Javascript

There were two posts in this blog talks about how to call server method from client side (Javascript) using XML HTTP AJAX (Post1) and ICallBackHandler(Post2). This post talks about calling server method from Javascript using ASP.NET Web Services.

After WCF technology launched with .Net runtime, using ASP.NET Web Services reduced more as WCF provides lots more flexibility then Web Services. But even WCF takes over Web Services, Web Services are very simple and easy to program. So for calling server for simple process from client, going with Web Services is a better option.

In this post, I am going to take the following scenario for implementing with Web Service calling from Client Side. The same example has been implemented with other two posts pointed out earlier with XML HTTP AJAX and ICallBackHandler.

The requirement in the implementation is to create a user creation entry screen. The user can enter the User Id, Name and Email id and Save the details in the database. When the user types the User Id and get the focus out from the text box, the system should automatically call a server method (Web Service method) to verify the User Id already exist in the database or not. If the User Id already exists, the system should show message to inform the user that the User Id is Not Available for register otherwise Available.

The call made to the server for verifying User Id existence must be done thro’ an AJAX call and there should not be any post back. For this kind of requirements we can use some Javascript (or JQuery) and call the server using AJAX, CallBackHandler or Web Service method. As the request and response can be made in Asynchronous method, there won’t be any post back in the page.

In this implementation, I have an XML file (UserDetails.xml) which stores the user details. The xml markup looks like –
<?xml version="1.0" encoding="utf-8"?>
<Users>
  <User>
    <UserID>A-C71970F</UserID>
    <FirstName>Aria</FirstName>
    <LastName>Cruz</LastName>
    <MailId>Aria.Cruz@gmail.com</MailId>
    <IsLocked>1</IsLocked>
  </User>
  <User>
    <UserID>A-R89858F</UserID>
    <FirstName>Annette</FirstName>
    <LastName>Roulet</LastName>
    <MailId>Annette.Roulet@gmail.com</MailId>
    <IsLocked>1</IsLocked>
  </User>
</Users>
There is Web Service (UserService.asmx), which contains a method (IsUserIdExist) for verifying the User Id exist or not.
/// <summary>
    /// Summary description for UserService
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    [System.Web.Script.Services.ScriptService]
    public class UserService : System.Web.Services.WebService
    {

        [WebMethod]
        public int IsUserIdExist(string userId)
        {
            try
            {
                // Sleep statement is for testing Processing image on the screen
                System.Threading.Thread.Sleep(1500);

                string strFileName = HttpContext.Current.Request.PhysicalApplicationPath + @"Data\UserDetails.xml";

                XPathDocument doc = new XPathDocument(strFileName);
                XPathNavigator nav = doc.CreateNavigator();
                XPathNodeIterator iterator;

                iterator = nav.Select(@"//User[UserID='" + userId + "']");

                while (iterator.MoveNext())
                {
                    XPathNavigator nav2 = iterator.Current.Clone();

                    if (nav2.Select(@"//Users").Current.SelectSingleNode("UserID").InnerXml.Length > 0)
                        return 1;
                }
                return 0;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
    }
Please note, normally when we create a web service the below attribute of the service will be commented. To make the web service to be able to call from Javascript, the attribute must present with uncommented.
[System.Web.Script.Services.ScriptService]
Another important process is to register the web service into the web page. Normally to use web services in code behind, we will be adding Service Reference and create object of the client and use it. But to use the web service in web pages (aspx script or Javascript) it must be registered as below in the aspx script.
<asp:ScriptManager ID="ScriptManager1" runat="server">
    <Services>
        <asp:ServiceReference Path="~/UserService.asmx" />
    </Services>
</asp:ScriptManager>
Once it is registered, we are free to use the service in Javascript as defined below NameSpace.ServiceName.WebMethodName(Parameter1, Parameter2, .. , onSuccessMethodName, onFailureMethodName)

Here if NameSpace is defined for the Web Service, than it must be mentioned with the web service call. The parameters of the web service will contain the list of parameters to Web Method with Success and failure methods i.e., the last two parameters are used for successful response and failure response method calls respectively.

Below is the aspx script:
<div>
    <table>
        <tr>
            <td>User Id</td>
            <td>
                <asp:TextBox ID="txtUserId" runat="server" Width="120px" onchange="UserNameCheck(this.id)" CssClass="TextStyle" style="float:left;"></asp:TextBox><span id="spanAvailableStatus" style='display:none'></span><img id='spanProcessing' alt='' src= "Images/ajax-loader.gif" style='display:none;float:left;padding-top:7px;padding-left:5px' />
            </td>
        </tr>
        <tr>
            <td>First Name</td>
            <td><asp:TextBox ID="txtFirstName" runat="server" Width="200px" CssClass="TextStyle"></asp:TextBox></td>
        </tr>
        <tr>
            <td>Last Name</td>
            <td><asp:TextBox ID="txtLastName" runat="server" Width="200px" CssClass="TextStyle"></asp:TextBox></td>
        </tr>
        <tr>
            <td>Mail Id</td>
            <td><asp:TextBox ID="txtMailId" runat="server" Width="200px" CssClass="TextStyle"></asp:TextBox></td>
        </tr>
        <tr>
            <td colspan="2" style="text-align:center">
                <asp:Button ID="btnSave" Text="Save" Width="60px" runat="server" 
                    onclick="btnSave_Click" />
                <asp:Button ID="btnClear" Text="Clear" Width="60px" runat="server" />
            </td>
        </tr>
    </table>
</div>
Here is the Javascript. The web service call highlighted in the below code.
// This function will be called when lost focus of User Id
function UserNameCheck(id) {
    var strUserId = document.getElementById(id).value.replace(/^\s+|\s+$/g, "");
    if (strUserId.length > 0) {
        document.getElementById('spanAvailableStatus').style.display = "none";
        document.getElementById('spanProcessing').style.display = "block";
        CallServerFromClient.UserService.IsUserIdExist(strUserId, onSuccess, onFailed);
    }
}
// This function will be called when the web service call completed successfully.
function onSuccess(response) {
    if (parseInt(response) == 1) {
        document.getElementById('spanAvailableStatus').innerHTML = 'Not Available';
        document.getElementById('spanAvailableStatus').className = 'Red';
    }
    else {
        document.getElementById('spanAvailableStatus').innerHTML = 'Available';
        document.getElementById('spanAvailableStatus').className = 'Green';
    }
    document.getElementById('spanAvailableStatus').style.display = "block";
    document.getElementById('spanProcessing').style.display = "none";
}

// This function will be called if any error occured in the webservice method.
function onFailed(error) {
    alert("There is an error occured \n" + error.get_message());
}
Calling Web Service with Multiple Parameter from Javascript

Here, the web service method getting First Name, Last Name and returning with Hi message.
[WebMethod]
public string ForVerifyingTwoParameter(string FirstName, string LastName)
{
    return "Hi " + FirstName + " " + LastName;
}
I added two text box for getting First Name and Last Name in aspx script and a button to call Web Service.
First Name : <input id="txtFirstName" type="text" value="" class="TextStyle" />
Last Name : <input id="txtLastName" type="text" value="" class="TextStyle" />
<input type="button" value="Call With Two Paramter" onclick="CallTwoParameter()" />
The Javascript calling the Web Method with First Name, Last name. On successful response from Web Service, the system just popup the returned message.
// Example for calling Web Service with two paramter
function CallTwoParameter() {
    CallServerFromClient.UserService.ForVerifyingTwoParameter(document.getElementById("txtFirstName").value, document.getElementById("txtLastName").value, onSuccess, onFailed);
}
function onSuccess(response) {
    alert(response);
}
// This function will be called if any error occured in the webservice method.
function onFailed(error) {
    alert("There is an error occured \n" + error.get_message());
}
Caching with Web Services

Caching is a good future in Web Services, which will improve your application performance more. Incase if your Web Method does lots of data to produce its response and that method required to be called frequently, we have the option the cache the response for some seconds. So any other request comes to the Web Method within the mentioned time, the Web Service will return the cached data instead of going for executing the code to produce the output.

The caching depends of the parameter value calling the Web Method. For example, a Web Method accepts one parameter (consider Year) and returns an array (Holiday List). The Web Method declared to cache the output for 60 seconds. When a first call comes to the service with year 2011, the method will search the database, catch the data and return an array of holidays. The next call comes with 2010; it won’t return the cached array as the parameter value is different. It will search again the database, cache and return value. In case the third call to the service with year 2011 within 60 seconds of the first call, then the return cached data for 2011. If the 60 seconds time elapsed after first call then the system will go to the database to fetch the data again.

For the implementation, I am getting the server time using web services and show on the web page. I cache the Web Method with 10 seconds duration. So whatever call I made to the Web Service within 10 seconds of the first call, it will return the same time which was fetched at first call. Once the time elapsed it will return the new current time.

Web Service
[WebMethod(CacheDuration=10)]
public string GetServerTime()
{
    return DateTime.Now.Hour.ToString() + ":" + DateTime.Now.Minute.ToString() + ":" + DateTime.Now.Second.ToString() + ":" + DateTime.Now.Millisecond.ToString();
}
Javascript
// Example for calling Web Service with two paramter
function CallTwoParameter() {
    CallServerFromClient.UserService.GetServerTime(onSuccess, onFailed);
}
function onSuccess(response) {
    document.getElementById("divResponse").innerHTML = "Data From Web Service : " + response + "<br/>" + "Current Time : " + Date();
}
// This function will be called if any error occured in the webservice method.
function onFailed(error) {
    alert("There is an error occured \n" + error.get_message());
}

This code has been tested with IE 6.0/9.0, Firefox 3.6, Opera 11.01

Below is the output of the screen,
Screen output of Calling Web Service from Javascript

download the working example of the source code in C# here and in VB here

0 Responses to “Call Web Services from Javascript”

Post a Comment