Getting Images from Live Search API
I couldn’t believe it, it was the forth straight snow day !
Actually, it was getting really nasty out there, with drivers spinning on icy roads and bumping into each others’ car and subzero temperatures. Better stay inside, for sure!
I would not feel guilty to dedicate a bit more time to keep developing the Image Slide control for getting images from Live Search through its APIs, described in part 1 of this blog series.
Query and ImageQuery Classes
As you probably read in part 2, I had left my work thinking about how to facilitate the creation of Microsoft Live Search queries. What I wanted to develop was a component that would help me reduce the chances of making errors while using the various operators.
I started up defining few enumerations for names and codes of Countries and Languages.
It would definitely help me reduce spelling errors. Well, I am sure that is only my problem and you all know how to consistently spell Latvian and/or Lithuanian in your code.
At the same time, it would avoid the need to look up for cryptic codes. Again, I should know better, and always remember that "zh_chs","zh_cht" are code names for Simplified Chinese and Traditional Chinese.
With these types defined, I could extend my Query wrapper object, adding a couple of collections to store the list of Countries and Languages that I wanted to include in my queries.
I needed another couple of collections for the list of Sites that should be included and/or excluded from the queries.
These two properties can be very interesting if you want to make sure that the query results are coming from content in specific sites, or they avoid other sites. Call it human relevance boost! :-)
What else did I need?
Oh, sure! Live Search API allows to specify the aspect ratio, the type of images, size and subjects. These are all string filters that can be added to the query.
I could definitely use other enumerations here. And, I could then add a few properties to my Query object to refer to the instances.
But, wait! Hold on… not so fast…
The Live Search Web Service Application Programming Interface (API) Version 2.0 enables developers to build applications that can retrieve different types of information from the Internet, supporting different types of information, including: Web, Images, News, Instant Answers, Ads, Related Search, Spell, Phonebook. (You can look up the documentation on MSDN).
So, really, these image related properties would be good for image oriented queries but not, let’s say, for News or Web ones.
Well, I could always move these properties in a subclass of the Query object, say ImageQuery, couldn’t I?
Actually, now that I thought of it, the MaxNumOfImages properties that I had previously defined in the Query object could be in the ImageQuery as well. Or should I change its semantics and generalized it to make it become the MaxNumOfResults?
Well, I thought the former would work better for my purpose, as I would make it easier for me to develop the web control and its design time support code.
Having said that, I was almost done…
In fact, I was left with reviewing serialization and de-serialization for the ImageQuery class, and then with creating a method that would output a well formed Live Search query, transforming the strongly typed property values in those strings that I had hard time manually composing and spelling.
Additionally, I needed a helper method that would create a Live Search SearchRequest starting from the content of the ImageQuery, I called it LiveSearchExpression.
Finally, I could use the ImageQuery object to create a well formed Live Search API SearchRequest object, using the BuildRequest method, whose code is shown below.
public SearchRequest BuildRequest(String myAppId,
uint nImageOffset,
AdultOption myAdultOption)
{
SearchRequest request = new SearchRequest();
request.AppId = myAppId;
request.Sources = new SourceType[] { SourceType.Image };
request.Image = new ImageRequest();
// Image-specific request fields (optional)
request.Image.Count = 50; // Always ask for maximum
request.Image.CountSpecified = true;
// Get images starting from a certain offset;
request.Image.Offset = nImageOffset;
request.Image.OffsetSpecified = true;
// Common request fields (required)
// Get Well Formed Query Text from this obiect
request.Query = LiveSearchExpression();
// Common request fields (optional)
[...]
return request;
}
A coffee and a breakfast later, I was done with all that.
And, I hope the class diagram below will help you have a better sense of it.
Using Query/ImageQuery Classes
Now, I had no trouble in processing queries that I would send to Live Search invoking its APIs, neither within the web control nor inside the web service that was actually calling Microsoft Live Search.
For example, within the code-behind the user control, I could write snippets like the following, where Query was the control property storing the query text, and the SlideShowExtender was the name of the homonym Ajax control used at runtime to invoke the web services, passing the ContextKey as its parameter.
if (!string.IsNullOrEmpty(Query))
{
ImageQuery myIQ = new ImageQuery();
myIQ.Text = Query;
myIQ.IncludedCountries.Add(Countries.United_States);
myIQ.ImageColor = ImageQuery.ImageColors.Color;
myIQ.ImageSize = ImageQuery.ImageSizes.Medium;
myIQ.ImageType = ImageQuery.ImageTypes.Photo;
myIQ.ImageSubject = ImageQuery.ImageSubjects.NonPortrait;
myIQ.MaxNumOfImages = 100;
this.SlideShowExtender.ContextKey = myIQ.ToJSON();
}
Processing the query in the web service was also a breeze.
// Deserialize the ImageQuery from the passed parameter
ImageQuery myImgQuery = ImageQuery.CreateFromJSON(contextKey);
[…]
//Build the request for the right query at the right offset
SearchRequest request = myImgQuery.BuildRequest(m_LiveSearchAppId,
nOffset,
AdultOption.Moderate);
Yep, implementing these wrapper classes, Query and ImageQuery, had been time well spent.
You know? Using Live Searh API was much easier than before.
It was almost fun! :-)
My end to end scenario was still working fine, my second coffee was long gone. It was definitely time for another one and a break.
Yes, I needed some fresh energy before tackling the development of the full blown web control, especially the design time support part… :-)
Don’t you love implementing design time support for web controls?
Well, I will tell you more on the next part… I guess.