65.9K
CodeProject is changing. Read more.
Home

WebService Behavior

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.30/5 (10 votes)

Feb 20, 2004

4 min read

viewsIcon

101405

downloadIcon

663

The WebService behavior enables methods that are implemented on Web Services to be called from client-side script in a web page. The main advantage of the WebService behavior is that it is now possible to update contents of the web page without reloading the whole page.

Introduction

The WebService behavior enables methods that are implemented on Web Services to be called from client-side script in a web page. The main advantage of the WebService behavior is that it is now possible to update contents of the web page without reloading the whole page. For example, in this article I have used the behavior to display continuously quotes at regular intervals without reloading the page. You can use this feature to display continuously featured products, latest news etc.

XML Web services

XML Web services are program components that allow you to build scalable, loosely coupled, platform-independent applications. XML Web services enable disparate applications to exchange messages using standard protocols such as HTTP, XML, XSD, SOAP, and Web Services Description Language (WSDL).

To study the WebService behavior I have written a simple FactorialService WebService and QuoteService WebService. FactorialService WebService contains the following WebMethod

  <WebMethod()> Public Function Factorial(
      ByVal Number As Integer) As String
    Try
     If Number = 0 Then
      Return 1
     Else
      Return Number * Factorial(Number - 1)
     End If
    Catch ex As Exception
     Return ex.Message
    End Try
  End Function

QuoteService WebService contains the following WebMethod.

  <WebMethod()> Public Function GetQuote() As String
    Select Case getRand.Next(4)
     Case 0
      Return "Where there is a will there is a way"
     Case 1
      Return "Necessity is the mother of invention"
     Case 2
      Return "Be the head and not the tail"
     Case 3
      Return "Rome was not built in a day"
    End Select
  End Function

Attaching the WebService Behavior

The WebService behavior is implemented with an HTML Component (HTC) file as an attached behavior. So it can be used in Microsoft Internet Explorer 5 and later versions.

To attach a WebService behavior to a page we need to follow the following steps,

  • First download the WebService HTC File file and put a copy in the same directory as the pages that use the behavior.
  • The next step in using the WebService behavior is to attach it to an HTML element using the STYLE attribute and set the id attribute so that this element can be easily referenced in script.
<div id="Service" style="behavior:url(webservice.htc)"></div>

In our code we have used the following div tag:

<div id="Service" style="BEHAVIOR:url(webservice.htc)" 
  onresult="Service_Result()"></div>

The event handler for the Onresult event is the default for the behavior. We will be shortly dealing with it.

Identifying Web Services

The useService method is used to identify the WebService. This method has two parameters i.e.. "ServiceURL" and "FriendlyName". The method maps the Web Service URL to a FriendlyName. The friendly name for the Web Service is later used directly in script to reference the Web Service URL.

The syntax of the useService method is as follows:

id.useService("ServiceURL","FriendlyName");

The id is the id attribute of the HTML tag to which the behavior is attached.

In our code we have used the following Javascript code:
  //---------------------------------------------------
  // Init is used to indentify the webservices
  //---------------------------------------------------
    function Init()
    {
    //useService is used to identify the FactorialService webservice
     Service.useService("WebServices/FactorialService.asmx?WSDL",
        "FactorialService");
    //Function is used to call the QuoteService webservice at 
     //regular intervals
     GetNewQuote();
     setInterval( "GetNewQuote()", 5000 ) 
    }
  //-----------------------------------------------------
  // GetNewQuote is used to indentify the webservices and 
  // call webmethods at the same time
  //-----------------------------------------------------
    function GetNewQuote()
    {
     //useService is used to identify the QuoteService webservice
     Service.useService("WebServices/QuoteService.asmx?WSDL","QuoteService");
     
     // callService method is used to invoke methods and 
     // QuoteService_Result is the callback event handler
     
     intCallID = Service.QuoteService.callService( QuoteService_Result, 
        "GetQuote" );
    }

Init function is called in the body tag as shown:

<body bgColor="#ffffff" text="#000000" link="#0000cc" vLink="#0000cc" 
  aLink="#ff0000" leftmargin="0" topmargin="0" marginwidth="0"
  marginheight="0" onload="Init()">

Calling WebMethods

The callService method is used to call WebMethods of the WebService. The WebService behavior supports both synchronous and asynchronous remote procedure calls to WebServices. The asynchronous mode of remote method invocation is used as default.

The syntax of the callService method is as follows:

iCallID = id.FriendlyName.callService([CallbackHandler,] 
  "MethodName", Param1, Param2, ...);

The first parameter of the callService method is a callback handler function to process the results received from the method call which is optional. If callback handler is absent, then the event handler for the onresult event is used. The onresult event is fired by the WebService behavior as soon as the result of the remote call is completed. MethodName is the name of the WebMethod while Param1, Param2, ... are the parameters to be passed to the WebMethod.

In our code, when you click the Callback button, CallBackButton_Click event is fired which calls the Factorial method of the WebService. Factorial_Result serves as the callback handler.

 
  function CallBackButton_Click()
  {
   intCallID = Service.FactorialService.callService( 
      Factorial_Result, "Factorial", txtFactorial.value );
  }

  function Factorial_Result( result )
  {
    if ( result.error )
     {
      lblFactorial.innerText = result.errorDetail.string;
     } 
     else
     {
     lblFactorial.innerText = "The factorial of " + 
      txtFactorial.value + " is " + result.value;
     }
  
  }

When the Normal button, NormalButton_Click event is fired which calls the Factorial method of the WebService.

  function NormalButton_Click()
  {
     intCallID = Service.FactorialService.callService( 
      "Factorial", txtFactorial.value );
  }

In the absence of the callback handler, onresult event handler of the html tag is fired which in turn calls the Service_Result method.

  function Service_Result()
  {
   if ( event.result.error )
   {
    lblFactorial.innerText = event.result.errorDetail.string;
   } 
   else
   {
    lblFactorial.innerText = "The factorial of " + 
      txtFactorial.value + " is " + event.result.value; 
   }
  }

For the QuoteService, GetNewQuote is used to identify the WebService and call WebMethods simultaneously. QuoteService_Result is the callback event handler for the QuoteService.

  //--------------------------------------------------
  // GetNewQuote is used to indentify the webservices and 
   // call webmethods at the same time
  //---------------------------------------------------
      function GetNewQuote()
      {
       //useService is used to identify the QuoteService webservice
       Service.useService("WebServices/QuoteService.asmx?WSDL",
                "QuoteService");
       
       // callService method is used to invoke methods and 
         // QuoteService_Result is the callback event handler
       
       intCallID = Service.QuoteService.callService( 
              QuoteService_Result, "GetQuote" );
      }
  //------------------------------------------------------
  // QuoteService_Result is the callback event handler 
   // for the QuoteService
  //-------------------------------------------------------
      function QuoteService_Result(result)
      {
       if (result.error) 
       {
       divQuote.innerText = result.errorDetail.string;
       }
       else
       {
       divQuote.innerText = result.value;
       }
      }

The Result Object

Whenever callService is invoked, an object containing results data is generated. When the eventhandler is present, the result object is referenced as the name of the parameter being passed to the user-defined callback function. In the absence of the eventhandler, the result object is referenced as event.result when the event handler is absent or as the name of the parameter being passed to the user-defined callback function.

Here is the list of properties of event.result we have used in our code..

event.result.error Returns a boolean value
event.result.errorDetail.string Returns the detailed information of the error
event.result.value Returns result of the webmethod

When the eventhandler is present, the result object is referenced as the name of the parameter being passed to the user-defined callback function. Here is the list of properties it exposes.

result.error Returns a boolean value
result.errorDetail.string Returns the detailed information of the error
result.value Returns result of the webmethod

When an error or problem occurs for a method call, the error property is set to true and the errorDetail is generated at runtime. The errorDetail object exposes several properties, which can be quite helpful in diagnosing the error.

It is always good programming practice to verify a function call. Hence in our examples, the error property is checked to determine if the remote method invocation was processed successfully.

Limitations

The following are the limitations of the behavior

  1. The behavior accesses Web Services in the same domain as the web page.
  2. There is no direct support for complex types such as DataSets, DataTables, collections or custom objects, etc. It supports all the base .NET types and arrays of the the base .NET types