he Web browser/Web server combination used today was originally designed to deliver HTML, which implicitly contains display information as well as data. But this doesn’t mean that the Web server must deliver HTML. When a page contains an element, or a hyperlink to a ZIP file, the Web server delivers the content in its native format. OK, so the content might be UU-encoded for transmission across the Internet, but it certainly isn’t HTML when it arrives.
Delivering Simple Text Strings As an example of a non-HTML information delivery, assume that a server uses one of the timeserver resources on the Internet to accurately maintain its internal clock. Therefore you can easily deliver the current time value from the server to any client upon request by generating a response containing the server’s current time as a simple string. In ASP.NET, for example, you can use:
<%@Page Language="VB" %>
The data stream returned from the Web Server contains the usual HTTP headers required for communication between server and client, but the content of the returned “page” is just something like 10:25:07. A Web browser will display this, but any other application that references the page can use the text string as required.
Author’s Note: Notice that the preceding code snippet sets the MIME type (using the ContentType property in ASP.NET) to tell the browser what to expect. The obvious choice is to use “text/text” as the MIME type value, but that confuses some browsers because they then try and use the file extension (.aspx) to decide what to do with the content. Using “text/html” effectively tells the browser just to display it, even though there are no or elements in the content. As you can see, the Internet provides everything required for the basic mechanism of making server calls and returning responses.
But the World Wants XML! But simple text strings are not generally the most useful type of data. Looking at the issues in a more general way, what’s really needed is a way of delivering information that:
Has a structure defined through some universal standard
Can represent complex data types, and not just simple string values
Allows the recipient to identify the structure and data types within the content
Supports validation of the content for both structure and permitted content
All these features have, in fact, long been on the agenda of both the Internet standards bodies (such as the W3C) and of those developers and corporations whose life revolves around data interchange. The result today is the evolving standards for Web services, as supported by most of the major players in the IT world?such as IBM, Microsoft and Sun. You can glean some idea of the huge amount of work going on in the Web services arena here.
Delivering a DataSet It goes without saying that the obvious choice of format for data exposed by a Web site or application is one that best suits the data itself. Anything much beyond a single value, such as a string, requires a data structure that can store multiple items; therefore some kind of rowset or recordset seems the ideal solution. The columns can contain items of different data types, such as integers, strings, real numbers, currency values, etc. There can also be one or more rows, providing the required flexibility for exposing all kinds of data.
For those of us who live in the Microsoft .NET world, the ideal container for a rowset is the .NET DataSet class. DataSets can contain one or more tables (rowsets), the metadata that defines features such as primary and foreign keys, default values, etc., and the relationships between the tables. The DataSet class is also optimized for reading and writing content as XML using Microsoft’s proprietary diffgram format.
You can easily expose a DataSet object from a Web site or application using ASP.NET Web services, and thereby provide the best opportunity for any client to use the data in the way that they choose. And, best of all, clients that don’t understand .NET and the DataSet diffgram format can still use the data by treating it as a “normal” XML document.
Two Ways to Access ASP.NET Web Services Because of the hive of activity in the Web services world, Microsoft chose to include Web services technology in their release of the .NET Framework a couple of years ago. You create a Web service by building a Class file that has the .asmx file extension. The Web server (IIS) maps this to the ASP.NET engine, which compiles and executes the class to expose the functionality it contains to the current request and response objects.
Effectively, this means that you can “call” a Web service using a standard HTTP request, and get back an XML-formatted string as the response (see Figure 1).
An Example?Exposing Site Traffic Data The author’s site serves as an example of exposing data via Web services. Figure 3 shows the main Web service page. You can see that there are four public methods available. Each returns a diffgram containing the relevant information.
Building a Web Service In essence, all you need to do in .NET to create a Web service is to decorate the Class declaration with the WebService attribute, and then mark each method that you want to expose with the WebMethod attribute. To expose the method via your Web server, create an .asmx page containing a WebService page directive, supplying the language and class name of the Web service implementation as shown below.
Alternatively, you can create a new Web service file using Visual Studio, which automatically creates an .asmx page containing the WebService page directive and a class file in the project language and associates the two via the Codebehind attribute in the page directive:
Unlike ASP.NET Web forms (.aspx files), ASP.NET and Visual Studio do not import basic namespaces into Web service files by default, so at minimum, you’ll need to import the System, System.Web, and System.Web.Services namespaces. In addition, import the namespaces for any data access classes you use (the sample code uses both System.Data and System.Data.SqlClient). Don’t forget the System.Configuration namespace, which lets you access settings in the web.config file to extract a connection string or other configuration information. You may need other namespaces as well, such as System.Collections (if your code uses a collection class such as an ArrayList), or System.Xml to access XML documents:
You need to decorate the PublicClass statement with the WebService attribute and set its properties, using the rather odd syntax required for VB.NET. The Description property value should contain a brief description of the service, and set the Namespace value to something unique to your site and service that differentiates it from all other Web services on the Internet:
_ Public Class PublicIISLogs _ Public Function TrafficSummary() As DataSet Dim oDS As New DataSet ... code to fill DataSet as required ... Return oDS End Function End Class
Author’s Note: The Namespace property value does not have to be a URI?it can be anything unique, such as a GUID. Also note that the class name in the page directive must match the name of the public class you define within the file or assembly that implements the Web service.
The WebService attribute added to the public class defines the Web service itself. You mark any Public methods within it (any Sub or Function in VB.NET) that you want to expose through the Web service using the WebMethod attribute as shown in the previous listing. You can add Description and other properties to the WebMethod declaration to control caching, ASP.NET session support, buffering and transaction support. Search the .NET SDK for “WebMethodAttribute Members” for more details.
The Sample Web Service The sample PublicIISLogs Web service (see the sample code) exposes four Web methods, including one named TrafficSummary that returns data on the total traffic for our site over the past 52 weeks. Here’s the code for that method:
_ Public Function TrafficSummary() As DataSet Try Dim sTableName As String = "WeekSummary" Dim dFromDate As Date = DateTime.Now.AddMonths(-12) Dim sSQL As String = GetSQLStatement( _ sTableName, dFromDate) Return GetDataSet(sSQL, sTableName) Catch oErr As Exception Return GetErrorDataSet(oErr.Message) End Try End Function
You can see that it uses three other routines within the class file: GetSQLStatement, GetDataSet, and GetErrorDataSet. These are all declared as Private and aren’t available as Web service methods because they don’t have the WebMethod attribute. The GetSQLStatement method builds the rather complex SQL statement required to extract rows from the IISLogs database, using the table name and starting date values passed into this routine as parameters:
Private Function GetSQLStatement(sTableName As String, _ dFromDate As Date) As String Dim oCal As New System.Globalization.GregorianCalendar Dim iYear As Integer = dFromDate.Year Dim iWeek As Integer = oCal.GetWeekOfYear( _ dFromDate, Nothing, Nothing) sSQL = "SELECT Year = MAX(TYearNumber), Week = _ MAX(TWeekNumber), " _ & "Hits = SUM(HitCount), KBytes = SUM(KBytes), " _ & "Sessions = SUM(Sessions) FROM " & sTableName _ & " WHERE ((TYearNumber = " & iYear.ToString() _ & " AND TWeekNumber > " & iWeek.ToString() _ & ") OR (TYearNumber > " & iYear.ToString() _ & ")) GROUP BY TYearNumber, TWeekNumber " _ & "ORDER BY TYearNumber, TWeekNumber" Return sSQL End Function
The method returns the completed SQL statement. The GetDataSet method uses this statement and the table name to populate a DataSet with the required results. The source database connection string comes from a key value named IISLogs within the web.config file:
Private Function GetDataSet(sSQL As String, _ sTableName As String) As DataSet Dim sConnect As String = _ ConfigurationSettings.AppSettings("IISLogs") Dim oDS As New DataSet() Dim oConn As New SqlConnection(sConnect) Dim oDA As New SqlDataAdapter(sSQL, oConn) oDA.Fill(oDS, sTableName) Return oDS End Function
The method returns the populated DataSet object.
Managing Error Situations and Returning Status Information One interesting problem that arises regularly when dealing with a Web service involves managing errors. It’s easy enough to trap an exception in the ASP.NET code, and get details of the error that caused the exception to be raised. But how do you communicate error information to the client is a useful way?
If you’re passing back a simple string, such as the current time (as described at the start of this article), you could just trap the error and send back a string such as: “Sorry, an error occurred”, or even something more detailed like: “The remote time server failed to respond”. However, if the client is expecting a non-string data type then you can’t send back a string.
For example, if the Web service usually returns an integer value, you might be able to use a specific value (perhaps -1 or 999) to represent an error. This pre-supposes that the client and server can agree beforehand on what return values are valid, what values are treated as errors, and what error each value represents.
But in this example, the clients expect a DataSet, and so your choices are to send back a DataSet or the value Nothing (null in C#), to indicate a failure, but that’s not particularly expressive or useful. Instead, the sample code creates a DataSet containing a single table named Errors, which has a single column named Message. When an error occurs, this column contains the text error message returned to the client. The code calls the GetErrorDataSet function whenever any error occurs while executing the TrafficSummary method:
Private Function GetErrorDataSet(sMessage As String) _ As DataSet Try Dim oDT As New DataTable("Errors") oDT.Columns.Add("Message", _ System.Type.GetType("System.String")) Dim oDR As DataRow = oDT.NewRow() oDR("Message") = sMessage oDT.Rows.Add(oDR) Dim oDS As New DataSet("Error") oDS.Tables.Add(oDT) Return oDS Catch Return Nothing End Try End Function
Figure 4 shows an example of the XML returned when an error occurs.
Consuming Web Services While the previous sections have blithely mentioned sending SOAP or HTTP requests to the server, how do you actually accomplish that task? Sending an HTTP request is easy?the client just has to send an HTTP GET or POST request to the Web service, specifying the method they want to execute and any parameters that method requires. The example Web service shown above takes no parameters, so a request looks like this:
When the Web service method does require parameters, you add them to the URL as a query string for GET requests, or place them into the body of a
with two text boxes for the parameter values (the week and year number) and a “submit” button; plus an ASP.NET DataGrid control:
Starting from week: year:
The “submit” button simply executes a routine named ShowData. Because the assembly is in the bin folder of the ASP.NET application, you can reference it by importing the namespace (in this case the name of the public class within the assembly). Then, within the ShowData routine, create a new instance of the proxy class and call its methods.
The ShowData routine is listed below. The method it calls is named TrafficSummaryFromWeekYear, which takes the starting week and year as parameters. You get these values from the text boxes on the page, and bind the result?a DataSet object?to the ASP.NET DataGrid control to display the contents of the WeekSummary table:
<%@Import Namespace="IISLogsParameters" %> Sub ShowData(sender As Object, args As EventArgs) Dim oWS As New IISLogsParameters() dgr1.DataSource = oWS.TrafficSummaryFromWeekYear(txtWeek.Text, _ txtYear.Text) dgr1.DataMember = "WeekSummary" dgr1.DataBind() End Sub
Figure 5 shows the example page in use. It contains extra formatting attributes on the DataGrid to provide the results you see here, but functionally the code is as simple as we’ve just described.
Accessing a Web Service with the IE5 Web Service Behavior The ASP.NET example provides a neat and simple solution to consuming a Web service, though it only works because ASP.NET understands the objects we’ve used?an ASP.NET Web service and a .NET DataSet. Other clients may not have the same level of support for .NET objects, but that doesn’t mean they can’t be persuaded to use a Web service.
For example, Internet Explorer has no concept of.NET, and the scripting languages it provides (VBScript and JScript) are not managed code languages. However, IE (version 5 and higher) can take advantage of a script behavior (a HyperText Component or HTC) that you can use to interact with a Web service from client-side script.
You can find more information and download the IE5 Web service behavior here. You place the behavior file (which is named webservice.htc) on your Web server and the client then fetches it when required.
The ie5-client.aspx page (in the ie5-client folder) demonstrates the use of this Web service behavior. You insert the behavior component into a page using the standard approach for HTCs, by defining it in a style attribute of an element using the special behaviour:url() selector. The example page attaches the behavior to the element that contains the page heading:
Accessing a Web service using the IE5 Web service Behavior
The remainder of the visible part of the page consists of a couple of text boxes for the week and year values, and a “submit” button that runs the client-side code (as the button is not within a
it will not cause a postback when clicked). There’s also a element that shows interactive status messages, and a
to display the results:
Starting from week: year:
The code required to use the Web service behavior is not complex, but can become quite lengthy if you choose to handle errors properly. It also makes sense to load the results of the Web service method call asynchronously, so that the page can continue to operate (and display status details) as the Web service is located and accessed?which also requires additional code.
Basically, you start by calling the useService method of the component to establish the connection to the Web service. This downloads the WSDL service definition (you can see that “?WSDL” is appended to the URL as a query string), and establishes a “friendly name” used to refer to the Web service later in the code.
After this, you can call the method(s) of the Web service using the “TrafficData” friendly name. The following code collects the week and year values from the text boxes on the page, and uses those as parameters to call the TrafficSummaryFromWeekYear method:
var sWeek = document.all['txtWeek'].value; var sYear = document.all['txtYear'].value; var iCallID = htcWService.TrafficData.callService(dataLoaded, "TrafficSummaryFromWeekYear", sWeek, sYear);
The first parameter to the callService method shown in the last line of the preceding code is the name of a delegate or event handler to execute when the component has finished downloading the SOAP message returned by the Web service. The next listing shows that dataLoaded delegate function. It first checks for an error, and if all is well, creates a new instance of the MSXML parser provided with IE5 (the code uses the free-threaded version because it has to perform an XSLT transformation on the content later for display):
Again, the code uses asynchronous loading, this time by specifying the delegate named changeFunction to be executed each time the readystate property of the MSXML parser changes. Now you can start loading the parser with the XML document that lies within the SOAP envelope that the Web service behavior received from the Web service. The Web service behavior passes a “result” object to this callback function. You get at the “content” by accessing the raw.xml property of the result object. This XML document is, of course, the diffgram that represents the .NET DataSet.
As the MSXML parser initializes, extracts the XML document from the SOAP package, loads it, parses it and validates it, the readystate property of the parser changes at each stage, so the changeFunction method gets called repeatedly. It’s only when the readystate property reaches the value 4 that the process is complete. At this point you can check for an error, and if everything succeeded, call another routine that will display the XML document:
function changeFunction() { if (oXMLData.readyState == 4) { if (oXMLData.parseError.errorCode != 0) // ... display error details ... else { showData(); } } }
The problem is that IE5 doesn’t know what a DataSet is and so you can’t use techniques such as data binding to display it. As far as IE5 is concerned, the Web service return value is just an XML document with an inline schema, loaded into an instance of the MSXML parser. Fortunately, that means you can use any technique that works with XML documents to process the content.
The ShowData routine uses a simple XSLT stylesheet to transform the XML document into an HTML table for display. The transformation process loads the stylesheet into another instance of MSXML (you must use the free-threaded version for this approach to work), creates s XSLTemplate and Processor instances, and performs the transformation to return a string. The string is then inserted into the
element on the page:
function showData() { // create a new parser object instance and load stylesheet var oXMLStyle = new ActiveXObject( 'MSXML2.FreeThreadedDOMDocument'); oXMLStyle.async = false; oXMLStyle.load('style-dataset.xsl'); if (oXMLStyle.parseError.errorCode != 0) { // ... display error message ... return; } // create a new XSLTemplate object and set stylesheet var oTemplate = new ActiveXObject('MSXML2.XSLTemplate'); oTemplate.stylesheet = oXMLStyle; // create a processor and specify the XML parser to use var oProc = oTemplate.createProcessor(); oProc.input = oXMLData; // perform transformation and display results in the page if (oProc.transform() == true) divResult.innerHTML = oProc.output; else // ... display error message ... } //-->
The result of the process is shown in Figure 6. You can see that the results are much the same as you get when accessing the Web service through a .NET proxy in an ASP.NET page, although the grid formatting is less garish in this example.
Accessing a Web Service as an XML Document The previous two examples have demonstrated how you can access a Web service using SOAP. But this example (aspnet-xml-client.aspx in the aspnet-client folder) uses a technique that doesn’t rely on SOAP to access the Web service, or on using a .NET DataSet object to handle the results. It uses an ASP.NET page to access the Web service, but does so using the HTTP GET protocol rather than SOAP. Then it handles the results as an XML document, and not as a DataSet. The page contains basically the same controls as the preceding ASP.NET example, except that now there is an ASP.NET Xml server control instead of a DataGrid control:
Starting from week: year:
When the user clicks the submit button, the code builds a string containing the URL of the Web service. As shown earlier, the URL must contain the method name and any parameter values, in the following format:
So the example specifies the trafficparameters.asmx Web service file, the TrafficSummaryFromWeekYear method, and adds as the query string the values extracted from the “week” and “year” text boxes. Then it creates a new XmlDocument instance and loads it with the returned XML . This time, the XML consists of the schema and data that represents the DataSet?there’s no SOAP envelope or other containing elements because you’re making an HTTP GET request this time, not a SOAP request:
<%@Import Namespace="System.Xml" %> Sub ShowData(sender As Object, args As EventArgs) Dim sURL As String = "http://localhost/SynchWebService/webservices/" & _ "trafficparameters.asmx/TrafficSummaryFromWeekYear?" & _ "Week=" & txtWeek.Text & "&Year=" & txtYear.Text Dim oXmlDoc As New XmlDocument() oXmlDoc.Load(sURL) xmlResult.Document = oXmlDoc xmlResult.TransformSource = "style-dataset.xsl" End Sub
After loading the XML (it would, of course, be a good idea to use a Try…Catch construct here to trap any errors), you can take advantage of the clever ASP.NET Xml server control to display it. The Xml control takes the XML document, plus the XSLT stylesheet you specify as the TransformSource property, and performs the transformation. The result is inserted into the page returned to the client. Figure 7 shows the result. This example uses the same style sheet as in the preceding IE5 Web service behavior example, so it generates the same output.
The earliest cell phones included boxy designs full of buttons and antennas, and they only made calls. Needless to say, we’ve come a long way from those classic brick phones
When it comes to programming, a good mechanical keyboard can make all the difference. Naturally, you would want one of the best mechanical keyboards for programmers. But with so many
In the age of digital transformation, the internet has become a ubiquitous part of our lives. From socializing, shopping, and learning to more sensitive activities such as banking and healthcare,
The world of software development is changing drastically with the introduction of Artificial Intelligence and Machine Learning technologies. In the past, software developers were in charge of the entire development
Cybercriminals constantly adapt their strategies, developing newer, more powerful, and intelligent ways to attack your network. Since security professionals must innovate as well, more conventional endpoint detection solutions have evolved
Artificial intelligence – commonly known as AI – means a form of technology with multiple uses. As a result, it has become extremely valuable to a number of businesses across
Artificial intelligence (AI) has been transforming industries and revolutionizing business operations. AI’s potential to enhance efficiency and productivity has become crucial to many businesses. As we move into 2023, several
Creating a website is not easy, but protecting your website is equally important. Implementing copyright laws ensures that the substance of your website remains secure and sheltered. Copyrighting your website
One of the biggest trends of the 21st century is the massive surge in analytics. Analytics is the process of utilizing data to drive future decision-making. With so much of
Kubernetes from Google is one of the most popular open-source and free container management solutions made to make managing and deploying applications easier. It has a solid architecture that makes
One of the most significant cyber threats faced by modern organizations is a ransomware attack. Ransomware attacks have grown in both sophistication and frequency over the past few years, forcing
Data dictionaries are crucial for organizations of all sizes that deal with large amounts of data. they are centralized repositories of all the data in organizations, including metadata such as