Calling web service using javascript. Part -3
In the part 1 of this blog we saw how to invoke web service methods using pure javascript and in part 2
 we made use of web service behavior to invoke web methods. The previous
 two blogs were not dependent on server technologies used by the user 
but this blog will have that constraint because we will have a look at 
how to invoke web methods using “ScriptManager”. “ScriptManager” is an 
ASP.NET server side control which is key to AJAX functionality in 
ASP.NET. Without any further delay let’ see our first web method 
invocation using “ScriptManager”. For this blog we will making use of 
the same web service as we have used in our previous two blogs. Below is
 the code for the first web service method we are going to invoke. 
namespace ScriptManagerService
{
    //The attribute which makes the web service callable from script.
[System.Web.Script.Services.ScriptService]
public class TestService : System.Web.Services.WebService
    {
[WebMethod]
public string HelloWorld()
        {
return "Hello World";
}
}
}
The
 above web service code is pretty straight forward. We have a simple 
“HelloWorld” method which returns a string. What makes this web service 
special is the “[System.Web.Script.Services.ScriptService]” attribute 
added on top of the “TestService” web service class. The attribute makes
 the web service callable from JavaScript. Also when the proxy classes 
are generated the attribute generates JavaScript object corresponding to
 the web service class. Once the web service is created now we need to 
create our web page to invoke the web method. Create a new aspx page and
 add a “ScriptManager” control to it. Sample aspx page with the 
“ScriptManager” tag is added below.
<body>
<script language="javascript" type="text/javascript">
function invokeSimpleWebMethod()
{
ScriptManagerService.TestService.HelloWorld(handleResult);
}
function handleResult(result)
{
alert(result);
}
</script>
<form id="form1" runat="server">
<div>
<asp:ScriptManager ID="scrMgr" runat="server">
<Services>
                <asp:ServiceReference Path="TestService.asmx" />                
</Services>
</asp:ScriptManager>
<asp:Button ID="btnHW" runat="server" Text="Hello World" OnClientClick="invokeSimpleWebMethod();" />
</div>
</form>
</body>
In
 the above code we can see that we have a “ScriptManager” server control
 added. And inside the “Services” tag we have added reference to our 
local web service using the “ServiceReference” tag. The path attribute 
of the “ServiceReference” tag has the url of the web service which needs
 to be invoked. You can add multiple web services by adding additional 
“ServiceReference” tags. What ASP.NET does here is that it generates 
JavaScript proxy classes for each of the web services mentioned in the 
“ServiceReference” tag. All the auto generated JavaScript proxy classes 
derive from “Sys.Net.WebServiceProxy”.
Also we 
have an ASP.NET Button server control which calls a 
“invokeSimpleWebMethod” javascript method on its “OnClientClick” event. 
In the “invokeSimpleWebMethod” javascript method we have made use of the
 namespace (in which the web service is defined) followed by the web 
service name and finally the method name which needs to be invoked. 
Behind the scene ASP.NET has done the extra work of registering the 
namespace and creating the proxy classes and also adding the methods 
defined inside the web service into a proxy JavaScript class. If you 
notice the “HelloWorld” method takes an argument. The argument is 
nothing but the name of the JavaScript function which needs to be 
invoked when the web service method has been successfully executed and 
results are returned to the browser. You can also pass the name of the 
function which needs to be invoked when the web service method 
invocation request fails. We will see the same shortly. The 
“handleResult” JavaScript method gets called when the asynchronous 
request is successfully returned. The method gracefully displays the 
result in an alert message box.
That’ about how to
 use the “ScriptManager” server control to invoke a web service methods 
i.e. namespace followed by class name followed by the method name. One 
thing to note is that “ScriptManager” control can only be used to call 
web services in the same domain. Now lets see how to pass parameters to 
web methods.
Passing parameters to web method
We will use the following web method to see how we can pass parameters by using “ScriptManager”.
[WebMethod]
public string CombineName(string firstName, string midleName, string lastName)
{
return string.Concat(string.Concat(firstName, " - ", midleName), " - ", lastName);
}
The above method is pretty straight and it is the same method which I have used in my previous blog.
 The method takes three string arguments and concatenates them and 
returns them as a single string. Now lets see how we can pass the three 
parameters from JavaScript.
Below is the JavaScript method which invokes the web method with the three string parameters.
function webMethodWithParams()
{    
ScriptManagerService.TestService.CombineName("Sandeep", " ", "P.R", handleResult, handleError);
}
In the above JavaScript function we are invoking the “CombineName” method the same way we invoked the “HelloWorld” web method. But the difference here is that instead of the callback function as the first argument we are passing the arguments first, followed by the success callback function name and then the failure callback function. The funda behind is simple, if your web method accepted three parameters pass them first in the same order as defined in the web method followed by the callback methods. Similarly if the web method takes different number of parameters then make sure that, that many number of parameters are passed first followed by the success callback function. Success callback and error callback functions are optional. Our “handleError” javascript function looks something like this.
function handleError(error)
{
alert(error.get_message());
}
The
 above “handleError” javascript function is pretty straight forward. It 
takes an error object as one of the argument. The error object passed by
 the system has various methods and properties to retrieve the details 
of the exception happened on the server side. Some of the methods and 
properties are as follows.
- get_exceptionType method or _exceptionType field/property can be used to get the type of exception raised by the server like “System.Exception”.
 - get_message method or _message field/property can be used to get the error message returned by the server.
 - _stackTrace field/property or get_stackTrace method can be used to get the stack trace of the error from the server.
 - get_statusCode method or _statusCode field/property can be used to retrieve the HTML status code returned from the server.
 
The
 error object which is passed to the “handleError” JavaScript function 
is of type “Sys.Net.WebServiceError”. “Sys.Net.WebServiceError” is a 
simple class with the above explained methods or fields/properties.
Now the next step is to pass complex objects from JavaScript to a web method. Lets see how that can be accomplished.
Passing complex objects
Let see the code of the web method which accepts a complex object and processes it.
[WebMethod]
public string GetCar(Car car)
{
return "Model: " + car.Model + ", Color: " + car.Color; //", Cubic capacity: ";//+ car.CC +
}
public class Car
{
public string Model
    {   get; set; }          
public string Color
    { get; set; }
    public Engine CarEngine
    { get; set; }
}
public class Engine
{
public int CC
    { get; set; }
public int Cylinders
    { get; set; }
}
The
 “Car” class has three properties namely “Model”, “Color” and 
“CarEngine”. “Model” and “Color” are of type string and “CarEngine” is 
again a complex object of type “Engine”. The “Engine” class has two 
properties of type int namely “CC” and “Cylinders”. The above “Car” 
class is the one which we will be passing to the web method from within 
JavaScript using ScripManager. The code is pasted below.
function sendComplexObject()
{
    //Create a new Object and assign the same properties as those in the Car class.
var car = new Object();
    car.Model = "Ferrari California"
    car.Color = "Ferrari Red"
    car.CarEngine = new Object()
car.CarEngine.CC = 4500
car.CarEngine.Cylinders = 12
    //Execute the web method.
ScriptManagerService.TestService.GetCar(car, handleResult, handleError);
}
In
 the “sendComplexObject” method we are first creating a “Car” object by 
creating an object of type “Object”. Then to that object we are adding 
all the properties that the “Car” class has. Since JavaScript is a 
dynamic language you can add all the properties by just giving the name 
and the value. As the “Car” class has another complex object, Engine, as
 one of its property named “CarEngine” we are also creating the complex 
engine object also the same way. Once we have created the object we are 
finally executing the web method in the final line of code. Isn’t simple
 to pass complex objects from JavaScript to server. To help us to do 
write such a simple code the ScriptManager does the extra work 
converting the JavaScript objects to server objects. 
Below is the JSON way of creating the complex Car object.
function sendComplexObject()
{
    //Create an object of type "ScriptManagerService.Car" and pass all the properties 
    //as a javascript string array.
var car = new ScriptManagerService.Car({"Model" : "Ferrari California", "Color" : "Ferrari Red", "CarEngine" : {"CC" : "100", "Cylinders" : "5"}})
    //Invoke the web method.
ScriptManagerService.TestService.GetCar(car, handleResult, handleError);
}
In
 the above code we are trying to create a “ScriptManagerService.Car” 
object. This is possible because the ScriptManager generates the Proxy 
classes automatically for us. Now lets see handling a complex type 
returned from the server. It also is quite simple.
Handling a complex object returned by the server
Lets see the web service which returns the complex object.
[WebMethod]
public Car GetCarObject()
{
return new Car
    {
        Model = "Ferrari",
        Color = "Ferrari Red",
        CarEngine = new Engine { CC = 2500, Cylinders = 8 },
        test = "test"
};
}
The
 above web method does the hard work of creating a car object and 
returning the same. We are going to invoke the above web method using 
the ScriptManager and use the very complex object in JavaScript. The 
JavaScript code is pasted below.
function receiveUseComplexObject()
{
    //Invoking the web method that returns complex object.
ScriptManagerService.TestService.GetCarObject(handleResult, handleError);
}
//Modified handleResult function
function handleResult(result)
{
    //Using the complex object returned by the web method in JavaScript.
var carDef = "Model: " + result.Model + ", Color: " + result.Color + ", Engine-CC: " + result.CarEngine.CC;
    carDef += ", Engine-Cylinders: " + result.CarEngine.Cylinders;
alert(carDef);
}
In
 the “receiveUseComplexObject” we are not doing any drastic than 
invoking the “GetCarObject” web method. The main work is done by the 
modified “handleResult” function. The web method returns a “Car” object,
 the parameter of the “handleResult” also is the JavaScript proxy “Car” 
object representing the server object. The ScriptManager does all the 
work of converting the returned object as a JSON “Car” object. This is 
why we are able to use the properties of the “Car” object as we would do
 in a normal OOPS programming language.
Calling methods in a page
 Using “ScriptManager” one can access method of a web page as well. One 
catch here is that you can execute only static page methods. To call a 
page method from JavaScript by making use of “ScriptManger” you need to 
add the “WebMethod” attribute to the method you want to call. Lets see 
“.cs” file of a web page.
public partial class TestPage : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
    {    }
[System.Web.Services.WebMethod]
public static string HelloWorld()
    {
return "Hello world";
}
}
As
 mentioned above, we have added the “WebMethod” attribute to a static 
method and that’ it you need to do to make a page method callable by 
“ScriptManager”. In “ScriptManager” you need to set “EnablePageMethods” 
property to “true”. What this property does is it generates a 
“PageMethods” JavaScript class which has the necessary code to call all 
the static page methods which are decorated by the “WebMethod” 
attribute. Lets see the ASPX page and the JavaScript.
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebSerCalServiceMngr.aspx.cs" Inherits="WebServiceUsingJS.WebSerCalServiceMngr" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<script language="javascript" type="text/javascript">
function callPageMethods()
{
PageMethods.HelloWorld(handleResult);
}
</script>
<form id="form1" runat="server">
<div>
<asp:ScriptManager ID="scrMgr" runat="server" EnablePageMethods="true">
</asp:ScriptManager>
<asp:Button ID="Button3" runat="server" Text="Call page method." OnClientClick="callPageMethods();" />
</div>
</form>
</body>
</html>
In
 the above code we have set “EnablePageMethods” property to true and on 
the click of a button we are calling “callPageMethods()” JavaScript 
function. Inside the “callPageMethods” JavaScript function we are making
 use of “PageMethods” proxy class to execute our page method. So with 
“ScriptManager” doing all the extra work at the back, as a developer we 
are having great time. 
Try to know more
No comments:
Post a Comment