Where’s John Been?

Some may have noticed that lately I’ve been a little slower than normal in answering questions. I’ve even beed posting answers with a few typos in them.

It’s because I’ve had a problem with Retinal Detachment.

 

BTW, see the linked site for more than you could ever want to know about the subject.

I had been warned by my optometrist, Dr. Asha K. Sherring (below) in Autumn 2008, that I should expect to develop cataracts. I noticed on Saturday, May 30, that the center of my visual field on the right was being blocked by something “like a piece of fine cloth”, so I called Dr. Sherring. She was concerned about how quickly the problem had developed, and correctly so, since it was not a cataract.

 

She got me in for an appointment the same day I called her (Tuesday, June 2). The good news was that this was not a cataract. The bad news is that she discovered a retinal elevation.

She referred me to Dr. Shalesh Kaushal, M.D., Ph.D., of UMass Memorial, who saw me on Monday, June 8, and confirmed that I did, indeed, have a retinal tear. Fluid from the eye had entered behind the tear, and raised, or detached, the retina at that point.

He scheduled me for surgery on June 10. The great people at the UMass Day Surgery center at the Hahnemann Campus made this, my first surgery, the one to beat. Any other surgical operation will have to contend for a nicer staff, and a more professional operation.

The surgery went well (what I can remember of it), and I went home that afternoon (after they tricked me into a wheelchair. Next time I’ll know better: “sit here and we’ll put your shoes on”, indeed!).  The follow-up visit today, with Dr. Kaushal and his staff, also went well. I can already see a bit out of the right eye (I can tell you that there are fingers, just not how many). I should be back to work on Monday, and I’m looking forward to that.

Fortunately, my son, Brian, travelled from Phoenix to be with me until Sunday. He’s losing a week’s work to be with me (and, since he’s paid by the hour, that’s no small thing). I thank my father, John W. Saunders, Jr. for his help in paying for Brian’s plane fare. Thanks to my mother, Joyce Gittoes, for checking up on me several times a day. And thanks to all my family for their support and good wishes.

I’d especially like to thank my old friend Chris Johnson. When I called Chris to let him know about the surgery, I found that he was quite familiar with UMass, as he had just been there the day before! Seems I need to keep better track of my friends!

Advertisements
Posted in Personal | Leave a comment

How to Consume a Web Service

This question comes up more than you would imagine. Although it’s a simple question, it’s hard to find a simple answer. This post will attempt to be the simple answer. Any complications will be added as other posts, referencing this one.

Creating the Test Service

I’ll just start by creating a simple WCF service for us to consume later. This will also create the Visual Studio Solution we’re going to use. Start with File->New Project:

This brings up the New Project dialog. I’ll choose the “WCF Service Application” project template, just for simplicity. In general I would have chosen “WCF Service Library” from the WCF page.

 

This results in the following solution structure:

Actually, Visual Studio has provided all we need for this example. It created a Data Contract class for our use:

[DataContract]
public class CompositeType
{
    [DataMember]
    public bool BoolValue { get; set; }

    [DataMember]
    public string StringValue { get; set; }
}

It also created a service contract that our service will implement. This contract uses the Data Contract:

[ServiceContract]
public interface IService1
{
    [OperationContract]
    string GetData(int value);

    [OperationContract]
    CompositeType GetDataUsingDataContract(CompositeType composite);
}

It also created the service as a class that implements the service contract:

public class Service1 : IService1
{
    public string GetData(int value)
    {
        return string.Format("You entered: {0}", value);
    }

    public CompositeType GetDataUsingDataContract(CompositeType composite)
    {
        if (composite.BoolValue)
        {
            composite.StringValue += "Suffix";
        }
        return composite;
    }
}

It also created the Service1.svc file that will tell IIS (or the Visual Studio Development Server) which class to create to handle calls to the server:

<%@ ServiceHost Language="C#" Debug="true" Service="WcfService1.Service1" CodeBehind="Service1.svc.cs" %>

When a request for Service1.svc arrives at the URL the service is on, IIS will create an instance of the  System.ServiceModel.ServiceHost class to host instances of the the WcfService1.Service1 class. As requests for this service arrive, they will be dispatched to instances of the WcfService1.Service1 class.

The web.config has also been created with the default configuration necessary for this service.

Creating a Simple Client

There is no real difference between consuming a web service in a Console application as opposed to an ASP.NET application or a Windows Forms application, so I’ll just use a console application:

This produces:

We start by adding a Service Reference to the project. Right-click the ConsoleApplication1 project and choose “Add Service Reference”:

The value you place into the “Namespace” text box at the bottom is important, so I often fill it out first, so I don’t forget. Note here that I have changed the default of “ServiceReference1” to “Service1Reference”, to indicate that this will be a reference to “Service1”.

The “Address” text box at the top can be used to type the URL to the Service Description, or “WSDL” file. Since the service is in the same solution as the project we’re trying to add it to, we can take advantage of the “Discover” dropdown at the right. Clicking the arrow shows “Services in this solution”:

Clicking this will populate the “Address” box with the URL to our service, and will populate the “Services” list with the “Service1” service:

Now, a service may implement more than one service contract. You should click the “+” sign next to the service to expand the service down to the service contracts and their operations. Unfortunately, doing so now will illustrate that I’ve made a common error. After attempting to launch our service, the text below the service list will change to say “An error (Details) occurred while attempting to find services at http://localhost:50730/Service1.svc” Clicking the Details link will show:

Note that this is a bunch of HTML! In fact, there’s so much of it, that there is a scroll bar to the right. if you scroll to the very bottom, you’ll see the reason for this problem, and the solution to it:

Yes, I forgot to build the service! After successfully building the service and starting over, you’ll be able to expand the service all the way to the bottom, and see that both methods are visible:

Visual Studio will add several project references to your project, and will add the service reference:

Note that it also added an app.config. This will contain the configuration details necessary for the client to communicate with the service. These will be the defaults, and can be modified as required.

It’s usually at this point where someone new to web services stops to ask: “Now, what?”

What’s In a Service Reference?

A service reference is a convenient way for you to access a web service in your code. It takes all the complexities of web services and boils them down into a single name, in this case “Service1Reference”. But in order to see “what’s in a name”, all we have to do is right-click the service reference and choose “View in Object Browser”. The first thing it shows is actually interesting, so stop and look:

You’ll see that Visual Studio has created a new namespace under the namespace for this application. Any names brought over from the service cannot interfere with names in your application, because those names are all created in a separate namespace.

Expanding the namespace shows what’s inside:

Visual Studio has created a “CompositeType” class, since the service contract uses a class with that name. It has also created an IService1 interface to represent the service contract, as well as a Service1Client class that we’ll use shortly. If you click on IService1, you’ll notice that it has the expected GetData and GetDataUsingDataContract methods. If you expand Service1Client to see the base classes, you’ll see that it implements IService1, so that it contains implementations of the GetData and GetDataUsingDataContract methods.

This all makes it sound more difficult than it is. Let’s write some code instead! First, let’s get the data we’ll send to the service:

Console.Write("Enter BoolValue: ");
var line = Console.ReadLine();
if (line == null)
{
    return;
}

var boolValue = bool.Parse(line);

Console.Write("Enter StringValue: ");
line = Console.ReadLine();
if (line == null)
{
    return;
}

This is just simple-minded logic for reading in the two values we need to construct a CompositeType.

using (var svc = new Service1Client())
{
    var request = new CompositeType
                      {
                          BoolValue = boolValue,
                          StringValue = line
                      };
    var result = svc.GetDataUsingDataContract(request);

This is straightforward. Just create an instance of the Service1Client proxy class, create an instance of CompositeType , and call the method, passing the request and receiving the response. The response can be displayed in a simple manner:

Console.WriteLine("The result is:");
Console.WriteLine(
    "BoolValue={0}, StringValue={1}", 
    result.BoolValue,
    result.StringValue);
Console.Write("ENTER to continue:");
Console.ReadLine();

After that, we’re through. This can be tested by using CTRL+F5 to run the code without debugging. The result is:

But What About…

There’s one little problem in the code above. In every case, when your code creates an instance of a class that implements IDisposable, then your class should ensure that Dispose gets called on that instance. In most cases, the way to do that is shown above: create the instance within a using statement. Unfortunately, the designers of WCF made a mistake that causes the use of WCF proxy classes to be the one case where this doesn’t work. See Indisposable – WCF Gotcha 1 (7/3/2008) for the details, but we’re going to have to change our code a little. Instead of:

using (var svc = new Service1Client())

{

    // Do something with svc

}

we have to do this:

Service1Client svc = null;
bool success = false;
try
{
     svc = new Service1Client();
     
     var request = new CompositeType
     {
         BoolValue = boolValue,
         StringValue = line
     };
     var result = svc.GetDataUsingDataContract(request);

     Console.WriteLine("The result is:");
     Console.WriteLine(
         "BoolValue={0}, StringValue={1}",
         result.BoolValue,
         result.StringValue);
     Console.Write("ENTER to continue:");
     Console.ReadLine();

    svc.Close();
    success = true;
}
finally
{
    if (!success && svc != null)
    {
        svc.Abort();
    }
}

The highlighted code is the only difference. To make a long story short, if you don’t follow this pattern, and if an exception is thrown inside of your using block, then you may lose your exception. The exception will attempt to leave the using block, the block will call Dispose for you, and then Dispose may throw an exception of it’s own, losing you any information about what really went wrong in your using block. In the code above, if Close is never called, then Abort will be called, and it’s abort that will do the cleanup.

Don’t let this keep you from the using block in every other case. It is only because the WCF designers decided to have Dispose call Close, and since Close can throw its own exception, that this is an issue. As far as I know, there is nowhere else in .NET where calling Dispose can throw an exception.

Posted in Web Services | 14 Comments

Why I’m In a Bad Mood Today (or, “Cowardly Credit Card Companies”)

This is the first thing I’ve posted here of a personal nature. It’s a pity it has to be on a subject like this.

All of us, at least all of us in the United States, have been hearing about the Banking Crisis, and the Economic Crisis, and how it’s moving from Wall Street to Main Street. Well, I guess it’s hit my street, but not in a way I would have expected.

On April 7, 2009, I received a letter in the mail from Bank of America, about my credit card. It seems that they had decided to cut my credit limit in half, to $500. The letter said this was being done not because of any problems I’d had with Bank of America, but because of problems they saw in my credit report.

I thought, “Well, Ok, it’s their card, if they want to be cautious that’s ok. This will all resolve itself in a year or so.” I had been out of work for a few months, and although I had returned to work in February, I thought they might have seen a late payment or two. No big deal.

This was an issue only because I was using that card to rent a car: my car had finally died, and I got a great rate from Enterprise Rent-A-Car, and am being paid enough to afford this. Enterprise had wanted $500 to be free on the card, and with the new limit, I paid the $25 balance I had outstanding and called to ask Bank of America if they could put in a temporary $25 credit line increase until the payment posted in a day or so.

They told me that they could not, since they were cancelling the card outright. It seems that their computer had decided to cut the credit limit, but the very nice human I spoke to on the phone decided to just close the account instead.

Note that this had nothing to do with my experience with Bank of America. I had no late payments or any other problems with them. They closed the account because my ‘”Credit Profile” (not even the full credit report) showed late payments to other creditors. .

Yes, if you’re out of work for three months, a late payment or two is not unlikely. Apparently, it is now a reason to close an entirely different credit card.

I considered this to be an isolated case, so I called Enterprise and told them we’d be switching cards to American Express. I’ve had an American Express Card for ten years and counting, and have kept that card pristine – I hardly used it, so it had almost no chance of having any problems. So, I paid $600 to American Express to get enough room on the card for Enterprise to use.

The following day, American Express closed my account, for the same reason as Bank of America. Ten years and stop counting.

As I see it, the problem is that:

  1. Due to being out of work for a while, I missed a few payments on two credit cards. Those have since been brought up to date, now that I’m working again.
  2. In both cases, my balance on the card was less than half the credit limit. This means that, even if I decided to be a deadbeat and not pay what I owed on these cards, they wouldn’t lose much money (of course, I pay what I owe, so that’s not something they’ll ever learn).
  3. I’ve never had, or needed, a high credit limit on these cards. This means that losing me as a customer isn’t a great loss for these companies.

So the bottom line is that some large companies, who would ordinarily not act like cowards, have begun to do so, at least in the case of small customers like me: they seem to be deciding that there’s more downside risk of keeping me as a customer, than there is upside potential of me being a better customer – they felt they had a better chance of losing money by keeping me as a customer, than they had of gaining money by keeping me as a customer.

So, with the equation changed, I’m back to being in the cash-only economy, at least to an extent. I’ll be taking a cab to work tomorrow, at a cost of more than half a week’s car rental; and I’ll be looking to rent a room near work, probably for a cost of more than twice what it would cost to rent a car.

I’ll be working, though, and I’ll be alive to complain about this, and to anticipate the tax refund I’ll be receiving next year: I’m going to have so much deductable commuting expense.

BTW, I have more props for Enterprise: not only do they pick you up and drop you off, but when dropping me off today (after I returned the rental car), the manager there suggested that I rent from them over the weekend for a special rate. Since it will only be a weekend rental, they will only need to use a credit card with $300 on it. That, I still have, so I’ll probably be driving one of their cars this weekend. The contrast between Enterprise on the one hand, and Bank of America and American Express on the other hand, is revealing.


EDIT: I don’t feel so bad anymore – they’re doing it to everyone, even people with good credit. See http://moneycentral.msn.com/community/message/thread.asp?board=ConsumerActionForum&threadid=1080789.

Technorati Tags: ,

Posted in Personal | 4 Comments

One Way to Serialize Dictionaries

If you try to use XML Serialization on anything that implements IDictionary, and you’ll get an exception telling you it can’t be serialized. This question comes up, time and time again. This post will present one way to do it, using a “proxy” class.

The Code

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Xml.Serialization;

/// <summary>
/// Proxy class to permit XML Serialization of generic dictionaries
/// </summary>
/// <typeparam name="K">The type of the key</typeparam>
/// <typeparam name="V">The type of the value</typeparam>
public class DictionaryProxy<K, V>
{
    #region Construction and Initialization
    public DictionaryProxy(IDictionary<K, V> original)
    {
        Original = original;
    }

    /// <summary>
    /// Default constructor so deserialization works
    /// </summary>
    public DictionaryProxy()
    {
    }

    /// <summary>
    /// Use to set the dictionary if necessary, but don't serialize
    /// </summary>
    [XmlIgnore]
    public IDictionary<K, V> Original { get; set; }
    #endregion

    #region The Proxy List
    /// <summary>
    /// Holds the keys and values
    /// </summary>
    public class KeyAndValue
    {
        public K Key { get; set; }
        public V Value { get; set; }
    }

    // This field will store the deserialized list
    private Collection<KeyAndValue> _list;

    /// <remarks>
    /// XmlElementAttribute is used to prevent extra nesting level. It's
    /// not necessary.
    /// </remarks>
    [XmlElement]
    public Collection<KeyAndValue> KeysAndValues
    {
        get
        {
            if (_list == null)
            {
                _list = new Collection<KeyAndValue>();
            }

            // On deserialization, Original will be null, just return what we have
            if (Original == null)
            {
                return _list;
            }

            // If Original was present, add each of its elements to the list
            _list.Clear();
            foreach (var pair in Original)
            {
                _list.Add(new KeyAndValue { Key = pair.Key, Value = pair.Value });
            }

            return _list;
        }
    }
    #endregion

    /// <summary>
    /// Convenience method to return a dictionary from this proxy instance
    /// </summary>
    /// <returns></returns>
    public Dictionary<K, V> ToDictionary()
    {
        return KeysAndValues.ToDictionary(key => key.Key, value => value.Value);
    }
}

Construction and Initialization

XML Serialization requires that the class being serialized have a default constructor. But in this case, the Original dictionary is not set. Making the Original property public and read/write permits the caller to set the dictionary after construction but before serialization.

The Proxy List

The data that are actually serialized and deserialized are a list of key/value pairs. I could have chosen to use the System.Collections.Generic.KeyValuePair type, but I wanted control over serialization, so I created my own simple KeyAndValue type.

To understand the details of how the KeysAndValues property works, you have to understand how XML Serialization handles collections. On serialization, nothing very special happens. We create an empty collection, fill it from the Original dictionary, then return the filled collection. The XML Serializer then enumerates the elements in the list and serializes each one.

It’s a different story on deserialization. First, an instance of the DictionaryProxy class is created, using the default (parameterless) constructor. Note that this leaves Original set to null. The KeysAndValues property getter is then called. It finds _list to be null, so creates an empty collection. It finds Original still set to null, so just returns _list.

However, the XML Serializer then takes the collection we just returned (_list), deserializes each KeyAndValue item it finds, then adds them to the collection. Since we first stored a reference to that collection in _list, the XML Serializer is filling our internal list from the deserialized elements.

Note that I originally made a common mistake, and used a local variable instead of the field, _list. The result was that I returned this local variable, the XML Serializer filled the collection in the local variable, I returned the local variable with the filled elements, and the next time KeysAndValues was called, the filled collection is empty because we threw away the local variable that was filled!

ToDictionary

A simple method to turn the proxy type into a real dictionary is also provided. It takes advantage of the LINQ ToDictionary extension method. The particular overload of this method that was used accepts two delegates. The first translates a KeyAndValue instance into a key, and one that translates a KeyAndValue instance into a value. These are simple enough that I included them inline, as lambda expressions.

Next Steps

Although I haven’t tested it, I also created a class to serialize Hashtables:

public class HashTableProxy : DictionaryProxy<object, object>
{
    public HashTableProxy(Hashtable original)
    {
        var temp = new Dictionary<object, object>(original.Count);
        foreach (DictionaryEntry entry in original)
        {
            temp.Add(entry.Key, entry.Value);
        }

        Original = temp;
    }
}

I also want to note that I could also have implemented IXmlSerializable on this class instead of depending on the XML Serializer to produce the desired XML.

Technorati Tags:

Posted in Serialization | 7 Comments

A REST Client Library for .NET, Part 1

Recently, a poster on the ASP.NET XML Web Services Forum asked how to invoke a particular REST-based web service and get the returned XML. Since this sort of question has been asked many times before, I thought I’d try to answer it with some code.

The poster wanted to access one of the web services of EarthTools™, by Jonathon Stott. The time zone or local time service is invoked by issuing an HTTP “GET” request to a URL that includes the latitude and longitude. The response is an XML document containing information about the time zone at that location. This is very easy to do with .NET, by using the System.Net.WebRequest class. The remainder of this article describes how I created a simple console application to invoke the service. In the next part of this series, I’ll describe how I then refactored that application to produce the first draft of a library that can be used to call other REST-based web services.

Main Program

I started by creating a C# Console application in Visual Studio 2008. I named it WebRequestClient, so that became the default namespace.  Following my typical pattern for a sample application, I modified Program.cs as follows:

Program.cs
using System;

namespace WebRequestClient
{
    internal class Program {
        private static void Main(string[] args)
        {
            var latitude = double.Parse(args[0]);
            var longitude = double.Parse(args[1]);
            var client = new TimeZoneClient();
            var result = client.GetTimeZone(latitude, longitude);

            Console.WriteLine(
                "version={0}, localtime={1}, offset={2}, suffix={3}",
                result.version, result.localtime,
                result.offset, result.suffix);
            Console.Write("ENTER to exit:");
            Console.ReadLine();
        }
    }
}

All the real work is performed in the TimeZoneClient class. This pattern permits me to create the code functionality in a simple console application, yet isolates the “user interface” from the “business logic” so that I can later substitute a Windows Forms or ASP.NET user interface, if warranted.

TimeZone Client – Original Version
using System;
using System.Net;
using System.Xml.Serialization;

namespace WebRequestClient
{
    internal class OriginalTimeZoneClient {
        private const string BASE_URL = "http://www.earthtools.org/timezone";
        private const string REQUEST_URL_FORMAT = "{0}/{1}/{2}";

        public timezone GetTimeZone(double latitude, double longitude)
        {
            var uriString = String.Format(REQUEST_URL_FORMAT, BASE_URL, latitude, longitude);
            var requestUri = new Uri(uriString);

            var request = WebRequest.Create(requestUri);
            using (var response = request.GetResponse())
            {
                using (var responseStream = response.GetResponseStream())
                {
                    var ser = new XmlSerializer(typeof (timezone));
                    var result = (timezone) ser.Deserialize(responseStream);
                    return result;
                }
            }
        }
    }
}

 

First, the URL is computed. For a latitude and longitude of 35.66 and 95.36, the URL would be http://www.earthtools.org/timezone/35.66/95.36. I then create a System.Uri instance from the constructed string. Whenever you have a choice between using an API that accepts the string form of a URL and System.Uri, you should use System.Uri. The constructor parses the URI string, and will throw an exception if the format is incorrect. It is better to have that exception thrown at an obvious location (the constructor call), rather than deep inside the API, which will eventually call the System.Uri constructor if you haven’t already done so.

Issuing the Request

The System.Net.WebRequest class is the abstract base class used for processing request/response interactions to a server, based on the URL. It defines the static Create factory method that is used to create an instance of the appropriate derived request class. In this example, since the URL uses the “http:” scheme, an instance of the System.Net.HttpWebRequest class is created. In this particular example, the defaults are used for all of the properties of the WebRequest, but one can set the Timeout, Proxy, Credentials, and other properties of the request before the request is issued.

The request is only issued when the GetResponse method is called. It returns an instance of the appropriate System.Net.WebResponse derived class. Since this class implements the System.IDisposable interface, the GetResponse method is called in a using block. This ensures that the Dispose method is called when the WebResponse is no longer needed, permitting the network connection to be closed. If the request resulted in an HTTP error code (4xx or 5xx), then a WebException would be thrown.

If the request is successfully issued, then the code calls the GetResponseStream method. this returns a System.IO.Stream instance that can be read from in order to return the body of the response. In this case, that body will contain the response XML. If I had wanted to process the XML directly, I would have loaded the stream into an XmlDocument or XPathDocument, or I would have used the stream to create an XmlReader over the bytes of the response.

The XML Schema

The EarthTools™ site provides an XML schema that describes the results. Unfortunately, although the provided schema accurately describes the individual elements being returned, it does not describe the response as a whole. I’ve modified that schema to reflect the entire message. I loaded the original schema into Internet Explorer by typing its URL into the address bar (http://www.earthtools.org/timezone-1.1.xsd). I then used the “File->Save As” command to save the schema to the project directory. I then added it to the project by using the “Add->Existing Item” command. I then modified the schema by adding the “timezone” element to describe the entire document, referring to the elements already defined in the schema. The resulting schema is as follows:

Modified timezone-1.1.xsd
<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> <xs:element name="version" type="xs:string"/> <xs:element name="location"> <xs:complexType> <xs:sequence> <xs:element name="latitude" type="xs:string"/> <xs:element name="longitude" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="offset" type="xs:string"/> <xs:element name="suffix" type="xs:string"/> <xs:element name="localtime" type="xs:string"/> <xs:element name="isotime" type="xs:string"/> <xs:element name="utctime" type="xs:string"/> <xs:element name="dst" type="xs:string"/> <xs:element name="timezone"> <xs:annotation> <xs:documentation> This element was added to describe the overall structure of the XML response.
        The original schema consists of all elements above the timezone element.
      </xs:documentation> </xs:annotation> <xs:complexType> <xs:sequence> <xs:element ref="version"/> <xs:element ref="location"/> <xs:element ref="offset"/> <xs:element ref="suffix"/> <xs:element ref="localtime"/> <xs:element ref="isotime"/> <xs:element ref="utctime"/> <xs:element ref="dst"/> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>

Deserializing The Result

I wanted to do a little more than the poster had requested. Rather than returning the raw XML, I wanted to use XML serialization to return an instance of a class that corresponds to the XML schema. But, first, I had to create that class, based on the XML Schema. To do this, I used the XSD.EXE tool included with Visual Studio. I started a “Visual Studio 2008 Command Prompt” window available in the “Visual Studio Tools” folder of the “Visual Studio 2008” start menu folder. I set my default to the folder containing the project, then issued a simple command:

Using XSD.EXE to Create Classes from XML Schema
WebRequestClient>xsd /c /n:WebRequestClient timezone-1.1.xsd
Microsoft (R) Xml Schemas/DataTypes support utility
[Microsoft (R) .NET Framework, Version 2.0.50727.3038]
Copyright (C) Microsoft Corporation. All rights reserved.
Writing file ‘WebRequestClient\timezone-1_1.cs’.

WebRequestClient>

This simply tells XSD.EXE to create classes from the schema (/c), and to use “WebRequestClient” as the namespace for those classes. XSD.EXE creates the file “timezone-1_1.cs”, which I added to the project. This includes the “timezone” type into which I deserialized the response:

Deserializing the Stream
var ser = new XmlSerializer(typeof (timezone));
var result = (timezone) ser.Deserialize(responseStream);
return result;

Conclusion

Nothing more is necessary for this simple example. It issues the request, receives the response and a Stream against the body of the response, and finally deserializes that stream into a result object. This pattern can be followed for any REST web service that uses the HTTP “GET” method and which has an XML Schema that describes the results.

With a little bit of editing, you can have a separate copy of this code for each service and result type you need to process. In the next part of this series, I’ll discuss how to refactor this code so that you won’t need to have multiple copies to maintain.

Technorati Tags: ,
Posted in Web Services | 2 Comments

Basics: How Web Services Work

Web Services are all about XML:

  1. A Web Service is described by a document in XML format, in the XML language known as WSDL (Web Services Description Language). This describes the service in terms of the operations, messages, and bindings that it contains, and may provide a URL at which the service may be called.
  2. The structure of the messages is described using XML Schema (XSD) which is either contained in, or referred to by, the WSDL
  3. The messages sent to, and received from, the web service are all in the form of XML that complies to the schema, and which follows the protocols described by the WSDL, using an XML protocol known as SOAP (for Simple Object Access Protocol)

The usual way to access a web service in .NET is as follows. Other platforms have similar mechanisms.

  1. The developers of the web service make the WSDL accessible. They can either place it on a web site, or the web service can generate the WSDL automatically.
  2. The developer of a client application will add a Service Reference if using WCF, or a Web Reference if using the older ASMX technology. This amounts to telling Visual Studio the location of the WSDL for the web service.
  3. Visual Studio requests the WSDL. It parses the file to gain an understanding of the web service. From this information, it will create some classes. These are known as proxy classes (not to be confused with an Internet proxy server). These classes stand in for the web service, allowing you the illusion that you are simply calling normal methods on normal classes. But these classes are not normal.
  4. The client code will create an instance of the proxy class for the service. It will call an instance method of the class, perhaps passing some parameters. The proxy class will turn these parameters into properly-formatted SOAP XML and will send them to the service.
  5. On the server side, the XML will likely be turned into parameters again, and a server-side method will be called with those parameters.
  6. The server will do what it was requested to do, and may then return a result. This result will be turned into SOAP XML, which will be sent back to the client.
  7. The proxy class on the client will receive this XML, turn it back into return values and will return that to the caller

The result is that the caller of a web service can treat the service operations just like normal methods on normal objects. In most cases, even the developer of the web service can treat the service like it is a normal object with normal methods. But everything in the middle is happening in SOAP XML, described by XML Schema, referenced by a WSDL in XML.

One of the consequences of this is that only things that can be described by WSDL and XML Schema will ever appear in a client proxy class. Neither WSDL nor XML Schema describe programming language concepts. For instance, note that the term "operation" is used, and not "method", "function", "subroutine", or "procedure". Neither can describe things like constructors, indexers, events, generics, or indexed properties.

Proxy classes are generated by "Add Web Reference", "Add Service Reference", WSDL.EXE or SVCUTIL.EXE. There are two kinds of class that will be generated. One class will be generated as a proxy for the service itself. This class will have methods in it that correspond to the operations of the service. Depending on how the proxy class is generated, there may also be events that will be raised  with the operations complete. The second kind corresponds to custom types used as input parameters to the service, or return values from the service, and of course all of the custom types referred to by these, recursively. These types will only contain properties. They are meant only to aid in communicatng data to and from the service – they share no behavior with the actual types used by the service itself.

One way to think about this is to realize that the Web Services platform is meant to be independant of the programming language or execution platform of the client or the service. With this in mind, it will be obvious why, for instance, a parameterized constructor will not appear on the client due to the fact that the server-side class had one. The client may not even have a concept of constructors, much less parameterized ones!

Posted in Web Services | 2 Comments

Getting Started With .NET Web Services

All new web service development should use WCF, if possible. There’s an excellent portal to WCF at http://msdn.microsoft.com/wcf. In particular, see Windows Communication Foundation, Conceptual Overview, and Getting Started Tutorial.

The old ASMX web service technology is still supported, but is nearing end of life. See Microsoft: ASMX Web Services are a “Legacy Technology”. In my opinion, this makes it unsuitable for production use, unless there’s no other choice. 

There are a few other Microsoft web service technologies I will mention only to warn you away from. They are obsolete and should not be used for new development. In fact, anyone using the following technologies should migrate to WCF as soon as possible.

Web Service Enhancements, or WSE were a set of stopgap releases that added to the ASMX technology to permit developers to work with the emerging WS-* standards as they were being developed by the industry. That means you will often find WSE mentioned in conjunction with security. This does not mean that WSE is the solution to security in web services, it means that WSE was that solution until WCF was released. WCF supersedes WSE, which is now obsolete.

Even more obsolete is the SOAP Toolkit. This was a way to create clients for web services, and worked for old VB or ASP applications. Do not use it.

Posted in Web Services | Leave a comment