Search

HTML Client for Web Services using DHTML Behavior

0 views

Understanding the Components

When you build a web application that needs to perform logic on a server, the usual path is to embed that logic in the page or to call a server‑side script. An alternative is to expose the logic as a Web Service and let the page talk to it over HTTP. In this example the page is pure HTML with only JavaScript, no .NET references or ActiveX controls. The communication is handled by a DHTML behavior – a small piece of code that can be attached to any element in Internet Explorer 5.5 and newer. The behavior reads the service description from the WSDL, generates a JavaScript interface, and raises events when results return.

Web Services are built on top of standard Internet protocols such as HTTP and SOAP. The service exposes a set of methods that clients can call by sending an XML message. The server processes the request and returns an XML response. Because the format is platform independent, any client that can build a SOAP request can use the service. DHTML behaviors take advantage of this by parsing the WSDL, wiring up a call stack, and exposing a simple JavaScript API.

The benefit of this architecture is that you can write complex logic once, host it on a server, and have many static HTML pages call it without writing server‑side code for each page. The client page stays lightweight, and the server can be maintained separately. For developers who are comfortable with JavaScript but need to leverage .NET libraries, this approach offers a clear separation of concerns.

Because the behavior is specific to Internet Explorer, you will need to host the page in an IE environment to see the effect. The file that implements the behavior, webservice.htc, can be downloaded from the Microsoft sample library. Save it in the same folder as the HTML file, and the behavior will load automatically when the page is opened in IE.

In summary, the three key players in this scenario are: a .NET Web Service that exposes one or more methods; a DHTML behavior that turns those methods into JavaScript calls; and an HTML page that loads the behavior, maps a friendly name to the service URL, and invokes the methods when the user interacts with the page.

Crafting the C# Web Service

The first step is to create the server component that performs the calculation. The service is defined by a simple class decorated with the [WebService] attribute. Inside the class, each public method that you want to expose must be marked with [WebMethod]. The following code shows a minimal example that adds two integers:

Prompt
<%@ WebService Language="C#" Class="TestWS" %></p> <p>using System;</p> <p>using System.Web.Services;</p> <p>[WebService]</p> <p>public class TestWS : System.Web.Services.WebService</p> <p>{</p> <p> [WebMethod]</p> <p> public int Add(int num1, int num2)</p> <p> {</p> <p> return num1 + num2;</p> <p> }</p> <p>}</p>

Save the file as TestWS.asmx and drop it into a folder that is served by IIS. When you navigate to the file in a browser, you should see a page that says “Web Service Description” and a link to the WSDL. The WSDL contains a machine‑readable description of the Add method, its input parameters, and its return type. The DHTML behavior will later request this WSDL to build the JavaScript interface.

Because this service uses only standard .NET types, it requires no additional configuration. However, you must ensure that the folder is configured for ASP.NET and that the .asmx file is mapped correctly. If you are using a newer version of IIS, the default settings will typically pick this up automatically. The service can be tested by sending a SOAP request directly with a tool like SoapUI or by navigating to http://localhost/YourFolder/TestWS.asmx?op=Add in a browser and entering values in the form that appears.

Once the service is deployed and the WSDL is accessible, you can proceed to the client side. The client will reference the WSDL URL and the service will become available to the JavaScript code through the behavior. This separation means that future changes to the logic do not require any modifications to the static HTML pages.

Setting Up the HTML Page

With the service in place, the next step is to write an HTML page that will use the behavior. The page must include the webservice.htc file in the same directory. The behavior is attached to a <div> element by setting its style attribute. In the example below, the id of the element is service and the onresult attribute points to a JavaScript function that will handle the response:

Prompt
<div id="service" style="behavior:url(webservice.htc)" onresult="onWSresult()"></div></p>

Next, the script needs to map a friendly name – Calculator – to the service URL. This mapping occurs in the onload handler of the page so that the service is ready before any call is made. The mapping code uses the useService method exposed by the behavior:

Prompt
<body onload="service.useService('http://localhost/YourFolder/TestWS.asmx?WSDL','Calculator');"></p>

All of the interactive elements – two input fields for numbers, a read‑only field for the result, and a button to trigger the call – are placed after the div. Each input is given a name attribute so that JavaScript can access its value using document.getElementsByName or, in the example, by referencing the global variables created automatically when the page loads. The final structure of the page looks like this:

Prompt
<html></p> <p><head></p> <p><title>Calculator</title></p> <p><script language="JavaScript"></p> <p>var iCallID;</p> <p>function ExecuteWS()</p> <p>{</p> <p> iCallID = service.Calculator.callService("Add", num1.value, num2.value);</p> <p>}</p> <p>function onWSresult()</p> <p>{</p> <p> if (event.result.error && iCallID == event.result.id) {</p> <p> var xfaultcode = event.result.errorDetail.code;</p> <p> var xfaultstring = event.result.errorDetail.string;</p> <p> var xfaultsoap = event.result.errorDetail.raw;</p> <p> document.writeln("ERROR. Method call failed!");</p> <p> document.writeln("Call ID:" + iCallID);</p> <p> document.writeln("Fault Code:" + xfaultcode);</p> <p> document.writeln("Fault String:" + xfaultstring);</p> <p> document.writeln("SOAP Data:" + xfaultsoap);</p> <p> } else if (!event.result.error) {</p> <p> sum.value = event.result.value;</p> <p> }</p> <p>}</p> <p></script></p> <p></head></p> <p>Number: <input type="text" name="num1"></p> <p>Number: <input type="text" name="num2"></p> <p>Total: <input type="text" name="sum" readonly></p> <p><button onclick="ExecuteWS()">Add Numbers</button></p> <p></body></p> <p></html></p>

The page does not contain any server‑side code. All interaction with the service is handled through JavaScript. The behavior will send a SOAP request when callService is invoked and will raise the onresult event when the response arrives.

Executing the Service Call

The heart of the client logic is the ExecuteWS function. It records the call ID returned by callService so that the response can be matched to the request. This is useful if multiple calls are made in quick succession. The call uses the friendly name – Calculator – and the method name – Add – followed by the two arguments from the input fields.

The onWSresult function receives the event that the behavior raises. The event object contains a result property with several sub‑properties:

  • error – a boolean that is true if the service reported a fault.
  • errorDetail – an object containing the fault code, string, and raw SOAP message when an error occurs.
  • value – the return value of the method when the call succeeds.
  • id – the call ID that was returned by callService

    In the function, the first check ensures that the response belongs to the current call by comparing event.result.id with the stored iCallID. If an error is detected, the details are written to the page using document.writeln. In a production page you might want to update a <div> instead, but for clarity the example writes directly to the document stream.

    If the call succeeds, the sum input field is updated with the numeric result. Because the field is marked readonly, users cannot change it directly, only through the service call. This simple pattern can be extended to many methods by adding additional input fields and updating the callService parameters accordingly.

    The asynchronous nature of callService means the page remains responsive while waiting for the server. The browser does not block; the user can continue to interact with other parts of the page. When the server returns, the onresult event is triggered automatically.

    Testing the Solution

    After the service is deployed and the HTML page is saved in the same folder as webservice.htc, open the page in Internet Explorer. The page displays two blank input boxes labeled “Number” and a third field labeled “Total” that shows nothing initially. A button reads “Add Numbers.”

    Enter a valid integer in each number field, for example and , and click the button. The page should display in the Total field after a brief moment. This confirms that the JavaScript call reached the server, the service added the numbers, and the response was handled correctly.

    To test error handling, input a non‑numeric value such as xyz into one of the number fields and click the button. The server will return a SOAP fault because the method expects integers. The onWSresult function will detect the fault, and the page will write a series of messages to the document: “ERROR. Method call failed!,” followed by the Call ID, Fault Code, Fault String, and the raw SOAP data. These messages provide insight into what went wrong and can be used for debugging.

    Because the page and the service are both located on the same local server, latency is minimal and responses appear quickly. In a real deployment, you would host the service on a production web server and link the page to that URL. The DHTML behavior would retrieve the WSDL from the remote server, allowing any HTML page to call the service regardless of its location.

    With the basic structure in place, you can extend the service to expose additional methods – such as subtraction, multiplication, or more complex business logic – and add corresponding input fields and buttons to the page. The same pattern of mapping the service, calling the method, and handling the result remains unchanged, making it straightforward to scale the solution.

Suggest a Correction

Found an error or have a suggestion? Let us know and we'll review it.

Share this article

Comments (0)

Please sign in to leave a comment.

No comments yet. Be the first to comment!

Related Articles