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.

16 comments:

  1. Hi Danijel,

    I think tah you are great guy. You will be inspirations for new generations of programmers. Thanks of this great post.

    Be what you are !!!

    Sincerely yours,
    Pablo Garcia

    ReplyDelete
  2. Good article. Brings our some points that I dont see in any blogs.

    ReplyDelete
  3. Hi Danijel nice job !

    I ve try to do as you. But i don't got a silverlight.zip and a silverlighttoolkit.zip

    I got all dll.zip :
    System.ComponentModel.DataAnnotations.zip
    ...
    ...

    I ve done all your step.

    Did i do somethingwrong ? Is it possible that because of giving to the folder the name References instead of Reference ?

    Thanks a lot

    ReplyDelete
  4. @Nk54

    Download uri in all *.extmap.xml files must be set properly:

    "Download uri" attribute in "extension" node in all *.extmap.xml files should be set for Silverlight dlls:
    extension downloaduri="Silverlight.zip"
    and for SilverlightToolkit dlls:
    extension downloaduri="SilverlightToolkit.zip"

    ReplyDelete
  5. First, thanks a lot for your quick answer :)

    I've taken your extmap from your source code :p

    http://nsa11.casimages.com/img/2009/11/04/091104022519446302.jpg

    here is a sample jpg which show the uri. And my project.
    (I've put some black on my project name which is the name of my compagny.)

    As you will see, it seems correct.
    Any suggestion ?

    Thanks. (if message post two time i apologize. get an error at first time)

    ReplyDelete
  6. @Nk54

    Check that dll references in your Silverlight application are from solution folder, and not from c:\Program Files\Microsoft SDKs\Silverlight\v3.0\Libraries\Client\

    ReplyDelete
  7. This was it. Sorry :/

    Should i have to create extmap.xml foreach dll i use ?

    Is there some dll that we don't need to add by ref to Reference folder instead of c:\Program Files\Microsoft SDKs\Silverlight\v3.0\Libraries\Client\ ?

    Thanks for your help. Your solution is cleaner than other that we can find on many blog even some codeplex developer's blog ;)

    ReplyDelete
  8. It's still me. Have a good question (i think ...)

    Could it be interesting to do the same for silverlight framework dll ?
    -> System.ServiceModel.dll
    -> System.core.dll

    By that way, is the xap file would be smaller ?

    I think it's my last newbie question :)

    Else, it's working fine ! Thx for your precious time !

    ReplyDelete
  9. There is no need to cache Silverlight core assemblies since they are installed on client when Silverlight plugin is installed :).
    Hope that helps ;).

    ReplyDelete
  10. xD yep it helps a lot ^^

    i've forgotten that clients already get the plugin ^^

    thanks again and have a nice end of week :)

    ReplyDelete
  11. One Question : Do I need to have my assembly strongly named ?

    ReplyDelete
  12. Hi,

    I am using 3rd party infragistic dll in my silverlight 3 project. I see that it does not create the respective zip file to be used for application library caching feature. Is there any way to implement that?

    ReplyDelete
  13. @Imran,

    Of course! You need to manually create extmap.xml file in the same folder where .dll is and add reference to that .dll. Refer to links in blog post for more information on manually creating extmap.xml file.

    ReplyDelete