Entries:
Comments:
Posts:

Loading User Information from Channel 9

Something went wrong getting user information from Channel 9

Latest Achievement:

Loading User Information from MSDN

Something went wrong getting user information from MSDN

Visual Studio Achievements

Latest Achievement:

Loading Visual Studio Achievements

Something went wrong getting the Visual Studio Achievements

Using the Google Web Service

  This article demonstrates consuming a Web service. It uses Google Search Web services to build an application that searches for given keywords.

Difficulty: Easy
Time Required: 1-3 hours
Cost: Free
Software: Visual Studio Express Editions, Google API.
Hardware:
Download: Download

If you're like me, you probably spend more time at Google than any other place on the Internet. It remains my first and usually best choice for Internet-based research. Did you know that Google also has a Web service? With the Google Web service, you can bring the power of the Google search engine to any .NET Framework-based application.

If you read my earlier post about the Amazon Web service, the following should be familiar to you. The Google Web service is free, and you can download their developer kit without being registered, but if you want to do anything meaningful you'll first need to register with Google. Google will email you a license key that lets you make up to 1,000 automated queries per day.

I doubt I'll ever have the need to make that many requests on any given day. Maybe you can think of a unique way to make use of all those requests. Google itself offers these suggestions for ways you can use their Web service.

  • Auto-monitor the Web for new information on a subject
  • Glean market research insights and trends over time
  • Invent a catchy online game
  • Create a novel UI for searching
  • Add Google's spell-checking to an application

Since I use Google primarily for research, my goal for using the Google Web service was to build a simple desktop application for basic research. I wanted to emulate my typical use of Google on the Web: that is, have a form for inputting a query and executing a search, and places to list and show the results of my query.

For this example, we'll use one of the new Visual Studio 2005 Express Editions. The Express Editions of Visual Studio 2005 are simplified, streamlined and lightweight versions of Visual Studio tailored for hobbyist, novice, and student developers. Beta 2 of the Express editions can be downloaded at http://msdn.microsoft.com/express. Any of the Visual Studio 2005 Express Editions allow you to build applications which consume Web services; I'm using Visual C# 2005 Express Edition in this example.

Visual C# Express shares all of the great data access capabilities you'll also see in Visual Studio 2005. Working with the Google Web service API let me explore the Visual Studio Data Sources Window, which is a new tool window that displays objects in a project that you can use to create data bound forms. This includes data provided by Web services. With a Web service as a data source, it is virtually effortless to add data from the Web service to a form.

Now, usually all you should have to do to get to that place is add a Web reference to your project and Visual Studio takes care of discovering the data types. I expected that to be the case with the Google Web service. But instead I ran head first into a known problem. I should say it was not known to me when I first added a Web reference to the Google WSDL using the wizard in the Visual C# Express development environment. Nor was it known to me when I tried to figure out how to bind to data that was not appearing in the Data Sources Window accurately. The picture below illustrates what was wrong.

While the Web service appeared in the Data Sources Window and I could use it to query the service and get back a result, nothing I tried would let me display the data on a form. As you will see as I continue my story, the GoogleSearchResult type contains an array of ResultElements, and this is what I wanted to bind to on the form. But they didn't show up. After an hour (or two) of head scratching and then some old fashioned Google research, I found myself in the Visual Studio 2005 Beta 2 readme file. Under the Data Access section of the known issues, I found this item:

5.10.    Binding to Web services

Web services do not correctly display in the Data Sources Window for binding in Windows Applications.

To resolve this issue

Web service references are created with public fields instead of properties, and as a result do not yet work correctly at design time. As a work around, manually run the WSDL.exe tool to generate the correct web reference file. For more information, see the topic titled "How to: Run WSDL.exe to Prepare a Web Service to be used as a Data Source" in the Visual Studio help collection.

If you followed the link to the article you will note (perhaps with as much irony as I did) that the example Microsoft provides for correcting the problem is the Google API. At any rate this article had me back on track. The next picture shows what my Data Sources Window looked like after I added the manually generated Web reference file to my project.

Working in the Data Sources Window, you can view all the data types available from a Web service. This view represents what you'll see if you have a Windows form open in design mode. The icons next to each item in the tree represent the type of control you can create by dragging the element onto a form. You can change the control type using the drop-down arrow that appears when you select an item.

Anyway, the real beauty of this is that once you have your data ducks in a row you can begin building a data-bound user interface by dragging and dropping items from the Data Sources Window onto the form. Below is an early draft of my user interface. I built this in a matter of seconds by dragging items from the Data Sources Window onto the form. Visual Studio automatically created the necessary Data Connectors.

I ultimately decided to make this application have a browser-like look and feel. So in addition to a ToolStrip menu a status bar, I used a ListBox control at the top of my application to display the title of each search result. And then below that, I added a Web browser control to the form to display the associated Web page when a user selects an item from the list.

If you read through the documentation that comes with the Google developer kit, you'll find you have many different ways to submit a search query. You can apply language and country filters, for example, or search specific domains. You can also limit the search by date or file type. Basically, you have all the options available on the Google Advanced Search Web page. To experiment a bit with these possibilities, I added a ComboBox control to my application's ToolStrip to designate a language for a given search.

Behind the user interface elements, I leveraged the asynchronous processing capabilities of the Web service proxy class. The WSDL.exe tool automatically generates asynchronous versions of the Web methods it finds in the WSDL file. This lets you call a Web method on a separate thread to avoid locking up the application. Of course, you have other ways to boost performance. For example, I limited the number of results returned from the Google Web service to 10. But if I really want to make full use of the tool, asynchronous processing will help you to overcome performance bottlenecks.

To implement asynchronous processing, I added a BackgroundWorker component to the form and set up event handlers in the Form's constructor method.


backgroundWorker.DoWork +=new DoWorkEventHandler(backgroundWorker_DoWork);
backgroundWorker.ProgressChanged +=
new ProgressChangedEventHandler(backgroundWorker_ProgressChanged);
backgroundWorker.RunWorkerCompleted +=
new RunWorkerCompletedEventHandler(backgroundWorker_RunWorkerCompleted);

The code in my Search button's click event handler calls a helper method called StartSearch to begin the asynchronous Web service call using the BackgroundWorker. To pass the two user input values (the query text and the language selection) to the thread on which the BackgroundWorker runs, component executes the Web service call, I used a string array.


string[] searchCriteria = { this.queryText.Text, this._language };

And then passed the array as an argument to the RunWorkAsync method of the BackgroundWorker.


backgroundWorker.RunWorkerAsync(searchCriteria);

That invokes the method I delegated above called backgroundWorker_DoWork. This method executes on a separate thread. That's why I need to pass the values from the Windows form as input to this method (they aren't available to me from another thread). After first instantiating an instance of the Web service, the code reconstitutes the input argument (e.Argument) as a string array and then passes those values as parameters to the BeginGoogleSearch method of the Web service proxy class.


Google.GoogleSearchService googleWS = new Google.GoogleSearchService();
string[] searchCriteria = e.Argument as string[];
IAsyncResult asyncResult = googleWS.BegindoGoogleSearch(
LicenseKey,
searchCriteria[0], 0, 10, true,
searchCriteria[1], true, "", "", "", null, null);

As I said before, BeginGoogleSearch is the first of the pair of asynchronous methods that the WSDL.exe tool created from the synchronous Web method. In the code that follows, I create WaitHandle that allows me to monitor the progress of the asynchronous Web service call. At intervals of 200 milliseconds I report the progress back to the main thread using the ReportProgress methods of the BackgroundWorker.


worker.ReportProgress(percentageComplete);

This causes the code in the delegate method for the ProgressChanged event to execute. In this case, the name of the delegate is backgroundWorker_ProgressChanged, which contains a single line of code to update the value of the ProgressBar control on the form.


this.progressBar.Value = e.ProgressPercentage;

When the asynchronous call completes, the code in BackgroundWorker's RunWorkerCompleted delegate method executes. This method is named backgroundWorker_RunWorker; it performs some basic error and cancellation checking and then, if all went well, it processes the results of the Web service call. In the first line of code below, the result is cast from the input argument into an instance of the GoogleSearchResult. The next line updates the DataSource property of the DataConnector to use the collection of ResultElements (this is what contains the results of the Google search) which are exposed as a property of the GoogleSearchResult object.


Google.GoogleSearchResult searchResponse = e.Result as Google.GoogleSearchResult;
resultElementDataConnector.DataSource = searchResponse.resultElements;

The DataSource for the ListBox is the DataConnector named resultElementDataConnector. The DisplayMember property of the ListBox is “title”, which maps to the title property of the ResultElement type, and the ValueMember property of the ListBox is set is similarly mapped to the “URL” property of the ResultElement.

Finally, the code in the handler for the ListBox's SelectedValueChanged event updates the Url property of the Web browser control, which causes the Web page associated with the search result to display on the form.


itemBrowser.Url = resultList.SelectedValue.ToString(); 

That completes the tour of this application. What started out for me as an exploration of how to leverage the Google search services in a Windows application became something of an odyssey. But it was a journey that had a happy conclusion and made me appreciate the powerful data binding capabilities of Visual Studio 2005 more deeply. I encourage you to download Visual C# Express and explore this application for yourself.

Follow the Discussion

Remove this comment

Remove this thread

close

Comments Closed

Comments have been closed since this content was published more than 30 days ago, but if you'd like to continue the conversation, please create a new thread in our Forums,
or Contact Us and let us know.