Friday, August 28, 2009

ServerTooBusyException in WCF, possible cause

I wanted to post this confusing error and solution in case this can help anyone else.  Here is my general situation:

1. I was testing my WCF service hosted on a remote IIS server.  I had an identical IIS setup on my local development machine, and I wanted to switch to use it instead for better debugging support. 

2. When I ran the exact same service-calling code on my local machine, service calls always hit the ServerTooBusyException exception.  I checked my local IIS setup, confused that I was getting a different result when all of the virtual directories, ports, bindings, etc. were identical to the remote server.  I manually accessed my service’s URL in a local web browser, i.e. http://localhost/MyService/MyService.svc.  I got the error:

Service Unavailable


HTTP Error 503. The service is unavailable.

Huh?  Not very descriptive.  And being a newbie, I have had no luck following the convoluted steps of getting any sort of service trace logging to work – and I wasn’t even sure if this would help.  (As an aside, PLEASE comment if you know how to enable the type of logging that ultimately would have revealed this problem.)

3. Finally I found a vague comment on a forum regarding changed credentials, and it dawned on me: The account associated with the app pool I was using had had its password changed recently, and I hadn’t updated it on my local server to reflect this.  Once I re-set the credentials for the app pool user, everything worked perfectly.

 

I hope this post saves a headache or two.

Friday, August 7, 2009

Code Analysis / Team Foundation context menu items missing!

I had an issue recently in which my Team Foundation (2008) enlistment appeared to be partially corrupt.  Some of the symptoms:

1. My “Work Items” folder had a red ‘x’ next to it permanently; I could never connect to my work items on my main PC (but I could from other PCs).

2. When right-clicking on a Code Analysis warning in the Error List panel of Visual Studio, I didn’t get the usual options of “Create Work Item” and “Suppress Message(s)”.

3. Some of the Team menu items were missing, or their sub menu items were greyed out, and displayed error messages such as “value does not fall within the expected range.”

I tried all sorts of painful, time-consuming solutions, even uninstalling/reinstalling everything, but ultimately the solution was simply to delete my local app data Team Foundation Cache folder, located here:

%localappdata%\Microsoft\Team Foundation\2.0\Cache

I hope that someone finds this and it saves them hours of headache.

Monday, July 27, 2009

Resolving “CREATE DATABASE permission denied in database 'master'. (Microsoft SQL Server, Error: 262)”

To those of you who have Microsoft SQL Server Management Studio, and you’re un-hardcore users like myself who simply want to create a simple database to play around with, you might run into this cryptic error when you try to create a new database. 

image

Naturally the help URL link provided merely consoles you with an all-too-common “sorry, we can’t help” message.

We're sorry

There is no additional information about this issue in the Error and Event Log Messages or Knowledge Base databases at this time. You can use the links in the Support area to determine whether any additional information might be available elsewhere.

Given that you’re not a hardcore MS SQL Server user, and neither am I, this error makes little sense.  There’s a system database called master, but I’m not creating that… I’m creating my own database, called ‘MyDatabase’.  I don’t care about the permissions to the database called ‘master.’  Further, I’m the admin on my PC, and I’m using “Windows Authentication”… to me that sounds like I should have the highest possible access to do whatever the heck I want with my local SQL server. 

Well, yeah, you do, but here’s the catch: You have to run the damn SQL Management Studio as administrator.  That’ll make this hellish error go away.  I sincerely hope that this blog post has saved at least one person from the frustration they might otherwise endure.

Sunday, May 3, 2009

Oh noes! Expectation Failed (417) in my WCF service at Tully’s

Just when I thought my WCF service was working properly with regard to different network set-ups (i.e. my work network versus my home network), I found an annoying error occurring whenever I try to call one of my service methods.

Aside: Is that the proper terminology? Do I say: “Whenever I call a service method” or instead do I say: “Whenever I connect to my service” or : “Whenever I access my service” ? I’m not sure of the proper lingo.

image

For the benefit of search engines, that’s: “ProcolException was unhandled. The remote server returned an unexpected response: (417) Expectation failed.”

I verified (via remote desktop) that my home PC is still getting a proper response from the service. So what’s going on? Why am I unable to live up to my web service’s expectations when I’m on my laptop at Tully’s? Well, either it has something to do with my local system configuration, or it has something to do with the network settings here. I don’t really have a convenient way to test another network here, so I’m going to work on the hypothesis that it has something to do with Tully’s wifi network configuration. This seems especially likely given that my web browser is having a heck of a time loading web pages fully. Nevertheless, I don’t want to lazily write this off as an extreme case. I’ll need to use Google to get to the bottom of this.

So, after looking at Google, I’ve found several forums in which people have had a similar problem, and a solution which seems to work is described on my new favorite code-help site, stackoverflow.com:

System.Net.HttpWebRequest adds the header 'HTTP header "Expect: 100-Continue"' to every request unless you explicitly ask it not to by setting this static property to false:

System.Net.ServicePointManager.Expect100Continue = false;
Some servers choke on that header and send back the 417 error you're seeing.

Sure enough, I added this line before my call to the WCF service and everything worked as expected. Of course, it’s still basically magic to me. I understand little about how these requests and responses behave. MSDN demystifies it a little bit more:

When this property is set to true, client requests that use the POST method expect to receive a 100-Continue response from the server to indicate that the client should send the data to be posted. This mechanism allows clients to avoid sending large amounts of data over the network when the server, based on the request headers, intends to reject the request.

For example, assume the Expect100Continue property is false. When the request is sent to the server, it includes the data. If, after reading the request headers, the server requires authentication and must send a 401 response, the client must resend the data with proper authentication headers.

If this property is true, the request headers are sent to the server. If the server has not rejected the request, it sends a 100-Continue response signaling that the data can be transmitted. If, as in the preceding example, the server requires authentication, it sends the 401 response and the client has not unnecessarily transmitted the data.

Changing the value of this property does not affect existing ServicePoint objects. Only new ServicePoint objects created after the change are affected.

The Expect 100-Continue behavior is fully described in IETF RFC 2616 Section 10.1.1.

Sunday, April 19, 2009

My Experience Trying to Host a WCF Service on a Shared Hosting Plan

So I was about to try to host a WCF service on my shared hosting plan, and I was excited given my knowledge that such a tutorial had already been written – or so I thought.  I began by reading through some of the many WCF service creation tutorials available on the web.  These explained the fundamentals, and gave the steps required to create a working WCF service.  I was able to host these locally without much trouble, given that Visual Studio 2008 automagically does everything for you.  I can shut off my brain (a bad habit in coding, mind you) and trust that everything will work for me behind the scenes.

But once I was ready to test in a shared hosting environment, I drew a blank.  What the heck was I supposed to do?  No sweat, I told myself.  I just referred to an article written by our very own D-roc entitled: “Hosting WCF Services on a Shared Hosting Plan.”  Much to my horror, this article didn’t explain the first thing about hosting a WCF service on a shared hosting plan; it merely warned me of a single “gotcha” that could occur.  It should have been titled: “One Thing To Look Out For When Hosting a WCF Service on a Shared Hosting Plan.”  It lost me on the fourth sentence:

If you would try to run a web service using this markup,

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

Huh?  What’s this markup?  Where does that markup live?  I don’t have that markup anywhere in my code.  Is that supposed to be on my web server somewhere?  Where do I find/put it?

I had to refer back to one of my tutorials at codeidol.com, under the topic of WCF Essentials –> Hosting.  I was a little worried because these articles seem a little outdated, but not too outdated, I hoped.  In this topic, the author describes how to use IIS (Microsoft Internet Information Server) hosting.  Now, I don’t know much about IIS, but I know that it’s Microsoft’s server software for allowing servers on the internet to host web pages, FTP sites and that sort of thing.  I also know that my web hosting company has IIS installed and lets me administer it somehow.  So I figured this was my best bet.

Specifically, the article said that in order to host a service, I need to create a “virtual directory” and “supply an .svc file”.  Okay, I’d heard the term “virtual directory” before but I had no idea how to create one.  I was guessing it’d be a setting in my web host administration tool, so I looked.  Sure enough, in my web host administration control panel, I had a menu heading called “IIS Manager” and a setting called “Set Virtual Dir.”  I also noticed way too many settings that had to do with FrontPage extensions.  Microsoft doesn’t even make FrontPage, and hasn’t since 2003.  Why is this a big supported feature?  But I digress:

image

So I clicked this option and it brought up a page that let me specify the name of the virtual directory, and the actual directory where it should point.  I created a directory and made the virtual directory the same name.  Hopefully your web host will have something similar:

image

Now, I needed to somehow let the web server know that I have a service there.  Well, I don’t yet, but I wanted to make it think that I did.  So I opened up notepad and created an .svc file.  Now, rather than using the sample from codeidol.com, I decided to use D-roc’s example, since I assumed that his would be the “newer” of the two, in case there were any differences, and I didn’t want to do things the “old” way.  So I created a file called myservice.svc with the contents:

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

I then FTP’d to the folder which I set as an IIS virtual directory, and copied this svc file there.  Then I navigated to this folder in a web browser.  Predictably:

Directory Listing Denied

This Virtual Directory does not allow contents to be listed.

Okay, so somehow I needed to give the appropriate permissions.  From experience, I know that if you set global execute permissions using your FTP client, you can make the directory viewable to anyone browsing to it in a web browser, but I was pretty sure this was something different… perhaps an IIS setting.  So, back to my web host control panel I went, and look what I saw:

image

Sounds promising.  Sure enough, after clicking that option, I was able to browse all my directories and set “Browsing On” for whichever I chose.  I then browsed to this folder using a web browser.  I expected it to somehow run the service, then throw up an expected error saying that it couldn’t find it.  Instead, I got a directory listing with a single file: myservice.svc.  @#$%.  I don’t want people to actually be able to browse my svc file.  I want it to actually be run.  So I disabled browsing on that folder.  Strike 1. 

Alright, I saw another option that looks just vague enough to be promising:

image

Maybe this would set a certain file to be considered a “.NET App”, and maybe run as such.  (I should have mentioned earlier that I had Google’d every step of this process and ran into several dead-ends, hence the need to even post this article-blog-entry.)  Google led me to believe that this was for running ASP.NET applications, but there was some hint that it applied to web services as well.  A WCF web service is a .NET application, technically, isn’t it?  At least, it’s run within one.  So choosing this option let me pick a folder to set as a .NET application.  This made little sense to me, because a folder is a folder, not an application.  But I assumed that IIS would intelligently look inside the folder for an applicable application.  So I choose my “myservice” folder and set it as an application.  Back to the web browser:

Directory Listing Denied

This Virtual Directory does not allow contents to be listed.

@#%$!!!!!

Okay okay, no sweat.  I will try to turn browsing on; because maybe it will work properly in conjunction with setting that folder as a .NET App.  WRONG.  It still browsed the folder, .svc and all.  Okay, I will try to give execute permissions to the actual directory via my FTP client:

Directory Listing Denied

This Virtual Directory does not allow contents to be listed.

At this point, I’m thinking to myself: “Wow, that would have been super swell if D-roc had actually explained the first thing about getting this set up in his article.”

Okay, maybe I’m going about this with some wrong assumptions.  I mean, who cares if I can’t browse the folder?  I shouldn’t be able to browse the folder anyway, right?  This web service isn’t even supposed to be accessed via a web browser; it’s supposed to be accessed via some other client app on a user’s PC.  So, I start thinking to myself: Visual Studio is cool enough not to require me to manually FTP a freakin’ svc file to my web server.  There should be a way within Visual Studio to do this.  Well, luckily enough, I have my Visual Studio Web Service project I had previously created.  And sure enough, if I right-click that project, I see a “Publish…” option.  So I chose that option, and it prompted me for the target location.  I entered: http://mydomain.com/myservice and chose the default options, and clicked Publish. 

Much to my amazement, it worked the first time!

Connecting to http://mydomain.com/myservice…
Publishing folder /...
Publishing folder bin...
========== Build: 2 succeeded or up-to-date, 0 failed, 0 skipped ==========
========== Publish: 1 succeeded, 0 failed, 0 skipped ==========

I verified that in fact there were files published to this location.  Okay, okay, that’s a first step!  Now I want to test this service, which, by the way, simply takes an input string and manipulates it in a simple way.  I had some trusty code at my disposal from an online tutorial involving using WCF for interprocess communication.  Even though that’s not what I was doing, I still needed to make a connection using a similar method (or so I assumed).

So, in short, my client needs to create a channel between itself and the server.  It can do this using the handy ChannelFactory class provided by WCF:

ChannelFactory<IMyService> httpFactory = new ChannelFactory<IMyService>(
            new BasicHttpBinding(),
            new EndpointAddress("http://mydomain.com:8000/MyService"));

IMyService httpProxy = httpFactory.CreateChannel();

So this is my client app.  It references a shared contracts library which defines IMyService.  In case you haven’t tell by now, I’ve replaced the real names of my things with fake ones, to protect my billion dollar ideas.  If you want a full explanation of my logic here, please refer to the tutorial I referenced earlier.  So, I figured that something would go wrong if I ran this code, so I did – just to get a taste of what this brand of failure looked like, so that I’d recognize it in the future.

When I ran the test client, the handy built-in Visual Studio service host launched.  This was a bit disconcerting, since the ServiceHost I care about is the one allegedly hosted on my web server, so I didn’t want the local one to interfere.  But I carried on.  To my not-so-surprise, no exceptions were thrown when I called httpFactory.CreateChannel.  The real test would be the following line:

string translatedMessage = httpProxy.TwistMessage("I am a message.");

This code should actually connect to my service through my proxy, send it some message and get a string response, all handled for me.  Right?  I mean, I published my service already, so hopefully I can expect good things.  No such luck; I got an EndpointNotFoundException:

Could not connect to http://mydomain.com:8000/MyService. TCP error code 10060: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond xx.xxx.xx.xx:8000.

Okay, so let’s review my understanding: The endpoint is somewhere on the web server.  It’s part of the service, which is hosted by a ServiceHost.  But IIS manages the ServiceHost.  Somehow I need a ServiceHost running from IIS on my web server.  I already used the management tool to set a folder as an IIS .NET application (which, again, makes little sense because a folder is not any sort of executable as far as I know).  But wait, why did I use port 8000?  I just assumed that was proper, because I copied it from an example.  So let’s remove it and see what happens when I run the TestApp again, and attempt to call a service method from the proxy:

image

Progress!  Maybe!  Virtually clueless, I google’d this problem.  I found some forum posts with little help provided, but also this seemingly potentially helpful MSDN article.  In a cryptic way, the article explained – or so I believe – that I need to associate svc files with a certain DLL (aspnet_isapi.dll) in IIS.  It gave instructions about how to do this, of course working from the assumption that I am running IIS locally, which I, like hundreds of thousands of other people, are not.  No matter, there’s got to be an obvious way to accomplish the same thing in my web host.  Sure enough, something promising:

image

Clicking this link led me to an administration page where I could choose file extensions and the “program” (for lack of a better term) to execute them with.  I didn’t see the aspnet_isapi.dll listed explicitly, but I saw the option “ASP.NET”, which seemed to be close enough:

image

BAM!  After clicking Add, sure enough, the association was listed as: C:\WINDOWS\MICROSOFT.NET\FRAMEWORK\V2.0.50727\ASPNET_ISAPI.DLL.  Ladies and gentlemen, this is called “progress”.  Carelessly ignoring the potential warning about waiting 5 to 10 minutes, I ran my test app again:

image

Dang.  Well, I can wait the 5-10 minutes, but in the meantime I’m going to check the files published to my folder, since earlier I explicitly removed my old bogus svc file (assuming Visual Studio would be smart enough to create one for me when publishing).  Yep, it did.  The svc file is sitting there in the folder, sure enough.  Okay, I will wait… 

WAITED.  SAME ERROR.

Okay, let’s try a new angle: I’m going to connect to the svc file with the web browser:

Server Error in '/myservice’ Application.

Runtime Error

Description: An application error occurred on the server. The current custom error settings for this application prevent the details of the application error from being viewed remotely (for security reasons). It could, however, be viewed by browsers running on the local server machine.

…

Okay, I’ve had experience with this type of exception before, and it gave me instructions for getting specific details about the error message by modifying my web.config file:

<!-- Web.Config Configuration File -->

<configuration>
    <system.web>
        <customErrors mode="Off"/>
    </system.web>
</configuration>

So I’ll try this.  Nothing to lose.  I quickly discover that I don’t have a Web.Config, but I do have an App.Config.  Close enough, right?  It has a <configuration> group, so that’s probably the same, right?  BOOM, added.  Published.  Dang, no change.  Viewing the Web.Config in my app directory via FTP revealed that the customErrors tag was not added.  But wait, was I deceived?  My healthy skepticism of software brought my attention to a Publish dialog option.  Which one?

image

Choosing the “Delete all existing files prior to publishing” option made the customErrors tag propagate, and I was finally able to see the actual error:

[ArgumentException: This collection already contains an address with scheme http.  There can be at most one address per scheme in this collection.
Parameter name: item]

Oh my, look what we have here!!  After hours of struggling trying to learn how to host a WCF service in a shared hosting plan, I’ve finally reached the point where D-Roc’s tutorial, entitled “Hosting Wcf Services on a Shared Hosting Plan” begins!  Well hey, whaddya say we follow his instructions?

(Please refer to D-Roc’s tutorial for a walkthrough of this process.)

Now that I’ve completed the steps D-Roc described, I’m gonna try loading the svc file in a web browser again.  I don’t expect anything to work, since I’m not actually calling the service’s methods, but I just want to see what happens:

 

Server Error in '/myservice’ Application.


The resource cannot be found.

Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable.  Please review the following URL and make sure that it is spelled correctly.

Eh, that’s not the first thing I expected, but I’m going to assume that there’s just some dependency of the service that can’t be loaded considering I’m like… not properly connecting to the service.  Shaky reasoning, I know, but really, what would I expect to happen if I connected in this unorthodox way?

Anyway, if I recall, I had a test app that I was playing around with.  Let’s see if my recent changes made any difference regarding the problem I was having.  I ran it and….

image

Ugh, kill me.  Alright, I Google’d some more and found that someone had had a similar issue, and solved their problem by changing their endpoint address to actually point to the svc file rather than just the virtual directory.  In plain English, instead of:

ChannelFactory<IMyService> httpFactory = new ChannelFactory<IMyService>(
            new BasicHttpBinding(),
            new EndpointAddress(http://mydomain.com/MyService/));

I should (maybe) write:

ChannelFactory<IMyService> httpFactory = new ChannelFactory<IMyService>(
            new BasicHttpBinding(),
            new EndpointAddress(http://mydomain.com/MyService/MyService.svc));

So I made this change and ran the test app.  Here is what I got:

ServiceActivationException was unhandled
The requested service, 'http://mydomain.com/MyService/MyService.svc' could not be activated. See the server's diagnostic trace logs for more information.

I DON’T HAVE ACCESS TO THE SERVER’S DIAGNOSTIC TRACE LOGS!  It’s a remote host!!

So at this point, I’m thinking I was better off without specifying the svc file in the endpoint address.  At least before I was getting an exception that seemed to imply that my service was being contacted and my method request was being rejected.  This new exception makes it sound like my service isn’t even executing.

So, by now you must be anxiously awaiting my resolution to this problem.  Unfortunately, I haven’t come across one yet!  I will have to leave you in suspense until I actually figure out how the heck to get this thing working properly.  (Hint: I will ask D-Roc to tell me what the @#$% he did.)

Update: It turns out that my custom factory created from D-Roc’s tutorial was actually expecting the service to be accessed via “www.mydomain.com” rather than “mydomain.com”.  Here’s the tiny change I had to make:

ChannelFactory<IMyService> httpFactory = new ChannelFactory<IMyService>(
            new BasicHttpBinding(),
            new EndpointAddress(http://www.mydomain.com/MyService/MyService.svc));

But then, when running the test client and calling my service method on the proxy, I got a ProtocolException: Content Type text/xml; charset=utf-8 was not supported by service…  To fix this, I needed to change BasicHttpBinding to WSHttpBinding, like this:

ChannelFactory<IMyService> httpFactory = new ChannelFactory<IMyService>(
            new WSHttpBinding(),
            new EndpointAddress(http://mydomain.com/MyService/MyService.svc));

Thanks to this article for explaining this.

Update 2: I found it quite odd that a Visual Studio 2008 Web Service project item wouldn’t create an svc file within the project.  Instead, it would generate a generic one automatically every time I published my service (via Visual Studio’s Publish… option).  But, as it turns out, if I manually add an svc file into the project, it will publish that one instead, and won’t generate one on its own.  The more you know.

After all this headache, my web service finally ran.  I feel much smarter now.  Oh, and to put things in perspective, all of these struggles I’ve encountered are still much less of a headache than the iPhone development experience.

Monday, March 2, 2009

Another user experience brought to you by Microsoft

Just so I’m not accused of being biased in favor of Microsoft, let me bring you an example of the user experience we’ve all come to expect from this company.

So today, looking to expand my budding WPF knowledge by working on a Silverlight application, I decided to download the Silverlight 2 Toolkit from MSDN.  Easy enough, right?  Not quite.  Here is a summary of my experience:

1. Visited http://msdn.microsoft.com.  Conveniently, there was a link on the left pane of the web site labeled Silverlight, so I clicked on this and it led to a page that pointed me in the right direction to install “Microsoft® Silverlight™ Tools for Visual Studio 2008 SP1”.  Now, I assume that I have VS2008 SP1 installed.  I mean, if I didn’t, it would have shown up in Microsoft Update, right?  So I ran the installer.

2. Oops!

image

I guess I didn’t have it installed.  Weird, I was sure I keep my computer up-to-date with Windows Update.  No worries, I just clicked the link as provided and it conveniently took me to the installer for VS2008 SP1. 

3. I downloaded SP1 and ran the installer.  Uh oh, another problem:

image

Ah well, I guess I have to run some program to clean up the beta I installed a while ago.  So I clicked the link, downloaded and ran the installer.  Then I ran the SP1 update.  Then I ran the Silverlight 2 installer.  I have to wonder why this couldn’t have been done for me somehow.

Now let’s pretend that I’m not Vargo.  I’m another user who attempts to solve the problem another reasonable way.  Instead of clicking the first link to download VS2008 SP1, I go to Windows Update to look for the update.  I see nothing.  So I open Visual Studio and select Help->Check For Updates.  This can’t fail, right?  Wrong.  Not only does it take me to the same Windows Update site which failed me previously, but it opens it in my default browser: Firefox, and I get an error stating that I need to load the Windows Update site in Internet Explorer in order to get it to work!  MSN—no, sorry—“Windows Live” Messenger has no qualms about annoying me by opening hyperlinks in my non-default browser; why can’t Visual Studio do the same thing when it’s actually necessary!

Microsoft really has some work to do when it comes to the user experience.  But I’m not really shocking anyone here.

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