1. Trang chủ
  2. » Công Nghệ Thông Tin

ASP.NET AJAX Programmer’s Reference - Chapter 14 ppt

62 287 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Consuming Web Services Via JSON Messages
Trường học University of Example
Chuyên ngành Web Services
Thể loại lecture notes
Năm xuất bản 2007
Thành phố Unknown
Định dạng
Số trang 62
Dung lượng 391,35 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Listing 14-6: The _invoke Method function Sys$Net$WebServiceProxy$_invokeservicePath, methodName, useGet, params, onSuccess, onFailure, userContext return Sys.Net.WebServiceProxy.invok

Trang 1

Consuming Web Ser vices

V ia JSON Messages

As you saw in the previous chapter, you can use the XMLHttpExecutor , WebRequestManager , and WebRequest classes to make requests to the server However, this approach requires you to write lot of code to make a request The ASP.NET AJAX client-side framework includes a class named WebServiceProxy that encapsulates all the logic that uses the XMLHttpExecutor ,

WebRequestManager , and WebRequest classes to make a request to the server This enables you

to make a request with minimal time and effort The downside of the WebServiceProxy approach

is that it supports only JSON messages If you need to use normal SOAP messages to communicate with a Web service, you have to use the techniques discussed in the previous chapter This chapter begins by discussing the important members of the WebServiceProxy class

WebSer viceProxy

As you can see in Listing 14-1 , the constructor of the WebServiceProxy class doesn’t do anything

Listing 14-1: The Constructor of the WebServiceProxy Class

Sys.Net.WebServiceProxy = function Sys$Net$WebServiceProxy() { }Sys.Net.WebServiceProxy.registerClass(‘Sys.Net.WebServiceProxy’);

Timeout

The WebServiceProxy class exposes a getter named get_timeout and a setter named

set_timeout that enable you to get and set the request timeout, as shown in Listing 14-2

Trang 2

Listing 14-2: Getting and Setting the Request Timeout

Default Succeeded Callback

You call the set_defaultSucceededCallback method on the WebServiceProxy object to specify a

JavaScript function as the default succeeded callback for Web requests (see Listing 14-3 ) As the name

implies, this JavaScript function is automatically invoked when a request is completed successfully You

call the get_defaultSucceededCallback method on the WebServiceProxy object to return a

refer-ence to the JavaScript function registered as the default succeeded callback (see Listing 14-3 )

Listing 14-3: Getting and Setting the Default Succeeded Callback

Default Failed Callback

You can call the set_ defaultFailedCallback method on the WebServiceProxy object to

specify a JavaScript function as the default failed callback for Web requests (see Listing 14-4 ) As the

name suggests, this JavaScript function is automatically invoked when a request fails Call the

get_defaultFailedCallback method on the WebServiceProxy object to return a reference to

the JavaScript function registered as the default failed callback (see Listing 14-4 )

Listing 14-4: Getting and Setting the Default Failed Callback

Trang 3

Path

Call the set_path method on the WebServiceProxy object to specify a URL as the target URL for Web requests (see Listing 14-5 ) Call the get_path method on the WebServiceProxy object to return the target URL (see Listing 14-5 )

Listing 14-5: Getting and Setting the Path

function Sys$Net$WebServiceProxy$set_path(value){

this._path = value;

}

function Sys$Net$WebServiceProxy$get_path(){

return this._path;

}

Invoking a Web Method

Invoking a Web method is at the heart of the WebServiceProxy class The main responsibility of the _invoke method is to invoke the Web method with a specified name and parameter names and values that belong to a Web service with a specified URL As you can see in Listing 14-6 , the _invoke method takes the following parameters:

❑ servicePath : This parameter specifies the target URL for the Web service For example, if you have a Web service named Service.asmx running locally on your machine, its service path is as follows:

of your application The WebServiceProxy class does not do anything with the user context It simply keeps it somewhere and passes it into the JavaScript functions referenced by the

onSuccess and onFailure parameters when they’re invoked

Trang 4

Listing 14-6: The _invoke Method

function Sys$Net$WebServiceProxy$_invoke(servicePath, methodName, useGet,

params, onSuccess, onFailure, userContext)

return Sys.Net.WebServiceProxy.invoke(servicePath, methodName, useGet, params,

onSuccess, onFailure, userContext, this.get_timeout());

}

Note that the _invoke method returns a reference to the WebRequest object that represents the request

made to the Web service

Now, let’s walk through the implementation of the _invoke method If no JavaScript function has

been assigned to the onSuccess parameter as a succeeded callback, the _invoke method calls the

get_defaultSucceededCallback method to return and use the JavaScript function registered as

the default succeeded callback:

if (onSuccess === null || typeof onSuccess === ‘undefined’)

onSuccess = this.get_defaultSucceededCallback();

If no JavaScript function has been assigned to the onFailure parameter as a failed callback, the _invoke

method calls the get_defaultFailedCallback method to return and use the JavaScript function

registered as the default failed callback:

if (onFailure === null || typeof onFailure === ‘undefined’)

onFailure = this.get_defaultFailedCallback();

If no JavaScript object has been assigned to the userContext parameter, the _invoke method calls the

get_defaultUserContext method to return and use the JavaScript object registered as the default user

context:

if (userContext === null || typeof userContext === ‘undefined’)

userContext = this.get_defaultUserContext();

Finally, the _invoke method delegates the responsibility of invoking the Web method with a specified

name and parameter names and values to the invoke static method of the WebServiceProxy class:

return Sys.Net.WebServiceProxy.invoke(servicePath, methodName, useGet, params,

onSuccess, onFailure, userContext, this.get_timeout());

Note that the _invoke method passes the return value of the get_timeout method as the last parameter

into the invoke method This return value specifies the request timeout

Trang 5

invoke

Listing 14-7 presents the internal implementation of the WebServiceProxy class’s invoke static method

Listing 14-7: The invoke Static Method of the WebServiceProxy Class

Sys.Net.WebServiceProxy.invoke =function Sys$Net$WebServiceProxy$invoke(servicePath, methodName, useGet, params, onSuccess, onFailure, userContext, timeout){

var request = new Sys.Net.WebRequest();

request.get_headers()[‘Content-Type’] = ‘application/json; charset=utf-8’;

if (!params) params = {};

var urlParams = params;

if (!useGet || !urlParams) urlParams = {};

request.set_url(Sys.Net.WebRequest._createUrl(servicePath+”/”+methodName, urlParams));

var body = null;

if (!useGet) {

body = Sys.Serialization.JavaScriptSerializer.serialize(params);

if (body === “{}”) body = “”;

} request.set_body(body);

var statusCode = response.get_statusCode();

var result = null;

try { var contentType = response.getResponseHeader(“Content-Type”);

if (contentType.startsWith(“application/json”)) result = response.get_object();

else if (contentType.startsWith(“text/xml”)) result = response.get_xml();

else result = response.get_responseData();

}

(continued)

Trang 6

Listing 14-7 (continued)

catch (ex)

{

}

var error = response.getResponseHeader(“jsonerror”);

var errorObj = (error === “true”);

if (result && errorObj)

error = result.get_exceptionType() + “ “ + result.get_message();

Trang 7

else alert(msg);

} }

return request;

}

This method first instantiates a WebRequest object to represent the current Web request:

var request = new Sys.Net.WebRequest();

Next, it calls the get_headers method to return a reference to the dictionary that contains the names and values of the request headers, and assigns the string ‘application/json; charset=utf-8’ as the value of the Content-Type request header:

request.get_headers()[‘Content-Type’] = ‘application/json; charset=utf-8’;

This value instructs the server that the body of the message contains a JSON object As you’ll see later, the server-side code uses a serializer to deserialize a NET object from this JSON representation

Next, it checks whether at least one of the following conditions are met:

❑ You’re making a GET HTTP request to the server As previously discussed, the third parameter passed into the invoke method is a Boolean that specifies whether the GET HTTP verb must be used

❑ The Web method being invoked does not take any arguments

If at least one of these conditions is met, the invoke method passes the dictionary that contains the names and values of the arguments of the Web method being invoked as the second argument to a method named _createUrl If neither of the conditions is met, the invoke method passes an empty dictionary as the second argument

The main responsibility of the _createUrl method is to create a URL that consists of the following two main parts:

❑ The URL part, which itself consists of two parts separated by the forward slash character ( / ), where the first part contains the service path (the target URL) of the Web service, and the second part contains the name of the Web method being invoked As you can see in the following code excerpt from Listing 14-7 , the Web method name is passed to the server as part of the URL

❑ The query string part, which consists of query string parameters and their associated values, where each parameter and its associated value respectively contain the name and value of an argument of the Web method being invoked As you can see in the following code excerpt from Listing 14-7 , the names and values of the arguments of the Web method are passed to the server

as a query string if at least one of the previously mentioned conditions is met

Trang 8

var urlParams = params;

if (!useGet || !urlParams)

urlParams = {};

var url = Sys.Net.WebRequest._createUrl(servicePath+”/”+methodName, urlParams);

Next, the invoke static method calls the set_url getter on the WebRequest object that represents the

current request to specify the URL returned from the _createUrl method as the target URL of the request:

request.set_url(url);

Then, the invoke method checks the value of its third parameter to determine whether it must make a

POST HTTP request to the server If so, it invokes a static method named serialize on an ASP.NET

AJAX class named JavaScriptSerializer , passing in the dictionary that contains the names and values

of the arguments of the Web method being invoked to serialize this dictionary into a JSON object It

assigns this JSON object to a local variable named body , which contains the body of the POST HTTP

request being made to the server

var body = null;

Next, the invoke static method calls the set_body method on the WebRequest object that represents

the current request, passing in the body local variable to set the body of the request:

request.set_body(body);

If the request is a GET HTTP request, the body is null If the request is a POST HTTP request, the body

contains the JSON representation of the names and values of the parameters of the Web method being

invoked In other words, the names and values of the parameters are passed as part of query string if the

request is a GET HTTP request, and as part of the body of the request if the request is a POST HTTP request

Next, the invoke static method calls the add_completed method on the WebRequest object that represents

the current GET or POST HTTP request, to register a private JavaScript function named onComplete as an

event handler for the completed event of the WebRequest object:

request.add_completed(onComplete);

This object raises its completed event when the request finally completes

The onComplete function is private to the invoke static method and cannot be accessed from outside

this method (discussed in more detail later in this chapter)

Next, the invoke static method calls the set_timeout method on the WebRequest object that represents

the current GET or POST HTTP request to set the request timeout:

Trang 9

if (timeout && timeout > 0) request.set_timeout(timeout);

Finally, it calls the invoke method on the WebRequest object to make the request to the Web service:

❑ url : This parameter is a string that contains the target URL

❑ queryString : This parameter is a dictionary that contains the names and values of parameters being sent to the server as a query string For example, in the case of Listing 14-7 , these parame-ters are the parameters of the Web method being invoked

Listing 14-8 : The _createUrl Static Method of the WebRequest Class

Sys.Net.WebRequest._createUrl =function Sys$Net$WebRequest$_createUrl(url, queryString){

if (!queryString) return url;

var qs = Sys.Net.WebRequest._createQueryString(queryString);

if (qs.length > 0) {

}

The _createUrl static method first calls the _createQueryString static method on the WebRequest class, passing in the dictionary that contains the names and values of the parameters being sent to the server as a query string:

Trang 10

Listing 14-9 presents the internal implementation of the WebRequest class’s _createQueryString

static method As you can see, this method takes the following two parameters:

❑ queryString : This parameter references a dictionary that contains the names and values of the

parameters to be embedded in the query string In the case of Listing 14-7 , this dictionary

contains the names and values of the parameters of the Web method being invoked

❑ encodeMethod : This parameter references a JavaScript function that takes a string as its

parameter and encodes certain characters in the string

Listing 14-9 : The _createQueryString Method of the WebRequest Class

The _createQueryString method first checks whether the caller has specified a value for the encodeMethod

parameter If not, it uses the JavaScript encodeURIComponent function as the encoding method:

if (!encodeMethod)

encodeMethod = encodeURIComponent;

Trang 11

The encodeURIComponent function takes a string as its parameter and replaces certain characters in the string with their UTF-8 encoding representations

Next, the _createQueryString method creates a StringBuilder object:

var sb = new Sys.StringBuilder();

Then, it iterates through the items in the dictionary passed into it as its first argument and takes the following steps for each enumerated item (in the case of Listing 14-7 , each enumerated item contains the name and value of a parameter of the Web method being invoked):

1 It uses the name of the enumerated item as an index into the dictionary to access the associated value of the parameter:

var obj = queryString[arg];

2 It calls the serialize static method of an ASP.NET AJAX class named JavaScriptSerializer , passing in the value of the parameter to serialize this value into its JSON representation:

var val = Sys.Serialization.JavaScriptSerializer.serialize(obj);

3 It calls the append method on the StringBuilder object to append the name of the parameter:

Regardless of whether the current request is a GET or POST HTTP request, the Web service must expect

to receive the JSON representations of the parameter values of the Web method being invoked It must also be able to deserialize these JSON representations into the objects of the types that the Web method expects before it passes these parameter values into the method This requires some changes in the nor- mal ASP.NET Web service–handling infrastructure to enable it to process requests coming from the ASP.NET AJAX applications, because the normal ASP.NET Web service handler expects to receive the names and values of the parameters of the Web method being invoked as part of the body of the SOAP message They also expect to receive the SOAP representations of the values of these parameters, not their JSON representations This is discussed in more detail later in this chapter

Trang 12

onComplete

As you saw in Listing 14-7 , the invoke static method of the WebServiceProxy class registers the

onComplete private JavaScript function as the event handler for the completed event of the WebRequest

object that represents the current request Listing 14-10 shows the internal implementation of this

function

Listing 14-10: The onComplete Private JavaScript Function

function onComplete(response, eventArgs)

var error = response.getResponseHeader(“jsonerror”);

var errorObj = (error === “true”);

if (errorObj)

result = new Sys.Net.WebServiceError(false, result.Message,

result.StackTrace,

result.ExceptionType);

var statusCode = response.get_statusCode();

if (((statusCode < 200) || (statusCode >= 300)) || errorObj)

Trang 13

error = result.get_exceptionType() + “ “ + result.get_message();

else error = response.get_responseData();

alert(String.format(Sys.Res.webServiceFailed, methodName, error));

} }

else if (onSuccess) onSuccess(result, userContext, methodName);

}

else { var msg;

new Sys.Net.WebServiceError(response.get_timedOut(), msg, “”, “”), userContext, methodName);

else alert(msg);

} }

When this function is invoked, two parameters are passed into it The first parameter references the

WebRequestExecutor object responsible for executing the current request As discussed in the previous chapters, the completion of a request does not automatically mean that everything went fine and the server response has successfully arrived Because the completed event could be raised for a number

of reasons, the onComplete method must first determine what caused the completed event to fire (as does any method registered for a WebRequest object’s completed event) The boldface portions of Listing 14-10 contain the code that makes this determination

As you can see in the following excerpt from Listing 14-10 , if the request has completed because something went wrong (for example, because the request timed out), the onComplete function invokes the failure JavaScript function if such a function has been specified Otherwise, it simply calls the

alert function to display the error massage in a pop-up box

var msg;

if (response.get_timedOut()) msg = String.format(Sys.Res.webServiceTimedOut, methodName);

else msg = String.format(Sys.Res.webServiceFailedNoMsg, methodName)

(continued)

Trang 14

If the request has completed because the server response has successfully arrived, the onComplete

function performs the following tasks:

1 It invokes the getResponseHeader method on the WebRequestExecutor object responsible for

executing the current request to return the value of the response header named Content-Type :

var contentType = response.getResponseHeader(“Content-Type”);

2 If the value of the Content-Type response header starts with the string “application/json” ,

the response contains a JSON object and, consequently, the onComplete method invokes the

get_object method on the WebRequestExecutor object to access this JSON object, and stores

the object in a local variable named result :

if (contentType.startsWith(“application/json”))

result = response.get_object();

3 If the value of the Content-Type response header starts with the string “text/xml” , the

response contains an XML document and, consequently, the onComplete method calls the

get_xml method on the WebRequestExecutor object to access this XML document, and stores

this document in the result local variable:

else if (contentType.startsWith(“text/xml”))

result = response.get_xml();

4 If the value of the Content-Type response header does not start with either the

“application/json” string or the “text/xml” string, the onComplete method calls the

get_responseData method on the WebRequestExecutor object to access the server response,

and stores it in the result local variable:

else

result = response.get_responseData();

Next, the onComplete method calls the getResponseHeader method on the WebRequestExecutor

object to return the value of a response header named jsonerror :

var error = response.getResponseHeader(“jsonerror”);

If the server response contains this response header, and if the value of this header is the string

“true” , the response contains information about an error that occurred when the server was processing

the current request The server response is stored in the result local variable, and the server uses the

jsonerror custom HTTP header to signal the onComplete method that the response contains

information about an error This information includes the error message, stack trace, and exception type

As the following excerpt from Listing 14-10 shows, the onComplete method creates an instance of a

class named Sys.Net.WebServiceError , passing in the error message, stack trace, and exception type,

and stores this instance in the result local variable:

Trang 15

var errorObj = (error === “true”);

if (errorObj) result = new Sys.Net.WebServiceError(false, result.Message, result.StackTrace, result.ExceptionType);

Next, the invoke method calls the get_statusCode method on the WebRequestExecutor object to return the HTTP status code of the server response:

var statusCode = response.get_statusCode();

The method then checks whether at least one of the following conditions is met:

❑ The HTTP status code is less than 200, or greater than or equal to 300, which indicates that a server error has occurred

❑ The server response contains a response header named jsonerror with a value of true Either of these conditions indicates a server error and, consequently, the invoke method takes the following steps to report the error:

1 If the onFailure parameter is not null , it means the caller of the invoke method has specified

a JavaScript function as the value of this parameter Consequently, the invoke method sets the _statusCode property of the result local variable to the server response’s HTTP status code, and invokes the JavaScript function referenced by the onFailure parameter, passing in three parameters The first parameter references the result local variable, the second parameter references the user context object, and the third parameter references the name of the Web method that was invoked:

result._statusCode = statusCode;

onFailure(result, userContext, methodName);

2 If the caller of the invoke method has not specified a value for the onFailure parameter, the method invokes the alert function to display the error message in a pop-up box:

alert(String.format(Sys.Res.webServiceFailed, methodName, error));

3 If the server response HTTP status code is a number equal to or greater than 200 but less than

300, this indicates that everything has gone fine on the server side and, consequently, the

invoke method invokes the JavaScript function referenced by the onSuccess parameter (if any), passing in three parameters The first parameter references the result local variable, the second parameter references the user context, and the third parameter contains the name of the Web method invoked:

else if (onSuccess) onSuccess(result, userContext, methodName);

Using WebSer viceProxy

Listing 14-11 presents a page that uses the WebServiceProxy class If you run this page, you’ll get the result shown in Figure 14-1

Trang 16

Listing 14-11: A Page that Uses the WebServiceProxy Class

var servicePath = “http://localhost/WebServicesViaJSON/Math.asmx”;

var methodName = “Add”;

var useGet = false;

var xValue = $get(“firstNumber”).value;

var yValue = $get(“secondNumber”).value;

var params = {x : xValue, y : yValue};

var userContext = $get(“result”);

var webServiceProxy = new Sys.Net.WebServiceProxy();

webServiceProxy.set_timeout(0);

request = webServiceProxy._invoke(servicePath, methodName, useGet, params,

onSuccess, onFailure, userContext);

}

</script>

</head>

<body>

<form id=”form1” runat=”server”>

<asp:ScriptManager runat=”server” ID=”ScriptManager1” />

Trang 17

This page consists of two text boxes where the end user enters two numbers When the user clicks the

Add button, the page connects to the Web service shown in Listing 14-12 in asynchronous fashion, invokes its Add method, and uses DHTML to display the result of this method The Web service is marked with the ScriptService metadata attribute, which enables it to process JSON messages from the client code Without this metadata attribute, the Web service will act like a normal Web service, which responds only to SOAP messages

Listing 14-12: The Web Service Used by Listing 14-11

<%@ WebService Language=”C#” Class=”MyNamespace.Math” %>

Trang 18

Now let’s walk through the implementation of the add JavaScript function Note that Listing 14-11

registers this function as the event handler for the click event of the Add button

The add function begins by instantiating an instance of the WebServiceProxy class:

var webServiceProxy = new Sys.Net.WebServiceProxy();

Next, it sets the request timeout:

webServiceProxy.set_timeout(0);

You must call set_timeout to set the request timeout Otherwise you’ll get an error

Next, the add function specifies the parameters that you need to pass into the _invoke method of the

WebServiceProxy instance The first parameter is the service path, which is the URL where the Web

service is located:

var servicePath = “http://localhost/WebServicesViaJSON/WebService.asmx”;

The second parameter is the name of the Web method being invoked, which is the Add method in this case:

var methodName = “Add”;

The third parameter is a Boolean value that specifies whether the WebServiceProxy instance must make

a GET or POST HTTP request to the Web service In this case, you set the Boolean parameter to false

because you want the WebServiceProxy instance to make a POST HTTP request to the Web service:

var useGet = false;

The fourth parameter must specify the names and values of the parameters of the Web method being

invoked As Listing 14-12 shows, the Add Web method takes two parameters named x and y The add

function retrieves the values of these two parameters from the user-entry text boxes:

var xValue = $get(“firstNumber”).value;

var yValue = $get(“secondNumber”).value;

var params = {x : xValue, y : yValue};

Trang 19

The fifth parameter is a reference to a JavaScript function that the WebServiceProxy instance will automatically invoke when everything goes fine and the server response arrives In this case, this is a JavaScript function named onSuccess , which simply displays the return value of the Add Web method:

function onSuccess(result, userContext, methodName) {

userContext.innerHTML = “ <b><u>” + result + “</b> </u>”;

}

The sixth parameter is a reference to a JavaScript function that the WebServiceProxy instance will automatically invoke when something goes wrong In this case, this JavaScript function is named

onFailure , which will be discussed shortly

The seventh (and final) parameter is a reference to the user context In this case, the user context references

a <span> HTML element with the id value of “result” , where the onSuccess and onFailure JavaScript functions display the result:

var userContext = $get(“result”);

As you can see in the following excerpt from Listing 14-11 , the add function calls the _invoke method

on the WebServiceProxy instance, passing in the seven parameters to invoke the Add Web method:

request = webServiceProxy._invoke(servicePath, methodName, useGet, params, onSuccess, onFailure, userContext);

The _invoke method returns a reference to the WebRequest object that represents the current request, and provides you with complete information about the current request

WebSer viceError

As shown previously in Listing 14-7 , the invoke static method of the WebServiceProxy class registers the onComplete method as an event handler for the completed event of the WebRequest object that represents the request made to the Web service Listing 14-10 contained the implementation of the

onComplete method This implementation is shown again in Listing 14-13 , with highlighted portions showing how the onComplete method invokes the onFailure JavaScript function when an error occurs This function takes three parameters The first parameter references a Sys.Net.WebServiceError object that contains the complete information about the error, the second parameter references the user context, and the third parameter is a string that contains the name of the Web method

Listing 14-13: The onComplete Method

function onComplete(response, eventArgs) {

if (response.get_responseAvailable()) {

var error = response.getResponseHeader(“jsonerror”);

var errorObj = (error === “true”);

(continued)

Trang 20

var statusCode = response.get_statusCode();

if (((statusCode < 200) || (statusCode >= 300)) || errorObj)

As you can see, the constructor of the Sys.Net.WebServiceError class takes four parameters:

result = new Sys.Net.WebServiceError(false, result.Message,

result.StackTrace,

result.ExceptionType);

Listing 14-14 presents the definition of the WebServiceError class

Trang 21

Listing 14-14: The WebServiceError Class

Sys.Net.WebServiceError =function Sys$Net$WebServiceError(timedOut, message, stackTrace, exceptionType){

get_timedOut: Sys$Net$WebServiceError$get_timedOut, get_statusCode: Sys$Net$WebServiceError$get_statusCode, get_message: Sys$Net$WebServiceError$get_message, get_stackTrace: Sys$Net$WebServiceError$get_stackTrace, get_exceptionType: Sys$Net$WebServiceError$get_exceptionType}

Sys.Net.WebServiceError.registerClass(‘Sys.Net.WebServiceError’);

The constructor of this class takes the following four parameters:

❑ timedOut : This Boolean parameter specifies whether the WebServiceError error was raised because of a request timeout As Listing 14-14 demonstrates, the WebServiceError constructor assigns the value of this parameter to a private field named _timedOut The WebServiceError class exposes a public getter named get_timedOut that you can call from your client code to access the value of this private field:

function Sys$Net$WebServiceError$get_timedOut(){

return this._timedOut;

}

For example, the last highlighted portion of Listing 14-13 (as shown again in the following code fragment) invokes the get_timedOut method on the WebRequestExecutor object responsible for executing the current request to return a Boolean value that specifies whether the request has timed out Note that the return value of the get_timedOut method is passed into the constructor of the WebServiceError class as its first argument:

var msg;

if (response.get_timedOut()) msg = String.format(Sys.Res.webServiceTimedOut, methodName);

else msg = String.format(Sys.Res.webServiceFailedNoMsg, methodName)

if (onFailure) onFailure(

new Sys.Net.WebServiceError(response.get_timedOut(), msg, “”, “”), userContext, methodName);

Trang 22

❑ message : This parameter is a string that contains the error message As you can see in Listing

14-14 , the WebServiceError constructor assigns the value of this parameter to a private field

named _message The WebServiceError class exposes a public getter named get_message

that you can call from your client code to access the value of this private field:

function Sys$Net$WebServiceError$get_message()

{

return this._message;

}

❑ stackTrace : This parameter is a string that contains the stack trace As you can see in

Listing 14-14 , the WebServiceError constructor assigns the value of this parameter to a

private field named _stackTrace The WebServiceError class exposes a public getter named

get_stackTrace that you can call from your client code to access the value of this private field:

function Sys$Net$WebServiceError$get_stackTrace()

{

return this._stackTrace;

}

❑ exceptionType : This parameter is a string that contains the fully qualified name of the

type of the exception that the server side code raised (if any) As you can see in Listing 14-14 ,

the WebServiceError constructor assigns the value of this parameter to a private field

named _exceptionType The WebServiceError class exposes a public getter named

get_exceptionType that you can call from your client code to access the value of this

Note that the WebServiceError also features a private field named _statusCode whose value is set

outside the constructor, as you can see in the boldfaced part of the following excerpt from Listing 14-13 :

if (!result || !errorObj)

result = new Sys.Net.WebServiceError(false /*timedout*/,

String.format(Sys.Res.webServiceFailedNoMsg, methodName), “”, “”);

result._statusCode = statusCode;

onFailure(result, userContext, methodName);

As a matter of fact, the WebServiceError class exposes a public property named get_statusCode that

you can call from your client code to access the value of the _statusCode private field:

function Sys$Net$WebServiceError$get_statusCode()

{

return this._statusCode;

}

Trang 23

Using WebSer viceError

Listing 14-15 presents a page that uses the WebServiceError class to get more information about an error This page invokes the Divide Web method of the Web service shown in Listing 14-16 This Web method takes two parameters, divides the first parameter by the second parameter, and returns the result

Note that this Web method raises a System.DivideByZeroException exception if its second parameter is 0

Listing 14-15: A Page that Uses the WebServiceError Class

Trang 24

Listing 14-15 (continued)

function divide()

{

var servicePath = “http://localhost/WebServicesViaJSON/Math.asmx”;

var methodName = “Divide”;

var useGet = false;

var xValue = $get(“firstNumber”).value;

var yValue = $get(“secondNumber”).value;

var params = {x : xValue, y : yValue};

var userContext = $get(“result”);

var webServiceProxy = new Sys.Net.WebServiceProxy();

webServiceProxy.set_timeout(0);

request = webServiceProxy._invoke(servicePath, methodName, useGet, params,

onSuccess, onFailure, userContext);

}

</script>

</head>

<body>

<form id=”form1” runat=”server”>

<asp:ScriptManager runat=”server” ID=”ScriptManager1” />

Trang 25

Listing 14-16: The Web Service

<%@ WebService Language=”C#” Class=”MyNamespace.Math” %>

return x / y;

} }}

Let’s walk through the implementation of the onFailure method The WebServiceProxy automatically invokes this method when something goes wrong The onFailure method takes three parameters: the first parameter references the WebServiceError object that provides complete information about the error, the second parameter references the user context object, and the third parameter is a string that contains the name of the Web method invoked

The onFailure method method instantiates a StringBuilder and populates it with the complete information about the error First, it calls the get_timedOut method on the WebServiceError object to return a Boolean value that specifies whether the request has timed out, and appends this Boolean value

Trang 26

Then, it calls the get_stackTrace method on the WebServiceError object to return a string that

contains the stack trace, and appends this string to the StringBuilder :

Next, it calls the get_exceptionType method on the WebServiceError object to return a string

that contains the fully qualified name of the type of the exception, and appends this string to the

StringBuilder In this case, the string is “System.DivideByZeroException” because this is the

exception that the Divide Web service method raises:

builder.append(“exceptionType: “);

builder.append(result.get_exceptionType());

builder.appendLine();

builder.appendLine();

Next, it calls the get_statusCode method on the WebServiceError object to return the server

response status code and appends it to the StringBuilder In this case, this status code will be 500

when the Divide method raises its System.DivideByZeroException :

If you run the page shown in Listing 14-16 and enter 0 for the second number, you’ll get the pop-up

box shown in Figure 14-2 , which displays the contents of the previously mentioned

StringBuilder

Trang 27

Calling Page Methods

As you saw in the previous section, if you have some server-side logic that you need to execute from your client code, you can create a Web service with a Web method that encapsulates this logic and invoke this method from your client code The downside of this approach is that it requires you to move this logic to a separate file with the extension asmx There are times when you need to keep this logic in your Web page together with the rest of the page

The ASP.NET AJAX framework enables you to encapsulate this logic in a method in your Web page and invoke this method from your client code, provided that this method meets the following requirements:

❑ It must be public

❑ It must be static

❑ It must be annotated with the WebMethodAttribute metadata attribute

Listing 14-17 presents a version of Listing 14-16 where the division logic is encapsulated in a public static method named Divide on the aspx page (the first boldface portion of the listing) instead of a Web service in a separate asmx file The service path is set to the URL of the current page, as shown in the bottom boldface portion of the listing and again here:

var servicePath = “/AJAXFuturesEnabledWebSite2/PageMethods.aspx”;

Figure 14 -2

Trang 28

Listing 14-17: A Page that Allows You to Invoke its Methods from Your Client Code

Trang 29

alert(builder.toString());

}

function divide() {

var servicePath = “/WebServicesViaJSON/PageMethods.aspx”;

var methodName = “Divide”;

var useGet = false;

var xValue = $get(“firstNumber”).value;

var yValue = $get(“secondNumber”).value;

var params = {x : xValue, y : yValue};

var userContext = $get(“result”);

var webServiceProxy = new Sys.Net.WebServiceProxy();

webServiceProxy.set_timeout(0);

request = webServiceProxy._invoke(servicePath, methodName, useGet, params, onSuccess, onFailure, userContext);

} </script>

</head>

<body>

<form id=”form1” runat=”server”>

<asp:ScriptManager runat=”server” ID=”ScriptManager1” />

Trang 30

Calling Custom Methods

If you have some application logic that you need to execute from your client script, you can encapsulate

it in a method, and invoke this method from your client script in asynchronous fashion The fundamental

question is where this method should go Two options have been discussed thus far:

❑ You can turn this method into a Web method, which is part of a Web service in a separate file

with extension asmx

❑ You can add this method directly to your Web page

There may be times when neither of these two solutions meets your requirements because this method

must be part of a custom class that is neither part of a Web service nor a Web page The most common

application of this scenario is what is known as a Web services bridge

As you saw in previous chapters, the ASP.NET AJAX network programming infrastructure uses

XMLHttpRequest to communicate with the server Due to security considerations, XMLHttpRequest

cannot be used to make requests to resources that reside on a site other than the site from which the

current page was downloaded in the first place

Therefore, if your client code needs to communicate with a Web service that does not reside on the same

site from which your client code was downloaded, it has no choice but to do this indirectly through its

downloading site This means that you need to encapsulate or wrap the logic that invokes the

Web method of the remote Web service in a method on your site, and have your client side invoke this

method instead of directly invoking the remote Web method

This raises the following question: Where should this wrapper method go? The ASP.NET AJAX

frame-work provides you with three choices:

❑ Make this wrapper method a Web method that belongs to a Web service on your site This Web

service acts as an intermediary between your client side code and the remote Web service, as

discussed earlier in this chapter

❑ Make this wrapper method a public static page method that belongs to a Web page on your site

This public static page method acts as an intermediary between your client side code and the

remote Web service, as discussed earlier in this chapter

❑ Make this wrapper method a public method that belongs to a custom class on your site This

custom class acts as an intermediary between your client side code and the remote Web service

This option is called a Web services bridge and is discussed in this section

To use a Web services bridge, you must take the following steps:

1 Add your custom class to the App_Code directory of your application This saves you from

having to manually compile your class Another option is to compile your custom class into an

assembly and reference the assembly from your application

2 Create a file with extension .asbx that describes your custom class, and add the file to the root

directory of your application

3 Instruct the IIS Web server to hand over to the ASP.NET framework all resource requests with

extension asbx

Trang 31

The best way to understand these three steps is to look at an example that uses them

Listing 14-18 presents a new version of the Divide method shown in Listing 14-17 As you can see, the new version is now an instance method of a custom class named Math

Listing 14-18: The Math Custom Class

using System;

namespace CustomComponents{

public class Math {

public double Divide(double x, double y) {

if (y == 0) throw new DivideByZeroException();

return x / y;

} }}

The second step of the previously mentioned three-step procedure requires you to create a new file with extension asbx that describes the Math custom class defined in Listing 14-18 Listing 14-19 presents the contents of the Math.asbx file As you can see, an asbx file is just an XML file

Listing 14-19: The.asbx File that Describes the Math Custom Class

<?xml version=”1.0” encoding=”utf-8” ?>

<bridge namespace=”MyNamespace” className=”MyMath”>

<proxy type=”CustomComponents.Math, App_Code”/>

The bridge document element contains a child element named proxy that exposes an attribute named

type You must set the value of the type attribute to the fully qualified name of your custom class, including its complete namespace containment hierarchy, plus its location In this case, the fully qualified name of the custom class is CustomComponents.Math , which is located in the App_Code directory of the application

The proxy element basically describes your custom class As Listing 14-19 shows this element contains a child element named method that exposes an attribute named name You must set this name attribute to the name of the method being described, which in this case is the Divide method of your custom class

Ngày đăng: 09/08/2014, 06:23

TỪ KHÓA LIÊN QUAN