.NET Web Services Made Easy

Interested in .NET? Don’t miss SitePoint’s .NET Feature Guide — it’s an excellent resource!

No doubt you’ve heard of Web Services, even if you’re an ASP, PHP, Java, .NET or XML developer. If you haven’t, or don’t really know what they are, have a look at Kevin Yank’s "Web Services Demystified".

Web Services are neither a new concept, nor a Microsoft creation. The idea has been around for a long time — Netscape touched on the concept with their IIOP (Internet Inter-ORB Protocol) — and was discussed in an article by the cofounder of Netscape, Marc Andreessen, at the end of 1996.

In this article we’ll explore how you can build and utilise your own Web Service.

Prerequisites

I’m assuming that you have a basic knowledge of .NET, Web forms, and accessing data. I’ll use an MS SQL Server database for this project, but you can also use Microsoft MSDE, which comes with the .NET Framework (if you need help finding this, have a look at the SitePoint Forums), or edit the code to work with an Access database through the OLEDB Namespace.

Usable Protocols

Because Web Services are designed to be as accessible as possible, one of the primary and most important aspects of the architecture is to exchange data in a common format. You can use three protocols to transfer data in a .NET Web Service: Http-Get, Http-Post and SOAP (Simple Object Access Protocol). Let’s go over these protocols now. Because Http-Get and Http-Post are essentially the same thing, we’ll cover them together.

The Http-Get and Http-Post Protocols

Http-Get uses name/value pairs to pass data to and from a Web Service, and, as an HTTP-based protocol, it’s widely accepted. You’ve probably worked with before if you’ve ever used the Request.QueryString() in ASP or ASP.NET. The Http-Get protocol appends a UUencoded string to the end of a URL, which commonly appears like this:

www.e4ums.com/search.aspx?searchtext=search% 
20for%20this&from=index.aspx

Look familiar? Thought so.

Http-Post is also an HTTP-based protocol that uses name/value pairs, but instead of appending the URL, these pairs are passed in request header. If you’ve every used Request.Form(), then you’ve worked with Http-Post data. The actual HTTP header for an Http-Post request looks like this:

POST search.aspx HTTP1.1 
Host: http://www.e4ums.com
Content-Type: application/x-www-form-urlencoded
Content-Length: length

searchtext=search%20for%20this&from=index.aspx

SOAP (Simple Object Access Protocol)

This lightweight data exchange protocol uses XML structure to describe objects and their properties and methods. Using HTTP and other Internet technologies, SOAP has seamlessly been integrated into .NET Web Services. Although only designed for one way transmission, SOAP messages can be combined to implement systems like request/response.

A SOAP message might look something like this:

POST search.aspx HTTP/1.1 
Host: http://www.e4ums.com
Content-Type: text/xml; charset="utf-8"
Content-Length: nnn
SOAPAction: http://www.e4ums.com/ws

<?xml version="1.0" encoding="utf-8" ?>
<soap:Envelope xmlns:xsi=http://www.w3c.org/2001/XMLSchema-instance"
xmlns:xsd=http://www.w3c.org/2001/XMLSchema  
xmlns:soap=http://schemas.xmlsoap.org/soap/envelope>
  <soap:Body>
     <tipOfDay xmlns=http://www.e4ums.com>
        <date>05/12/2002</date>
     </ tipOfDay >
  </soap:Body>
</soap:Envelope>

The SOAP that is returned would look like this:

HTTP/1.1 200 OK 
Content-Type: text/xml charset="utf-8"
Content-Length: nnnnn

<?xml version="1.0" encoding="utf-8" ?>
<soap:Envelope xmlns:xsi=http://www.w3c.org/2001/XMLSchema-instance"  
xmlns:xsd=http://www.w3c.org/2001/XMLSchema  
xmlns:soap=http://schemas.xmlsoap.org/soap/envelope>
  <soap:Body>
     <tipOfDay xmlns=http://www.e4ums.com>
        <returnTip>Never stick a light build in your back  
        pocket</returnTip>
     </tipOfDay>
  </soap:Body>
</soap:Envelope>

Data Types

Like the functions you create for your site, Web Services accept and return a variety of data types:

  • String
  • Int
  • Boolean
  • Byte
  • Double
  • Datatype
  • Enumeration
  • Float
  • Long
  • Short
  • Unsignedbyte
  • Unsignedint
  • Unsignedlong
  • Unsignedshort

And, as with normal classes and methods, you decide what data types can be accepted. However, the types that you can accept will be heavily influenced by what protocol is used to consume the Service. SOAP is the most extensible because it’s an XML-based protocol, but because of this it also uses the most bandwidth. Http-Get and Http-Post on the other hand, being name/value pairs, use less bandwidth, but are also more limited.

Our First Simple Web Service

Let’s create a Web Service! We’re going to build a simple script that returns a string — something nice and simple to start with. After that, we’ll move onto bigger and brighter things!

Creating the Web Method

If you’ve worked with .NET before, and you’ve created a custom class, then you’re not that far from creating a Web Method! There isn’t that much difference between the two really: exposed public methods are available through the Web Service, much like the public methods of a class are available to the rest of the application.

Ok, so open your favorite text editor or IDE, and save a blank document as webservice1.asmx. No, I didn’t mistype the extension. .NET Web Services files are saved as .asmx.

Ok, so you’ve waited until now to get your hands on some code, so here you are:

<%@ WebService Language="VB" Class="SitePoint" %>  
 
Imports System.Web.Services  
 
<WebService(NameSpace:="http://www.sitepoint.com/")>  
Public Class SitePoint  
 
 <WebMethod(Description:="It say hello!!")> Public  
 Function returnHello() As String  
 Return "HELLO TO THE BIG WIDE WORLD!"  
 End Function  
End Class

Look a little familiar? Thought so! Let’s go over it.

<%@ WebService Language="VB" Class="SitePoint" %>

The first line looks a little like the normal Page directive, but instead of Page, it’s a WebService directive, which tells the .NET Framework that this class is to be exposed as a Web Service.

Imports System.Web.Services

Next we import the System.Web.Services Namespace so we can access .NET Web Services classes.

<WebService(NameSpace="http://www.sitepoint.com/")>   
Public Class SitePoint

This line provides an XML Namespace for the Web Service. Now, if we’d left this line out (it’s optional) it would have bee assigned the Namespace<http://tempuri.org>. It’s generally a good idea to supply your own Namespace, as this helps to distinguish yours from other Web Services.

<WebMethod(Description:="It say hello!!")>   
Public Function returnHello() As String

To create a Web Service, you have to expose part of it. You can do this by using the WebMethod attribute, and by declaring the class and methods as public. In the above line, we declare the returnHello function as a WebMethod and public, which means that it will be available as a service.

      Return "HELLO TO THE BIG WIDE WORLD!"  
  End Function  
End Class

With these lines, we return a simple string, and close the function and class. Now, navigate to the webService1.asmx file and you’ll see that the .NET Framework has automatically rendered it.

993_ws1

Cool, eh? As you can see, the page displays the name of the Web Service at the top of the page and then lists the methods that have been made available, using the WebMethod attribute. Now click the name of a WebMethod, in this case the returnHello method, and a page describing the Web Service will appear.

You’ll see the method name, along with the description we set in the code. Below this you’ll find a header called Test and a button with Invoke written on it. Don’t hit it yet, we’ll come back to this in a moment!

Below this, you’ll see some sample SOAP, Http-Get and Http-Post requests and responses. They should look a little familiar!

Now hit the Invoke button! A window should pop up that looks something like this:

993_ws2

This is how our exposed service will appear.

Ok, now back to the first page. There’s something we never covered, anyone notice what it was?

993_ws3

This link will open the Service Description, funnily enough, which is called the WSDL document. If you read Kev’s article, congratulations – you know what I’m talking about! If not, shame on you!

Basically, the WSDL (Web Service Description Language) defines the Web Service and how it will be consumed. There are sections that detail how to interact with it using SOAP, Http-Get and Http-Post. Not bad, eh? As you can see, the .NET Framework makes creating Web Services easier than cooking toast!

Ok, we’ve built a simple Web Service that returned a string. Let’s move onto a Web Services that you can actually interact with!

Build an Interactive Web Service

So, here we go then. This time, we’re going to create a fully functional Web Service. But what will it do? Well, we’re going to create a Web Service that exposes two WebMethods, randomQuote() and addQuote(). Our Web Service will be a simple quote system, offering users the ability to have a section on their site that will display a random quote and provide users with the ability to add new quotes.

Before we get started, create a new folder in your Web root (usually c:intetpubwwwroot) called quoteWS, and turn it into a new virtual directory.

The Database

We’re going to create a simple database to hold the quotes, and design it in a way that will allow you to easily change it to an Access database. Create a new database and call it quoteDatabase. Here’s what the schema looks like:

993_ws4

Once you’ve made the table, save it as tblQuotes.

Now we’ve made the table, let’s look at our first WebMethod, randomQuote()

randomQuote() Web Method

Before we start our start our WebMethods we have to set up the class we want to expose:

<%@ WebService Language="VB" Class="Quote" %>   
 
Imports System.Web.Services  
Imports System  
Imports System.Data  
Imports System.Data.SqlClient  
 
 
<WebService(Namespace:="http://www.sitepoint.com/Quote.")> _  
Public Class Quote  
   
 ' Private string to hold the connection details  
 Private strConnection As String    
 = "server=localhost;database=quoteDatabase;uid=sa;pwd=;"  
 
End Class

Save the file as quote.asmx. Everything you see should be familiar; first we have the @WebService directive, and then we import the Namespaces for the classes and methods we're going to use. Next we declare our XML namespace, and the class we're going to expose. The only line we have inside the class is a private string that holds our database details.

With the basic bones our service laid down, let's look at our first WebMethod.

<WebMethod(Description:="Returns a random quote    
on each request in the form of a DataSet")> _  
 Public Function randomQuote() As DataSet  
   
   Dim objDataAdapter As New SQLDataAdapter '    
   DataAdapter that will get the data from the  
   Dim objConnection As New SQLConnection(strConnection) '    
   Connection object that will allow the DataAdpater to    
   connect to the    
   Dim DS As New DataSet() ' Will store the data  
   Dim returnDS As New DataSet() ' Will be the DataSet    
   that is returned  
     
   Dim quoteID As Integer ' Will hold the ID number    
   of the random quote  
     
   objDataAdapter = New SQLDataAdapter("SELECT * FROM    
   tblQuotes", objConnection)  
     
   objDataAdapter.Fill(DS, "quoteTable")  
     
   quoteID = DS.Tables("quoteTable").Rows.Count * Rnd()  
     
   Dim tmpDataTable As New DataTable("returnRow")  
   tmpDataTable = DS.Tables("quoteTable").Clone  
   tmpDataTable.ImportRow(DS.Tables("quoteTable").Rows(quoteID))  
     
   returnDS.Tables.Add(tmpDataTable)  
     
   Return returnDS  
 End Function

Let's quickly review the code. When we declare the WebMethod, we supply a description, the function name, and what we're going to return.

<WebMethod(Description:="Returns a random quote    
on each request in the form of a DataSet")> _  
 Public Function randomQuote() As DataSet

The next few lines declare the objects and variables we're going to use:

Dim objDataAdapter As New SQLDataAdapter '    
DataAdapter that will get the data from the  
Dim objConnection As New SQLConnection(strConnection) '    
Connection object that will allow the DataAdpater to    
connect to the database  
Dim DS As New DataSet() ' Will store the data  
Dim returnDS As New DataSet() ' Will be the DataSet    
that is returned  
     
Dim quoteID As Integer ' Will hold the ID number    
of the random quote

The next lines return the data from the database:

objDataAdapter = New SQLDataAdapter("SELECT * FROM    
tblQuotes", objConnection)  
objDataAdapter.Fill(DS, "quoteTable")

Now that we have a DataSet containing our quotes, we have to select one of them randomly. For this we use the row numbers from the DataSet and the rnd() function. There are better, more reliable ways to do this, but for speed and ease, we're going with this option.

quoteID = DS.Tables("quoteTable").Rows.Count * Rnd()

We then create a DataTable to hold the row we want to return. We clone the table that's holding the current quotes, and then copy the row over.

Dim tmpDataTable As New DataTable("returnRow")   
tmpDataTable = DS.Tables("quoteTable").Clone  
tmpDataTable.ImportRow(DS.Tables("quoteTable").Rows(quoteID))

Because we can't return the DataTable through the Web Service, we have to insert it into a DataSet.

returnDS.Tables.Add(tmpDataTable)

Then finally we return the DataSet.

Return returnDS

With that, we've finished our WebMethod that returns our random quote! Why not surf along and test it out?

addQuote() WebMethod

Now we can return the quotes, we're going to build the functionality to allow someone to add a quote:

<WebMethod(Description:="Allows anyone     
to add a quote to the database" _    
 & "<br />Takes 3 inputs" _    
 & "<br /><strong>1. quoteConent</strong> - Content    
 of the quote" _    
 & "<br /><strong>2. submittedBy</strong> - Name of the    
 person who submitted the quote (50 chars)" _    
 & "<br /><strong>3. webSite</strong> - Web Site of the    
 person who submitted the quote (50 chars)" _    
 & "<br /><br />Returns true or false depending if    
 the quote was successfully added")> _    
   Public Function addQuote(quoteContent As String,    
   submittedBy As String, webSite As String) As Boolean    
   Dim objConnection As New SQLConnection(strConnection)    
   Dim objCmd As SQLCommand    
   Dim objParam As SQLParameter    
       
   Try    
     objCmd = New SQLCommand("INSERT INTO tblQuotes    
     (displayContent, submittedBy, webSite) VALUES    
     (@displayContent, @submittedBy, @webSite)", objConnection)    
         
     objParam = objCmd.Parameters.Add(New SQLParameter    
     ("@displayContent", SQLDBType.Text))    
     objParam.Value = quoteContent    
         
     objParam = objCmd.Parameters.Add(New SQLParameter    
     ("@submittedBy", SQLDBType.VarChar, 50))    
     objParam.Value = submittedBy    
         
     objParam = objCmd.Parameters.Add(New SQLParameter    
     ("@webSite", SQLDBType.VarChar, 50))    
     objParam.Value = webSite    
         
       objCmd.Connection.Open()    
       objCmd.ExecuteNonQuery()    
       objCmd.Connection.Close    
         
     Return True    
   Catch ex As Exception    
     Return False    
   End Try    
 End Function

If you've ever used ASP.NET, the above code should be very familiar (so should everything else really!). The first thing we do, as you already know, is declare the WebMethod. But this time you'll notice that the description is longer. As you can see, it supports HTML, which means that you can supply a detailed description with your Web Service! We take three inputs, quoteContent, submittedBy and website) and return a Boolean (True or False).

<WebMethod(Description:="Allows anyone to     
add a quote to the database" _    
 & "<br />Takes 3 inputs" _    
 & "<br /><strong>1. quoteConent</strong> - Content of the quote" _    
 & "<br /><strong>2. submittedBy</strong> -    
 Name of the person who submitted the quote (50 chars)" _    
 & "<br /><strong>3. webSite</strong> - Web Site    
 of the person who submitted the quote (50 chars)" _    
 & "<br /><br />Returns true or false depending if    
 the quote was successfully added")> _    
 Public Function addQuote(quoteContent As String,    
 submittedBy As String, webSite As String) As Boolean

Next, we declare all the objects we're going to use:

Dim objConnection As New SQLConnection(strConnection)    
Dim objCmd As SQLCommand    
Dim objParam As SQLParameter

Then we insert the data supplied into the database using a Try...Catch...Finally block. As you can see, we do not validate of the data, which means the client would have to.

  Try    
     objCmd = New SQLCommand("INSERT INTO tblQuotes    
     (displayContent, submittedBy, webSite) VALUES    
     (@displayContent, @submittedBy, @webSite)", objConnection)    
         
     objParam = objCmd.Parameters.Add(New SQLParameter    
     ("@displayContent", SQLDBType.Text))    
     objParam.Value = quoteContent    
         
     objParam = objCmd.Parameters.Add(New SQLParameter    
     ("@submittedBy", SQLDBType.VarChar, 50))    
     objParam.Value = submittedBy    
         
     objParam = objCmd.Parameters.Add(New SQLParameter("@webSite",    
     SQLDBType.VarChar, 50))    
     objParam.Value = webSite    
         
     objCmd.Connection.Open()    
     objCmd.ExecuteNonQuery()    
     objCmd.Connection.Close    
         
     Return True    
   Catch ex As Exception    
     Return False    
 End Try

It's as simple as that! If we surf along to our quote.asmx file now, we'll see something like this:

993_ws5

Why not try the Web Services we created? They're both fully functional!

Consuming Our Web Service

Now we've created a simple Web Service, let's look at consuming it.

For someone to use a Web Service, they have to make a proxy client, which is then allowed access to all the exposed WebMethods. This can be coded by hand, but the .NET Framework includes a tool that will do this for you. We'll look at that shortly; the first thing we have to do is get ready to consume the Web Service.

The first thing we have to do is set up a new folder for the consumer site, so in your Web root (usually c:inetpubwwwroot) create a folder called consumerSite. Now, enter that folder and make a folder called bin.

993_ws6

Now we'll look at creating our proxy class.

WSDL.exe

This is a command-line utility (more information on the command-line at WebmasterBase.com) that's used to generate proxy classes using any of the useable protocols. WSDL.exe assesses the Web Service and generates a proxy class in VB.NET, C# or Jscript, which then compiles the class into a DLL that's available to the consumer site.

Let's create our proxy class now. Open the command prompt and type:

wsdl http://localhost/quoteWS/quote.asmx?wsdl /l:vb /n:Quote      
/nologo /out:C:inetpubwwwrootconsumerSitebinquote_proxy.vb

993_ws7

If you browse to the bin directory, you'll find the file quote_proxy.vb! Cool, eh? You can find out more about the WSDL tool by entering this:

wsdl /?

Now we need to compile it into a DLL, so the site can use it:

vbc /t:library /out:C:inetpubwwwrootconsumerSitebinquote.dll      
/r:System.Web.Services.dll, System.dll, system.xml.dll, system.data.dll      
c:inetpubwwwrootconsumerSitebinquote_proxy.vd

Consuming The randomQuote() WebMethod

Ok, now that we've created our proxy class for the Web Service, we can look at actually consuming it!

The first WebMethod we're going to consume is the randomQuote(). Open your text editor and enter this code:

<%@ Page Language="VB" %>     
<%@ Import Namespace="System.Data" %>    
<%@ Import Namespace="Quote" %>    
   
<script language="VB" runat="server">    
 Sub Page_Load(ByVal obj As Object, ByVal e As EventArgs)    
   If ( NOT isPostBack ) Then    
     generateQuote(obj, e)    
   End If    
 End Sub    
     
 Sub generateQuote(ByVal obj As Object, ByVal e As EventArgs)    
   Dim randomQuote As New quote.quote()    
       
   Dim getQuote As DataSet = randomQuote.randomQuote()    
       
   returnQuote.DataSource = getQuote    
   returnQuote.DataBind()    
 End Sub    
     
 Function checkWebSite(byVal submittedBy As String,      
 byVal website As String) As String    
   Dim returnString As String    
       
   If ( Regex.isMatch(website, "b(www|http)S+b") ) Then    
     returnString = Regex.Replace(website,      
     "b(www|http)S+b", "<a href=""$0"" target=""_blank"">"      
     & submittedBy & "</a>")    
   Else    
     returnString = submittedBy    
   End If    
       
   Return returnString    
 End Function    
</script>    
<html>    
 <head>    
   <title>Quote Web Service!</title>    
   <meta http-equiv="Content-Type" content=    
   "text/html; charset=iso-8859-1">    
   <style>    
     .body { font-family: Verdana, Arial, Helvetica; font-size: 11; }    
   </style>    
 </head>      
 <body>    
   <form name="form1" runat="server">    
     <ASP:Repeater ID="returnQuote" runat="server">    
       <itemTemplate>    
         <table width="500" style="border:      
         1 solid #8080C0" class="body">    
         <tr>    
           <td>Quote Number: <%# DataBinder.Eval    
           (Container.DataItem, "quoteID") %></td>    
         </tr>    
         <tr>    
           <td>    
             <%# DataBinder.Eval(Container.DataItem,      
             "displayContent") %>    
           </td>    
        </tr>    
        <tr>    
           <td>    
             <%# checkWebSite(DataBinder.Eval    
             (Container.DataItem, "submittedBy"), DataBinder.Eval    
             (Container.DataItem, "website")) %>    
          </td>    
        </tr>    
      </table>    
      </itemTemplate>    
     </ASP:Repeater>    
     <br>    
     <ASP:LinkButton id="newQuoteButton" runat="server"      
     OnClick="generateQuote" Text="Get Another!" CssClass="body" />    
   </form>    
 </body>    
</html>

Save this file as default.asopx, browse along to the consumerSite URL, and you should see something like this:

993_ws8

How cool is that! Let's go over the code.

In the first few lines we have our page directive and the Namespaces we want to import. As you can see, we are importing our Web Service proxy. This allows use easy access to the methods.

<%@ Page Language="VB" %>      
<%@ Import Namespace="System.Data" %>      
<%@ Import Namespace="Quote" %>

Next we have our Page_Load function, which contains some code to kick up the generateQuote() function, but only if the page has not been posted back.

  Sub Page_Load(ByVal obj As Object, ByVal e As EventArgs)      
   If ( NOT isPostBack ) Then      
     generateQuote(obj, e)      
   End If      
End Sub

We have our generateQuote() function now. This creates an instance of the Web Service, and creates a new DataSet using the returned data. Then we bind it to a repeater class.

  Sub generateQuote(ByVal obj As Object, ByVal e As EventArgs)      
   Dim randomQuote As New quote.quote()      
       Dim getQuote As DataSet = randomQuote.randomQuote()      
       returnQuote.DataSource = getQuote      
   returnQuote.DataBind()      
 End Sub

Let's jump to the Repeater Web Control. We didn't have to use this Web Control, but for simplicity, we'll stick with it.

Inside the Control, we have a table that holds out returned quote -- quite simple really. You might notice, though, that one of the lines is slightly different.

  <ASP:Repeater ID="returnQuote" runat="server">      
   <itemTemplate>      
     <table width="500" style="border: 1 solid #8080C0" class="body">      
       <tr>      
       <td>Quote Number: <%# DataBinder.Eval      
       (Container.DataItem, "quoteID") %></td>      
       </tr>      
       <tr>      
         <td>      
           <%# DataBinder.Eval(Container.DataItem,      
           "displayContent") %>      
         </td>      
       </tr>      
       <tr>      
         <td>      
           <%# checkWebSite(DataBinder.Eval      
           (Container.DataItem, "submittedBy"), DataBinder.Eval      
           (Container.DataItem, "website")) %>
     
         </td>      
       </tr>      
     </table>      
   </itemTemplate>      
 </ASP:Repeater>

The line in bold is a little different to the rest. Instead of sending the data straight to the browser, it sends it to a function called checkWebSite(). This function checks to see if the website is a link. If it is, the function returns a link using the website and submittedBy value, and if it's not, it simply returns the submittedBy value.

  Function checkWebSite(byVal submittedBy       
 As String, byVal website As String) As String      
   Dim returnString As String      
         
   If ( Regex.isMatch(website, "b(www|http)S+b") ) Then      
     returnString = Regex.Replace(website,      
     "b(www|http)S+b", "<a href=""$0"" target=""_blank"">"      
     & submittedBy & "</a>")      
   Else      
     returnString = submittedBy      
   End If      
         
   Return returnString      
 End Function

And that's how you consume the randomQuote() WebMethod! Nice and easy! Now, let's move onto the addQuote() WebMethod.

Consuming The addQuote() WebMethod

The addQuote() WebMethod allows the user to add quotes to the database. If you remember, the WebMethod didn't validate the data, so we'll include some simple validation.

Open a new document in your text editor and add the following:

<%@ Page Language="VB" %>      
<%@ import Namespace="System.Data" %>      
<%@ import Namespace="Quote" %>      
<script runat="server">      
     
 Sub addQuote(byVal obj As Object, byVal e As EventArgs)      
 If ( page.isValid) Then      
   Dim randomQuote As New quote.quote()      
           
   Dim addOK As Boolean = randomQuote.AddQuote      
   (quoteContentTxt.Text, submittedByTxt.Text, websiteTxt.Text)      
           
     If ( addOK ) Then      
       result.Text = "Quote was successfully added!"      
       quoteContentTxt.Text = ""      
       submittedByTxt.Text = ""      
       websiteTxt.Text = ""      
     Else      
       result.Text = "Quote was not added!"      
     End If      
   End If      
 End Sub      
</script>      
<html>      
 <head>      
   <title>Untitled Document</title>      
   <meta http-equiv="Content-Type" content="text/html;      
   charset=iso-8859-1" />      
 <style>      
     .body {      
     FONT-SIZE: 11px; FONT-FAMILY: Verdana, Arial, Helvetica      
     }      
 </style>      
 </head>      
<body>      
   <form name="addQuoteForm" runat="server">      
   <ASP:Label id="result" CssClass="body" Font-Bold="true"      
   runat="server"></ASP:Label>      
   <table style="border: 1 solid #8080C0" class="body">      
     <tr>      
       <td valign="top">Quote Content:</td>      
       <td width="10">&nbsp;</td>      
       <td>      
         <asp:textbox id="quoteContentTxt" runat="server" TextMode=      
        "MultiLine" Width="290px" Height="121px">      
       </asp:textbox>      
       <asp:RequiredFieldValidator id="quoteContentValidator"      
       runat="server" ControlToValidate=      
       "quoteContentTxt" Display="Dynamic"      
       ErrorMessage="<br />You must supply a      
       quote!"></asp:RequiredFieldValidator>      
       </td>      
     </tr>      
     <tr>      
       <td valign="top">Your Name:</td>      
       <td>&nbsp;</td>      
       <td>      
         <asp:textbox id="submittedByTxt" runat="server"      
         TextMode="SingleLine"></asp:textbox>      
         <asp:RequiredFieldValidator id="submittedByValidator"      
         runat="server" ControlToValidate="submittedByTxt"      
         Display="Dynamic" ErrorMessage="<br />      
         You must supply your name!"></asp:RequiredFieldValidator>      
       </td>      
     </tr>      
     <tr>      
       <td>  Web Site:</td>      
       <td>&nbsp;</td>      
       <td>      
         <asp:textbox id="websiteTxt" runat="server"      
         TextMode="SingleLine"></asp:textbox>      
       </td>      
     </tr>      
     <tr>      
       <td>&nbsp;</td>      
       <td>&nbsp;</td>      
       <td>      
         <asp:button id="addQuoteButton" onclick="addQuote"      
         runat="server" Text="Add Quote!"></asp:button>      
       </td>      
     </tr>      
   </table>      
   </form>      
 </body>      
</html>

Now save it as addQuote.aspx, and surf to it. You should see this:

993_ws9

Try it! Cool, eh? Let's go over the code.

The first few lines were the exact same as the previous page: they contained our page directive and imported the namespaces.

<%@ Page Language="VB" %>      
<%@ import Namespace="System.Data" %>      
<%@ import Namespace="Quote" %>

We'll skip the actual code right now and jump to the form. As you can see, it's a standard Web Form, using 3 textboxes, 1 button and 2 validators. The validators only check the quoteContentTxt and submttedByTxt to make sure they have some content.

<form name="addQuoteForm" runat="server">      
   <ASP:Label id="result" CssClass="body" Font-Bold="true"      
   runat="server"></ASP:Label>      
     <table style="border: 1 solid #8080C0" class="body">      
       <tr>      
         <td valign="top">Quote Content:</td>      
         <td width="10">&nbsp;</td>      
         <td>      
           <asp:textbox id="quoteContentTxt" runat="server"      
           TextMode="MultiLine" Width="290px"      
           Height="121px"></asp:textbox>      
           <asp:RequiredFieldValidator id="quoteContentValidator"      
           runat="server" ControlToValidate="quoteContentTxt"      
           Display="Dynamic" ErrorMessage="<br />You must      
           supply a quote!"></asp:RequiredFieldValidator>      
         </td>      
       </tr>      
       <tr>      
         <td valign="top">Your Name:</td>      
         <td>&nbsp;</td>      
         <td>      
           <asp:textbox id="submittedByTxt" runat="server"      
           TextMode="SingleLine"></asp:textbox>      
           <asp:RequiredFieldValidator id="submittedByValidator"      
           runat="server" ControlToValidate="submittedByTxt"      
           Display="Dynamic" ErrorMessage="<br />You must      
           supply your name!"></asp:RequiredFieldValidator>      
         </td>      
       </tr>      
       <tr>      
         <td>  Web Site:</td>      
         <td>&nbsp;</td>      
         <td>      
           <asp:textbox id="websiteTxt" runat="server"      
           TextMode="SingleLine"></asp:textbox>      
         </td>      
       </tr>      
       <tr>      
         <td>&nbsp;</td>      
         <td>&nbsp;</td>      
         <td>      
           <asp:button id="addQuoteButton"      
           onclick="addQuote" runat="server"      
           Text="Add Quote!"></asp:button>      
         </td>      
       </tr>      
   </table>      
   </form>

When the submit button is clicked, the addQuote() function is fired. It first checks to make sure that the page is valid, the creates an instance of the Quote Web Service. Then it creates a new Boolean that will hold the result of the addQuote() call. If it's retuned true, then the quote was added, and if it's retuned false, then the quote wasn't added.

Sub addQuote(byVal obj As Object, byVal e As EventArgs)      
 If ( page.isValid) Then      
   Dim randomQuote As New quote.quote()      
           
   Dim addOK As Boolean = randomQuote.AddQuote      
   (quoteContentTxt.Text, submittedByTxt.Text, websiteTxt.Text)      
           
 If ( addOK ) Then      
       result.Text = "Quote was successfully added!"      
       quoteContentTxt.Text = ""      
       submittedByTxt.Text = ""      
       websiteTxt.Text = ""      
 Else      
       result.Text = "Quote was not added!"      
 End If      
 End If      
End Sub
Finishing Up

Congratulations, you've just made you're first Web Service! While what we covered was very simple, you can always add more functionality to this base, such as returning the number of quotes, or building in the ability to edit or delete quotes. The only limit to what you can do is how much you can be bothered programming!

Web Services are a new and exciting way to open up Websites to the public or your customers! There is no real limit to what you can do with Web Services, and with .NET's platform independence, you can use Web Services that have been generated in any language!

The example we covered was a very simple one, but it should show you want is possible! There are a myriad of resources for Web Services, the most obvious one being the .NET SDK, and Microsoft's newly released Web Enhancements Package for .NET.

This article is part of SitePoint's .NET Feature Guide -- an excellent resource for aspiring and experienced .NET developers. Don't miss it!

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

No Reader comments

Comments on this post are closed.