Searching is fine…let’s make it easier, or even fun! Part 3
19 February 09 06:33 AM | maurore | 0 Comments   

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.

image


 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.

Searching is fine…let’s make it easier, or even fun! Part 2
14 February 09 01:54 AM | maurore | 1 Comments   

Getting Images from Live Search API

So, if you read part I of this post, by now you should have an idea of the type of experience and components that I aimed to develop…
a web server rendering a client page with inside a custom control used to show and animate images found on Microsoft Live Search by invoking a web service running on web server…
Wow, that was mouthful! :-)

I hope the following diagram will help you navigate this architecture and have a feeling for the interactions among components… some details will follow

image

Ok, let’s get it started…

Sketching out the Web Control

I wasn’t sure exactly how the control would look like, so I decided to sketch it using a user control (.ascx) instead of starting with a full blown web control. That way I was able to experiment with the UX while figuring out the properties I needed for the control to support my user experience, and I would not have to work on the design time support until the control design was hardened…

Creating the first instance of the control was a piece of cake.
After all, I needed just a label for the image Title, an Image for the picture, a label for the image Description (which I decided to use to show the images’ source), and the Play/Stop, Next, Prev buttons to control the slide show. Pretty much something like this…

<asp:Panel ID="PD_SearchImagesSlideShow" runat="server" CssClass="searchimages_pd_slideshow">
            <asp:Panel ID="PD_Photo" CssClass="searchimages_pd_photo">
                <asp:Panel ID="PD_Title" CssClass="searchimages_pd_title" runat="server">
                    <asp:Label ID="lblImageTitle" runat="server"   />
                </asp:Panel>                                          
                <asp:Image  ID="myImage"  runat="server" CssClass="searchimages_pd_image" />                             
                <asp:Panel ID="PD_Desc" CssClass="searchimages_pd_desc" runat="server">
                    <asp:Label ID="lblImageDescription" runat="server"  />
                </asp:Panel> 
            </asp:Panel>
            <asp:Panel ID="PD_Btns"  runat="server" CssClass="searchimages_pd_btns">           
                <asp:Button ID="Btn_Previous" runat="server" Text="Previous"  />
                <asp:Button ID="Btn_Play" runat="server" Text="Play"/>
                <asp:Button ID="Btn_Next" runat="server" Text="Next"/>              
            </asp:Panel>
</asp:Panel>    
Embed everything in a panel, assign each controls a CssClass, create the style sheet… ok I got that one from another project…
but CSS is easy anyway… isn’t it? :-)

Oh, I almost forgot, the controls needed also an Ajax SlideShow extender, which comes with the Microsoft Ajax Control Toolkit. That would make the trick of requesting the images from my web service and animating them in a slide show on the client. If you are not familiar with extenders, think of them as Javascript that is associated with server controls (once they are instantiated in a web page) and used to extend (i.e. improve, aka make cool) their functionalities.

<ACT:SlideShowExtender ID="SlideShowExtender" AutoPlay="true" Loop="true"
                 ImageTitleLabelID="lblImageTitle"
                 TargetControlID="myImage"                                    
                 ImageDescriptionLabelID="lblImageDescription"  
                 PreviousButtonID="Btn_Previous"
                 PlayButtonID="Btn_Play" PlayButtonText="Play"  StopButtonText="Stop"
                 NextButtonID="Btn_Next"                                    
                 SlideShowServicePath="~/services/..." SlideShowServiceMethod="SearchPhotos"  
                 UseContextKey="true"
                 runat="server">                                   
</ACT:SlideShowExtender> 

For example (see snippet above), in the case of the SlideShow extender, you associate that to (at least) an image and – at runtime - the extender will fetch images from a web service and replace the content of the associated image in response to a client timer event. 
  So, the effect would be that of a… slideshow – precisely!

Now, the control was showing up correctly in a test .aspx page even before my second coffee and before my kids woke up… brilliant!
Was it the second, or third one? … It must have been the second…
I couldn’t see any sun light outside yet…

Now the interesting part, the control’s properties and logic…

Control Properties

  • Width and Height – to make sure the control could be properly sized in different web pages.
  • QueryText – I needed a string for the query that should be issued to Microsoft Live Search.
  • MaxNumberOfImages  - to define the maximum number of images the client would request to the web service and, ultimately, to Microsoft Live Search.

That was it. I was determined to keep it simple…

Control Logic ?

A handful of statements to initialize the control, a few other lines for the presentation, just enough to arrange and scale the controls inside the panel based on the Width and Height defined by the user.
Then, I had to make sure the SlideShow extender would carry the right parameters for the web service invocation, namely: QueryText and MaxNumberOfImages.

Hmmm… the SlideShow’s ContextKey property used to pass information to the invoked web service is a string though…
you can’t pass the two properties just like that.
Not too bad though. I just had to serialize both properties and assign the serialized string to the ContextKey property. 
  You know? I used to hate serialization, but now Microsoft .NET offers plenty of choices to do it, it’s not fun yet.. but much better. 
  I just needed a wrapper object for the two properties.
  So, I created the Query object to carry that information and to implement the serialization.

Web Service

I developed of the web service in phases…

At first, I tested the client / server interaction, then I carried on with requesting images to Microsoft Live Search APIs.
  I started with a simple stub for the web service, encapsulating just enough logic so that it would return a few images taken from my web’s images directory…   Hey, it was not much, I know…, but that would do it for a first test of the service, and it would also show a slideshow on the client too.

That worked out quite well!
  By breakfast time, my control was invoking the web service, and showing a slide show of the returned images on the client. 
  The end to end lacked only the integration with Microsoft Live Search.
  I was almost done, wasn’t I? :-)

Plus, it was about time to enjoy some quality time with my family…
Yet, they were all sleeping… why would I wake them up?
And, Oh.. Noooo… :-)  it was snowing again!

Well,… I went downstairs to prepare a cup of coffee, while reading the documentation of Microsoft Live Search APIs.
  I had not made up my mind yet whether I would use the HTTP Get or SOAP as protocol. I knew HTTP would probably be a little bit lighter weight, but that meant I would need to deal with parsing some XML documents back and forth. Then, I opted to use SOAP, out of laziness I guess… the facility offered by the typed objects provided with the SOAP APIs was way too appealing.

Even more intriguing were the neatly assembled samples provided with the APIs. I had them working , and I adapted them within my web service code even before I finished my coffee… the third one!

Finally, I had a prototypical implementation of the end to end scenario that exercised the whole architecture.
And, it was working quite well.

However, a few doubts started crossing my mind when I got fancy with the queries using Live Search operators like site: or language: or location:
  These questions became more pressing when, with specific reference to image queries, I started using some other operators in order to filter results on image properties such as ImageAspectRatio (Tall, Wide, Square), ImageType (Photo, Graphics), etc… 
  I was a bit frustrated I had to write an application to do build a long and complicated query to interoperate with the Microsoft Live Search.
Truth to be told, everything was working fine, but my experience as a developer could have been better… 
  The reasons was that the components I had built so far, did not know anything about these operators. Their knowledge was only in my mind and hmm…. in Microsoft Live Search APIs’.
  And, I thought it was a pity none of my components would expose that knowledge in a more useful way.

I knew it!

All that had little to do with my little project.
  I was already thinking how Microsoft Live Search APIs could be extended and/or simplified… :-)

I could not help it though.  

I had to take another look at that Query wrapper. 
  Yep, its responsibilities could be expanded with great benefit for the overall solution.

But that was enough for the day… and for this part!

Searching is fine… let’s make it easier, or even fun!
10 February 09 07:07 AM | maurore | 2 Comments   

Getting Images from Live Search APIs – part 1

I don’t like the snow.
  When it is fresh, it is white and beautiful, but it is way too cold…
  Then, if you live in a city, it quickly gets dirty and muddy…
And, we had plenty this year in Seattle, especially around Christmas.

So, I’d rather stay home when it snows,  enjoying the family and, 
if possible, doing something cool… whatever happens to be cool for me at the time.

This time, I ended up doing some work for my little web site for fishing aficionados. A web I use more as a web developer fitness center than a real web app… right! go figure… :-)

Since I reviewed Microsoft’s Live Search APIs 2.0, a few days before the Christmas break, I thought it would be interesting to include some of the content they make available, like search results, news and images on my web’s pages.

Boy, these APIs make accessing Microsoft Live Search really easy!

You compose a query in a search request and you get a collection of results back. Both request and results are typed, i.e. images and news have different types, with specific properties, etc.. And, you can use different protocols, such as SOAP, XML, to communicate with the Live Search API service.

Building an application around them is quite simple. So, developers can really focus on how to implement the user scenarios.

For my web, I thought it would be cool to have an image slideshow, showing fishing photographs taken from those indexed on the net, within the context imposed by any given container page, yet picked in a somewhat random way and always fresh (making sure to properly show their source/credits).

I started envisioning something like this… Great fish, by the way!

image

So, let’s see… what are we looking at here?

A custom ASP.NET server control, a composite one, with an Ajax slide show extender to animate the images and interact with the user through the buttons… and some code to connect to the Microsoft Live Search service.

Yes, that would do it.

As a second thought, I would need to expose the application ID on the client Javascript code, hmmm… not good… not good!
   It is not that the AppID could not be sniffed on the net, but the idea of plainly exposing it, didn’t sound right.

More importantly, if my web had many users that would translate in many requests to Microsoft Live Search API, one per active client.
Yet… if two or more clients were looking at the same page – say the one about Alaska, i.e. issuing the same query (like: “Fishing Alaska”), wouldn’t I be able to cache the request/content on my web, before serving that page?

Gotcha!!

I just needed a service on my web, to support client requests and forward them to the Microsoft Live Search APIs and/or cache them and their results.

Perhaps two, three days of work for a solid prototype…

Sure! Why not?

After all, there were two feet of snow outside…

And so I did… and it was almost like I predicted.

The architecture it is working fine, and the results are neat.
Plus, I managed to create another couple of interesting components on the way…

And now that the snow melt for long, I thought I would share this experience with you. That is.

Stay tuned for the incoming parts…

GAT / DSL Integration Scenarios
07 June 06 02:00 AM | maurore | 0 Comments   
 
Microsoft Guidance Automation Package (GAT) and Domain Specific Language Toolkit (DSL)
are two key technologies, recently released by Microsoft, which allow architects and developers
to author and package guidance and domain specific languages.
GAT and DSL offer considerable value when used on a separate basis, and even more when used together.
And, given that Victor Aprea (Clarius Consulting) and I have been working on GAT/DSL integration for some time,
we decided to publish a paper about it.
So, here they are few GAT / DSL integration scenarios…

Providing DSL users with context / guidance

Every Domain Specific Language is designed and implemented based on the requirements
of the domain it is intended to model. When that language is used as part of the development
process of a given solution however, the solution’s context may affect the way that language
is used and how its artifacts are consumed.
 
For starters, DSL users will need to know whether there are only specific places in the solution
structure where DSL instances should be created/stored. And, it’s the task of the guidance provided
with the solution template to support and enforce these solution’s well-formed-ness rules.
Again, it must be noted that this knowledge may not be available to the DSL author.
            Imagine a business analyst is using a Business Process DSL while developing a solution
within Visual Studio. That analyst may not have the necessary information and skills to determine
where to put the Business Process model files inside the solution, or how to process them.
In fact, that knowledge belongs much more likely to the solution developer.
 
Additionally, for each artifact that can be created using a certain DSL, developers will need to know
what the artifact lifecycle is, in the context of a solution development process in which that DSL is used.
            In fact, the DSL toolkit support a very basic lifecycle –i.e. create, save (possibly delete),
apply report templates - for DSL model files.
            The designer of a specific solution may want to change and extend that lifecycle significantly.
For example, certain pre-conditions -verifiable at solution/project/file level in the solution- may need to
be validated before a DSL instance of a certain type may be created. Or, as we will see more in details
later on, the use of one language may be affected by and/or dependent by other DSLs used in the same solution.
            In a way similar problems need to be solved for all the artifacts in a solution. For example,
solutions developers need to address same problems for source code files or even binaries.
However, usage scenarios for programming languages are much more predictable, because better known,
than a generic DSL. Similarly, DSLs virtually span through many level of abstraction and their scope can
be very different from one another. That makes providing the necessary guidance to enable the DSL
artifact life cycle very important.
           
As part of that guidance, DSL users will also need to be educated on which procedures or commands
can be applied to language instances, and which artifacts will be created – if any – when these commands are applied.
            For example, a designer of a solution may have created various transformations that
–depending on the solution’s state – may be applied to instances of a certain DSL.
So, commands to launch these transformations may appear - within a context sensitive menu -
when the developer selects certain DSL model files, or model elements or even a DSL design surface..
 
Indeed, GAT can be very effectively used to provide DSL users with necessary guidance about how
to use a certain language and to embed into a solution the necessary support for the specific lifecycle
on DLS’ instances, model elements, etc...

Using GAT to extend consumption of DSL artifacts

Using DSL Toolkit, a DSL author can define transformations on DSL instances in order to create various artifacts.
            An example of a transformation can be the compilation of instances of a custom application
architecture language into programming modules containing classes implementing the applications
or patterns defined by that architecture.
 
In order to define a transformation, a DSL author uses the DSL debugging environment,
which is natively provided by the DSL toolkit when a new DSL language solution is created,
and that provides start up transformation templates.
            To make transformations available to language users, templates need to be copied
inside the solution or project where the instances of that language are created. 
 
Solution developers can select a transformation template and apply it to the language instance,
just asking the development environment to apply the template.
When launched, a transformation may load one or more models of one or various DSLs
to get its input data. However, the artifact generated must be directed to a single file. This last fact,
depending on the particular development scenarios, may be perceived as a significant limitation
on use and adoption of DSL.
 
On the other hand, GAT can be used to overcome this evident limitation.
In fact, GAT recipes make it easier to invoke transformation templates from within code.
And, the recipe writer can more freely determine where to direct the output of the transformation,
if one or more artifact are generated as results of the application of that transformation.
For example, a recipe can be written which repeatedly applies a text template to the same model,
perhaps using different model elements each time and generating different artifacts, one per model element.
 
Interestingly enough, the transformations developed by the DSL author within the DSL toolkit debugging
environment can be brought – almost with no changes – into the GAT package containing the solution guidance.
 
In this way, a solution developer can also apply different transformations to the same model element
or have a single transformation that applies to various model elements even of different languages.
                    
By using additional libraries (for example Clarius has started developing one) you can have your T4 templates
accept both, GAX recipe arguments and T4 model files, giving you a powerful combination in terms
of the code you can write in the template.
 

DSL cross language integration

As mentioned in our introduction, DSLs are generally relatively small, highly focused languages used
to model and solve certain -clearly identifiable- problems that various developer roles may have
to tackle as part of the software development lifecycle.
 
The limited scope of a DSL should not be perceived as a negative factor though.
Actually, the smallest the scope the greatest is the language potential effectiveness in solving problems
that belong to that scope, and supporting the specific needs of roles who are supposed to be the primary
stakeholders for the area of concern/abstraction level (viewpoint) that is associated with that scope.
 
Nevertheless, in many cases, architects and developers need to be able to navigate through various viewpoints,
i.e. through different areas concerns and across various abstraction levels. Other times, they need to be able
to transform artifacts created while designing and developing a certain viewpoint, into other artifacts
belonging to a different viewpoint.
 
Navigation across viewpoints and transformation of related artifacts imposes new requirements on DSL design,
especially in terms of integration among them. Perhaps the most important is the ability to refer to model elements
of one language from a different one (more specifically from the latter’s model elements or properties)
            For example, let’s assume modeling of Business Message Types and Business Entities in developing
a SOA application has been done using two different DSL. While using the Business Message Types DSL,
the message designer may need to refer to instances of business entities, specified using the other language,
in order to specify the payload for the message.
 
The current release of DSL toolkit does not support any integration across different DSLs. More specifically,
it’s not natively possible to refer from the model elements or properties in a language to those modeled
and instantiated in another one.
 
However, that level of integration can be programmatically obtained. In fact, a DSL integration service
can be designed to allow DSL author/users to browse through model elements defined in different languages
and to establish the necessary cross language references.  Additionally, one need to develop custom property
editors that will extend the DSL user interface to activate the integration service, and allow DSL users to actually
instantiate cross language references.
 
While GAT does not provide any native mechanism to support DSL cross language integration,
once the integration service is available GAT recipe patterns can be used to package the necessary
integration capabilities in a way that makes it easier for the solution developer to use.

We have developed a DSL Integration Service that we are now testing with the preliminary bits of the version of
DSL Toolkit that will be released later on august. We will make these bits available to the community at large for test.
 

DSL constraint checking across languages

Using the DSL toolkit, a DSL author can specify as many validity checking and constraints as necessary,
within a single DSL. All she/he needs to do is to define extension to the classes implementing certain modeling
elements, following the guidelines offered by the validity checking framework provided with the DSL toolkit.
            Checking the validity of the constraints on the model instances can be activated on demand or
when particular events, like file save, happen.
 
However, for the very same reasons why one may need to integrate different DSLs, validity checking may
need to be extended to span across multiple languages.
            For example, a DSL may define a model element named Business Process, which refers to
Business Rules that have been defined in a different language. Of course, for the model to be valid
– as a whole – instances of the Business Process in the first language have to refer to Business Rules
that exist in the second, i.e. have been instantiated using the Business Rules DSL. In this case, the solution
developer can use cross DSL integration to make sure models created are valid by design, instead
of having to check it afterwards
.
 
 
So? what do you think?
Are we missing something important?
 
What would be other integration scenarios?
 
Mauro Regio
Architect | Microsoft Corp.

Search

This Blog

Syndication

Page view tracker