Click here to Skip to main content
Click here to Skip to main content

An introduction to web services: Daily Dilbert

, 12 Apr 2003
Rate this:
Please Sign up or sign in to vote.
An introduction to web services via creating a web service to retrieve the daily Dilbert image and a client to consume this service.

Introduction

Web services are a very powerful technology, greatly motivating the idea of distributed computing. Rather than creating or reinventing protocols for the sake of better technology, web services make use of strong, dependable technologies like XML, HTTP, and SSL.

Web service creation has been greatly improved from the days of the Microsoft SOAP Toolkit. Web service architecture has been integrated into the .NET framework, which enables you to get a working web service with just a few clicks.

With this article, I plan to give you a basic introduction to creating a web service, using the Microsoft .NET framework and Visual Studio .NET. I will walk you through the creation of a web service that retrieves the daily Dilbert image, and also a client that consumes that service.

This article will assume that you have a basic understanding of the C# language, and are also familiar with the Visual Studio .NET IDE.

Let’s begin...

We will create a new ASP.NET Web Service project entitled DailyDilbert. Once this project is created, you will see a few project files in the Solution Explorer. The web service itself is located in Service1.asmx. To make things a little clearer, our first step we will rename this file to something more appropriate. Let’s call it DilbertService.asmx.

To create a web service from our class, we will need to derive our class from System.Web.Services.WebService. Using attributes, we will describe our web service class, giving it a namespace, and a description. The MSDN library defines XML namespaces as "a way to create names in an XML document that are identified by a Uniform Resource Identifier (URI). By using XML namespaces, you can uniquely identify elements or attributes in an XML document. The service description for an XML web service is defined in XML, specifically in Web Services Description Language (WSDL)." The namespace is arbitrary and does not need to point to an Internet site.

The code should resemble this:

[WebService(
    Description="Provides methods to access the daily Dilbert image",
    Namespace="http://mattberther.com/webservices/dailydilbert")]

Our web service will utilize functions in the System.Net, System.IO, and System.Text.RegularExpressions namespaces, so lets add the following lines to the top of the DilbertService.asmx.cs file:

using System.Net;
using System.IO;
using System.Text.RegularExpression;

Now that we have our class declaration in order, let’s get on to the fun part. Add the following method to your DilbertService class:

public string GetDailyDilbertUrl()
{
    string address = "http://www.dilbert.com/comics/dilbert/archive/";

    WebClient httpRequest = new WebClient();
    StreamReader rdr = new StreamReader(httpRequest.OpenRead(address),
        System.Text.Encoding.ASCII);
    string streamText = rdr.ReadToEnd();
    rdr.Close();

    Match match = Regex.Match(streamText,
        @"/comics/dilbert/archive/images/(\w+).gif",
        RegexOptions.IgnoreCase);

    if (match != Match.Empty)
    {
        return "http://www.dilbert.com" + match.Value;
    }
    else
    {
        return "";
    }
}

This method is fairly straight forward. We open a web request to the daily Dilbert page, and retrieve a string of the HTML page. When you do a View Source from http://www.dilbert.com/comics/dilbert/archive/, we see that the displayed image is located in /comics/dilbert/archive/images. The regular expression matches that pattern and takes one more more word character up to the point that it encounters .gif. If the regular expression parser encounters a match, the value of that match is appended to the base URL and returned to the client.

So, we now have a method that retrieves the URL for the daily Dilbert image. However, when we run our web service (via F5), we see that there are no available operations on our web service. To make our method callable from remote Web clients, we need to apply the WebMethod attribute to our method. Add the following line directly above your method declaration:

[WebMethod(
    Description="Retrieve the URL for the daily Dilbert image")]

Now, when we run our web service, we see that our method is available by clicking on the link in Internet Explorer. When you click on this link, there is an auto generated page that displays information about our method. This information includes syntax information for accessing this service via SOAP and HTTP POST. You also are provided an opportunity to test your web service via the "Invoke" button.

Let’s add one more method to our web service, which will return a byte array of the image itself. Add the following code to the DilbertService class:

[WebMethod(
    Description="Retrieve a byte array containing the daily Dilbert image")]
public byte[] GetDailyDilbertImage()
{
    WebClient httpRequest = new WebClient();
    String imageUrl = GetDailyDilbertUrl();

    BinaryReader rdr = new BinaryReader(
        httpRequest.OpenRead(imageUrl));

    byte[] imageArray = ConvertStreamToByteArray(rdr.BaseStream);
    rdr.Close();

    return imageArray;
}

private byte[] ConvertStreamToByteArray(Stream theStream)
{
    int b1;
    MemoryStream tempStream = new MemoryStream();
    while( (b1 = theStream.ReadByte()) != -1)
    {
        tempStream.WriteByte(((byte)b1));
    }

    return tempStream.ToArray();
}

Again, this is a very straight forward method. We use our previously created method to retrieve the image URL, and then create a BinaryReader to read in the .gif file. We have added a simple helper method to convert the Stream object to a byte array.

Now, when we run the project, we see that this additional method is available as well. When we click on the new method, and test it, we get back a base64encoded string containing the image data.

Our web service is not useful if we don’t have anyone consuming it, so let’s go ahead and create a simple WinForms application to consume our new web service.

Add a new Windows application named DilbertServiceClient to your solution. To reference the web service, we will need to add a web reference. Right click on the DilbertServiceClient project and select Add Web Reference. Type http://localhost/DailyDilbert/DilbertService.asmx into the URL box and click Go. Again, you will see the same page that you saw when you executed the web service through Visual Studio (via F5). Update the web reference name to a namespace you desire. For this article, I will use MattBerther.DailyDilbert. Consuming this web service is now as simple as creating an instance and calling the appropriate method, as demonstrated in the following code located in Form1.cs.

protected override void OnLoad(EventArgs e)
{
    base.OnLoad(e);

    MattBerther.DailyDilbert.DilbertService ws =
        new MattBerther.DailyDilbert.DilbertService();

    Byte[] imageData = ws.GetDailyDilbertImage();
    System.IO.MemoryStream strm = new System.IO.MemoryStream(imageData);
    Bitmap bmp = new Bitmap(strm);
    strm.Close();

    PictureBox box = new PictureBox();
    box.Image = bmp;
    box.Height = bmp.Height;
    box.Width = bmp.Width;

    this.Controls.Add(box);
    this.Height = bmp.Height;
    this.Width = bmp.Width;

    this.Text = "Daily Dilbert Image: " + ws.GetDailyDilbertUrl();
}

Now that we have created both a web service and a client that consumes it, let’s look at some ways that we can enhance this service. First of all, you may realize that the output from these methods only change once per day. Rather than parsing the daily Dilbert page upon every request, it would make sense to cache the request. Caching a web method result is very straight forward. Simply add the CacheDuration property to the WebMethod attribute as shown below:

[WebMethod(
    Description="Retrieve the URL for the daily Dilbert image",
    CacheDuration=43200)]

The CacheDuration gets or sets the number of seconds the response should be held in the cache. To make as few requests as possible to the main Dilbert page, let’s set it to cache the response for 12 hours (43200 seconds). We can verify that the caching is working, by placing a breakpoint on the first line in our web method, and then running the client consecutive times. The client will be fed the cached response up until either:

  1. The cached timeout has expired, or
  2. IIS has been reset.

As we look to deploy our Dilbert application to other desktops, we may want to provide some functionality to change the URL our web service points to. Using Visual Studio .NET and the .NET framework, this is as simple as changing the URLBehavior property on our web reference from static to dynamic. When you change to dynamic, a key entitled DilbertServiceClient.MattBerther.DailyDilbert.DilbertService will be added in the app.config file. The value of this key is the URL to point to for consumption of the web service.

History

  • 1.0 - 04.13.2003
    • First release version

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Matt Berther
Web Developer
United States United States
I am a 31 year old software developer from Boise, Idaho. I have been working with computers since approximately age 12, when my 6th grade teacher got me hooked. My parents got me a Commodore 64 for Christmas that year, and it's been downhill ever since. Wink | ;)
 
I have taught myself software development, beginning with Microsoft's Visual Basic 4.0. Approximately 5 years ago, I was given an opportunity to work in the tech field for a company called HealthCast. HealthCast's web-based technology solutions manage and control access to applications and patient information stored in legacy systems, client-server applications, or web solutions.
 
I left HealthCast in February 2003, to pursue a fantastic opportunity with Healthwise. Healthwise provides content to organizations and informs people to help them make better health decisions, creating Prescription-Strength Information™ tools that doctors trust and consumers use.
 
I have been working with the .NET framework since version 1.0, beta 2 and have not looked back since. Currently, I am most intrigued by the uses of the .NET framework and XML to create distributed, reusable applications.

Comments and Discussions

 
GeneralMy vote of 3 PinmemberChathura Roshan17-Oct-12 21:40 
GeneralMy vote of 2 PinmemberMasba3-May-11 22:07 
Nice for Beginner
Generalhiiii PinmemberPrashanth_gowda1-Feb-11 19:06 
Questionweb service's future? Pinmemberjason_wang1113-Oct-08 16:30 
GeneralMessage Automatically Removed PinmemberDotNetGuts10-Sep-08 12:44 
GeneralGreat, but... Pinmembersuperdummy200129-May-08 14:50 
GeneralVery cool stuff! PinmemberMartin Brice14-Apr-08 17:11 
Generalthanks! clear and simple PinmemberMember 225670818-Mar-08 9:43 
QuestionWeb service SSL Pinmemberulfhaga22-Jan-08 9:44 
General\r\n converted to \n PinmemberCsupor Jeno11-Dec-06 1:58 
GeneralRe: \r\n converted to \n PinmemberCsupor Jeno8-Mar-07 8:40 
QuestionGenerating XML using Web Service in asp.net Pinmembersheetal alaspure20-Sep-06 21:14 
GeneralThanks Matt PinmemberShawn_H11-Aug-06 7:40 
QuestionWhat would be the code to consume this through a web form? Pinmembertima8227-Feb-06 23:58 
QuestionWhat if C++ PinmemberAlexEvans31-Jan-06 13:23 
QuestionHelp!!!! Error!!!!!!!! Pinmemberundead14213-Sep-05 16:53 
GeneralSome online resources. PinsussAnonymous14-Aug-05 3:00 
General401 error Pinmemberkittygrins25-Jun-05 15:41 
Generalerror in ASP.net Pinmemberdoancongxd970717-Apr-05 21:41 
AnswerRe: error in ASP.net Pinmembersirlatrom20-Dec-05 3:40 
GeneralSample Needed PinmemberSGRAVI2K17-Jan-05 23:33 
Generalhi Pinmemberbahadir_cambel26-Oct-04 10:28 
GeneralRe: hi Pinmembermarkjuggles7-Dec-04 16:31 
GeneralMany Thanks PinmemberRikB11-Oct-04 4:56 
GeneralCool Pinmemberho_min29-Sep-04 22:54 
GeneralI got a Parser Error PinmemberXueXX27-Aug-04 13:15 
GeneralStupid question Pinmemberjsanjosem26-May-04 21:37 
GeneralRe: Stupid question PinmemberMatt Berther27-May-04 6:02 
GeneralThanks! PinmemberMatt Philmon8-Jan-04 17:49 
GeneralQuestion Pinmemberenjetek23-Dec-03 9:03 
GeneralRe: Question PinmemberTerryRus18-Mar-04 14:49 
GeneralWhen I attempt to use this service from a client app I get an error PinsussAnonymous15-Oct-03 15:34 
GeneralRe: When I attempt to use this service from a client app I get an error Pinmemberjdp24-Oct-03 6:50 
GeneralRe: When I attempt to use this service from a client app I get an error PinmemberHui Shen6-Apr-05 18:45 
QuestionHow to consume this web service C++? PinmemberAnthony_Yio18-May-03 15:55 
AnswerRe: How to consume this web service C++? PinmemberMatt Berther18-May-03 19:33 
GeneralRe: How to consume this web service C++? PinmemberAnthony_Yio19-May-03 15:23 
GeneralRe: How to consume this web service C++? PinmemberTerryRus18-Mar-04 14:28 
GeneralThis is what I need PinmemberAnthony_Yio18-Apr-03 0:10 
GeneralCool example PinmemberMatt Newman15-Apr-03 15:54 
GeneralRe: Cool example PinmemberTheDude12645-Oct-05 13:37 
GeneralNice article PinmemberFabrizio Camera13-Apr-03 23:22 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140721.1 | Last Updated 13 Apr 2003
Article Copyright 2003 by Matt Berther
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid