Welcome to MSDN Blogs Sign in | Join | Help

During the last few weeks I was working with Silverlight again quite a bit. This meant I had to write some code for several showcase projects, too. Of course no real production code (beware) but nevertheless in the end the applications were doing what they were supposed to do. However as it usually happens in those cases you have to decide between a quick and dirty fire and forget kind of stumble into the programming of the app or to put some basic effort in planning and designing to have at least the basic rudiment of an application architecture. And although I’m in the role of architect evangelist I’m always tempted to start coding without big thinking right away. This time however we took some time and designed our applications so that we would have a nice separation between UI and application logic. In particular we chose a ViewModel approach which is quite common in the world of WPF and Silverlight. ViewModel stands for Model-View-ViewModel (MVV) and is a variation of the widely known Model-View-Controller (MVC) pattern. I won’t dig deep into the explanation of this patterns as they have been described in depth at many places already including John Gossman’s or David Hill’s Blog for MVV or the Portland Pattern Repository for MVC. This said I want to focus on a short example driven walkthrough on how to create an Silverlight Application implementing the MVV pattern.

 

The example application allows to view songs and song lyrics of the current top artists listed on LastFM. In order to aggregate the data this small sample application already is a mash up of two different web services.

So in order to give you a high level impression of the application here is a simple architecture sketch.

Architecture Sketch

The Visual Studio 2008 project is organized accordingly. To maintain the highest level of simplicity a service access layer has been omitted although this would be something you would probably want to consider in a real application development project.

Project Structure

The folders contain the following:

  • Icons contains the icons for the Silverlight 3 out-of-browser feature as I enabled OOB for this sample app however it is obviously not relevant for the ViewModel part
  • Model contains, well, the ViewModel class and any other class necessary to build the object model for this application. In this case those are classes like Artist and Track which mainly consist of private fields and the related public properties.
  • Views contains the UI which in this sample is a single XAML page with it’s code behind
  • Servicedata contains some constant REST URIs for the services I call

As this baseline structure could be already called something like a best practice for ViewModel projects one could use such a structure as a base template for such applications.

Now let’s start with the meat of the application. The best way to start off with would probably be to create an empty ViewModel class stub which basically is a standard C# class stub. Next step could be to create something like a ViewModel Base class which enables change notification for properties of the ViewModel. This is absolutely helpful in order to have your views automatically updated when the properties change to which any UI Element is bound to.

This would look something like this:

public abstract class ViewModelBase : INotifyPropertyChanged
{
    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
 
    public event PropertyChangedEventHandler PropertyChanged;
}

So the ViewModel then extents this ViewModelBase class and instantly gains those notification capabilities when the OnPropertyChanged method is called in the setter of a property.

The same requirement also exists for collections which are data bound however this is almost even easier as Silverlight (as well as WPF) comes with a special collection class which implements the Observer pattern which of course is tightly related with any MVC pattern. This class is a generic collection class and is called ObservableCollection<T>. So with this knowledge we can start filling our ViewModel with life. For this sample this would look like the following up until now:

public class RadioGaGaViewModel : RadioGaGa.Model.ViewModelBase
    {
        #region Fields
        private ObservableCollection<Artist> topArtists;
        private ObservableCollection<Track> topTracks;
        private string currentLyrics = string.Empty; 
        #endregion
 
        #region C'tor
        public RadioGaGaViewModel()
        {
            this.topTracks = new ObservableCollection<Track>();
            this.topArtists = new ObservableCollection<Artist>();
        } 
        #endregion
 
        #region Properties
        public string CurrentLyrics
        {
            get { return this.currentLyrics; }
            set
            {
                this.currentLyrics = value;
                OnPropertyChanged("CurrentLyrics");
            }
        }
 
        public ObservableCollection<Track> TopTracks
        {
            get { return this.topTracks; }
        }
 
        public ObservableCollection<Artist> TopArtists
        {
            get { return this.topArtists; }
        } 
        #endregion
    }

Now what we have to do next is to make the ViewModel available to the UI for data binding. This can be easily done by following this little sequence of tasks:

  • Register an event handler for the Loaded-Event of the UserControl in the XAML markup of the respective view.
<UserControl
    ...
    x:Class="RadioGaGa.MainPage" 
    Loaded="OnMainPage_Loaded">
  • Create a handler method stub in the code behind file of the XAML page
private void OnMainPage_Loaded(object sender, RoutedEventArgs e)
        {
            
        }
  • Instantiate a new ViewModel object
private void OnMainPage_Loaded(object sender, RoutedEventArgs e)
        {
            RadioGaGaViewModel model = new RadioGaGaViewModel();
            
        }
  • Create a public property which sets the DataContext for the UserControl
public RadioGaGaViewModel ViewModel
        {
            get { return DataContext as RadioGaGaViewModel; }
            set { DataContext = value; }
        } 
  • Set the property and assign the ViewModel instance you just created
private void OnMainPage_Loaded(object sender, RoutedEventArgs e)
        {
            RadioGaGaViewModel model = new RadioGaGaViewModel();
            ViewModel = model;
        }

After doing all this you can bind your the properties of your UI controls to the Properties of your ViewModel which are surfaced to the controls via the DataContext set on the top level FrameworkElement. For example you could create a DataTemplate for the items of a ListBox and could bind the respective properties like shown in the sample below.

<ListBox.ItemTemplate>
    <DataTemplate>
        <Border CornerRadius="5" BorderThickness="1" BorderBrush="Black" Margin="1,0,0,1" Padding="2" MinWidth="320">
            <Border.Background>
                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                    <GradientStop Color="#FFB2B2B2"/>
                    <GradientStop Color="#FFFFFFFF" Offset="1"/>
                </LinearGradientBrush>
            </Border.Background>
            <Grid Height="55" HorizontalAlignment="Left">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition MaxWidth="40" />
                    <ColumnDefinition />
                </Grid.ColumnDefinitions>
                <StackPanel Orientation="Vertical" Grid.Column="0" MaxWidth="40" HorizontalAlignment="Left">
                    <TextBlock Text="{Binding Path=Rank}" FontSize="12" FontWeight="Bold" Foreground="Black" TextAlignment="Left" VerticalAlignment="Center" Padding="5,0,0,0" />
                    <Image Source="{Binding Path=Images[0]}" Height="30" Width="30" HorizontalAlignment="Left"/>
                </StackPanel>
                <StackPanel Orientation="Vertical" Grid.Column="1" HorizontalAlignment="Left">
                    <TextBlock Text="{Binding Path=Title}" FontSize="12" FontWeight="Bold" Foreground="Black" TextAlignment="Left" VerticalAlignment="Center" Padding="5,0,0,0" />
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="Artist:" FontSize="12" Foreground="Black" TextAlignment="Left" VerticalAlignment="Center" Padding="5,0,0,0" />
                        <TextBlock Text="{Binding Path=Artist.ArtistName}" FontSize="12" Foreground="Black" TextAlignment="Left" VerticalAlignment="Center" Padding="5,0,0,0" />
                    </StackPanel>
                    <TextBlock Text="{Binding Path=Playcount}" FontSize="12" Foreground="Black" TextAlignment="Left" VerticalAlignment="Center" Padding="5,0,0,0" />
                </StackPanel>
            </Grid>
        </Border>
    </DataTemplate>
</ListBox.ItemTemplate>

And that’s basically all for creating a ViewModel pattern based architecture. Next step would be to implement the business logic that fills the ViewModel properties. In my case these are the calls to the different REST based web services, which of course are called asynchronously (also as Silverlight doesn’t support anything else) in order to still have an responsive UI while the services are accessed.

For our sample the final result can be tested here: http://www.level70.de/silverlight/RadioGaGa/RadioGaGa.html

As I already equipped my development machines with Silverlight 3 Beta this only works with the SL3 Beta runtime. So if you are still on 2 you have to be content with this screenshot (pretty, eh? ;))

screenshot

The Visual Studio 2008/SL 3 Beta Tools solution can be downloaded from my SkyDrive.

I hope this all is helpful and easy to understand. As always feel free to send comments or corrections, etc.

Two more Sidenotes:

  1. LyricsWiki also offers a SOAP web service however I was not able to use it with Silverlight when letting Visual Studio generate the service proxy (with svcutil for Silverlight probably). So I switched to the REST based version
  2. This project can quite easily be migrated to WPF and vice versa. I’ve done this two time due to the fact mentioned in <1> because I wasn’t aware of the REST interface in the beginning. This shows that WPF and Silverlight get closer and closer with their features and APIs so that a develop once run everywhere scenario will become more and more feasible.


DeliciousBookmark this on Delicious Share  

Due to quite some unexpected demand for the sources of the knowledge management showcase published in this blogpost even now almost 2 years after the initial post I took some short time and updated the solution. So now should at least rudimentary work with Silverlight 2 and 3 Beta.

Unfortunately I had to strip out dragging support because I was constantly experiencing System.Argument.Exceptions when calling the MouseEventArgs.GetPosition() method and didn’t want to invest to much time into debugging.

So for me the solution basically works including the HTML-Search Button that calls into the Silverlight application however there is still no optimized or well documented code. It was and still is a quick hack and only should demonstrate how to innovatively visualize dry business content. So use at your own risk and feel free to send me comments or optimized versions. ;)

 

You can download the solution here.

Not just in order to show that this Blog is still alive but also because it may be a little useful hint for all of you doing the first steps with M, the language of the Oslo Developer Center.

As you might already know you can create data models with M which are parsed and transformed into T-SQL Reference by the M-Parser.

Not only can you define Types & Values but can also assign a storage container for the defined types. Depending on the Grammar used to translate the M-File it is transformed in something that provides real storage e.g. a table in a relational database.

In the following snippet the extent definition is marked in red.

   1:  module MyModule {
   2:      type OrderItem {
   3:          Description : Text;
   4:          Quantity : Integer32;
   5:      }
   6:      OrderItems : OrderItem*;
   7:  }

In the sample above M does not care about how the storage is physically populated. In case of using the T-SQL variant this line would only create the table but wouldn’t insert any items (which is absolutely comprehensible behavior). However sometimes it could make sense to also initialize the storage with some values. And therefore M supports what is called extent initialization. And this works for all types supported by M and the respective data store.

So you could easily define an extent initalizer for the following type.

   1:  type Task
   2:  {
   3:          Id:Integer32 = AutoNumber();
   4:          Name:Text;
   5:          DueDate:DateTime?;
   6:          Owner:Text;
   7:  } where identity Id;

However if you wonder what format to use for the DueDate field and stumble across the example documented in this MSDN documentation you will probably end up with an error message like shown in the screenshot below.

image

The issue here is that DateTime is specified following the following lexical structures for Date & DateTime literals.

Date literals are used to write a date independent of a specific time of day.

DateLiteral:

                Signopt  DateYear  -  DateMonth  -  DateDay 

The tokens of a DateLiteral must not have whitespace.

DateDay: one of

                01  02  03  04  05  06  07  08  09  10  11  12  13  14  15

                16  17  18  19  20  21  22  23  24  25  26  27  28  29  30

                31

DateMonth: one of

                01  02  03  04  05  06  07  08  09  10  11  12

DateYear:

                DecimalDigit  DecimalDigit  DecimalDigit  DecimalDigit

So the cause for the error is obvious as there is the sample only states a single digit for DateDay. So changing this to a double digit variant will resolve this issue. The complete lexical structure of M can be found in the MSDN library as well.

If you want to know more about ‘Oslo’ and ‘M’ check out the MSDN Developer Center and visit the blogs of Douglas Purdy and the Intellipad Team.

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  

The release of Internet Explorer 8 RC1 is just around the corner and fortunately there is a significant number of people and organization that want to release their own customized version of IE8. Luckily Microsoft publishes a tool that can let you easily customize IE8. The tool is called the Internet Explorer Administration Kit (IEAK) and its freely available. There are already quite a few blog posts about the tool itself so I don't want to rephrase all that if you are new to IEAK just go to the IEBlog and read the post by Jatinder Mann.

The current published version of the IEAK is the Beta 2 version that corresponds to the exact same version of IE8. So in order to prepare your customized IE8 package with RC1 bits for those that already have access to the IE8 builds > Beta2 there is no corresponding IEAK to those builds. However there is an easy workaround to use the Beta 2 IEAK with the newer bits. Just follow those 3 simple steps and you are done.

  1. Rename the IE8 RC1 setup executable to IE-REDIST.EXE
  2. Backup the original IE8 binaries used by the IEAK (usually in %ProgramFiles%\Microsoft IEAK8\Download\<Platform>\<Locale>\iebin\) and overwrite it with the newer file renamed in step 1. If you use IEAK for the first time the path and files may not exist so you need to start the IEAK wizard once and let it create the path and download the contents.
  3. Start and use the IEAK wizard as usual and create your customized IE8

Well I have to hurry up a bit as I initially planned to have this series finished even a while ago and now I'm even struggling to finish it until the end of the year. Anyway here is the next part and as promised this time I will focus on the search providers which feed the aggregator component with their content. As already mentioned since there are not many video portals that publish APIs I limited the search and implemented two providers which is however probably enough for demonstration purposes.

In order to live a bit of separation I first created a real simple interface which of course also describes the what the implementing search controllers can do. Since there is only one specific task the search controllers have to do is to fill a Section object which simply contains an array of objects. The interface itself is quite simple and contains only one method signature DoSearch(object obj) which takes an object as a parameter. Although in all cases the object that is filled is a Section object I needed to parameterize it with object because I use a threaded model for executing the searches with a ParameterizedThreadStart which unfortunately doesn't allow to pass on data to the thread procedure in a type-safe way. Alternatively I could have encapsulated the threaded calls to DoSearch() into a helper object which I would have initialized with the Section object to be filled by this thread however I didn't design the service in such a fine granular type-safe manner although it would have been relatively easy. If anybody follows the section and does his own implementation or variation the mentioned variant is described here. In any way here is the interface definition for the search controllers:

public interface ISearchController
{
   void DoSearch(object obj);
}

And here is the Section class which contains the results of the search:

[System.Serializable]
 public class Section
{
    [XmlElement]
    public object[] items { get; set; }
}

Now that I created the interface I was finally able to start with the implementation of the SearchControllers for the different providers.

  • YouTubeSearchController

    For the YouTube search I used the .Net Client Library which is a library that exposes the YouTube data API through a handy .Net object model which of course makes it really easy to perform searches and retrieve relevant content. Above that the API allows for some tweaking. For example I set the YouTubeQuery.NumberToRetrieve property to 5 as we don't need more because the number of results displayed by the VisualSearch window is limited and we want to display results from the other sources as well. So in order to create as little overhead as possible it is probably very sensible to limit the number of results.
    In order to be able to use the API you need a Google account need to register for a developer key and need to specify a name for your application in which you use the API.

    The search specific code in my YouTubeSearchController is outlined here:

    public void DoSearch(object youTubeSection)
    {
       try
       {
          ...
         
    this.youTubeSection = (Section)youTubeSection;
         
    YouTubeService service = new YouTubeService("<Your Application Name>");
         
    YouTubeQuery query = new YouTubeQuery(YouTubeQuery.DefaultVideoUri);
         
    query.OrderBy =
    "viewCount";
         
    query.Racy =
    "exclude";
         
    query.VQ = searchquery;
         
    query.NumberToRetrieve = 5;
         
    YouTubeFeed videoFeed = service.Query(query);
          this.youTubeSection.items = new object[videoFeed.Entries.Count + 1];
          Separator youtubeSeparator = new Separator();
          youtubeSeparator.title =
    "Videos On YouTube";
          this.youTubeSection.items[0] = youtubeSeparator;
          foreach (YouTubeEntry entry in videoFeed.Entries)
          {
            
    SectionItem secI = new SectionItem();
            
    if (!String.IsNullOrEmpty(entry.Title.Text))
            
    {
               
    secI.title = entry.Title.Text;
            
    }
            
    else
            
    {
               
    secI.title =
    "Title not available";
            
    }
            
            
    if (!String.IsNullOrEmpty(entry.Media.Description.Value))
            
    {
               
    if (entry.Media.Description.Value.Length > 50)
               
    {
                  
    secI.description = entry.Media.Description.Value.Substring(0, 50);
               
    }
                else
                {
                  
    secI.description = entry.Media.Description.Value;
               
    }
            
    }
            
    else
            
    {
               
    secI.description =
    "Description not available";
            
    }
            
    if (!String.IsNullOrEmpty(entry.AlternateUri.Content))
            
    {
               
    secI.url = entry.AlternateUri.Content;
            
    }
            
    else
            
    {
               
    secI.url =
    "Media URI not available";
            
    }
            
           
    ThumbnailCollection thumbs = entry.Media.Thumbnails;
           
    if (thumbs != null && thumbs.Count > 1)
           
    {
              
    Thumbnail thumb = new Thumbnail();
              
    thumb.source = thumbs[0].Url;
              
    thumb.alternateText = secI.title;
              
    thumb.height =
    "35";
              
    thumb.width =
    "35";
              
    secI.image = thumb;
            
    }
            
    else
            
    {
               
    secI.image =
    new Thumbnail();
            
    }
            
    this.youTubeSection.items[counter] = secI;
            
    ...
         
    }
         
    catch
         
    {
            
    throw new Exception();
         
    }
    }
     

  • Metacafe

    Metacafe also does provide an API however they offer a RSS API and return an XML feed for the search results. So the implementation for the MetaCafeSearchController looks a lot different.

    public void DoSearch(object metaCafeSection)
    {
       try
       {
          ...
          this.metaCafeSection = (Section)metaCafeSection;
          string uri = "http://www.metacafe.com/api/videos?vq=" + searchquery + "&max-results=5";
          Uri searchUri = new Uri(uri);
          WebRequest req = WebRequest.Create(searchUri);
          WebClient client = new WebClient();
          Stream resultData = client.OpenRead(searchUri);
          StreamReader sR = new StreamReader(resultData);
          XmlReader reader = XmlReader.Create(resultData);
          XmlDocument doc = new XmlDocument();
          doc.Load(reader);
          XmlNamespaceManager nSmgr = new XmlNamespaceManager(doc.NameTable);
          nSmgr.AddNamespace(
    "media", http://search.yahoo.com/mrss/);
          XmlNodeList itemList = doc.SelectNodes("/rss/channel/item");
          this.metaCafeSection.items = new object[itemList.Count + 1];
          Separator metacafeSeparator = new Separator();
          metacafeSeparator.title =
    "Videos on metacafe";
          this.metaCafeSection.items[0] = metacafeSeparator;
          foreach (XmlNode node in itemList)
          {
             SectionItem item = new SectionItem();
             XmlNodeList childNodes = node.ChildNodes;
             foreach (XmlNode child in childNodes)
             {
                if (child.Name.Equals("title"))
                {
                   if (!string.IsNullOrEmpty(child.InnerText))
                   {
                      item.title = child.InnerText;
                   }
                   else
                   {
                      item.title =
    "Title not available";
                   }
                }
                else if (child.Name.Equals("media:description"))
                {
                   if (!string.IsNullOrEmpty(child.InnerText))
                   {
                      if (child.InnerText.Length > 50)
                      {
                         item.description = child.InnerText.Substring(0, 50);
                      }
                      else
                      {
                         item.description = child.InnerText;
                      }
                   }
                   else
                   {
                      item.description =
    "Description not available";
                   }
                }
                else if (child.Name.Equals("link"))
                {
                   if (!string.IsNullOrEmpty(child.InnerText))
                   {
                      item.url = child.InnerText;
                   }
                   else
                   {
                      item.url =
    "Link not available";
                   }
                }
                else if (child.Name.Equals("media:thumbnail"))
                {
                   Thumbnail thumb = new Thumbnail();
                   if (!String.IsNullOrEmpty(child.Attributes[0].Value))
                   {
                      thumb.source = child.Attributes[0].Value;
                      thumb.alternateText = item.title;
                      thumb.height =
    "35";
                      thumb.width =
    "35";
                      item.image = thumb;
                   }
                   else
                   {
                      item.image =
    new Thumbnail();
                   }
                }
             }
     
            this
    .metaCafeSection.items[counter] = item;
            counter++;
            ...
        }
        catch
        {
           throw new ArgumentNullException("searchquery not set"
    );
        }
    }

So now with these two search implementations I get two Section objects which then again are aggregated into one single SearchItem object. Which then is serialized into the service response and feeds the VisualSearch client in Internet Explorer 8. This process was already mentioned in the last part.

So that's it for part four. The next part is probably going to be the last part and deals about the accompanying features of the service like threading, caching and configuration in a little bit more detail.

Reference:

DeliciousBookmark this on Delicious Share  

It's definitely about time to publish the promised third part of this series. This time I will cover the class model which I used to let the .Net XmlSerializer generate the necessary XML structure. I want to utilize almost the full breadth of the capabilities the Visual Search component is offering with respect of information display. So in this case the features are:

  • Categories or sections
  • Descriptions/Abstracts
  • Urls
  • Images

So the XML structure needs to look like the following:

<SearchSuggestion version="2.0" xmlns="http://opensearch.org/searchsuggest2">
    <Query></Query>
    <Section>
        <Separator title=""/>
        <Item>
            <Text></Text>
            <Description></Description>
            <Url></Url>
            <Image source="" alt="" width="" height=""/>
        </Item>
        <Item>
            ...
        </Item>
        ...
        <Separator title="Videos on metacafe"/>
        <Item>
            ...
        </Item>
        ...
    </Section>
</SearchSuggestion>

As I already mentioned I'm using the XmlSerializer in the .Net framework to serialize the XML drafted above. XmlSerializer serializes objects into XML and probably most of the sources (responses from the video services APIs) are XML you might want to ask the question why doing the indirection via a .net object model and not simply use XML transformation with an XML Stylesheet and send it straight over the wire using an XmlWriter. This is a valid question and the main reason why I didn't do it that way is because I started off with the YouTube service which gave me a pretty nice .Net based client API and others probably will follow. Another reason is that I wanted to use WCF which gives you more flexibility in targetting other clients as well and some quality of service features and knobs to fine tune the service.

So the object model looks like outlined in the following class diagram.

image

The properties in the classes are all annotated with the necessary XmlSerializer Attributes. So for example the code for the SearchItem class looks like the following:

[System.Serializable]
[XmlRootAttribute(Namespace = "
http://opensearch.org/searchsuggest2", ElementName="SearchSuggestion")]
public class SearchItem
{
        [XmlAttribute]
        public string version { get; set; }
        [XmlElement(ElementName = "Query")]
        public string query { get; set; }
       
        [XmlArrayItem(ElementName="Separator", Type=typeof(Separator))]
        [XmlArrayItem(ElementName="Item", Type=typeof(SectionItem))]
        public object[] Section { get; set; }
    }

The most important thing to mention here is that you need to define an array of type object in order to create the child elements of the section element as it needs to take two different types of objects (SectionItem and Separator). Another thing to mention is that the Section property is the aggregation of all results of the integrated video services and therefore I created a helper object (Section class). Every SearchController gets an instance of such a helper object to populate it with its own items and separator. In the end all helper objects of type Section are merged together to populate the SectionItem.Section property.

SearchItem sI = new SearchItem();

Section youTubeSection = new Section();

Section metacafeSection = new Section();

...

youTubeThread.Start(youTubeSection);

metacafeThread.Start(metacafeSection);

...

MergeSections();

...

youTubeSection.items.CopyTo(mergedSection, 0);
metacafeSection.items.CopyTo(mergedSection, youTubeSection.items.Length);

...

sI.Section = mergedSection;

The rest of the model is quite straight forward and I think it needs no further illustration. I will publish the complete code of the Video Visual Search with the last part of this series anyway.

The next part which hopefully doesn't take as long to publish as this one will deal with the Search Interface and the concrete implementations of it. Here's as usual a little teaser.

image

Reference:

DeliciousBookmark this on Delicious Share  

Welcome to part two of this series on how to implement a visual search service for IE8 using the Windows Communication Foundation (WCF) and other .Net technologies or libraries. The first part described the overall scenario of the service and today I want to go into a little more details with respect to the service itself.

With respect to the service there are some determining factors which need to be taken into account when creating the service contract interface which are:

  • The client is determined (The IE8 Visual Search Component) and is a black box for us
  • The schema of the messages accepted by the client is determined and is POX and is outlined here.
  • The client queries the service using plain parameterizes URLs via HTTP GET requests

This translates straight into the following attributes for our service.

  • We have to create a restful service that returns plain XML (no full blown SOAP Services)
  • Since the scenario implies some sort of contract-first design it is not since there is no metadata that describes the service and its operation and this actually implies that there is no contract (if you want to know a little bit more about contract-first I can recommend this article on theserverside.net)
  • We need full control over the serialization of the resulting XML

No with having this knowledge we can start to create the service.

After creating the service project in Visual Studio 2008 the first thing we do is to create the service interface which is quite simple in the sense that it only defines one single service operation at this time. My service operation is named "Search" (which is kickass creative) and accepts a single string parameter which is the search query.

So in the simplest case our service interface would look like this:

[ServiceContract]
public interface IVideoVisualSearchService
{
   [OperationContract]
   SearchItem
Search(string query);
}

However since we do have the attributes mentioned above we need to add some specific attribute.

  1. First is the [WebGet] attribute in order to make the service accessible via HTTP GET requests.
  2. We need to have full control over the structure of the resulting XML and therefore cannot use the DataContractSerializer which WCF uses by default to serialize the responses but need to specify the standard XMLSerializer in the .Net Framework. Therefore WCF introduces an XmlSerializerFormat attribute within the ServiceModel namespace which does exactly this.
  3. In addition we need to configure the service so that it exposes itself as a restful service. Therefore we could use a ServiceFactory in order to skip the sometimes cumbersome configuration steps however for the sake of transparency I create a manual configuration and then we need to add an endpoint with an webHttpBinding.

Having done all those modifications our service contract looks like this:

[ServiceContract]
[XmlSerializerFormat]
public interface IVideoVisualSearchService
{
   [OperationContract]
   [WebGet]
   [XmlSerializerFormat]
   SearchItem Search(string query);
}

and the minimal endpoint configuration in the looks like this:

<endpoint address="" 
             
behaviorConfiguration="myRestfulBehaviour"
             
binding="webHttpBinding"
             
contract="VideoVSearchAggregator.IVideoVisualSearchService" />

and the behavior configuration section is as well minimalistic and looks like this:

<endpointBehaviors>
   <
behavior name="myRestfulBehaviour">
      <
webHttp />
   </
behavior>
</
endpointBehaviors>

This also already marks the end of part II. In the next part I will give some more detailed information about the object model of the service which defines the content of the search results and how it is attributed to generate exactly the XML that the visual search component of IE8 expects. As a small teaser here is already the class class diagram of the object model to construct the response messages.

MessageClassDiagram

Reference:

DeliciousBookmark this on Delicious Share  

Beta 2 of Internet Explorer has been out for a while now and as you already know one of the new functionalities of Beta 2 is the visual search feature. Since there is a really extensive introduction about visual search and the steps on the IE8 side in this article on the Internet Explorer Team Blog I do not want to go into detail about this but rather tell you how to implement a service that is consumed by the Internet Explorer 8 Visual Search feature by means of a quite comprehensive example.

I chose a scenario which might be quite popular and that is video search. However since a user must explicitly register a search provider into his Internet Explorer unless you provide a customized instance using the Internet Explorer Administration Kit (IEAK). So in order to get one of the rare slots on the users search provider list I wanted to create some kind of meta search that aggregates search results from multiple sources. Another reason was that this enabled me to include and write about topics like threading and caching as well. In order to access the entries of the relevant video assets of the video sites I used their public APIs. Unfortunately it is not yet very common for those sites to offer public APIs to access their content especially in Germany I found none except for MyVideo.de however the application for an API key still remains unanswered. However at least I found two suitable APIs which are the YouTube and the metacafe API. The architecture of the service would allow to include further video provider at a later stage through a simple interface which could even be made configurable with the service evolving.

The requirements I defined for the service are:

  • Retrieval of video asset information from multiple sources

In order to provide the most possible value to the end user the visual search should aggregate multiple sources and provide a categorized visual search XML document to Internet Explorer.

  • Sources should be accessed in a non-sequential non-blocking manner

The Visual Search functionality is very performance sensitive because its sole purpose is to provide a preview of search results or suggestions while you type. And as we are usually typing quite fast the service ideally needs to respond as fast as we type. However from my experience many people as they get used to the value of the preview take some more time to type and skim through the results. However performance is one of the crucial non functional requirements of such a service. So I split the search operations on the different video sites up into different threads which signal the main thread when they are finished and the final result message can be assembled and send back to the browser. As this already has some great impact on performance I also defined a timeout for the main thread to wait for the search workers to finish which ensures quality of service to the search users.

  • Source specific search controllers which translate the incoming feed information into the service specific data model

Since all of the APIs are different in the form how they issue data each one has to be handled separately. For the services used this means that there are two search controllers which prepare the incoming data in order to transform it into the XML structure needed by the visual search feature. The effort depends on the structure of the underlying APIs. In my example the YouTube API is a bit easier to use since they already offer .Net client libraries for easy consumption. In the case of metacafe we need to care about the network operations and the parsing of the response message from the service a little bit more.

  • Caching functionality to reduce costly network access and time-consuming processing of the incoming responses

Again this is something that is very much related to performance but also needs some careful considerations because caching one one hand greatly boosts the services ability to respond to the service requests that fire against the service as you type however it also introduces the risk of sending outdated results to the browser. Therefore the invalidation time needs to be carefully defined. Most important to cache are also probably the one or two letter searches which are rarely of relevance but would require a full roundtrip of the search service whenever a search is started being typed.

  • Robust and stable hosting environment

A service like this which could easily be used by millions of users needs to be very robust and stable. Since this is already a challenge for the service application itself this is also true for the hosting environment. As I didn't want to care to much about this for my example I chose to host the WCF Service in Internet Information Service 7 as this is a production proven high scale hosting environment for web services.

So the high level architecture of the service looks like the following:

Search Service Architecture

Technologies used for the search service are as follows:

That's all for the introductory and overview part. In the next parts we dig a bit deeper into the into the architecture and the components.

And in order to give you a little preview of what you can expect here's a screenshot of the service in action.

IE8 Visual Search Sceenshot

DeliciousBookmark this on Delicious Share  

Ok, once again some information regarding the new IE8. This product is occupying me quite a bit however I think it is important to tell the story about better W3C standards compliance and new compelling and easy to develop extensibility and what that means to users and site owners. Especially standards compliance unfortunately is something that may introduce the need to act for many site owners. What that means is that IE8 by default renders in the most standards compliant mode it supports however this may break the experience of existing sites if the site owner doesn't take actions since the markup and style information sent to browsers identified as Internet Explorer is not standards compliant or is optimized for older browsers. Luckily there is remedy for this issues and some of them are quite simple and can be implemented with a minimum of effort. Since those possibilities are already comprehensively documented on Microsoft websites I don't want to dig into the details of every aspect about how to attain site compatibility. But since I found that the resources are scattered across many different pages I want to summarize the possibilities and list them in a short, clear and easy to follow way in this blog post. There are two categories of changes that you can bring in in order to have your site rendered correctly. One is to tell Internet Explorer 8 to use a backwards compatibility mode to render the page or to alter the page markup and styles to reflect the latest W3C standards supported by IE8. So what is necessary to do so? Here are the compressed instructions.

  1. Tell Internet Explorer explicitly which document mode to use

    1. To do that you can place a meta-tag into the <head>-Section of your pages or page templates. The tag has the following name and format:

      <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />


      The content attribute of the tag accepts the values IE=5, IE=EmulateIE7, IE=IE7, IE=8, IE=Edge (or anything else however this could lead to unexpected behaviors ;)). The values, except for the "Edge" mode are probably self explaining however if you want more information there is a good explanation about those modes on the MSDN page already mentioned.
    2. You can instruct your webserver to add a custom header to the http-response when your pages are sent to the browser which has the advantage that you don't have to alter all your pages or templates but you are still able to control the rendering behavior in a very granular way since the header can be applied on an per application basis or for pages only that match a certain pattern.
      1. For IIS such a header can be applied by inserting a <customHeaders> section into the web.config file for the application like outlined in the sample below.

        <?xml version="1.0" encoding="utf-8"?>

        <configuration>

           <system.webServer>

               <httpProtocol>

                  <customHeaders>

                    <clear />

                    <add name="X-UA-Compatible" value="IE=EmulateIE7" />

                 </customHeaders>

              </httpProtocol>

           </system.webServer>

        </configuration>


      2. For an Apache 2.x webserver you need to add a Header directive to the httpd.config after enabling the headers module by uncommenting the LoadModule directive for the mod_headers.so module. So the LoadModule and the Header directive looks like outlined below.

        LoadModule headers_module modules/mod_headers.so
        Header set X-UA-Compatible IE=7

      If the you configure your webserver to set such a header and a page also includes a meta-tag already like described in 1.2.1 the tag in the markup takes precedence over the header set by the server.

  2. Deliver W3C standards compliant web documents

    1. Update your pages to reflect the latest W3C standards supported by Internet Explorer 8. The changes which were implemented in order to attain standards compliance are documented on MSDN.
    2. Since option 2.1 means quite some implementation and testing effort there might be already a solution that reduces, at least the implementation efforts for quite a bit and that is to use a site version that may probably be already available, e.g. the pages that you send out to other standards compliant browsers like Firefox. So the solution is to use the user-agent string to identify Internet Explorer 8 and to send back the pages also used for other browsers. The technique to evaluate the user-agent string to identify certain browser versions is already commonly known and used however for those of you who want to have in depth information about that can consult the documentation about user-agents, the detection of browser versions and how to evaluate them using regular expressions. The relevant part of the IE8 user-agent string however looks like this:

      Mozilla/4.0 (compatible; MSIE 8.0…

    But remember that Internet Explorer still is the released IE version with a significant market share and it will probably be around for another couple of years. So it would be not wise to follow a IE8 strategy only but keep a IE7 version as well. How strategies for versioning in conjunction with browser detection and conditional comments can be set up is briefly outlined in this whitepaper.

Of folks, I hope that this condensed reference is of some help to you and finally I will leave you with the call to action

To get compliant today to guarantee a seamless experience when users come to your site with IE8!

A few days ago I found a short essay on my hard drive which I wrote quite some time ago and wasn't published so far. The paper is about Application Lifecycle Management (ALM) and how Visual Studio Team System supports ALM. I thought this would be a good candidate for my blog. So I went  through it and changed some minor things which have changed since I originally wrote this paper.

However there was (and unfortunately still is) one little problem that bothered me quite a bit and that is the fact that I write my blog in English while the paper itself I wrote in German so its not a good fit to publish it here right away. So I thought well this could be a good match for an automatic translator. I started with our own product the Windows Live Translator. Here's the translation of the first paragraph.

"The challenges facing the software development in the broader sense, and thus also to the tools were in recent years dramatically. Distributed applications, several quickly changing platforms, several changing architecture Elle concepts, quality requirements and shortened life cycles are things that the development of a application not make.
Moreover, often economic considerations led development teams local by offshoring measures of the project leaders and architects. Result of all these developments were a variety of different tools for a variety of tasks whose artefacts seldom the other tools used could be as well as the need for global communication. As a result that the proportion for coordination tasks in a software development project in unacceptable proportions driven and many projects not time and budget be stopped."

English is not my native language but even me does realize that this is not really usable and many parts don't make really sense and are not even close to the German original with respect to the message I wanted to bring across. In order to make sure that this is not a Microsoft specific phenomenon I also tried the Google Translator (beta of course). And here is the Google result:

"The challenges to the software development in the broadest sense, and hence the tools were used in recent years dramatically. Distributed applications, diverse, rapidly changing platforms, diverse, changing architectural concepts, quality requirements and shorter life cycles are things the development of an application does not just have facilitated.
Moreover, economic considerations often led by local developer teams offshoring activities of the project managers and architects to be separated. Result of all these developments were a number of different tools for different tasks, their artifacts in the rarest cases of the other tools could be used as well as the need for global communications. This meant that the proportion of coordination functions in a software development project in unacceptable proportions and has driven many projects is not timely manner and within budget could be terminated."

In my opinion this is not much better. Admitting that we are talking about a technical text and this text is definitely not written with the easiest of all possible structures there might be chances that you could get those translators to produce some sensible lines of text. However as I'm not producing or optimizing texts for automatic translators I come to the conclusion that those automatic translators are still not ready to be used in a broad set of scenarios and especially not to translate technical texts although this is already done by quite some companies including Microsoft.

The consequence is that all my English speaking visitors will unfortunately not have the chance to enjoy :) my essays and I will continue to publish those as special pages like I already did with this text about BPM. In this case for all my German speaking visitors here's a link where you can download the whole essay. Everyone else who is not able to read German and wants to try some translation tools, feel free and good luck ;).

This time just a short announcement and no broad epic technical essay as usual. The announcement is about the Silverlight Gadget Award for all those who are developing cool and innovative Vista Sidebar Gadgets and want to introduce this to a even broader audience than just the people visiting the Microsoft Gadget Gallery. Now is the time to sign-up for the Silverlight Gadget Award. The winners will be officially announced and awarded at our large web conference Xtopia 08 taking place in Berlin in November.

Silverlight Gadget Award

There's exactly one major prerequisite for your Gadget that it qualifies for your nomination and this is that it must have at least some parts of it's presentation implemented with Microsoft Silverlight technology. If you used to create your RIAs with Flash, don't be disappointed there still is a small change that you can manage to participate. Just use the resources on Project Rosetta and become a Silverlight pro in just a few days by transferring all your Flash knowledge into Silverlight knowledge.

Project Rosetta - From Flash to Silverlight

This Site is really cool stuff - Check it out 

 
So start building a Silverlight gadget today, sign-up for the award and have the chance to win a banner campaign and free entrance to the conference with a giveaway pack you don't want to miss. Sign-up periods ends October 31st, so don't hesitate. And as a final remark: The Award is for German applicants and German audiences only

The Internet Explorer Beta 2 was released yesterday introducing quite some new features about which you already probably read in one of the various like the IE8 Homepage or the announcement on the official IE Blog. However there may be a feature that isn't mentioned too often which is the fact that now with beta2 RIA technologies like Silverlight are also supported in the flyout of a WebSlice. This is something that wasn't available with Beta1.

And since it is not as obvious to integrate a Silverlight portion into a WebSlice I will give you a littel walkthrough on how to do that.

First of all I want to introduce you to the concept of the different sources from which a WebSlice can retrieve its information. To understand that we first need to differentiate between the two main components of a slice which is the button in the favorites Bar on the one hand.

 image

and the WebSlice flyout on the other hand.

image

The button, besides it's task to open the flyout is to visualize to the user that the content of the WebSlice has changed. The source where the WebSlice itself retrieves the change information is called the update source. The source however where the flyout then retrieves the actual content to render it is called the display source. Those two sources are the same for many standard WebSlices and in that case represented through an annotated portion of a website like outlined in my last blogpost. However using this technique the inclusion of rich Silverlight content is not possible. In order to do that we have to define two separate  sources for update and display. Such a topology then looks like outlined in the following figure (see also the  WebSlice whitepaper on codeplex).

image

So that means that in order to display Silverlight content in the WebSlice flyout you have to create a webpage which takes the role of the display source and ideally meets the size restrictions of the WebSlice flyout which are 320px * 240px on a 96dpi screen. This page of course should include the Silverlight application. Then you need to create a reference to this alternate display source into the page which includes the annotated HTML with the "hslice" keyword representing the discovery and update source.

This is done by defining a link that includes the "entry-content" property in an "rel" attribute of the link element and of course the URL of the display source in an "href" attribute. So that a complete and valid link would look like this:

<a rel=”entry-content” href="http://www.example.com/display.html"/>

 

So now that we know how the overall structure is we can start with an easy full example.

The simplest Html for Basic.html:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
</head>
<body>
<div class="hslice" id="VidODay">
    <span class="entry-title">Video of the day: Media Center in action</span>
    <a rel=”entry-content” href="
http://www.level70.de/silverlight/mcpluscsXS/Default.html"/>
</div>
</body>
</html>

Html for Display.html (no hatom metainformation is needed for the display source. It's just a plain webpage with an Silverlight app)

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html xmlns="
http://www.w3.org/1999/xhtml">
<head>
    <script type='text/javascript' src="MicrosoftAjax.js"></script>
    <script type='text/javascript' src="Silverlight.js"></script>
    <script type='text/javascript' src="BasePlayer.js"></script>
    <script type='text/javascript' src="PlayerStrings.js"></script>
    <script type='text/javascript' src="player.js"></script>
    <script type='text/javascript' src="StartPlayer.js"></script>
    <title></title>
</head>
<body style="background-color: white;">
    <div id="divPlayer_0" style="width: 290px; height: 370px">
        <script type='text/javascript'>var player = new StartPlayer_0();</script>
    </div>
</body>
</html>

And the final result of this example then looks like shown in the figure below:

image

So you see it is quite easy and really powerful to include rich internet technologies into a WebSlice giving great opportunity to create compelling scenarios with superior user experience. I'm looking forward to seeing your RIA WebSlices.

Today the MIX Conference in Las Vegas opens its doors and there will be quite some interesting announcements there. I will surely blog about some of them and today I will take a start with the public release of Internet Explorer 8 and one of its new features. This is called Webslices & Activities and is as compelling as it is simple because it easily enables you to extend the IE Browser. Now you might say "piece of cake" can be done for years and not only with IE but with other browsers as well. Yes, that's correct however not entirely because it is not that easy. Well at least not as easy as it is now with Webslices & Activities. But before continuing with the prose let's shortly introduce you to:

  • Activities


    Activities are services which allow you to access a certain remote service of a website in the context of the site or parts of the site you are visiting. So an example could be that you are on the website of a local dealer and are interested in buying something there. Unfortunately this dealer has no delivery service and also does not have a store locator. So in that case you would usually take the address and get directions using a mapping tool of your choice. Now you could do the same with a mapping activity. But now the big difference is that you can do it in the context of the dealer's webpage. Just mark the address, rightclick and choose the mapping activity of your choice like shown in the screenshot below.

    Now what is an activity technically?

    Now that's the simple one because it is simply a XML configuration. In this XML configuration you specify the display name, an activity category and an activity action. Now the action is the most interesting part as this is the real meat of the activity. This instructs IE8 what request to send to the target service in order to let the activity do what it is supposed to do. So for the mapping example you would probably configure the URL including all the search parameters whose values are represented by variables like {Selection}, {documentUrl}, etc. So during runtime if you want to use the activity the browser simply opens up a new window and sends the custom request to the target site. Easy, isn't it?
    You can optionally also specify a preview action which is very powerful and is the charming part of IE8 Activities because it allows you to include already the full functionality of the service in a little preview window which is overlaying the website you are actually browsing so there is no redirection and no new windows stealing focus. And the best about those preview windows is the fact that it can utilize full browser functionality including installed plug-ins. So that means you could use Ajax, Silverlight and Flash for your previews.

    Below you can see a sample activity configuration which I created to demo Activities using the translation service by leo.org. Unfortunately, as they do not offer a stripped down result page the preview is not really usable for translating inline.

<?xml version="1.0" encoding="UTF-8"?>
<openServiceDescription xmlns="
http://www.microsoft.com/schemas/openservicedescription/1.0">
    <homepageUrl>
http://dict.leo.org/</homepageUrl>
    <display>
        <name>Translate with Leo.org</name>
        <icon>
http://dict.leo.org/favicon.ico</icon>
  </display>
  <activity category="Define">
    <activityAction context="selection" >
        <preview action="
http://pda.leo.org/ende?lp=ende&amp;lang=de&amp;searchLoc=0&amp;search={selection}&amp;relink=on"/>
        <execute action="
http://dict.leo.org/ende">
            <parameter name="search" value="{selection}" />
            <parameter name="lp" value="ende" />
            <parameter name="lang" value="de" />
            <parameter name="searchLoc" value="0" />
            <parameter name="cmpType" value="relaxed" />
            <parameter name="sectHdr" value="on" />
            <parameter name="spellToler" value="on" />
            <parameter name="relink" value="on"/>
        </execute>
    </activityAction>
  </activity>
</openServiceDescription>

So you see the whole magic are two URLs which point to the remote service. The rendering of the response is entirely up to the activity's service provider. The Xml configuration can be provided by the service provider or anyone else. The activities engine only checks that the homepageUrl is from the same domain as the actionUrls. This means however that you need to be careful and only register activities from sites you trust. And finally in order to have IE8 recognize an activity configuration as such you need to provide a link with the href is pointing to a javascript function and so the url must look similar to this: href="javascript:window.external.addService('http://www.level70.de/ie/activities/LeoTransActivity.xml'). So here is how it looks like in action.

Activity Selector Activity Preview

  • Webslices


    Webslices are simply portions of arbitrary websites to which a user can subscribe to. This enables a user to have updates of sites he regularly visits right at his fingertips without navigating to the respective sites. A webslice behaves just like an RSS Feed. The slice itself will be added to the Favorites bar of IE8 when a user subscribes to a webslice. In order to subscribe to a slice it must be discovered. The discovery is quite easy as IE8 will display a special symbol if a page offers a Webslice. There is one in the toolbar where also RSS feeds are marked as available:

    Slice marker in the toolbar

    And there is another one at one corner of the webslice protion on the site itself

    Slice marker at the slice's edge
     
    If you click on the marker symbol you can subscribe to the slice just as you would do for an RSS feed. After subscribing to the slice it becomes visible in the Favorites bar of IE8:

    Webslice in the Favorites bar
    When the content of the site changes the title text of the slice will change its font-weight to bold and it the slice button flickers from time to time. To get information on the slice you can hover over the slice button and you will see the full title and the URL of the slice's source.

    slice4
    And finally if you want to view the updated information you can click on the slice and get the the slice portion rendered in a small overlay window.

    slice5 
    So what is a slice technically? Technically a slice is nothing more than annotated HTML. The annotations are derived from the hAtom microformat. So in order to slice enable a part of your webpage the least you need to define is a container (usually a <div>-Element, a title and the content. In order to give you a hint how this looks like in reality here is a little sample:

    <div id="test" class="hslice" style='width: 280px; font-family: Segoe UI; text-align: center'>
        <div>
            <div class="entry-content">
                <h3>
                    <span class="entry-title">Seattle</span>, WA (98121) Weather
                </h3>
                <img src="images/cloudmoon.png" id="image" style='float: left' height='128' width='128' />
                <div class="entry-title" style='float: none;margin-left:20px'>
                    <p style='margin-top: 0px; margin-bottom: 0px; font-size: 26px; line-height: 32px;font-weight: bold;'>89<br />&deg;F</p>
                    <p style='margin-top: 0px; margin-bottom: 0px'>Drizzle</p>
                </div>
                <div>
                    <p style='font-size: smaller'>
                        <i>All fictional, of course!</i>
                    </p>
                </div>
            </div>
        </div>
        <div>
            <abbr class="updated" title="2007-07-25T20:51:00-05:00" />
            <p>Current conditions as of 10:35 AM</p>
        </div>
    </div>

I marked the important annotations with bold font. So you see that the annotations are encapsulated within class names of the respective HTML elements. So you can note that the container must be defined with a class name of "hslice", the title with the class name "entry-title" and the content with "entry-content". Needless to note that projected back on the screenshots shown earlier the "entry-title" is rendered as the slice button text and the hover text whereas the "entry-content" is rendered in the overlay window. If like in the sample the "entry-content" is enclosing the "entry-title" the title is as well part of the rendered view of the slice.

So that's it for a short introduction on Webslices and Activities coming with Internet Explorer 8. If you want to know more and want to dig deeper in the technical details you can go to the IE Developer Center and find everything you'll need.

If you want to try the activity sample I used in this post you can add it here.

And finally if you want to see how easy it is to have an Silverlight application in the preview window just check this out.

Today is IE8 day - Soon you will now why. And I will start with a short advisory regarding a change in strategy how web standards will be handled in IE8 as default rendering option. But before that I would like to to mention that especially with respect to open web standards compliance IE8 marks another big milestone in the support of those standards such as CSS 2.1. So the IE team needs the feedback of the development community to see if the specs have been implemented flawlessly. Shortly you will have a chance to do so.

Although comprehensive support of web standards is something desirable it can also introduce some issues. In this case it is that pages that were optimized for IE7 rendering will probably not be as expected anymore. To avoid this to render many sites out there useless the IE8 team implemented a IE7 compatibility mode which forces IE8 to render the pages as IE7 used to do.

However unlike announced earlier this will not be the default for the beta release and probably not for the final version. To switch the default from less to more standard conformity for me however was the right step as it puts a little pressure on web developers to create pages as near to the standard as possible and the step taken by the IE team is proof that the announcement of Microsoft becoming more open was not just some empty statement.

In order to enable smooth transition for sites that have optimized markup for IE7 the compatibility mode is still there and can be activated using one of two options.

  1. Developers can insert the meta tag below into their pages to tell IE8 to render in IE7 compatibility mode

    <meta http-equiv="X-UA-Compatible" content="IE=7" />
  2. Developers can send the following HTTP header in the response of their requests to enable IE7 compatibility

    X-UA-Compatible: IE=7;

So if you have a site running this is a simple and easy method to ensure correct rendering of your page. No user agent sniffing and separate pages are necessary to have broad IE support with your pages. More details about this can be found in the IE Blog.

More Posts Next page »
 
Page view tracker