modify silverlight ServiceReferences.ClientConfig after a build

I use NANT to automate the build process, now I face a little problem with silverlight. When you reference a service the designer of visual studio generate a ServiceReferences.ClientConfig  with configuration of the service, it contains the address of the service and it gets compiled inside the .xap file generated by compilation

I use to point to a localhost machine during debugging, but in the real environment the service maybe is in another machine, so I need to find a way to point the client to the right service inside a nant build file. Since .xap files are nothing but a zip file I try to setup an action to unzip file, modify the ServiceReferences.ClientConfig, zip the file again and the game is done….exept that this does not works. It seems that Nant task <unzip> generates error when It tries to uncompress the xap file.

The solution was simple, I included 7z.exe (7-zip) on the buildTools directory, and simply instruct nant to uncompress with 7z.

<target name="UpdateSilverlightConfiguration" depends="GetPublishingProperties" > <mkdir dir="${DebugSitePath}\ClientBin\Temp" /> <exec program="${sevenzip}" commandline=" x ${DebugSitePath}\ClientBin\RepManagement.SIlverlight.xap -o${DebugSitePath}\ClientBin\Temp -y" /> <copy file="${ConfigurationDir}\ServiceReferences.ClientConfig" tofile="${DebugSitePath}\ClientBin\Temp\ServiceReferences.ClientConfig" overwrite="True" /> <zip zipfile="${DebugSitePath}\ClientBin\Temp\RepManagement.SIlverlight.xap" ziplevel="9" failonerror="true" > <fileset basedir="${DebugSitePath}\ClientBin\Temp" > <include name="**"/> </fileset> </zip> <copy file="${DebugSitePath}\ClientBin\Temp\RepManagement.SIlverlight.xap" tofile="${DebugSitePath}\ClientBin\RepManagement.SIlverlight.xap" overwrite="True" /> <delete dir="${DebugSitePath}\ClientBin\Temp\" /> </target>

This is a very simple approach. I set 7z.exe in the build folder so it gets downloaded when subversion update the project directory, then I set a variable called sevenzip that points to the executable. Then uncompress the xap file, copy the production configuration from the configuration folder, overwriting the old one, then zipping all again.

This operation has a double advantage, because I can zip the xap file with higher compression rate to make it smaller.

alk.

Tags:

Visual studio for big web project… so slow

Yesterday I moved my first steps on silverlight, I’m working on a big solution with a big Web site, and the solution build time is really increased when I add silverlight project to the solution.

It is really frustrating because I change something in the silverlight control, then I had to at least issue a command of “build page” in the site, to make the xap file updates. This cost me about 45 seconds of waiting for….nothing, and I have a 10K RPM disk, with a 3.0 GHz Dual core CPU. This is absolutely embarrassing.

At the end of yesterday I was very happy of silverlight…but completely abhorrent about the time it took me to see the result of any little changes.

The solution I adopted today is the following, I created another solution that contains only the silverlight project and a simple test web site with only a page to host the silverlight application. Then I enable my service (of the main site hosted in my local IIS) to be called from other domain with a clientaccesspolicy.xml file placed in the root directory of my site. Here is the content

<?xml version="1.0" encoding="utf-8"?> <access-policy> <cross-domain-access> <policy> <allow-from http-request-headers="*"> <domain uri="*"/> </allow-from> <grant-to> <resource path="/" include-subpaths="true"/> </grant-to> </policy> </cross-domain-access> </access-policy>

This not so good for security, but this is my test server that only respond to localhost, so I have no problem. Then I’m able to invoke service function from a solution that contains only silverlight project, compile time is 1 second, and with 2 second I can visualize the page in IE…….really a better stuff respect the 45 seconds when I use the full solution. The only inconvenient is that you are not able to debug the service, but I have set up a lot of unit tests that assure me that the service works good.

The result is that if you are working with a big web site, you better work with a solution with only the silverligt project to work at full speed, especially during the first days, when quite often you are trying to do things for the first time (OK, if you already worked with WPF the step is really small) 😉

alk.

Tags:

Binding combobox to Enum in silverlight

These days I’m playing a bit with Silverlight, to realize a little piece of backoffice of an ASP.NEt classic application. We decided to give a chance to silverligth because the backoffice is used only internally and so we can make experience with a noncritical piece of software.

Even If I do not adopt a MVC or M-V-VM pattern I like to create a little domain model, than expose it with a transaction script pattern, make it avaliable through a WCF service, and create interface with really no logic. Each service method return DTO not real domain object,  this make possible for the caller not to worry about all the crap that can exists in the domain. The silverlight interface is a simple series of control, that can be bound to a DTO, so the typical pattern is to ask service for some object, then bind them to a control, let the user play with the interface and thanks to twoway binding we can simply wait for the user to press a “Save” button or other such events to call update method from the service.

Thanks to DTO all the work to update the real domain object is done by the service, that can do whatever check you want (optimistic concurrency,etc). The question is “how far can we push silverlight binding to avoid to write any code to make the DTO synchronized with the UI?” The answer is  “really far”.

As an example you can download this code, that shows you how you can bind a property of an object of some Enum type, both to a series of radio button and to a textbox. The example is a modified version of the enum binder that you can find from this article where you can find also a lot of good example about binding. The key of everything is in the IValueConverter interface that permits you to convert from a type to another and back. Here is my enum converter.

public class EnumConverter : IValueConverter { #region IValueConverter Members public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (targetType.IsAssignableFrom(typeof(Boolean)) && targetType.IsAssignableFrom(typeof(String))) throw new ArgumentException("EnumConverter can only convert to boolean or string."); if (targetType == typeof(String)) return value.ToString(); return String.Compare(value.ToString(), (String) parameter, StringComparison.InvariantCultureIgnoreCase) == 0; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { if (targetType.IsAssignableFrom(typeof(Boolean)) && targetType.IsAssignableFrom(typeof(String))) throw new ArgumentException("EnumConverter can only convert back value from a string or a boolean."); if (!targetType.IsEnum) throw new ArgumentException("EnumConverter can only convert value to an Enum Type."); if (value.GetType() == typeof(String)) { return Enum.Parse(targetType, (String)value, true); } else { //We have a boolean, as for binding to a checkbox. we use parameter if ((Boolean)value) return Enum.Parse(targetType, (String)parameter, true); } return null; } #endregion }

This is a first try implementation, not fully tested but it seems to work quite well. It handles conversion between the original enum type to a string or to a boolean value. The conversion to boolean value is needed to use it withRadioButton, in combination with the ConversionParameter. Back conversion is also implemented so you can easily use the twoway binding. Here is a typical use in a user control.

<UserControl x:Class="TestSilverlight.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:TestSilverlight="clr-namespace:TestSilverlight" Width="400" Height="300" Loaded="ControlLoaded"> <UserControl.Resources> <ResourceDictionary> <TestSilverlight:EnumConverter x:Key="EnumConverter"/> </ResourceDictionary> </UserControl.Resources> <Grid x:Name="LayoutRoot" Background="White"> <StackPanel Orientation="Horizontal" Grid.Row="2" Grid.Column="1" > <RadioButton GroupName="TestEnum" Content="One" IsChecked="{Binding Path=TestProp, ConverterParameter=one, Mode=TwoWay, Converter={StaticResource EnumConverter}}" /> <RadioButton GroupName="TestEnum" Content="Two" IsChecked="{Binding Path=TestProp, ConverterParameter=two, Mode=TwoWay, Converter={StaticResource EnumConverter}}" /> <RadioButton GroupName="TestEnum" Content="Three" IsChecked="{Binding Path=TestProp, ConverterParameter=three, Mode=TwoWay, Converter={StaticResource EnumConverter}}" /> <RadioButton GroupName="TestEnum" Content="Four" IsChecked="{Binding Path=TestProp, ConverterParameter=four, Mode=TwoWay, Converter={StaticResource EnumConverter}}" /> <TextBox Text="{Binding Path=TestProp, Mode=TwoWay, Converter={StaticResource EnumConverter}}" /> </StackPanel> </Grid> </UserControl>

As you can see for the textbox you need no particular stuff to do, only set the converter, but for the RadioButton you should set the ConverterParameter for each RadioButton to set the corresponding enum value. The game is done, my DTO object stay in sync with interface with no line of code 😀

alk.

Tags: