Monday, January 26, 2009

The Poor Man’s Stock Quote Web Service

Ever wanted to programmatically fetch stock quotes? Ever look into it? I did. StrikeIron charges top dollar for their stock quote service, and, frankly, I don’t have that kind of money. But I can always go to finance.yahoo.com, and get the same information for free. Let’s exploit that, let’s create The Poor Man’s Stock Quote Web Service.

See it in action!

Using Windows Communication Foundation (Wcf), we will build a web service that takes a ticker symbol for a stock, grabs the text from the yahoo finance webpage, parses out the relevant stock quote information, and then returns a sweet StockQuote struct full of information. The legality of all this in a commercial application could probably be put to question, but we’ll leave that as an exercise for the reader.

Building a Wcf Service is very straightforward, and the source linked at the bottom is a Wcf sample perfect to introduce you to Wcf. This article isn’t an intro to Wcf, but if you’re quick, which I’m sure you are, you could pick it all up from the sample. See my other blog post to see how to host a Wcf service on a shared hosting plan.

First, we must define the ServiceContract for our Wcf Service:

[ServiceContract]    
public interface IStockQuoteService    
{    
    [OperationContract]    
    StockQuote GetQuote(string ticker);    
    [OperationContract]    
    List<StockQuote> GetQuotes(string[] tickers);    
}

As mentioned earlier, I’m going to use the Yahoo Finance to provide information for my Stock Quotes. Thus, the YahooStockService was born:

/// <summary>    
/// The Stock Quote Web Service that scrapes values from Yahoo's finance stock page.    
/// </summary>

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]    
public class YahooStockService : IStockQuoteService

In our Wcf service, we programmatically grab the text from a website using the HtmlScraper.GetPageContent function:

public static string GetPageContent(string url)    
{    
    WebRequest wreq = HttpWebRequest.Create(url);    
    WebResponse wres = wreq.GetResponse();    
    StreamReader sr = new StreamReader(wres.GetResponseStream());    
    string content = sr.ReadToEnd();    
    sr.Close();

    return content;    
}

Now that we have the page’s text, we can clumsily parse the text for the value that prefixes the content we are looking for. I usually break in my debugger, grab the Html page’s string value from the Watch window, and paste it in notepad. Then I look for the company name, and copy whatever’s in front of it.

Here is a simple example of the YahooStockService parsing for the Company Name:

private string ParseCompanyName(string page)    
{    
    // Regex pattern pasted from Html page.    
    Regex parseFor = new Regex("<div class=\"yfi_quote_summary\"><div class=\"hd\"><h1>");    
    return HtmlScraper.ParseContent(page, parseFor, "</h1>");    
}       


And now here’s the source. Many other parse functions exist in the sample, and we eventually end up with all the stock information we could need. Now go forth, poor one, and gather stock information to your heart’s content. At the time of this writing, it’s probably all going down anyways. GGgggooooo Bailout!

One note about the sample: it uses a Silverlight web app to consume the Wcf Service, you might need to install the Silverlight SDK.

References: Building a Web Service to Provide Real-Time Stock Quotes

Objective-C versus C#, part 2: Loading, rotating, and saving an image

 

In this example, I’ll compare Objective-C/Cocoa Touch to C#/.NET in their ability to load an image from a file, rotate it 90 degrees, and then save the modified image.  Both platforms are perfectly capable of performing this task.  One of them, however, sucks orders of magnitude less.  I’ll leave it as an exercise to the reader to decide to which I’m referring.  I’ll list the C# example first this time, since I wouldn’t want to be accused of favoritism.  In fairness, I should point out that for the Objective-C version, I cut some corners.  By using a UIImageView to house the image, I saved many lines of code that would result from applying transforms to the graphics context directly.

C#/.NET

Image myImage = Image.FromFile(@"c:\myImage.png");
myImage.RotateFlip(RotateFlipType.Rotate90FlipNone);
myImage.Save(@"c:\newImage.png");

Objective-C/Cocoa Touch

UIImage* myImage = [UIImage imageNamed:@"myImage.png"];
UIImageView* imageView = [[UIImageView alloc] initWithImage:myImage];
[imageView setTransform:CGAffineTransformMakeRotation(M_PI / 2.0)];

CGSize newImageSize = CGSizeMake(myImage.size.y, myImage.size.x);
UIGraphicsBeginImageContext(newImageSize);
[imageView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage* newImage = [UIGraphicsGetImageFromCurrentImageContext() retain];
UIGraphicsEndImageContext();

[UIImagePNGRepresentation(newImage) writeToFile:@"myNewImage.png" atomically:YES];

[imageView release];
[newImage release];

Sunday, January 18, 2009

Objective-C versus C#, part 1: Searching for a substring within a string

 

I’ve been wanting to create a series of comparisons between the syntax of Objective-C and C#.  I’ve been writing a lot of both these days, so I have a lot of experience with each.  For our first example, let’s say we wanted to check for a substring within a string:

Objective-C

if ([myString rangeOfString:@"mySubstring"].location == NSNotFound)) {
   NSLog(@"mySubstring not found in myString: %@", myString);
}

I don’t know how you could get any more intuitive than that, but just for kicks let’s look at the C# equivalent:

C#

if (!myString.Contains(“mySubstring”))
{
    Console.WriteLine(“mySubstring not found in myString: “ + myString);
}

Monday, January 12, 2009

The Science of Debugging

One of the best pieces of advice I ever received about debugging code was something that I could have just as easily brushed aside.  I was attending a work-sponsored training course, and the instructor said something that struck me as obvious and profound at the same time: Always start with a hypothesis.

How many times have you found yourself chasing down a bug, clueless about its cause, blindly adding variables to your watch window (or for XCode Objective-C programmers, blindly opening up the console window and typing “print object.property” – no, wait, that common syntax isn’t supported by the debugger.  So you type “print [object property]”, then receive an error that it can’t determine what the type is without a cast, even though it’s just an integer, so you type “print (int)[object property]”) without really knowing what you’re looking for?  As you step through the code aimlessly, you finally realize that you’ve jumped past the part of the code which reproduced the bug, and you have to start over.  (This situation is magnified by the lateness of the hour and the length of time you’ve been coding prior.)

You repeat this process several times, gradually locking down more and more of your code until you’re picking it apart one line at a time.  But even this doesn’t help if you don’t know what you’re looking for.  But that’s just it – you don’t know what you’re looking for.  If you did, you wouldn’t need to be debugging in the first place. 

Rather than spinning your wheels, you need to come up with a hypothesis; an educated guess about what might be causing the behavior you’re seeing.  If a dialog isn’t appearing on the screen, a simple hypothesis might be:

The code which spawns the dialog is not being executed. 

Testing this hypothesis is simple; just set a breakpoint on the line of code responsible for displaying the dialog (assuming you find it – maybe that was the problem), run your program, and observe whether or not it’s hit.  If it’s hit and the dialog still doesn’t appear, that’s fine – great, even.  You’ve gained information about the situation.  Rather than going on a wild goose chase, you’ve narrowed down the issue.  Now you can test another hypothesis:

The dialog’s Visible property is set to false.

Failing that, try another:

The dialog’s bounds are outside of the screen’s bounds.

And other:

The dialog is rendering underneath another window of the application.

The key is that you’re learning more about the situation with every hypothesis, rather than repeating the same guesses, moving off in random directions based on hunches, and becoming more confused and frustrated.

Note that all of these hypotheses are testable and falsifiable.  That is, you can objectively demonstrate if the hypothesis is true or false through experimentation.  This is crucial not only in debugging but for science as a whole.  There’s a reason why Intelligent Design Theory is the butt of jokes; there’s nothing testable or falsifiable about the idea that the universe was created by (essentially) magic.  Science, on the other hand, gains from both confirmed and falsified hypotheses (a fact which is lost on evolution-deniers).  Just as science gains knowledge about the universe from a disproven hypothesis, you gain knowledge about your application the same way.

Obvious, right?  When you’re tracking down a frustratingly elusive bug while exhausted and over-caffeinated, it isn’t. 

Sunday, January 4, 2009

Using the PollingDuplexHttpBinding for a Silverlight Group Chat

1) A Quick Intro to the PollingDuplexHttpBinding

Comet technologies, such as AJAX push and HTTP server push, allow web pages to have data pushed to them from the server, rather than always having the client pull information. It mimics this feature by having the browser poll the server at regular but short intervals (~1 second) to check for updates. Now web pages can be updated dynamically without any user input. Lucky for us, Silverlight supports this using the PollingDuplexHttpBinding Wcf Binding, which does most of the heavy lifting.

In this article, we hope to build a basic Silverlight group chat application by connecting a PollingDuplexHttpBinding to a Wcf Service hosted on a shared hosting plan.

There are excellent introductory articles to this technology that are pretty much required reading if unfamiliar with the PollingDuplexHttpBinding (Skim the first link if pressed for time):

  1. Basketball score server by Dan Wahlin
  2. Stock quote server by Peter McGrattan

The bulk of the PollingDuplexHttpBinding functionality is covered in the blogs listed above. From here on out, I will talk about some of the higher level details involved in making the simple chat program on top of the PushDataReceiver.

2) The static list of clients.

Every time a client connects to our webservice, we instantiate a new instance of the GameStreamClient class and keep it in a static List<ChatClient>. This does restrict us to only being able to run our chat server on one appdomain.

private static List<IGameStreamClient> clients = new List<IGameStreamClient>();

Our service gets instantiated on a Per Session basis as shown by the mark up below. In retrospect, I actually think it should have been a singleton, but that's for another time.

[ServiceBehavior(InstanceContextMode =
    InstanceContextMode.PerSession,ConcurrencyMode = ConcurrencyMode.Single,AutomaticSessionShutdown = true)]


3) The inactivity timeout and the stay alive ping.

Each Wcf connection has an inactivity timeout that defaults to around 10 minutes. We want our clients to be able to idle in the chat room, and not get booted for inactivity. Here we introduce a stay alive packet to reset this inactivity timeout. The end user will know nothing of it, and this way they can idle all they want.

Message gameDataMsg =
    Message.CreateMessage(MessageVersion.Soap11,"Silverlight/IGameStreamService/Receive","stayalive");

gameDataMsg.Properties.Add("Type", "StayAlive");

this.localClient.BeginReceive(gameDataMsg, EndSend, this.localClient);

4) I remove when I catch an exception when sending to a client.

With the PollingDuplexHttpBinding, the only way we will know if a client disconnects, is when the server fails to deliver a message. We cannot rely on the client to tell us when they are disconnecting, especially when considering that they are connecting from a browser; there's no real way to elegantly close out the client. Plus, they could just crash. As a result, there is no real disconnect, there is more of a send failure mechanism, that removes clients from the static list of ChatClients. In the proceeding ChatMessage broadcast, any clients that throw a CommunicationException/TimeoutException are removed from the server's client list. These timeouts could block the server however, so we must handle this asynchronously so as not to penalize connected clients.

foreach (IGameStreamClient client in clients)
{
    try
    {
        //Send data to the client
        if (client != null)
        {
            Message gameDataMsg =
                Message.CreateMessage(MessageVersion.Soap11,"Silverlight/IGameStreamService/Receive",data,this.serializer);

            gameDataMsg.Headers.Add(MessageHeader.CreateHeader("Type", "", "DataWrapper"));
            client.BeginReceive(gameDataMsg, EndSend, client);
        }
    }
    catch (Exception ex)
    {
        // Exception caught when trying to send message to client so remove them from client list.
        // Should probably catch a more specific exception but I'll leave that as an exercise for the reader.
        clientsToRemove.Add(client);
    }
}
foreach (IGameStreamClient client in clientsToRemove)
{
    clients.Remove(client);
}


5) Using DataContracts and DataContractSerializers to send complex types.

Sending strings back and forth is not really fun. Complex types such as structs would allow for much richer data transfer. So it's a good thing Wcf supports DataContracts and has a DataContractSerializer that makes this process seemless.

private readonly DataContractSerializer serializer = new DataContractSerializer(typeof(ChatData));
// Serialize
Message
gameDataMsg =
    Message.CreateMessage(MessageVersion.Soap11,"Silverlight/IGameStreamService/Receive",chatData,this.serializer);

// Deserialize
ChatData
chatData = receivedMessage.GetBody<ChatData>(this.serializer);


6) Adding Header information to the Message object so the Processor can serialize to the appropriate type.

When your application gorws in complexity, you will probably have multiple DataContracts, but your Wcf Callback contract will only have one message handler, and you will need to programmatically handle the Message Body. To know what that body is so you can deserialize it, the sample tags the outgoing message with type strings in the Headers. This acts as a form of metadata for the message and allows the caller to deserialize the DataContract to the message of the passed type, allowing proper complexity to the callback contract. This is a lot better than clumsily having a class with a body and a type, and dealing with deserialization logic yourself.

//Server creates the message and tags it with a type.
Message gameDataMsg =
    Message.CreateMessage(MessageVersion.Soap11,"Silverlight/IGameStreamService/Receive","stayalive");

gameDataMsg.Properties.Add("Type", "StayAlive");

// Receiver parses the message type and deserializes using the correct deserializer.
// Check message type
string type = string.Empty;
for (int i = 0; i < receivedMessage.Headers.Count; i++)
{
    if (receivedMessage.Headers[i].Name == "Type")
    {
        type = receivedMessage.Headers.GetHeader<string>(i);
        break;
    }
}
// Dispatch message based on type.
switch (type)
{
    case "StayAlive":
    break;
    case "DataWrapper":


7) Source code.

Source code

Hosting Wcf Services on a Shared Hosting Plan

Hosting Wcf Services on a windows shared hosting plan has one issue that people should be aware of: You can only add one address per scheme to a service host. But what does this mean?

Shared hosting plans often run with the default IIS set up, which means that there are two addresses to your site: http://www.yourdomain.com and http://yourdomain.com. Wcf only allows one address of any scheme (ie http://) to be used as a Service host, but by default, it tries to add the two. If you would try to run a web service using this markup,

<%@ ServiceHost Language="C#" Debug="true" Service="SomeService" %>

You would receive the following error:

This collection already contains an address with scheme http.  There can be at most one address per scheme in this collection.

To get around this, you'll have to make a custom ServiceHostFactory that will select only one address, and have your markup use this custom factory with the 'Factory' attribute. Which address you prefer is up to you, just remember to use it in your Endpoint configurations!

.svc file:

<%@ ServiceHost Language="C#" Debug="true" Service="SomeService" Factory="SomeNamspace.AddressSelectorHostFactory" %>

   
 

AddressSelectorHostFactory.cs file:

public class AddressSelectorHostFactory : ServiceHostFactory
{
    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
    {
        // When hosting on a shared hosting plan, the default IIS configuration passes 2 addresses
        // to CreateServiceHost: http://www.yoururl.com and http://yoururl.com.
        //
        // You can only add ONE address of a certain scheme (ie: http://), so we just take the www address.

        
if (baseAddresses.Length > 1)
        {
            Uri address = (from u in baseAddresses where u.AbsoluteUri.StartsWith("http://www.") select u).First();
            return new ServiceHost(serviceType, address);
        }
        else
        
{
            return new ServiceHost(serviceType, baseAddresses[0]);
        }
    }
}

 
 

More about this can be read here.