Silverlight Playground
about Silverlight and other Amenities

A generic enum converter to map values...

2010-09-03T16:38:49+01:00 by Andrea Boschin

Many times I have to deal with enumerated values with databinding, and often this requires  the writing of a converter to map the enum to something else. As an example you can have a Status enum and you need to transform it to a color (or a brush) in the UI, or you have a series of values from the enumerator and need to change it to an image when it is presented to the user.

Finally these days I found a generic solution to these problems that let me create a mapping from a value (an enumerator, a series of integers, of also a boolean) to an instance of another object. To give you an example think at having this enumerator:

   1: public enum MessageType
   2: {
   3:     Normal,
   4:     Urgent,
   5:     Critical
   6: }

We want to map the values to a series of colors having White for Normal, Orange for Urgent and Red for Critical. Since usually you can override IValueConverter and write a specific converter that handles this enum I found useful to create a parametric value converter that lets me write the code below:

   1: <UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   2:              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
   3:              xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
   4:              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
   5:              xmlns:cv="clr-namespace:SilverlightPlayground.Converters;assembly=SilverlightPlayground"
   6:              mc:Ignorable="d" x:Class="SilverlightPlayground.MyApplication.Shell" d:DesignWidth="456">
   7:     <UserControl.Resources>
   8:         <cv:EnumConverter x:Key="mapTypeToBrush">
   9:             <cv:EnumConverter.Items>
  10:                 <SolidColorBrush Color="#00000000" />
  11:                 <SolidColorBrush Color="#FFFF9900" />
  12:                 <SolidColorBrush Color="#FFFF0000" />
  13:             </cv:EnumConverter.Items>
  14:         </cv:EnumConverter>
  15:     </UserControl.Resources>
  16:     <Grid x:Name="LayoutRoot">
  17:         <Rectangle Fill="{Binding ReveivedMessageType, Converter={StaticResource mapTypeToBrush}}" Width="100" Height="100" />
  18:     </Grid>
  19: </UserControl>

The beautiful of this converter is that with a single converter you can create a series of mappings in the App.xaml resources and share them across all the applications and centralize the conversion of application wide enums in a single position. The code of the converter is really simple and straightforward:

   1: public class EnumConverter : IValueConverter
   2: {
   3:     private List<object> items;
   4:  
   5:     public List<object> Items 
   6:     { 
   7:         get
   8:         {
   9:             if (items == null)
  10:                 items = new List<object>();
  11:  
  12:             return items;
  13:         }
  14:     }
  15:  
  16:     public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  17:     {
  18:         if (value == null)
  19:             throw new ArgumentNullException("value");
  20:         else if (value is bool)
  21:             return this.Items.ElementAtOrDefault(System.Convert.ToByte(value));
  22:         else if (value is byte)
  23:             return this.Items.ElementAtOrDefault(System.Convert.ToByte(value));
  24:         else if (value is short)
  25:             return this.Items.ElementAtOrDefault(System.Convert.ToInt16(value));
  26:         else if (value is int)
  27:             return this.Items.ElementAtOrDefault(System.Convert.ToInt32(value));
  28:         else if (value is long)
  29:             return this.Items.ElementAtOrDefault(System.Convert.ToInt32(value));
  30:         else if (value is Enum)
  31:             return this.Items.ElementAtOrDefault(System.Convert.ToInt32(value));
  32:  
  33:         throw new InvalidOperationException(string.Format("Invalid input value of type '{0}'", value.GetType()));
  34:     }
  35:  
  36:     public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  37:     {
  38:         if (value == null)
  39:             throw new ArgumentNullException("value");
  40:  
  41:         return this.Items.Where(b => b.Equals(value)).Select((a, b) => b);
  42:     }
  43: }

The converter has a list of items it use to make the conversion of integer values. It maps the integer to the index of the list and returns the n-th element found in the array. I didn't handled the out of bounds exception just because the errore returned to the user by the converter is already good to understand what it happen. The converter itself can handle both the directions if the Equals method is correctly overrided.

Finally, I  supported boolean values so it is possible to pass to the converter true/false and having it select the items from a list of two elements. This let me also map the Visibility to boolean values (that is a pretty frequent situation):

   1: <cv:EnumConverter x:Key="bool2Visibility">
   2:     <cv:EnumConverter.Items>
   3:         <Visibility>Collapsed</Visibility>
   4:         <Visibility>Visible</Visibility>
   5:     </cv:EnumConverter.Items>
   6: </cv:EnumConverter>

As you can see the trick is really simple but as usual simple things are the most beautiful and useful. I hope someone can judge this tip good to spare time. It has been very great for me.

FormsAuthentication and ClientHttpStack with mixed applications

2010-08-30T16:41:47+01:00 by Andrea Boschin

If you ever tried to have mixed applications, with some regular ASP.NET pages and a bunch of Silverlight applications, where the forms authentication is made with a traditional ASP.NET login page, you have for sure found that you are forced to use the BrowserHttp stack into the Silverlight applications because the FormsAuthentication cookie is not shared between the ASP.NET page and the new ClientHttp stack that is available since Silverlight 3.0.

Since the new ClientHttp stack for many reasons is a huge improvement, is would be a beautiful thing being able to use this stack every time there is the need to place HTTP calls. Finally I found a way to share this cookie across the two stacks, but I want to warn you that the sole way to accomplish this task require a little "dirty hack", that someone might consider unacceptable while it opens some minor security concerns I will detail at the end of the post.

Before continue reading this post please have in mind that my suggestion is to always use the BrowserHttp stack in these scenario, until you do not really need the new stack, e.g. if you have to use some special verb or for some other particular reason.

The dirty hack explained

The first thing you have to know is that when you are using the ClientHttp stack you are free to access the cookies issued by the server and it is also possible to add some cookies to attach to a call. The task we would have to accomplish is simply to read a cookie (often called .ASPXAUTH) from the BrowserHttp stack and add it to the ClientHttp stack and it may seems and easy task.

Unfortunately the BrowserHttp Stack prevent us from accessing the cookies. The cookies management is one of the features that has been added by the new ClientHttp stack and there is not any way to pump out them from the old one.

So my first try was to use the HtmlPage.Document.Cookies property, as I found in some examples on the Internet. Perhaps this may work when the authentication cookie is issued by a custom authentication system, but with FormsAuthentication it is another failed try because the cookies issued by the ASP.NET engine are HttpOnly. This attribute, added since IE6 SP1, prevents the browser scripts - and Silverlight is considered a client script - from accessing these cookies that remain hidden.

So, how can we share these cookies? The only thing you can do is to add the cookie to the InitParams collection when you initialize the plugin in the html page. You have to change this page to be an aspx page and then you can create two keys into the InitParams collection like the following:

   1: public string GetFormsAuthenticationCookie()
   2: {
   3:     return string.Format(
   4:         "FormsCookieName={0},FormsCookieValue={1}",
   5:         FormsAuthentication.FormsCookieName,
   6:         this.Request.Cookies[FormsAuthentication.FormsCookieName].Value);
   7: }

Then in the plugin I would like to have a centralized class reponsible of creating the cookie and adding it to each server call I do. First of all, if you are using WCF you have to enable the CookieContainer from the ServiceReferences.ClientConfig file. You have to add an attribute that exists only in the Siverlight side of the configuration:

   1: <basicHttpBinding>
   2:     <binding name="BasicHttpBinding_IWCFService" 
   3:               maxBufferSize="2147483647"
   4:               enableHttpCookieContainer="True"
   5:               maxReceivedMessageSize="2147483647">
   6:         <security mode="None" />
   7:     </binding>
   8: </basicHttpBinding>

The enableCookieContainer attribute initializes an instance of an IHttpCookieContainerManager into the WCF client an this allow us to manage cookies using the CookieContainer collection. Now we can write a simple application service to put into the app.xaml that we can use to instantiate and initialize the client. The reason of creating an application service is to have a common place where initialize a shared cookie container that reads the InitParam and add the received cookies into it:

   1: public class ClientCreatorService : IApplicationService
   2: {
   3:     public static ClientCreatorService Current
   4:     {
   5:         get
   6:         {
   7:             return Application.Current.ApplicationLifetimeObjects.OfType<ClientCreatorService>().Single();
   8:         }
   9:     }
  10:  
  11:     private CookieContainer SharedCookies { get; set; }
  12:  
  13:     public void StartService(ApplicationServiceContext context)
  14:     {
  15:         this.SharedCookies = new CookieContainer();
  16:         string formsCookieName = context.ApplicationInitParams["FormsCookieName"];
  17:         string formsCookieValue = context.ApplicationInitParams["FormsCookieValue"];
  18:         this.SharedCookies.Add(new Uri(Application.Current.Host.Source, "../"), new Cookie(formsCookieName, formsCookieValue));
  19:     }
  20:  
  21:     public K CreateClient<T, K>()
  22:         where K : ClientBase<T>, new()
  23:         where T : class
  24:     {
  25:         K client = new K();
  26:         IHttpCookieContainerManager cookieManager = client.InnerChannel.GetProperty<IHttpCookieContainerManager>();
  27:         cookieManager.CookieContainer = this.SharedCookies;
  28:         return client;
  29:     }
  30:  
  31:     public void StopService()
  32:     {}
  33: }

During the initialization the ClientCreatorService initialize the SharedCookies with the FormsCookieName and FormsCookieValue. Then the generic CreateClient methid is able to instantiate the required client and add the SharedCookies to it. The usage of the Application Service is pretty simple. Here is how to instantiate the client and place a call:

   1: WCFServiceClient client = ClientCreatorService.Current.CreateClient<IWCFService, WCFServiceClient>();
   2: client.GetIdentityCompleted += new EventHandler<GetIdentityCompletedEventArgs>(client_GetIdentityCompleted);
   3: client.GetIdentityAsync();

If you try the code you will find that the GetIdentity method is able to retrive the membership identity from the HttpContext.Current.User property. This means your service runs in an authenticated context.

What is the drawback?

When you make a dirty thing you have to be aware that there is always almost a drawback. In this case the problem is that the injection of the authentication cookie in the InitParams opens a subtle security concern that is mitigated by the fact that the informations we are disclosing are already public even before my trick was up and running. The use of HttpOnly cookies for authentication is an important improvement that prevent the use of XSS attacks. Having the cookie injected in the page, re-open the window to some pre-IE6 SP1 scripts that could try to access the InitParams collection from javascript and simulate the authentication to the system like our Silverlight application actually does.

This problem must be always in your mind and you have to put on the scale both the advantage of having the ClientHttp working and the security concerns of this trick. My hope is that the Silverlight team will be able to solve this issue in next releases of the plugin, so we can rely on a secure implementation and avoid dirty tricks.

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

Keeping an ObservableCollection sorted with a method override

2010-04-27T16:30:52+01:00 by Andrea Boschin

Usually the order of elements in a collection is something one does not feel to be important. We have plenty of methods in the Framework to order things and now that there is LINQ to Objects the need to sort something is really matter of seconds.

Since the introduction of LINQ the main problem is that you have many cases where a few lines of code are adding really complex iteration logic and often this hurts performances when the count of milliseconds is something important.

In these days I had this problem because I did need to make a lot of updates to a collection in the short time as possible, because I was working into the a CompositionTarget_Rendering event. A lot of hidden iterations through the collection, made by LINQ queries, has degraded the performances of the application and I had to put my nose on the iteration logic to optimize it.

In a case like this, having a collection that ensure a given order of the elements was key to solve my problem. So I decided to implement a SortedObservableCollection that helped me to minimize scans of the collection. Here is the simple code:

   1: public class SortedObservableCollection<T> : ObservableCollection<T>
   2:     where T : IComparable
   3: {
   4:     protected override void InsertItem(int index, T item)
   5:     {
   6:         for (int i = 0; i < this.Count; i++)
   7:         {
   8:             switch (Math.Sign(this[i].CompareTo(item)))
   9:             {
  10:                 case 0:
  11:                     throw new InvalidOperationException("Cannot insert duplicated items");
  12:                 case 1:
  13:                     base.InsertItem(i, item);
  14:                     return;
  15:                 case -1:
  16:                     break;
  17:             }
  18:         }
  19:  
  20:         base.InsertItem(this.Count, item);
  21:     }
  22: }

The trick has been done in a few minutes, just because the ObservableCollection exposes some overridable methods that enable the developer to change the Insert and Remove behavior. So I simply overriden the InsertItem method. I changed it trying to put elements in the right place, evaluating the position over the elements already in the collection. This helped me to move the sorting logic in another context, out of the Rendering event, and maximize the performances.

The code I wrote in this sample is really simple. I figure out you can improve again the performances of the InsertItem method implementing a binary search algorithm. But it is a little concern when you know where to act.

A generic ViewModel to publish sets of objects

2009-12-16T22:14:18+01:00 by Andrea Boschin

The programming with the MVVM pattern often requires a proliferation of types because there are more Views that need a ViewModel than you might think. You can think that you need to associate a ViewModel only to simple blocks of your user interface, but while you are writing code you often understand that there are other cases where a ViewModel is required.

As an example while populating a DataGrid binding simple entities to the grid is not  good idea. A single row of a grid not only contains some data to be displayed but often may contain some commands, a link to be clicked, a button to delete an item and so on.

All these are cases where you need a ViewModel to correcty handle the binding and the related commands. So you have to create a new type, add a bunch of properties and some commands and finally populate the grid with instances of the new type. Then you will find someway difficult to route the command from the child ViewModel to the one that has generated it.

Simple is better.

In my recent applications I found a reasonable workaround that correctly handle the situation but avoid a proliferation of classes and as usual in this cases the solution comes from a generic type. The trick comes from the understanding that often in this scenario you have some properties of an entity to be binded and one or two commands to be raised. And in the most cases the command have to be handled by a parent ViewModel. Imagine to have a collection which is shown in a DataGrid and a delete command on each row; To remove the row, the command has to be catched by the ViewModel which is exposing the collection. So I decided to create a simple class named RowViewModel this way:

   1: public class RowViewModel<T,K> : ViewModel
   2:     where T : ViewModel
   3: {
   4:     /// <summary>
   5:     /// Initializes a new instance of the RowViewModel class.
   6:     /// </summary>
   7:     /// <param name="parent">The parent.</param>
   8:     /// <param name="payload">The payload.</param>
   9:     public RowViewModel(T parent, K payload)
  10:     {
  11:         this.Parent = parent;
  12:         this.PayLoad = payload;
  13:     }
  14:  
  15:     /// <summary>
  16:     /// Gets or sets the parent.
  17:     /// </summary>
  18:     /// <value>The parent.</value>
  19:     public T Parent
  20:     {
  21:         get { return this.GetValue<T>("Parent"); }
  22:         set { this.SetValue<T>("Parent", value); }
  23:     }
  24:  
  25:     /// <summary>
  26:     /// Gets or sets the pay load.
  27:     /// </summary>
  28:     /// <value>The pay load.</value>
  29:     public K PayLoad
  30:     {
  31:         get { return this.GetValue<K>("PayLoad"); }
  32:         set { this.SetValue<K>("PayLoad", value); }
  33:     }
  34: }

To simplify the creation of the collection property I've created a class RowViewModelCollection that inherits from the ObservableCollection. This allow me to declare the observable properties with a less verbose syntax:

   1: public class RowViewModelCollection<T, K> : ObservableCollection<RowViewModel<T, K>>
   2:     where T : ViewModel
   3: { }

Now we are ready to publish a DataGrid using this class. The RowViewModel exposes T as the parent ViewModel and K as the payload. This is the entity we want to display in the grid. So we can write a XAML similar to this:

   1: <data:DataGrid ItemsSource="{Binding Tasks}">
   2:     <data:DataGrid.Columns>
   3:         <data:DataGridTemplateColumn>
   4:             <data:DataGridTemplateColumn.CellTemplate>
   5:                 <DataTemplate>
   6:                     <HyperlinkButton cmd:Click.Command="{Binding Parent.DeleteTaskCommand}"
   7:                                      cmd:Click.CommandParameter="{Binding PayLoad}"
   8:                                      HorizontalAlignment="Center" VerticalAlignment="Center" >
   9:                         <Image Height="16" HorizontalAlignment="Center" VerticalAlignment="Center" Width="16" Source="/Elite.TimeTracker.Client;Component/Images/delete.png" Stretch="Fill"/>
  10:                     </HyperlinkButton>
  11:                 </DataTemplate>
  12:             </data:DataGridTemplateColumn.CellTemplate>
  13:         </data:DataGridTemplateColumn>
  14:         <data:DataGridTextColumn Header="Cliente" Binding="{Binding PayLoad.Customer.Description}" />
  15:         <data:DataGridTextColumn Header="Ora" Binding="{Binding PayLoad.StartTime}" />
  16:         <data:DataGridTextColumn Header="Descrizione" Binding="{Binding PayLoad.Description, Converter={StaticResource ellipsis}}" />
  17:         <data:DataGridCheckBoxColumn Header="Chiam." Binding="{Binding PayLoad.IsPhoneCall}" />
  18:         <data:DataGridCheckBoxColumn Header="Compl." Binding="{Binding PayLoad.IsCompleted}" />
  19:     </data:DataGrid.Columns>
  20: </data:DataGrid>

In a couple of words we have:

ItemsSource="{Binding Tasks}" - This connect the DataGrid to a RowViewModelCollection declared in the parent ViewModel.

Binding="{Binding PayLoad.StartTime}" - This take advantage of the dot syntax of the DataBinding that allow to access complex properties of the binded objects. Remember that PayLoad is the instance of the entity to bind to the DataGrid so PayLoad.StartTime binds the StartTime property to the cell.

cmd:Click.Command="{Binding Parent.DeleteTaskCommand}" - This binds the click event of the HyperlinkButton to a command of the parent ViewModel.

cmd:Click.CommandParameter="{Binding PayLoad}" - This binding let me pass the entire entity the delegate command.

This tecnique simplifies the code required to handle the DataGrid. When a command is raised the parent ViewModel handle it and this reduce the need to use an EventBroker, and it gives a more simple and maintainable code.

Is this good only for DataGrids?

There are a lot of cases where you have to bind a collection to a control, the ItemsControl, the ListBox, and so on. Every time you encounter one of these cases you can obviously apply this tecnique. Of course it is useful only if you need to handle some commands, otherwise you can simply bind the entity directly to the control.
In the code I've attached to a my previous post - the -you can find a working sample of the workaround. 

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

How to configure an AuthenticationDomainService using Ria Services Class Library

2009-11-06T11:36:01+01:00 by Andrea Boschin

Using a Ria Services Class library to collect DomainServices and DomainContexts in a solution is a good practice because everyone know the value of having classes separated in projects instead of having them in the web project.

If you try to create this kind of project and then you add an Authentication Domain Service with the July 2009 CTP of Ria Services you will find two major drawbacks. First of all you will notice the generated code does not contains a RiaContext class. RiaContext is the class responsible to handle the User and roles and configure the type of Authentication to use in the application.

To workaround to this problem you may simply write by hand this class and put it in the client side part of the Ria Services library project. The code can be copied by an AuthenticationDomainContext generated in the web project but it is very simple and I show you the code here:

   1: public sealed partial class RiaContext : System.Windows.Ria.RiaContextBase
   2: {
   3:     #region Extensibility Method Definitions
   4:  
   5:     partial void OnCreated();
   6:  
   7:     #endregion
   8:  
   9:     public RiaContext()
  10:     {
  11:         this.OnCreated();
  12:     }
  13:  
  14:     public new static RiaContext Current
  15:     {
  16:         get
  17:         {
  18:             return ((RiaContext)(System.Windows.Ria.RiaContextBase.Current));
  19:         }
  20:     }
  21:  
  22:     public new User User
  23:     {
  24:         get
  25:         {
  26:             return ((User)(base.User));
  27:         }
  28:     }
  29: }

With this class you can configure the Authentication Domain Context as you did with the generated class. So you have to add it to the App.config, in the ApplicationLifetimeObjects tag and then add a kind of authentication like the WindowsAuthentication and FormsAuthentication.

The second drawback is that if you run the project this way and then you call the Login() method (or any other method) of the RiaContext you will get an error:

The DomainContextType is null or invalid and there are no contexts generated from AuthenticationBase<T>

This probably come from the fact that the RiaContext is not correctly initializated so when the class search for a valid domaincontext to handle the Login call it fails because it does not find it. The tip to correct this behavior is to specify the DomainContext property in the Authentication you have choosed. Here is how to change the App.xaml file:

   1: <Application.ApplicationLifetimeObjects>
   2:     <slpgria:RiaContext>
   3:         <slpgria:RiaContext.Authentication>
   4:             <appsvc:FormsAuthentication>
   5:                 <appsvc:FormsAuthentication.DomainContext>
   6:                     <slpgdc:MyAuthenticationDomainContext />
   7:                 </appsvc:FormsAuthentication.DomainContext>
   8:             </appsvc:FormsAuthentication>
   9:         </slpgria:RiaContext.Authentication>
  10:     </slpgria:RiaContext>
  11: </Application.ApplicationLifetimeObjects>

As you can see you have simply to give an instance of the generated Authentication Domain context class to the FormsAuthentication (or Windows Authentication as well). The RiaContext need to have this instance to make the calls to the BL methods in the Domain Service.

I really do not know if this behavior will be corrected in the next releases of RiaServices. The solution is pretty simple but take me some hours to understand what are going wrong. So I hope this may help you to spare some time making your experiments with the current release.

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

How to avoid flooding a PollingDuplex server

2009-10-06T14:37:39+01:00 by Andrea Boschin

Returning on the PollingDuplex argument, today I would like to illustrate a tecnique I used to avoid the flooding in my Polling Duplex service. The problem come from the fact that my server retain a list of connected clients and is unable to detect the disconnection in a short time. After a while the notification from the server to the disconnected client will timeout so the server handle the timeout and remove the client from its list. But if for some reason a client Register itself multiple times the server notification list will grow and this may become a problem causing the service to slow down its response time.

In a recent project I have to address this issue because of the way the polling client works. Imagine having a instant messaging client using PollingDuplex in all the pages of a portal. When the user navigate in the website the polling client will repeatly connect and disconnect from the polling server because the user may change page after short time.

How to generate a persistent ClientID

To handle this problem I need to have a globally unique id identifing the connecting client. If the ID is unique across different connected clients the server can use this ID to search previuos instances of the client in his notification list and if found it discart the old client and replace it with the new one. The solution is pretty simple but it require the ability to generate a very unique id (obviously a Guid) and then persist it across different browser session.

The trick is to use the Isolated Storage. The first time I start the client it generate the Guid and save it in the IsolatedStorageSettings collection. Then it use the guid to connect and register to the polling server.

All the other times the client find the Guid in the IsolatedStorageSettings and avoid to generate another Guid but use the old identifier. Here is the code to generate the guid or take id from the storage:

   1: private void Application_Startup(object sender, StartupEventArgs e)
   2: {
   3:     Guid key;
   4:  
   5:     if (!IsolatedStorageSettings.ApplicationSettings.Contains("InstanceKey"))
   6:     {
   7:         key = Guid.NewGuid();
   8:         IsolatedStorageSettings.ApplicationSettings["InstanceKey"] = key;
   9:         IsolatedStorageSettings.ApplicationSettings.Save();
  10:     }
  11:     else
  12:         key = (Guid)IsolatedStorageSettings.ApplicationSettings["InstanceKey"];
  13:  
  14:     this.RootVisual = new MainPage(key.ToString());
  15: }

I put the code in the Application_Startup method then I pass the key to the MainPage constructor because it must use the guid to connect to the server.

On the server side I've slightly changed the Register method and the Polling thread to handle the new guid. First of all I request the id in the Register method:

   1: public void Register(string sessionId)
   2: {
   3:     IPollingServiceClient client =
   4:         OperationContext.Current.GetCallbackChannel<IPollingServiceClient>();
   5:  
   6:     PollingMonitor.Current.Register(client, sessionId);
   7: }

Then the server checks his notification list to add or change the callback client:

   1: /// <summary>
   2: /// Adds the specified item.
   3: /// </summary>
   4: /// <param name="item">The item.</param>
   5: public void Add(IPollingServiceClient client, string sessionId)
   6: {
   7:     var found = (from c in this
   8:                  where c.SessionId == sessionId
   9:                  select c).SingleOrDefault();
  10:  
  11:     if (found != null)
  12:         found.ChangeClient(client);
  13:     else
  14:         this.Add(new PollingClient(client, sessionId));
  15: }

The ChangeClient() method simply put the new callback client in the object instance representing the client in the list.

There are only two drawbacks in this tecnique. The first is that the user can clear his IsolatedStorage using the Silverlight context menu. This deletes the saved Guid so the next time the client connect to the server it generate another Guid. On the other side someone may discover some privacy concerns on having an id globally identifying the client because this may become a way to track the user activities. You have to be aware of this problem and eventually you can mitigate the problem using a TTL to invalidate the Guid after some hours or days so the client will change the Guid and the tracking become hardest.

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

A Prism (Unity) Service to create Views

2009-08-31T21:10:03+01:00 by Andrea Boschin

After a long summer pause I’m back with this new post. This time I want to investigate an aspect of the Model-View-ViewModel pattern programming with Silverlight. During the summer I've started working on an application where I used Prism to implement MVVM and I found useful to write some code to easily create instance of views during application inizialization and during its lifetime. I really do not know if this is the better solution but I found it easy and useful so I've decided to share it with you. Let me say in this post I assume you are already aware of the reasons and benefits coming from the usage of the popular Model-View-ViewModel pattern and how the pattern works. I also assume you have a minimal knowledge of the Prism toolkit and Unity.

The relationship between the View and the ViewModel

In this section I would like to depict how the View and ViewModel collaborate and what we have to do to create an instance of a View and of its own ViewModel at the sole purpose of preparing the field for explaining my solution.

In the MVVM pattern the View represent the user interface and the ViewModel represent the business logic required to drive the informations displayed on the View. This way, every time we have to create a View we also have to create a specific ViewModel exposing the expected informations to be displayed. The ViewModel is not aware of the View, so It does not know how its properties are consumed, but it simply publish some data through some properties and the View will attach these properties using DataBinding.

What I've said reveal almost two things. The first is that the View does not know how the ViewModel works internally, but it have to know the structure of its surface. In other words the ViewModel have to implement a given well-known "interface" to let the View working fine. This interface contains only properties the View is expected to attach. This implementation is not truly required by the pattern but we can think it is near to reality.

The other thing we have to know is that to let the view binding to the ViewModel, we have to put the ViewModel in the DataContext of the View. So, the creation of the View involve the creation of a specific ViewModel -possibly implementing a given interface - and the assignment of this instance to the DataContext property of the View. Translating this concept in code we have to write something like this:

   1: MyView view = new MyView() 
   2: { 
   3:     DataContext = new MyViewModel() 
   4: }; 


In my projects I do not like to write this code because it does not let me impose to the ViewModel an interface implementation. I can obviously implement the interface but there is nothing checking that this implementation has been done. To avoid this problem I've decided to create a service I use every time I need to create a View. The service is responsible to check that the ViewModel implements a specific interface. So the creation of a View become this:

   1: // assuming "vbs" is an instance of the service 
   2: MyView view = vbs.CreateView<MyView>(); 

What is a service?

Before entering the service implementation details, I would like to explain what is a Service. As I've already said in the previous paragraphs I'm using , a.k.a . Prism is a collection of useful tools to let the developer apply easily the most common architectural patterns. For the purpose of this article we will use , a dependency injection container recently ported to Silverlight from the Microsoft Pattern and Practice team. It is available inside the Prism collection.

Unity is an "" container. It let you create and register instances of classes - giving them a lifetime manager responsible of how and when the class is created and destroyed - and then locate these classes when you need to use them. Creating a class and registering it in the IOC container let you having something similar to a service, always available and discoverable, you may dedicate to specific responsibility.

The purpose of Unity is to promote layer decoupling to enable unit testing of the applications, but this is out of the scope of this article. If you would like to read something about this argument please refer to the Unity home page on codeplex: http://www.codeplex.com/unity.

Anatomy of the ViewBuilderService

Now that I have briefly explained how a service works it is time to explain the basis of my ViewBuilderService. The trick is that the View have to declare somewhere the interface it expects the ViewModel to implement. We may have an interface "IMyViewModel" and a view "MyView" that can consume a ViewModel implementing this interface. Using a simple custom attribute we can decorate the View codebehind with the interface:

   1: [ViewModel(typeof(IMyViewModel))]
   2: public partial class MyView : UserControl
   3: {
   4:     public MyView()
   5:     {
   6:     }
   7: }

Declaring a custom Attribute is simple and it enable the ViewBuilderService to discover the interface to search for in the IOC container. In the next box there is the declaration of the ViewModelAttribute where I use the AttributeUsage attribute to inform the compiler where it have to expect the attribute to be applied.

   1: [AttributeUsage(AttributeTargets.Class)]
   2: public class ViewModelAttribute : Attribute
   3: {
   4:     public Type ViewModelType { get; set; }
   5:  
   6:     public ViewModelAttribute(Type viewModelType)
   7:     {
   8:         this.ViewModelType = viewModelType;
   9:     }
  10: }

To connect a ViewModel to its own interface we need to create the ViewModel and register it into the IOC container. This way the ViewBuilderService can read the ViewModelAttribute on the View and ask the container to resolve the interface and give us the ViewModel instance to put in the DataContext. The best place to register the ViewModels is a Module we have declared in the Unity Bootstrapper. In the sample attached to this article I've omitted to use a Module for the purpose of not complicate the sample. So the ViewModels are registered in the Bootstrapper itself.

   1: /// <summary>
   2: /// Registers the types.
   3: /// </summary>
   4: private void RegisterTypes()
   5: {
   6:     this.Container.RegisterType<IMyViewModel, MyViewModel>();
   7: }

Now all is ready and we can create the service. We have to remember that the service has to be registered in the IOC contained to be discoverable using the ServiceLocator. So we start creating a class that implements an interface IViewBuilderService:

   1: public class ViewBuilderService : IViewBuilderService
   2: {
   3:     private static IUnityContainer TheContainer { get; set; }
   4:  
   5:     public ViewBuilderService (IUnityContainer theContainer)
   6:     {
   7:         this.TheContainer = theContainer;
   8:     }
   9: }

The IViewBuilderService interface have to expose only a CreateView<T>() method we will implement in the service. This method is responsible of finding the ViewModel in the container, creating the View we specified in the T parameter and finally connect view and viewmodel together.

   1: public T CreateView<T>()
   2:     where T : UserControl, new()
   3: {
   4:     ViewModel vm = this.GetViewModel(typeof(T));
   5:     return new T() { DataContext = vm };
   6: }
   7:  
   8: private ViewModel GetViewModel(Type viewType)
   9: {
  10:     ViewModelAttribute attribute = 
  11:         viewType
  12:             .GetCustomAttributes(typeof(ViewModelAttribute), true)
  13:             .OfType<ViewModelAttribute>()
  14:             .SingleOrDefault();
  15:  
  16:     if (attribute == null)
  17:         throw new InvalidOperationException("Missing ViewModelAttribute");
  18:  
  19:     ViewModel vm = this.TheContainer.Resolve(attribute.ViewModelType) as ViewModel;
  20:  
  21:     if (vm == null)
  22:         throw new InvalidOperationException("Cannot Resolve ViewModel");
  23:  
  24:     return vm;
  25: }

Using the ViewBuilderService

It is time to use the service inside our applications. First of all we have to register the service into the IOC container. We can register the service like we already have registered the ViewModel using the RegisterType method. While we can use the same instance of the service in all the application we can use a ContainerControlledLifetimeManager. This type of lifetime manager will transform the service in a singleton instance.

   1: /// <summary>
   2: /// Registers the types.
   3: /// </summary>
   4: private void RegisterTypes()
   5: {
   6:     this.Container.RegisterType<IViewBuilderService, ViewBuilder>(
   7:         new ContainerControlledLifetimeManager());
   8:  
   9:     this.Container.RegisterType<IMyViewModel, MyViewModel>();
  10: }

Then now using the ServiceLocator we can discover the service when we need to create a View. The ServiceLocator is a Singleton class, that is capable to search registered types by its interface and return an instance. You can use the ServiceLocator everywhere you need to find the IViewBuilderService.  Here is the code to create a View and assign to the Shell:

   1: Grid grid = this.Shell.FindName("LayoutRoot") as Grid;
   2:  
   3: if (grid != null)
   4: {
   5:     IViewBuilderService vbs =
   6:         ServiceLocator.Current.GetInstance<IViewBuilderService>();
   7:  
   8:     MyView view = vbs.CreateView<MyView>();
   9:  
  10:     grid.Children.Add(view);
  11: }

Obviously I could use the RegionManager to put the new View into the user interface but I wanted to keep the example simple.

All the code I've tryied to explain in this post is attached at the end of the article. I hope you will find it useful in your applications and I will expect comments from you to improve my design and know your opinion about it.

Download: SilverlightPlayground.ViewBuilderService.zip (~430 kb)

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

Installing Silverlight 3.0 side-by-side with Silverlight 2.0

2009-03-22T08:35:21+01:00 by Andrea Boschin

A useful tip has been published by , about how to install Silverlight 2.0 and 3.0 on the same machine an continue working with both. You have to take note that the Silverlight 3.0 runtime will override the Silverlight 2.0 runtime but due to the big work in backward compatibility this would not be a big problem.

The tip require a batch script to switch from a version to another of the Visual Studio Tools. Included in the tip there is also a way to change the projects to work with both versions of the tools.

Link:

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