Introduction
This article explains the use of Web Services in an ASP.NET 3.5 AJAX environment and how to call Web Service methods from client-side JavaScript. It also outlines the new System.Web.Script
namespace, and explores the ways of defining client-calls to a Web Service method.
Calling Web Service methods in AJAX
To improve the web user experience, the AJAX functionality of ASP.NET has included, in its new version, new ways of calling web service methods from client-side JavaScript. Without submitting or rendering a whole page, AJAX enables you to call a server-side method with no post-back. The client script can make a request to a web method and pass data as input parameters to the method; and data can also be sent back to the client browser from the server.
To enable your application to call ASP.NET Web Services by using client script, the server asynchronous communication layer automatically generates JavaScript proxy classes. A proxy class is generated for each Web Service for which an <asp:ServiceReference>
element is included under the <asp:ScriptManager>
control in the page.
<asp:ScriptManager runat="server" ID="scriptManagerId">
<Services>
<asp:ServiceReference Path="WebService.asmx" />
</Services>
</asp:ScriptManager>
This proxy class is downloaded to the browser at page load time, and provides a client object that represents the exposed methods of a Web Service. To call a method of the Web Service, you call the corresponding method of the generated JavaScript proxy class. The proxy class in turn communicates with the Web Service. The requests are made asynchronously, through the XMLHTTP
object of the browser.
The <asp:ScriptReference>
element is specified to register a JavaScript file that is to be used in a web page. Only after registering the CallWebServiceMethod.js file, can you call methods on it.
Calling a Web Service method from a script is asynchronous. To get a return value or to determine when the request has returned, you must provide a succeeded callback function. The callback function is invoked when the request has finished successfully, and it contains the return value (if any) from the Web method call. You can also provide a failed callback function to handle errors. Additionally, you can pass user context information to use in the callback functions.
JSON – JavaScript Object Notation is the default serialization format using which data transformation takes place between client-server requests. You may disable all currently enabled protocols like HTTP-GET, HTTP-POST, and even XML-SOAP formatting used in the earlier forms of Web Services. The following settings in the Web.Config file just do the same.
<system.web>
<webServices>
<protocols>
<clear/>
</protocols>
</webServices>
</system.web>
The figure below shows in detail the different layers that lay on both the client and server sides. A request to a Web Service method passes through these layers. You can see how a method is called on to one of the available proxy object and the web request is handled by an XmlHttp
object on the client browser side. On the server side, your request is handled by an HTTP handler as usual and sent for XML/JSON serialization.
Example: Consuming Web Service methods in AJAX
Consuming Web Service methods in AJAX involves two steps. The first step is that there is a slight change in the way you create and define Web Services. Making calls using client script from a page to the service methods will be the second step.
Step 1: Creating a Web Service
In the System.Web.Scripts.Services
namespace, you may find an attribute class “ScriptSrvice
”, and this needs to be applied to a Web Service class so that the Web Service methods can be invoked from the client script. This would enable the proxy generation script to generate a proxy object that corresponds to the Web Service class.
Similarly, in the same namespace, you may find another attribute class “ScriptMethod
”, and upon applying this attribute to a web method, you can specify which HTTP verb is used to invoke a method and the format of the response. This attribute has three parameters, as described below:
UseHttpGet
: Setting it to true
will invoke the method using the HTTP GET command. The default is false
.ResponseFormat
: Specifies whether the response will be serialized as JSON or as XML. The default is JSON.XmlSerializeString
: Specifies whether all return types, including string types, are serialized as XML. The value of the XmlSerializeString
property is ignored when the response is serialized as JSON.
OK... now, create a new web site using the ASP.NET Web Service template in Visual Studio 2008, and modify the Web Service class as below:
using System.Web.Script.Services;
namespace AjaxWebService
{
[WebService(Namespace = "http://localhost:49232/AjaxWebService/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ScriptService]
public class Service : System.Web.Services.WebService
{
string myXmlData = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
<Book>
<Title>Programming ASP.NET 3.5, AJAX and Web Services</Title>
</Book>";
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
[WebMethod]
public string getNextBackupDate(int months)
{
return DateTime.Now.AddMonths(months).ToShortDateString();
}
[ScriptMethod(ResponseFormat = ResponseFormat.Xml)]
[WebMethod]
public string Greetings(string name)
public XmlDocument GetBookTitle()
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(myXmlData);
return xmlDoc;
}
[ScriptMethod(UseHttpGet = true)]
[WebMethod]
public string HelloWorld()
{
return "Hello, world";
}
}
}
Note: The Web Service created with ScriptService
enabled as above will not be tested on the browser, by default. You need to modify the settings in the Web.Config file as below to test the above Web Service.
<webServices>
<protocols>
<add name="HttpGet"/>
<add name="HttpPost"/>
</protocols>
</webServices>
Step 2: Call Web Service methods using client script
ASP.NET Web Service methods can be called from client scripts asynchronously without a postback and without refreshing the full page. Only data is transferred between the server and the client browser.
Currently, .NET framework 3.5 supports Web Service and client web page available in the same domain (same web site). You cannot call Web Service methods residing on the Internet or any other system using VS2008 Beta 2.
Now, add a new “AJAX Enabled Web Page” to the existing Web Service project, and add the controls to the web page as specified in the mark-up below.
Write JavaScript functions to call the Web Service methods and callback methods. Calls to Web Service methods are made by using the proxy class and a list of parameters, name of the succeeded callback function, the failed callback function, and the user context is passed as additional parameters in the call.
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>AJAX Web Form</title>
<script type="text/javascript">
function CallNextDate()
{
AjaxWebService.Service.getNextBackupDate(1, OnSucceeded);
}
function CallHelloWorld()
{
AjaxWebService.Service.HelloWorld(OnSucceeded);
}
function CallBookTitle()
{
AjaxWebService.Service.GetBookTitle(OnSuccess, OnFail,
"XmlDocument");
}
// This is the callback function that processes
// the Web Service return value in JSON format.
function OnSucceeded(result)
{
var myresult = document.getElementById("Text1");
myresult.value = result;
}
// This is the callback function that processes
// the Web Service return value in XML format.
function OnSuccess(result)
{
var myresult = document.getElementById("Text1");
myresult.value = "Title: " + result.documentElement.text;
}
// This is the callback function that processes
// the Web Service return value in XML format.
function OnFail(error)
{
var myresult = document.getElementById("Text1");
myresult.value = "Service Error: " + error.get_message();
}
</script>
<style type="text/css">
#Text1
{
width: 375px;
}
#Button2
{
width: 140px;
}
</style>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Services>
<asp:ServiceReference Path="~/Service.asmx"/>
</Services>
</asp:ScriptManager>
<br />
Result: <input id="Text1" type="text" /><br />
<br />
<input id="Button1" type="button"
value="Get Server Time" onclick="CallNextDate()" />
<input id="Button2" type="button"
value="Say Hello World" onclick="CallHelloWorld()" />
<input id="Button3" type="button"
value="Get Book Title" onclick="CallBookTitle()" />
<br />
<br />
<br />
</div>
</form>
</body>
</html>
In the above markup, notice how the path
attribute in the ServiceReference
element of the ScriptManager
control points to the Web Service class. This enables the Web Service method to be called from the script in the default.aspx page. The inline functions CallNextDate
, CallHelloWorld
, and CallBookTitle
are used to call the three Web Service methods. The OnSuccess
and OnFail
methods are callback methods that get executed as the Web Service method execution gets over.
Your web page layout would look somewhat like this:
In order to make the client web page to work, you need to add the following settings to the Web.Config file:
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Extensions"
publicKeyToken="31bf3856ad364e35"/>
<bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Extensions.Design"
publicKeyToken="31bf3856ad364e35"/>
<bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
This would redirect the ASP.NET engine to load the current version 3.5 of System.Web.Extensions.dll and other DLLs to exploit the built-in AJAX support in ASP.NET 3.5.
Conclusion
ASP.NET 3.5 along with the in-built AJAX client-server framework has increased the power of using client scripts to call Web Service methods. Most of the settings and JavaScript code files are loaded automatically when you use Visual Studio 2008. Calling Web Service methods in the earlier versions of AJAX, ATLAS has a few troubles that make the development and debugging a little difficult. Now, with ASP.NET 3.5, it has become an inherent part of the much simpler and familiar VS2008 IDE.