Saturday, July 25, 2009

Assembly Caching in Silverlight 3 - practical example

As an introduction on Silverlight 3 Assembly Caching feature, I suggest reading Tim Heuer's detailed blog post here . Following is a practical example of using Assembly Cache in new projects (for existing ones just skip Step 1 and 2).

Step 1 - Start new project

In Visual Studio 2008 start new Silverlight project: File -> New -> Project.

Step 2 - Choose hosting web application project

Check option "Host new Silverlight application in a new web site".

Step 3 - Add dlls of interest and appropriate .extmap.xml files into newly created Solution Folders

(For the sake of simpler walkthrough I will only show adding Silverlight and SilverlightToolkit dlls, but you can easily add your own specific ones)
Right click on Solution, Add -> New Solution Folder: type "Reference". Right click on Reference solution folder and add two new sub-solution folders: "Silverlight" and "SilverlightToolkit". Create a coresponding folder structure on the file system, too: {SolutionFolder}\Reference\Silverlight and {SolutionFolder}\Reference\SilverlightToolkit.

Silverlight 3 dlls and their *.extmap.xml files are located in the following folder: c:\Program Files\Microsoft SDKs\Silverlight\v3.0\Libraries\Client.
For instance, for a classical Silverlight 3 data application, the following dlls are needed:
  • System.ComponentModel.DataAnnotations.dll
  • System.Data.Services.Client.dll
  • System.Windows.Controls.dll
  • System.Windows.Controls.Data.dll
  • System.Windows.Controls.Data.Input.dll
  • System.Windows.Controls.Input.dll
  • System.Windows.Data.dll
  • System.Xml.Linq.dll
Copy all those dlls and their already generated *.extmap.xml files into {SolutionFolder}\Reference\Silverlight.

Silverlight Toolkit dlls for July 2009 release are located in the following folder: c:\Program Files\Microsoft SDKs\Silverlight\v3.0\Toolkit\Jul09\Bin, e.g.:
  • System.Windows.Controls.Toolkit.dll
  • System.Windows.Controls.Input.Toolkit.dll
Copy Silverlight Toolkit dlls and their *.extmap.xml files into {SolutionFolder}\Reference\SilverlightToolkit folder.
Unfortunetely, *.extmap.xml files for Silverlight Toolkit July 2009 release are not provided so they need to be manually created.
For the instructions on manual creating extmap.xml file, refer to Tim Heuer's detailed blog post here. There is also a small utility deloped by Alex Golesh for easier creating extmap.xml files here.

"Download uri" attribute in "extension" node in all *.extmap.xml files should be set for Silverlight dlls:
<extension downloaduri="Silverlight.zip"></extension>
and for SilverlightToolkit dlls:
<extension downloaduri="SilverlightToolkit.zip"></extension>
The solution should look like this, now.


Step 4 - Add reference in Silverlight project to external dlls in Solution Folders

Right click on Silverlight client project and select Add reference, then select Browse tab (not .Net tab!) and set "Look in" folder to corresponding Silverlight Reference Solution Folder. Select all dll files and click Ok. Do the same for SilverlightToolkit references.
In properties dialog of Silverlight client project check "Reduce XAP size by using application library cache" option.
If everything goes well, after rebuilding solution in ClientBin folder of your Silverlight client web application host project, Silverlight.zip and SilverlightToolkit.zip files will appear as shown below:

That sums it up. Startup Silverlight client XAP file size is now only 3 KB (!), and all Silverlight and Silverlight Toolkit dlls are in separate .zip files.
Silverlight.zip (for classic data application) takes 480KB and SilverlightToolkit.zip 135 KB. These .zip files are now ready for caching on client browser, since they are not going to be changed that often. Of course, you can organize your own dlls in your own logical .zip groups based on your project requirements and based on frequency of dll changes.
SilverlClient.xap files contains only SilverlClient.dll and AppManifest.xaml with following content (notice Deployment.ExternalParts node):


Download example solution

You can download example solution here. It contains all necessary *.extmap.xml files for dlls in this article.

Step 5 - Use absolute download uri with .zip version number

Since Microsoft has decided not to host .zip files for us at this point, you need to do it by yourself. On your official web server (where you host your Silverlight application) create AssemblyCache folder and copy Silverlight_3.0.zip and SilvelirghtToolkit_July09.zip files there. Change all *.extmap.xml files so that their downloadUri attribute points to new location, for instance:
<extension downloaduri="http://www.YourDomain.com/AssemblyCache/Silverlight_3.0.zip"></extension>
Version number should be included in download file path to make download url unique and it will help you handle possible version conflicts when one or all dlls in .zip file are changed.

Assembly Caching - When not to use it?

While assembly caching is easy to setup and use, there are certain scenarios when they are not appropriate.
The obvious downside of assembly caching feature is that all external *.zip files need to be loaded before starting the Silverlight application, which can be a problem in more advanced scenarios where not all libraries are required from the start. In those scenarios, you should leverage existing Prism for Silverlight or MEF for dynamically loading assemblies only when they are required (e.g. user request).
Silverlight 3 Assembly Caching doesn't work in combination with Out of Browser (OOB) feature, and in that case you can use Isolated Storage as a dll cache mechanism.

Conclusion

Silverlight 3 Assembly Caching feature makes XAP files much smaller, which can dramatically reduce download for your existing Silverlight 3 application users, resulting in much better user experience even if code is constantly evolving.
Assembly caching is practically collection of zip files holding third party or any other dlls that is downloaded to client's machine on Silverlight application start and saved in browser's cache via browser's cache mechanism.
Silverlight 3 Assembly Caching is not available in OOB scenarios and when external dlls are needed only on user's request.

Thursday, July 23, 2009

The joy of Silverlight 3 migration - no code required

In my previous post, I've showed how easy it was for me to migrate LOB application from Silverlight 2 to Silverlight 3, and now I would like to write about some Silverlight 3 goodies that don't require coding at all:

Better XAP compression rate

Silverlight 3 finally raised compression rate of XAP files, so in my case XAP file was reduced for about 10% of its previous size, although I had to add new System.Windows.Controls.Input.dll (93 KB). Very nice. No need for manually hacking compression rate anymore.

Assembly Caching

This is one of the features that is extremely useful even for very small projects. Basically, you can divide your code into couple of XAP files, for instance, third party libraries and your "changeable" code. Third party libraries can be cached, so when you change your code, only changed dlls will be downloaded to your existing clients, reducing overall payload size.

WCF binaryHttpBinding

There is no reason to keep the old WCF basicHttpBinding now the Silverlight 3 is out. "Old" Silverlight 2 sent text over wire, but now with just couple of web.config changes it is easy to setup binaryHttpBinding for WCF services and experience better WCF performances. Done. No turning back!

Better font rendering

It's hard to miss this one as that was the major reason some designers didn't like Silverlight. Finally, I am very happy that I can actually work with designers, though it looks like font rendering could be even better.

VirtualizingStackPanel in ListBoxes by default

I thought that I should do it by myself. But, hey... I get it for free :). In Silverlight 3, ListBox has VirtualizedStackPanel in ListBoxes by default, which practically means that only displayed items will be rendered, which increases performances on some forms. More details here.

New MouseWheel event

There is a new MouseWheel event exposed (without JavaScript hack!), which can be used the same way it is used in WPF application. I guess I will have to refactor old Silverlight 2 mouse wheel "quirk" code into the new simpler one.

No need for extra rebuild in bigger projects

When Silverlight 2 XAP file becomes bigger (1MB+), I have often experienced a need for separate rebuild prior starting application in debug mode, which slowed the development. It looks like it's fixed now, and I can just press F5. What a relief ;).

Noteble bug fixes

ComboBox DropDown height is finally fixed when using in cascading fashion, which caused problems in lots of LOB scenarios.

Some pitfalls

Out of browser (OOB) feature doesn't work in combination with Assembly Caching in Silverlight 3, but I guess one can overcome this limitation by using Prism for Silverlight framework or MEF for even better dynamically loading of assemblies, only when needed.
I still don't get why some classes are sealed: Shape and HtmlElement come to my mind first. There are some very old forum posts on this topic here, but apparently, nothing has changed.

These are some of my favourite Silverlight 3 enhancements which don't require any coding. How about that :).

Tuesday, July 21, 2009

Migration from Silverlight 2 to Silverlight 3

In one word: Smooth. In two words: Very Smooth! Read on if you want to know my experience of migrating http://www.primetimetable.com from Silverlight 2 to Silverlight 3:

Step 1 - Introduction

I have rechecked information published by Silverlight team here.

Step 2 - Installation

Downloaded and installed new stuff:Step 3 - Visual Studio Conversion Wizard

Started the old Silverlight 2 solution and converted it using Visual Studio Conversion Wizard.

Step 4 - Rebuild solution(s) and fix errors
  • As expected, Silverlight Toolkit controls needed the new Silverlight Toolkit July 2009 references
  • AutoCompleteBox has been moved into System.Windows.Controls.Input namespace as stated in the migration document.
  • WCF services showed errors even after updating them. Re-adding was enough for errors to disappear.
  • HierarhicalDataTemplate namespace for TreeView custom item template is now in System.Windows.Controls namespace instead of System.Windows.Controls.Toolkit.
Step 5 - Final touches
  • Minimum runtime version for Silverlight 3 object tag needs to be: 3.0.40624.0
  • Silverlight Toolkit NumericUpDown control needed some fixes for background color (?).
Step 6 - Testing

After exhaustive testing I found it hard to believe that all code just worked: custom window, ribbon, other custom controls, mouse wheel, mouse right click and all other stuff just worked. I have also experienced some fixes to Silverlight 3 controls which bugged me previously.

Step 7 - Publishing

Nothing new here. That's it. It's live since Silverlight 3 release date :) here: http://www.primetimetable.com/demo/

Conclusion:

Migrating from Silverlight 2 to Silverlight 3 took me only 1 hour(!) and I did it while I was on my vacation ;). This was the best upgrading experience I have ever had. I remember the old days when I tried converting Flash/ActionScript code to newer Flash version, and the code needed complete rewrite from the scratch - that's where I decided to completely stop developing Flash. Also, I remember converting Asp.Net 1.1 projects into 2.0 and later into 3.0 and 3.5. That was smooth, because the code basically remained the same, but there were always some gotchas and it took some time. Definitely, a pleasant surprise from Silverlight team. Thank you guys for great work!