With some delay here is the final part of the series on how to implement a IE8 Visual Search Service using WCF. In this last part I will deal with the small bits which are still open in order to be able to deploy a full functioning Visual Search service and those are:

  • Simple caching mechanism
  • "Spambreak" to control the number of requests that are processed
  • WCF Configuration
  • Visual Search Configuration XML
  • Webpage for adding the service to the IE search provider list

Implementing a simple caching mechanism

As already mentioned quite a few times performance is critical for a Visual Search service in order to get acceptance by the users so it is opportune to use some kind of caching mechanism. In order to follow the K.I.S.S principle I didn't want to implement a highly sophisticated caching mechanism on my own so I simply use the caching application block which is one of the components of the Enterprise Library created and published by Microsoft Patterns & Practices. The caching block allows you to integrate very effective, configurable and extendable local cache into your application. Information about the features and how it can be used is documented in the MSDN documentation. For my Visual Search service I used the simplest approach on using the cache. So it is an in-memory cache that simply adds search results as cache entries with the query string as their key. The overall simple (cache)-flow ;-) in the service is outlined in the figure below.

cache_flow

The relevant code portions are minimal.

  1. The initialization 

    ICacheManager searchResultCache = CacheFactory.GetCacheManager("Cache Manager");
  2. The check

    private bool CheckCache(string query)
    {
           return searchResultCache.Contains(query);
    }
  3. The retrieval

    sI = (SearchItem)searchResultCache.GetData(query);
  4. The addition

    searchResultCache.Add(query, sI, CacheItemPriority.High, null, new SlidingTime(TimeSpan.FromMinutes(30)));

Of course you need to be aware of the concurrency mode in which the service performs when dealing with the cache. There are two categories to take care of:

  1. Instancing

    For a service like this the instancing behavior should be set to single as this ensures that there is only one instance of the service and thus for the cache which then ensures that all requests are validated against the same set of cached items. So I set the InstanceContextMode to single.
    However if you are implementing a high scale service you need consider a slightly different approach and will probably have multiple instances that access an distributed cache or at least you will have a backing store ore some kind of replication mechanism that replicates the cache across multiple physical nodes.
  2. Concurrency

    For concurrency the most reasonable setting is probably to allow the single service instance to deal with multiple requests at a time because otherwise we would introduce significant performance constraints. This however requires that the service itself is thread safe which is not an easy task to acomplish. So for simplicity, rapid development and testing reasons I initially set the ConcurrencyMode also to single.

More about this topic can be found on MSDN.

"Spambreak" to control the number of requests that are processed

As unlimited resources in terms of scaling and workload are rarely available there may be the need to limit the number of incoming requests to a sensible amount. One good measure is to check the length of the search query. In many cases it doesn't make sense to retrieve results for a single letter or number. Therefore it could be useful to only cycle through the complete search process when the query string has passes a given threshold (e.g. 3 letters). If the length is below the threshold you can simply return a static default result which could significantly boost performance.

WCF Configuration

Every WCF service needs a configuration. Although configuration could completely happen in code it is handier most of the times to declaratively configure the service with an XML configuration. As we are using the Internet Information server as our service host we can include the service configuration details into the Web.config file and can edit it with the WCF Configuration Editor included in Visual Studio 2008 (see figure).

WCF_Config_Editor_s

As we create a restful service we need to create an rest endpoint and use the respective binding. In my case I created the configuration with the endpoint and associated binding and behavior attributes completely myself however there is also the possibility to use the Factory attribute of the ServiceHost directive.

For the Visual Search service I need to define an endpoint which in my case defaults to the default adress. Then we need to configure this endpoint with an webHttpBinding so that the service is exposed via HTTP requests and not via SOAP messages. Finally in order to allow clients to communicate via HTTP request we must attach the WebHttpBehavior to the endpoint. So the complete service configuration for the REST endpoint looks as follows.

<system.serviceModel>
 
<bindings>
 
<webHttpBinding>
  
<binding name="myRestfulBinding" />
 
</webHttpBinding>
 
</bindings>
 
<services>
 
<service behaviorConfiguration="VideoVSearchAggregator.VideoVisualSearchServiceBehavior"
 
             name="VideoVSearchAggregator.VideoVisualSearchService">
    <
endpoint address=""
                  
behaviorConfiguration="myRestfulBehaviour"
                  
binding="webHttpBinding
 
                  bindingConfiguration="myRestfulBinding
 
                 name="VisualVSearchAggregatorRestEndpoint" 
  
                contract="VideoVSearchAggregator.IVideoVisualSearchService" /> 
 
</service>
 
</services>
<behaviors
  <endpointBehaviors
   <behavior name="myRestfulBehaviour"
    <webHttp /> 
   </behavior
  </endpointBehaviors>
  <serviceBehaviors
   <behavior name="VideoVSearchAggregator.VideoVisualSearchServiceBehavior"
    <serviceMetadata httpGetEnabled="true" /> 
    <serviceDebug includeExceptionDetailInFaults="false" /> 
   </behavior>
  </serviceBehaviors
</behaviors
</system.serviceModel>

One thing to be aware of is the fact that your service itself opens HTTP connections via the SearchControllers so therefore if you deploy the service in an environment that uses a proxy server for outgoing requests you need to configure your environment respectively. For an IIS hosted WCF Service you can add the following elements to the Web.config.

<system.net>
 
<defaultProxy enabled="true">
  
<proxy bypassonlocal="true" proxyaddress="<proxy>" />
 
</defaultProxy>
 
</system.net>

Visual Search Configuration XML

In order to let people register the Visual Search service with their Internet Explorer it is necessary to create a XML search configuration that is published via a simple link in a hosting webpage. To create the configuration for a service it's best to follow the documentation on MSDN. My configuration looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
<ShortName>Video Meta Search</ShortName>
<Description>Online videos from many sources at on glance</Description>
<Url type="text/html" template="http://(host)/VSearch/VideoVisualSearchService.svc/Search?query={searchTerms}"/>
<Url type="application/x-suggestions+xml" template="http://(host)/VSearch/VideoVisualSearchService.svc/Search?query={searchTerms}"/>
<Image height="16" width="16" type="image/icon">http://(host)/VSearch/images/VideoMetaSearch.ico</Image>
</OpenSearchDescription>

Webpage for adding the service to the IE search provider list

Well and finally we need to add a link to a webpage that lets the user register the search service. This can be achieved by calling the IE8 AddSearchProvider function. The function takes the URL to the XML configuration as a parameter. So in my case the call would look something like this:

<input type="button" value="Add Search Provider" onclick='window.external.AddSearchProvider("http://<host>/VSearch/XML/VideoVSearchAggregator.xml");'/>

After that you are ready to go! Hope you enjoyed the series and found some of the information helpful. The code for my project is attached to this post.

Reference:

As I started early with this series and lost momentum and therefore needed almost 3 months to finish there was the change to finish with similar projects earlier than me. So I have to give some Kudos to Guy Burstein, who already posted a blogpost covering almost the same topic - Congrats ;).

 

DeliciousBookmark this on Delicious Share