XAML Playground
about XAML and other Amenities

Use CollectionViewSource effectively in MVVM applications

2009-07-18T23:13:15+01:00 by Andrea Boschin

In a my I've outlined the new CollectionViewSource introduced in silverlight with the latest release. This control is really useful while we need to sort and filter collection of objects in memory, but if we need to use a Model-View-ViewModel pattern to develop our application there is some problems using the control.

To implement the MVVM pattern we need to inject a ViewModel into the View using the DataContext property. This is usual in this kind of application because we need to bind the properties of the ViewModel to the controls in the View. So if we need to use a CollectionViewSource we can try to bind a collection from the ViewModel to the CVS and then bind the control to the CVS itself. Unfortunately this approach does not work because we cannot bind the CVS directly to the DataContext of the page. Trying to do this operation we will get a AG_E_BAD_PROPERTY_VALUE exception because the control does not inherits from FrameworkElement so it does not support DataBinding.

However, if it were possible, the CollectionViewSource would force us to put a lot of code in the codebehind to handle the Filter event and the sorting property. So, we have to follow another way to use the CollectionViewSource effectively with this kind of applications.

How to use the CollectionViewSource

The only way to use the CollectionViewSource with the MVVP pattern is to expose it as the type of the bindable property. This way we can manage the properties of the CVS and handle the Filter event from inside the ViewModel without putting anything in the codebehind of the View.

First of all we have to create two properties in the ViewModel. The first property will be the ObservableCollection<T> and we will populate it with the data to display. This property can be private because it will be used only to feed the ColectionViewSource of the second property. Here is how to initialize the properties:

   1: /// <summary>
   2: /// Gets or sets the names.
   3: /// </summary>
   4: /// <value>The names.</value>
   5: public CollectionViewSource Names { get; set; }
   6:  
   7: /// <summary>
   8: /// Gets or sets the names internal.
   9: /// </summary>
  10: /// <value>The names internal.</value>
  11: private ObservableCollection<string> NamesInternal { get; set; }
  12:  
  13: /// <summary>
  14: /// Initializes a new instance of the <see cref="MainPageViewModel"/> class.
  15: /// </summary>
  16: public MainPageViewModel()
  17: {
  18:     this.NamesInternal = new ObservableCollection<string>();
  19:     this.Names = new CollectionViewSource();
  20:     this.Names.Source = this.NamesInternal;
  21:  
  22:     // populate the ObservableCollection
  23:     foreach (string item in DataSource.GetNames())
  24:         this.NamesInternal.Add(item);
  25: }

Now, to bind the CollectionViewSource in the XAML we have to rely on his View property. If we put a reference to the CVS in the property ItemsSource in the XAML it simply will not work. Here is how to correctly bind:

   1: <ListBox ItemsSource="{Binding Names.View}" Margin="5,5,5,1" Grid.ColumnSpan="4" />

Once we have connected the CVS to the collection and the UI to the CVS we can handle the commands from the View and interact with the CVS to modify how to display the data. In the sample I have a togglebutton that is raising a ChangeSortDirectionCommand. I use the DelegateCommand<T> from Prism V2.0 and when someone send the command I change the SortDescriptor in the CollectionViewSource.

In the same View the TextChanged event is raised when the user type in the textbox. This command handled by the ViewModel let the CVS refresh itself. This way the Filter event will be evaluated again and the View will be updated with the filter applied.

I've attached to the post a new version of the sample I've proposed with the first article. Now the sample use the MVVM pattern with the CollectionViewSource.

Download: Elite.Silverlight3.CollectionViewMVVM.zip (~520 KB)

Categories:   Prism | Databinding | Prism
Actions:   E-mail | del.icio.us | Permalink | Comments (1) | Comment RSSRSS comment feed

Silverlight 3.0 RTW: An universal MouseWheelScrolling behavior

2009-07-10T17:45:00+01:00 by Andrea Boschin

Silverlight 3.0 RTW introduces a new event many people has asked for in the last months, the MouseWheel event. Handling this event is pretty simple while it simply raise and event that take a Delta to the developer with a positive or negative value according to the direction and the amount of the scrolling.

Showing an sample about MouseWheel take a few lines of code and is unuseful while I think many people can simply experiment and understant how it works in a few minutes. So I decided to merge this sample with some words about the new Behaviors introduced with Expression Blend.

My focus in this post is to show how to create a Behavior,  and using the MouseWheel event, add to all the scrollable controls the capability to scroll using the Mouse wheel.

What is a Behavior?

Some of you may have already used the Behaviors in the ASP.NET AJAX framework. The simple answer to the question of this paragraph is: "They are a Silverlight implementation of the ASP.NET AJAX semantics that allow to create reusable and attachable behaviors to HTML controls". You may find the origin of Silverlight Behaviors in an example posted by Nikhil Kothari during the May 2008.

While the simple answer is very clear and let you understand the concept under Behaviors we have to explore them more deeply to understant how to create a behavior and let it available to our projects.

The beta of Blend 3 introduces the concept of behavior into the Blend interface. There are some built-in behaviors we can simply drag on the design surface to give a new life to our graphical elements. Into the Asset folder, where usually we find controls, effects, resources and other thing, there is a new "behaviors" sheet like in the image I attached here on the right. 

With Expression Blend 3.0 many types of behaviors have been introduced. Behavior<T> is the most simple flavour that apply to a DependencyObject (the generic T) and handle events and other aspects from the source controls. A behavior can simply modify the aspect of a control, adding elements, changing the properties, or can handle one or more events to add some new features. The MouseDragElementBehavior is an example of it. Simply it attach Mouse events and let the element to be dragged into the page.

Writing a behavior

Writing a behavior is a pretty simple task. A behavior is a class extending Behavior<T> so the first thing to do is referencing the assemblies Microsoft.Expression.Interactions.dll and System.Windows.Interactivity.dll. from the following folder:

C:\Program Files\Microsoft SDKs\Expression\Blend 3\Interactivity\Libraries\Silverlight

If you add an existing behavior from Blend 3.0 a reference to these assemblies is automatically added to your project.

Once you have added the reference it is time to create the class:

   1: public class MouseWheelScrollBehavior : Behavior<Control>
   2: {
   3:     // Add implementation here
   4: }

While we are extending the "scrollable" components in Silverlight we need to create a type that can be attached to Control classes. In silverlight there is not any common class to scrollable components like ScrollViewer, DataGrid and ListBox. This imply we have to find a way to scroll eterogeneous components, but this is matter for the next paragraph. For now simply continue to analyze how to create the Behavior.

The next thing to do is to attach the MouseWheel event on the target object. Once we have extended the Behavior class we have two methods to override useful to handle attach and detach of the behavior to the target: OnAttached is called when the behavior attach an object and OnDetaching when it is detaching from the object. OnAttached and OnDetaching is the perfect location to attach and detach public events that we will handle to give the behavior to the target object. Obviously the target object is exposed by the Behavior<T> in the AssociatedObject property. Here is my code sample:

   1: /// <summary>
   2: /// Called after the behavior is attached to an AssociatedObject.
   3: /// </summary>
   4: /// <remarks>Override this to hook up functionality to the AssociatedObject.</remarks>
   5: protected override void OnAttached()
   6: {
   7:     this.AssociatedObject.MouseWheel += new MouseWheelEventHandler(AssociatedObject_MouseWheel);
   8:     base.OnAttached();
   9: }
  10:  
  11: /// <summary>
  12: /// Called when the behavior is being detached from its AssociatedObject, but before it has actually occurred.
  13: /// </summary>
  14: /// <remarks>Override this to unhook functionality from the AssociatedObject.</remarks>
  15: protected override void OnDetaching()
  16: {
  17:     this.AssociatedObject.MouseWheel -= new MouseWheelEventHandler(AssociatedObject_MouseWheel);
  18:     base.OnDetaching();
  19: }

Now the behavior is ready to be attached to the object but it still does nothing. We need to implement the scrolling for scrollable components, so it is time to enter the next paragraph.

Scrolling the Scrollable... not so simple!

While I'm writing the sample I've attached to this post, there were a moment when I thinked this behavior is impossible to be implemented and I was ready to switch to a less generic ScrollViewer scroller behavior. The reason for this is that there is not any common scrolling interface to scrollable components. So while creating a Behavior for a ScrollViewer is simple, it is not so simple to use it for DataGrid or ListBox.

Just a moment before discarting my sample I've gived a last chance to "bing" to find someone handling the same problem. I finally found this that explain how to use Automation API in Silverlight to enable the scrolling of components without extending them.

I leave the full explanation to the good article I've linked. Here the only thing we need to Know is that Automation API expose a IScrollProvider interface doing exactly what I'm searching for. So we need to change the OnAttached method to create the Automation Peer for the attaching object:

   1: /// <summary>
   2: /// Gets or sets the peer.
   3: /// </summary>
   4: /// <value>The peer.</value>
   5: private AutomationPeer Peer { get; set; }
   6:  
   7: /// <summary>
   8: /// Called after the behavior is attached to an AssociatedObject.
   9: /// </summary>
  10: /// <remarks>Override this to hook up functionality to the AssociatedObject.</remarks>
  11: protected override void OnAttached()
  12: {
  13:     this.Peer = FrameworkElementAutomationPeer.FromElement(this.AssociatedObject);
  14:  
  15:     if (this.Peer == null)
  16:         this.Peer = FrameworkElementAutomationPeer.CreatePeerForElement(this.AssociatedObject);
  17:  
  18:     this.AssociatedObject.MouseWheel += new MouseWheelEventHandler(AssociatedObject_MouseWheel);
  19:     base.OnAttached();
  20: }

First we search the Automation interfaces if the control already created it. If the interface has not been found we need to create it. The AutomationPeer is saved in a member property to be used when the MouseWheel event is raised. Here is the code to scroll the target:

   1: /// <summary>
   2: /// Handles the MouseWheel event of the AssociatedObject control.
   3: /// </summary>
   4: /// <param name="sender">The source of the event.</param>
   5: /// <param name="e">The <see cref="System.Windows.Input.MouseWheelEventArgs"/> instance containing the event data.</param>
   6: void AssociatedObject_MouseWheel(object sender, MouseWheelEventArgs e)
   7: {
   8:     this.AssociatedObject.Focus();
   9:  
  10:     int direction = Math.Sign(e.Delta);
  11:  
  12:     ScrollAmount scrollAmount = 
  13:         (direction < 0) ? ScrollAmount.SmallIncrement : ScrollAmount.SmallDecrement;
  14:  
  15:     if (this.Peer != null)
  16:     {
  17:         IScrollProvider scrollProvider =
  18:             this.Peer.GetPattern(PatternInterface.Scroll) as IScrollProvider;
  19:  
  20:         bool shiftKey = (Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift;
  21:  
  22:         if (scrollProvider != null && scrollProvider.VerticallyScrollable && !shiftKey)
  23:             scrollProvider.Scroll(ScrollAmount.NoAmount, scrollAmount);
  24:         else if (scrollProvider != null && scrollProvider.VerticallyScrollable && shiftKey)
  25:             scrollProvider.Scroll(scrollAmount, ScrollAmount.NoAmount);
  26:     }
  27: }

When we get the Delta we need to extract the direction of the scrolling. This is because we are unable to speficy the amount of pixels we have to scroll the target but simply the ScrollAmount that may be a SmallIncrement or SmallDecrement (or LargeIncrement, LargeDecrement). So using the direction we decide from Increment and Decrement.

While the controls can scroll both vertically or horizontally I decided to check if the shift key is pressed to allow horizontal scroll. Finally using the Scroll method in the IScrollProvider I apply the scrolling to the target control. This is very simple because the IScrollProvider does all the work for us. There is no need to check boundaries, we have simply to say how to scroll and all the work is done.

Using the Behavior

Using Blend is the simpler way to apply behaviors. The blend assets library scan the classes of the project and show them in the library so dragging the behavior on the scrollable component is sufficient to apply the behavior. We need to learn ho to apply the behavior by code. Here is a sample:

   1: <UserControl
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
   4:     xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 
   5:     xmlns:local="clr-namespace:Elite.Silverlight3.MouseWheelSample.Silverlight.Classes"
   6:     xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"
   7:     x:Class="Elite.Silverlight3.MouseWheelSample.Silverlight.MainPage" 
   8:     Width="Auto" Height="Auto">
   9:  
  10: ... omissis ...
  11:  
  12: <data:DataGrid Grid.Column="1" Grid.Row="0" ItemsSource="{Binding DataItems}" Margin="20">
  13:     <i:Interaction.Behaviors>
  14:         <local:MouseWheelScrollBehavior />
  15:     </i:Interaction.Behaviors>
  16: </data:DataGrid>

In the UserControl we declare the namespaces we have to use. In this sample "i" stand for interactivity, the assembly where the Behavior<T> classe is located. The "local" refer to the local classes where we put the new Behavior. In the second part we attach the behavior to a DataGrid. To attach the behavior to a ScrollViewer or to a ListBox the code is pretty similar. Running the project we will have the mouse wheel working on the DataGrid.

Conclusion

The tecnique I've illustrated has the big advantage or working for all the scrollable controls but not for ComboBox because it does not directly implements IScrollProvider interface. The drawback is that it works only on windows. This is a big problem but there is not any solution to it while as I already said it is the only way to scroll all the controls programmatically. Moreover we have to take note that the MouseWheel event only works in Windows with Internet Explorer and also with Firefox when you are not using the windowless mode. This is a limitation of the architecture of Safari and Firefox and the only way to work around it is using the DOM events. So due to this limitations the example is a good solution to be used where it works. In the others cases it simply does nothing.

Download: Elite.Silverlight3.MouseWheelSample.zip (1,2 MB)

Video: MouseWheelScrollBehavior.wmv (1.4 MB)

Silverlight 3.0 RTW: The CollectionViewSource

2009-07-10T17:45:00+01:00 by Andrea Boschin

Since the first release of WPF the framework contains a component called CollectionViewSource. The CollectionViewSource allow developer to apply sorting, filtering and grouping to in-memory collections of objects. This component is very useful when small collections (up to hundreds of items) is loaded in memory and need to give a better experience to the user.

Some months ago I of the CollectionViewSource for Silverlight 2.0. I worked hard to implement the component and finally I published a version with the only limitation of not allowing grouping. While sorting and filtering are implemented directly on the data seamless, the grouping require an infrastructure to be consumed (grouping support in ItemsControl) that I was unable to provide.

The new release of Silverlight 3.0 RTW comes with an implementation of this component that fill this hole but it has the same limitations of my CollectionViewSource. This limitations come from the same reason I cannot implement by myself: the missing grouping support in ItemsControls. However the native component has a some advantages on mine, first of all a very strict compatibility with the architecture of the WPF CollectionViewSource. In this post I will show you how to configure and use the component in a Silverlight application.

Using the CollectionViewSource

The Silverlight CollectionViewSource is a class that inherits from DependencyObject and usually can be inserted in a resource dictionary in the page where it has to work. The principle of the CVS (this is the shorter name I will use from this point in advace) is acting as a filter between the source collection (IEnumerable or IList) and the component where we are showing the data. While binding a ListBox directly to a flat collection will show all the instances in the collection, putting the CVS in the middle enable us to operate on its properties to sort and filter the source.

Here is an example that shows how to embed the CVS in a xaml page; The first part show a DataSource object SampleDataCollection in the UserControl.Resources, and a CollectionViewSource that reference it using StaticResource. In the second part there is a ListBox that reference the CVS also using a StaticResource markup extension.

   1: ... omissis ...
   2:  
   3: <UserControl.Resources>
   4:     <local:DataSource x:Key="dataSource" />
   5:     <CollectionViewSource x:Name="cvs" Source="{Binding Names, Source={StaticResource dataSource}}">
   6:         <CollectionViewSource.SortDescriptions>
   7:             <scm:SortDescription Direction="Ascending" />
   8:         </CollectionViewSource.SortDescriptions>
   9:     </CollectionViewSource>
  10: </UserControl.Resources>
  11:  
  12: ... omissis ...
  13:  
  14: <ListBox ItemsSource="{Binding Source={StaticResource cvs}}" 
  15:          Margin="5,5,5,1" Grid.ColumnSpan="4" />
  16:  
  17: ... omissis ...

The magic around CVS come from an interface called ICollectionView that is esposed by the CVS in the View property. This interface represent the real working object that behind the scenes understand the source type and manage to apply filtering and sorting seamless. When a datasource is connected to the CVS a specialized instance of the ICollectionView is created - EnumerableCollectionView for IEnumerable or ListCollectionView for IList - and this instance work knowing the source data. When we connect a consumer control to the CVS it is binded directly to the ICollectionView. Watching at this interface we will see it implements INotifyCollectionChanged. This mean that if we connect the CVS to an ObservableCollection<T> all the updates to the source collection will be transmitted to the consumer.

Sorting and Filtering

Now after the basics of the CVS it is time to try to use its properties to apply the features it implements. If we see at the CVS we will see a Filter event exposed to the markup or to the code. This event is raised by the CVS every time it need to understand if an item of the collection is valid for the filter the user is appling. In the semple I included at the end of this post I use the CVS to filter a collection of italian names (strings). In the Filter event I simply compare every item in the collection to the letters the use typed in a TextBox:

   1: /// <summary>
   2: /// Handles the Filter event of the cvs control.
   3: /// </summary>
   4: /// <param name="sender">The source of the event.</param>
   5: /// <param name="e">The <see cref="System.Windows.Data.FilterEventArgs"/> instance containing the event data.</param>
   6: void cvs_Filter(object sender, FilterEventArgs e)
   7: {
   8:     e.Accepted = ((string)e.Item).ToLower().StartsWith(searchKey.Text.ToLower());
   9: }

The FilterEventArgs class expose an Accepted property useful to indicate if the element (e.Item) we are evaluating has to be shown or not. This event is very simple to handle and let the developer to apply various filtering rules. We have only to pay attention to the time that the evaluation take because it is repeated one time for every element in the collection.

While the user type in the TextBox we catch the TextChanged event and force the refresh of the CVS this way:

   1: /// <summary>
   2: /// Handles the TextChanged event of the searchKey control.
   3: /// </summary>
   4: /// <param name="sender">The source of the event.</param>
   5: /// <param name="e">The <see cref="System.Windows.Controls.TextChangedEventArgs"/> instance containing the event data.</param>
   6: private void searchKey_TextChanged(object sender, TextChangedEventArgs e)
   7: {
   8:     this.cvs.View.Refresh();
   9: }

Applying sorting if simpler than filtering. It is done by using markup with the SortDescriptions property. This property accept a collection of SortDescription, one for every property we need to sort. For each property we can choice the direction of sorting using the Direction property:

<scm:SortDescription Direction="Ascending" PropertyName="Name" />

Here is a snippet of code from the sample i provide:

   1: <CollectionViewSource x:Name="cvs">
   2:     <CollectionViewSource.SortDescriptions>
   3:         <scm:SortDescription Direction="Ascending" />
   4:     </CollectionViewSource.SortDescriptions>
   5: </CollectionViewSource>

While I'm binding strings there is no need to specify a property because the sort has to be applied directly to the source string. If you need a more complex sorting logic it is always available the IComparable interface that is used to evaluate the elements during the sort operation.

Differences from WPF

While at the first look the CollectionViewSource implementation in Silverlight appear to be very close to the WPF component, there is some subtle differences. First of all if we examine the component we may found a property called GroupDescriptions. This property is used in WPF to apply grouping but in the Silverlight version it throw a NotSupportedException. Probably it is a placeholder for future extensions of the component.

The most important difference to me if about the structure of the object. The CVS inherits from DependencyObject but while in silverlight only classes derived from FrameworkElement may be subject of DataBinding the only way to put a CVS in markup would be using a StaticResource.

This would be a huge limitation to CVS but fortunately the people from the team found a way to workaround it. Also if CVS inherits from DependencyObject it is still possible to use databinding but it is needed to specify an explicit Source like the following example:

   1: <UserControl.Resources>
   2:     <CollectionViewSource x:Name="cvs" Source="{Binding Names, Source={StaticResource dataSource}}">
   3:         <CollectionViewSource.SortDescriptions>
   4:             <scm:SortDescription Direction="Ascending" />
   5:         </CollectionViewSource.SortDescriptions>
   6:     </CollectionViewSource>
   7: </UserControl.Resources>

This is very useful if we have a complex object like a ViewModel we want to use in a page with a CVS instance. The better would be to bind directly to the datasource but is is possible to put the ViewModel in the resources and then statically reference it from both the DataContext and the CollectionViewSource.

Conclusion

Last months I decided to start writing a component like CVS because I think it is really useful in some cases. Now I'm very glad to rely on a framework component. For some of you that have been used my component take note that the CVS interface is very close to my component so it is very easy to switch to it.

Download: Elite.Silverlight3.CollectionViewSample.zip (1,04 MB)

Video: CollectionViewSource.wmv (1.08 MB)

Categories:   Databinding | News
Actions:   E-mail | del.icio.us | Permalink | Comments (3) | Comment RSSRSS comment feed

What's new about Out Of Browser in Silverlight 3.0 RTW

2009-07-10T17:45:00+01:00 by Andrea Boschin

Some months ago, a couple of minutes after the first beta of Silverlight has been released, I've posted an article explaining how to configure the new Out of Browser feature in Silverlight 3.0. Now, just after the release of the final bits, I need to return back on the argument because something has changed during this time due to additional features and modification to the API I've explained.

What has changed and What has been added.

There is not any substantial change to the functionality of the OOB applications. As you may expect it is still available a context menu to detach the application from the browser - but this operation now has changed its name from "detach" to "install" - and there is a way to uninstall the application again with the same context menu. While the name of the operation has changed now the method and events related to is has also changed the name following this schema:

Previous Current
public bool Detach(); public bool Install();
public bool RunningOffline; public bool RunningOutOfBrowser;
public event EventHandler ExecutionStateChanged; public event EventHandler InstallStateChanged;
public enum ExecutionStates
{
    RunningOnline,
    Detaching,
    Detached,
    DetachedUpdatesAvailable,
    DetachFailed
}
public enum InstallState
{
    NotInstalled,
    Installing,
    Installed,
    InstallFailed
}


As you may have noticed one important enumeration member - DetachedUpdatesAvailable - has been removed but this feature has not been lost. Now there a couple of API to support the application updates giving a bit more control in the update flow. We can choice when check for updates using the CheckAndDownloadUpdateAsync() method and getting notified if the update process succeded by the event CheckAndDownloadUpdateCompleted. Here is how to check for updates:

   1: Application.Current.CheckAndDownloadUpdateCompleted +=
   2:     (s, e) =>
   3:     {
   4:         if (e.UpdateAvailable)
   5:             MessageBox.Show(@"Updates have been downloaded. 
   6:                               Please restart the application to 
   7:                               apply this updates.");
   8:     };
   9:  
  10: Application.Current.CheckAndDownloadUpdateAsync();

Once you have started the process there isn't any way to stop it or to rollback any downloaded update. You can only notify the user that the updates has been downloaded and that this updates will be available the next time the application will be started.

The most significant change to the Out-of-browser is in the feature configuration. Now the settings are placed in a specific file you can find into the Properties folder in the Solution Explorer. The file OutOfBrowserSettings.xml contains the same properties of the beta with some slight changes:

1. The Title property has been moved to the WindowSettings section
2. Width and Height properties has been added to configure the initial size of the window
3. The Icon size has to be specified using a comma separated value notation

Now Visual Studio 2008 can directly manage this properties using an Out-of-Browser Settings button in the Silverlight properties tab so there is no need to directly edit the xml file.

Out of browser configuration You have to be aware that there is not full control over plugin features while it is installed on the machine. The sole feature you can activate i the usage of GPU acceleration, but there isn't a way to change the backgroun color of the plugin. Also remember that the usage of html bridge is forbidden while in oob mode.

Updated Sample

I've just changed the downloadable sample attached to my previous article and I give you agan the link here to have a fully functional sample on how to configure and use the out of browser.

Download code: Elite.Silverlight3.ToDoList.zip (2.02 MB)

Demo Video: OutOfBrowserExperience.wmv (3.5 MB)

Silverlight 3.0 RTW: A new HTTP stack ready for REST

2009-07-10T17:45:00+01:00 by Andrea Boschin

The paradigm behind REST services is very fascinating while it allow to manipulate resources over the network relying to Uri and Http Methods. For a few of you that are not aware of what REST means I suggest to think at the web because it is the more REST thing you know. When you are pointing your browser to a "resource" on the Internet, for example a product in a ecommerce website, you will write an Url in the browser that univocally identify the product. You now can imagine to use Http Methods to operate on this resource: the GET verb will retrieve information about it, the PUT updates the resource, the POST creates it and finally the DELETE remove the resource from the web. In a few words these are REST operations and is very cool to be able to use this paradigm to access resources from a Database. ADO.NET Data Services is born to implement this paradigm into the .NET Framework 3.5 SP1, and many libraries has been build to support different technologies, Windows Forms, WPF, ASP.NET. And obviously Silverlight 2.0 come with an implementation of a Data Service client to operate with REST resources but it is not really RESTful as you may believe the first time you use it.

The problem with Silverlight 2.0, due to limitations to the http stack coming from the use of the Browser API, is that it cannot handle all the required http methods but only the GET and POST verbs. So to workaround this limitation the Data Service library simply use POST to send PUT and DELETE operations. This workaround violate the REST paradigm and it imply you are not able to use 3rd party REST resources.

What I've briefly explained in the previous paragraphs is the main reason we really need a new http stack to overcome this limitations and to be able to implement a full REST interface. This is not the only benefit we can give for the addition of new verbs: let think for example to a new way to upload files to the server, using the PUT method.

The latest release of Silverlight 3.0 got new features going in the direction I've just explained. In the next paragraphs I will explain how to use them by exploring the pretty new http Stack, called ClientHttp.

BrowserHttpStack vs ClientHttpStack

First of all we need to know that the new http stack is completely separated from the old stack. This is an important note while we are sure the old stack remain unaltered and our applications relaying on it continue to work without any change. All the working things we already know continue to work over this stack and does not use the new one.

The ClientHttpStack in opposite to the BrowserHttpStack (these are the official names of the two actors) can be created using a static class called WebRequestCreator. This class can create instances of HttpWebRequest for both the browser and the client stack. Here is a sample showing the usage of the class.

   1: // create an instance of the Client stack
   2: HttpWebRequest rq = (HttpWebRequest)WebRequestCreator.ClientHttp.Create(uri);
   3:  
   4: ...or...
   5:  
   6: // create an instance of the Browser stack
   7: HttpWebRequest rq = (HttpWebRequest)WebRequestCreator.BrowserHttp.Create(uri);

The HttpWebRequest created by this call is exactly the same we have used since Silverlight 2.0 so it can easily replace the browser stack in every existing application with a few line of code. We can immediately test the new stack assigning the Method property with the "PUT" value:

rq.Method = "PUT";

As we expect while the old stack thrown a "method not supported" exception, the new stack accept this assignment. Not all the http methods are allowed. Using TRACE, TRACK or CONNECT raise an error probably for security reasons. We will go deep inside some of the available methods in the next paragraph.

But this is only the most evident difference. Watching for the properties of the HttpWebRequest we will find a CookieContainer. It let us manage the cookies of the request. The old stack rely on cookies issued by the browser and it shares them with the browser itself. In the new stack we have full control of issued cookies; we can access cookies sent by the server or create our own cookies and send them. The drawback is that we cannot share cookies between client stack and browser stack but only rely on automatic management of server cookies from the client stack to allow forms authentication scenarios.

The next sample show how to use the CookieContainer to send our cookies:

   1: HttpWebRequest rq = (HttpWebRequest)WebRequestCreator.ClientHttp.Create(uri);
   2: rq.Method = "GET";
   3: rq.CookieContainer = new CookieContainer();
   4: rq.CookieContainer.Add(
   5:     uri, new Cookie("Author", "Andrea Boschin"));

Another great news, many people will really appreciate, is that the new stack is capable of retrieving status codes from the http response. One of the most common problems with Silverlight 2.0, especially the first time someone try to use the HttpWebRequest is the unability to get errors from the server. This is because the browser do not send all status codes to the plugins but only 404 (Not Found) and 200 (OK). The forum is filled of disoriented people not understanding why they get a 404 from the server while they are calling an existing uri and the most common suggestion is to use fiddler to search the error in the traced call.

To read status codes from the response we have to catch the WebException and then get the HttpWebResponse from the exception. This may seems a bit strange but is really simple. Here is the code:

   1: rq.BeginGetResponse(
   2:     r =>
   3:     {
   4:         try
   5:         {
   6:             WebResponse rs = rq.EndGetResponse(r);
   7:             // do something with response...
   8:         }
   9:         catch (WebException ex)
  10:         {
  11:             HttpWebResponse rs = (HttpWebResponse)ex.Response;
  12:  
  13:             MessageBox.Show(
  14:                 string.Format("Webserver returned status code {0}: '{1}'", 
  15:                     (int)rs.StatusCode, 
  16:                     rs.StatusDescription));
  17:         }
  18:     }, rq);

These features is really useful but they are not used from existing classes. WCF and WebClient can only use the classic http stack. To have access to the ClientHttpStack we have to use the HttpWebRequest and dealing with problems like thread syncronization that are solved by the WebClient. But the new stack is very important and now it is time to have some samples about usage of the http methods.

GET, POST, PUT & DELETE

In the sample solution attached at the end of this article I've enclosed a sort of file system browser application. It use the new http stack to make calls to the server and retrieve xml containing the response. This kind of application was possible also with Silverlight 2.0 but to explaing usage of http methods I've used them to mimic some filesystem operations. GET will list the content of a folder, PUT upload a file or create a directory, POST is used to send credentials and finally DELETE remove files and directories.

Doing an http call is very similar to using the previous stack. We need to create an instance of the stack, set the method we want to use and then create a request as the server will expect it. The following sample make a call to get the directory content. I've splitted the operations in two methods, one doing the raw http call and the other using this low-level method create the request and parse the result. This is the low-level DoGet() method:

   1: private static void DoGet(Uri uri, Action<Stream> success, Action<Exception> fail)
   2: {
   3:     try
   4:     {
   5:         HttpWebRequest rq = (HttpWebRequest)WebRequestCreator.ClientHttp.Create(uri);
   6:         rq.Method = "GET";
   7:         rq.CookieContainer = new CookieContainer();
   8:         rq.BeginGetResponse(
   9:             new AsyncCallback(
  10:                 r =>
  11:                 {
  12:                     try
  13:                     {
  14:                         WebResponse rs = rq.EndGetResponse(r);
  15:                         success(rs.GetResponseStream());
  16:                     }
  17:                     catch (WebException ex)
  18:                     {
  19:                         fail(CreateFailFromWebException(ex));
  20:                     }
  21:                 }), null);
  22:     }
  23:     catch (Exception ex)
  24:     {
  25:         fail(ex);
  26:     }
  27: }

The code in this listing shows the usual way to place an http call. First of all the DoGet method require I specify two callback methods to be called when the request will succeed or fail. This pattern helps to simplify the code to write avoiding handling multiple event handler. Using lambda expressions the code become very compact.

After the creation of the client stack I initialize the "Method" property with the GET verb, then I create an instance of a CookieContainer to allow the request to handle cookies. Finally calling BeginGetResponse place the call to the specified uri. When this method is called a new thread is created; In my case the body of the inner lambda expression contains the code executed in the thread. It call the EndGetResponse method (this trigger the call to the webserver) and finally ask for the Stream containing the body of the response.

As I explain in the previous paragraph I have to catch the WebException to read http status codes and translate it to an call to the fail() callback. You have to be aware that the two try-catch blocks are executed in different threads so the external block is unable to catch exception coming from the body of the lambda expression. This is the reason for having two separated blocks calling the fail method. Now watch to the following code:

   1: public static void GetDirectory(string path, Action<FileSystemItem[]> success, Action<Exception> fail)
   2: {
   3:    Uri uri = new Uri(
   4:        DataSource.ServiceUri +
   5:        "?action=directory" +
   6:        "&path=" + HttpUtility.UrlEncode(path));
   7:  
   8:    DataSource.DoGet(uri,
   9:        r =>
  10:        {
  11:            try
  12:            {
  13:                XDocument document = XDocument.Load(r);
  14:                IEnumerable<FileSystemItem> directories = DataSource.DeserializeItems(document);
  15:                Deployment.Current.Dispatcher.BeginInvoke(() => success(directories.ToArray()));
  16:            }
  17:            catch (Exception ex)
  18:            {
  19:                Deployment.Current.Dispatcher.BeginInvoke(() => fail(ex));
  20:            }
  21:        },
  22:        e => Deployment.Current.Dispatcher.BeginInvoke(() => fail(e)));
  23: }

This is the high-level method to get the directory content.  It use the same asyncronous pattern but maps the calls to the callback methods to the UI thread using an instance of the Dispatcher. While the HttpWebRequest make the calls in a different thread we need to marshal the context of the call to avoid cross-thread exception when we try to reach some UI components.

Using PUT to upload a file

Showing all the methods one-by-one is too much long. But there are another (last)  method I want to show. It is the PUT method we can use to upload files to a webserver in an alternate (and most simple) way to the use of the POST method. While the POST method require encoding the resource to base64 and forge a complex request, the PUT method simply ask to enqueue the full binary content. Here is the client code:

   1: private static void DoPut(Uri uri, FileStream file, Action<Stream> success, Action<Exception> fail)
   2: {
   3:     try
   4:     {
   5:         HttpWebRequest rq = (HttpWebRequest)WebRequestCreator.ClientHttp.Create(uri);
   6:         rq.Method = "PUT";
   7:         rq.CookieContainer = DataSource.Cookies;
   8:         rq.BeginGetRequestStream(
   9:             new AsyncCallback(
  10:                 result => DataSource.DoPutUpload(result, file, success, fail)), rq);
  11:     }
  12:     catch (Exception ex)
  13:     {
  14:         fail(ex);
  15:     }
  16: }
  17:  
  18: private static void DoPutUpload(IAsyncResult result, FileStream file, Action<Stream> success, Action<Exception> fail)
  19: {
  20:     HttpWebRequest rq = (HttpWebRequest)result.AsyncState;
  21:  
  22:     using (Stream stream = rq.EndGetRequestStream(result))
  23:     {
  24:         int read = 0;
  25:         byte[] buffer = new byte[1024];
  26:  
  27:         while ((read = file.Read(buffer, 0, buffer.Length)) > 0)
  28:             stream.Write(buffer, 0, read);
  29:     }
  30:  
  31:     rq.BeginGetResponse(
  32:         r =>
  33:         {
  34:             try
  35:             {
  36:                 WebResponse rs = rq.EndGetResponse(r);
  37:                 success(rs.GetResponseStream());
  38:             }
  39:             catch (WebException ex)
  40:             {
  41:                 fail(CreateFailFromWebException(ex));
  42:             }
  43:         }, rq);
  44: }

The first method (DoPut) is very close to the previous method I described. The core of the upload is the DoPutUpload. It open a stream in the HttpWebRequest and write the entire content of the file to upload just before calling the EndGetRequest. When this call is made the file is send on the network to the webserver. I use an httphandler and when the PUT is receives read from the InputStream the file I write to the filesystem.

   1: private void ProcessFileRequest(string path)
   2: {
   3:     this.EvaluateIsValidUser();
   4:  
   5:     if (File.Exists(path))
   6:         throw new Exception("File already exists");
   7:  
   8:     using (FileStream stream = File.OpenWrite(path))
   9:     {
  10:         byte[] data = new byte[1024];
  11:         int read = 0;
  12:  
  13:         while ((read = this.Context.Request.InputStream.Read(data, 0, 1024)) > 0)
  14:             stream.Write(data, 0, read);
  15:     }
  16:  
  17:     this.WriteOk();
  18: }

The last code runs on the server. It receive the path of the file to write and create it in the file system. The final WriteOk() method show I can write something on the response to notify the client it have successful uploaded the file.

Some final words

The main benefit coming with the introduction of the new stack is the opportunity to be able to get access to rest resources on the internet. This is the reason for the creation of this stack someone can consider a duplication on something already exists. But the presence of new methods, the cabapility to better handle server status codes and cookies give to Silverlight 3.0 a new resource to implement great applications.

The code I attached to this article show a full implementation of all the http methods I've talk about. You have only to change the server path where the filesystem has to be explored. You can achive this by changing the BaseFolder property in the HttpRequestManager class.

Download: Elite.Silverlight3.ClientHttpStack.zip (2,1 MB)

Video: ClientHTTPStack.wmv (10,1 MB)

Categories:   Networking | News
Actions:   E-mail | del.icio.us | Permalink | Comments (2) | Comment RSSRSS comment feed

A code snippet to quickly write Prism commands

2009-07-09T22:16:53+01:00 by Andrea Boschin

Crawling the Internet there are many samples about how to write commands for the Composite Application Guidance, aka Prism v2.0. One of my favorites is the .

I figure out the first time you see how many code you need, to write a working command you are really astonished. This also happened to me. But if you analyze the code you will see that the skeleton of a command is always the same, and you need to change only some names and types to have it working on different events.

This is the perfect situation where a code snippet works effectively so I decided to write my own and publish on this site. I've isolated some zones you have to replace and I've created some markers that will take advantage of the Visual Studio expansion snippets.

  1. command: the name of the command you are writing (e.g. MouseOver)
  2. control: the control type your command apply to (e.g. Button)
  3. event: the event of the control your command will wrap


Here is the snippet:

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
   3:     <CodeSnippet Format="1.0.0">
   4:         <Header>
   5:             <Title>prismcommand</Title>
   6:             <Shortcut>prismcommand</Shortcut>
   7:             <Description>Code snippet for an automatically implemented commands</Description>
   8:             <Author>Elite Agency</Author>
   9:             <SnippetTypes>
  10:                 <SnippetType>Expansion</SnippetType>
  11:             </SnippetTypes>
  12:         </Header>
  13:         <Snippet>
  14:             <Declarations>
  15:                 <Literal>
  16:                     <ID>command</ID>
  17:                     <ToolTip>Command Name</ToolTip>
  18:                     <Default>CommandName</Default>
  19:                 </Literal>
  20:                 <Literal>
  21:                     <ID>control</ID>
  22:                     <ToolTip>Control type</ToolTip>
  23:                     <Default>Control</Default>
  24:                 </Literal>
  25:         <Literal>
  26:           <ID>event</ID>
  27:           <ToolTip>Control Event</ToolTip>
  28:           <Default>Event</Default>
  29:         </Literal>
  30:       </Declarations>
  31:             <Code Language="csharp">
  32:         <![CDATA[public class $command$CommandBehavior : CommandBehaviorBase<$control$>
  33:     {
  34:         public $command$CommandBehavior($control$ targetObject)
  35:             : base(targetObject)
  36:         {
  37:             targetObject.$event$ += (s, e) => base.ExecuteCommand();
  38:         }
  39:     }
  40:  
  41:     public static class $command$
  42:     {
  43:         public static readonly DependencyProperty $command$BehaviorProperty =
  44:             DependencyProperty.RegisterAttached(    
  45:                 "$command$BehaviorProperty", typeof($command$CommandBehavior), 
  46:                 typeof($command$CommandBehavior), null);
  47:  
  48:         #region CommandProperty
  49:  
  50:         public static readonly DependencyProperty CommandProperty =
  51:             DependencyProperty.RegisterAttached(
  52:                 "Command", typeof(ICommand), typeof($command$),
  53:                 new PropertyMetadata(CommandProperty_Changed));
  54:  
  55:         public static ICommand GetCommand(DependencyObject obj)
  56:         {
  57:             return (ICommand)obj.GetValue(CommandProperty);
  58:         }
  59:  
  60:         public static void SetCommand(DependencyObject obj, ICommand value)
  61:         {
  62:             obj.SetValue(CommandProperty, value);
  63:         }
  64:  
  65:         private static void CommandProperty_Changed(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
  66:         {
  67:             $control$ targetObject = dependencyObject as $control$;
  68:  
  69:             if (targetObject != null)
  70:                 GetOrCreateBehavior(targetObject).Command = e.NewValue as ICommand;
  71:         }
  72:  
  73:         #endregion
  74:  
  75:         #region CommandParameterProperty
  76:  
  77:         public static readonly DependencyProperty CommandParameterProperty =
  78:             DependencyProperty.RegisterAttached(
  79:                 "CommandParameter", typeof(object), 
  80:                 typeof($command$), new PropertyMetadata(CommandParameterProperty_Changed));
  81:  
  82:         public static ICommand GetCommandParameter(DependencyObject obj)
  83:         {
  84:             return (ICommand)obj.GetValue(CommandParameterProperty);
  85:         }
  86:  
  87:         public static void SetCommandParameter(DependencyObject obj, ICommand value)
  88:         {
  89:             obj.SetValue(CommandParameterProperty, value);
  90:         }
  91:  
  92:         private static void CommandParameterProperty_Changed(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
  93:         {
  94:             $control$ targetObject = dependencyObject as $control$;
  95:  
  96:             if (targetObject != null)
  97:                 GetOrCreateBehavior(targetObject).CommandParameter = e.NewValue;
  98:         }
  99:  
 100:         #endregion
 101:         
 102:         private static $command$CommandBehavior GetOrCreateBehavior($control$ targetObject)
 103:         {
 104:             $command$CommandBehavior behavior = targetObject.GetValue($command$BehaviorProperty) as $command$CommandBehavior;
 105:  
 106:             if (behavior == null)
 107:             {
 108:                 behavior = new $command$CommandBehavior(targetObject);
 109:                 targetObject.SetValue($command$BehaviorProperty, behavior);
 110:             }
 111:  
 112:             return behavior;
 113:         }
 114:     }]]>
 115:             </Code>
 116:         </Snippet>
 117:     </CodeSnippet>
 118: </CodeSnippets>

To have this snipped installed you simply need to create a file named prismcommand.snipped and copy the code inside it (or simply download the attached file). This file has to be loaded in the My Code Snippets directory using the Code Snippet Manager in Visual Studio 2008.

Finally after creating a file in your project type "prismcommand" in the text editor and hit TAB. Two classes will be exploded and you will be asked to provide the expansion tags I listed above. Obviously you have to include the assemblies from Prism and reference the Microsoft.Practices.Composite.Presentation.Commands namespace to have it compile.

Download:

Categories:   Prism
Actions:   E-mail | del.icio.us | Permalink | Comments (2) | Comment RSSRSS comment feed

New articles are close to launch...

2009-07-07T01:04:55+01:00 by Andrea Boschin

logo After a long period of silence I'm close to publish some new articles. While I'm very busy in the last months I was unable to write additional content. I preferred to stop publishing instead of writing something of fast and low in quality.

Now the workload is going down to a normal level so I have time to work on something new and it will be published very, very soon...

Please be patient.

Categories:   News
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed