Silverlight for the Enterprises - Fundamentals

Delivering business processing logic through RIA (Rich Internet Application) format is very attractive to architects, developers and operators of IT shops. RIA combines the richness of the desktop application with the ease of deployment, ubiquity and platform independence of the web application.  RIAs in the form of mashups, are very popular in the consumer space but have yet to see similar success in the enterprise space. Enterprise applications are stateful and process-centric in nature. These applications operate in a logically trusted environment and ensure that the information is secure while in flight and at rest. Enterprise class applications require granular partitioning of programming logic that can originate from multiple web domains accessing services and resources hosted on multiple networks and domains.

Silverlight being the new RIA platform from Microsoft, there is very little material out on the Internet that focuses on the above enterprise aspects. So,  I will be writing a few blog posts that address the enterprise needs. Most Silverlight samples I found on Internet are deployed as a monolithic package that can be few megabytes in size for non trivial applications and can take long time to download on slow networks.  In the initial post, I will focus on some fundamentals and subsequently will write on application partitioning through multiple packages deployed on the same web server as well as cross-domain scenarios.

In order to reduce the Silverlight plug-in size, it is packaged into core runtime and the SDK libraries. The core runtime is installed as a part of the plug-in installation while the SDK libraries will be downloaded as a part of the application package (with extension .XAP). The number of the SDK DLLs contained inside the application XAP will be based on the dependency of the application code on the SDK.

For example, if the application does not program in DLR (Dynamic Language Runtime) languages to Iron Ruby, the Ruby language DLL will never be downloaded to the client. In light of this, it is absolutely important to make sure to trim the DLL references in the Silverlight project so that the package will not bloat unnecessarily.  Here is a simple dependency diagram of a Silverlight application contained inside InventoryManager.xap package:

sl2_001

Silverlight core runtime libraries

The core runtime contains the following managed assemblies (as of beta1):

  • System.dll
  • System.Windows.Browser.dll
  • System.Core.dll
  • System.Xml.dll
  • System.Net.dll
  • System.Windows.dll
  • Microsoft.VisualBasic.dll
  • System.Runtime.Serialization.dll
  • System.ServiceModel.dll
  • System.ServiceModel.Web.dll

Silverlight SDK libraries

The SDK libraries are optional and will be included in the package (XAP) based on the usage. The following is the list of SDK libraries as of beta1:

  • IronPython.dll
  • IronPython.Modules.dll
  • IronRuby.dll
  • IronRuby.Libraries.dll
  • Microsoft.JScript.Compiler.dll
  • Microsoft.JScript.Runtime.dll
  • Microsoft.Scripting.dll
  • Microsoft.Scripting.Silverlight.dll
  • System.ServiceModel.Syndication.dll
  • System.Windows.Controls.Data.Design
  • System.windows.Controls.Data
  • System.Windows.Controls.Design
  • System.Windows.Controls.dll
  • System.Windows.Controls.Extended.dll
  • System.Xml.Linq.dll
  • System.Xml.Serialization.dll
  • System.Xml.Utils.dll

If the Silverlight application does not program in Iron Ruby, the IronRuby.dll and IronRuby.Libraries.dll will not be included in the package. Likewise WaterMarkedTextBox is a part of the System.Windows.Controls.Extended.dll and should be taken out of the project references if none of the controls contained in this assembly are needed.

Silverlight Package

Silverlight application will be packaged into a compressed archive with an extension .XAP. The XAP file is a standard ZIP file and the contents can be viewed by renaming it to .ZIP and opening it in Windows file explorer.  Following is are the contents of the InventoryManager.xap (or InventoryManager.zip after renaming):

  • AppManifest.xaml
  • InventoryManager.dll
  • System.Windows.Controls.dll (included from the SDK library list)

The AppManifest.xaml will contain a list of included assemblies in the package. This will help enumerate this list using AssemblyPart and Deployment classes. Following is the sample code to load an assembly from a package stream:

 

//code not meant for production use

public class PackageUtil

{

   public static Assembly GetAssemblyFromXAP(Stream packageStream, string assemblyName)

   {

   StreamResourceInfo riManifest =

                Application.GetResourceStream(new StreamResourceInfo(packageStream, null),

                        new Uri("AppManifest.xaml", UriKind.Relative));

      string appManifestString = new StreamReader(riManifest.Stream).ReadToEnd();

      Deployment deployment = (Deployment)XamlReader.Load(appManifestString);

      Assembly asm = null;

  foreach (AssemblyPart assemblyPart in deployment.Parts)

  {

         if (assemblyPart.Source == assemblyName)

         {

            StreamResourceInfo streamInfo =

            Application.GetResourceStream(

            new StreamResourceInfo(packageStream, "application/binary"),

            new Uri(source, UriKind.Relative));

            asm = assemblyPart.Load(streamInfo.Stream);

            break;

         }

      }

      return asm;

    }

}

The XAP archive can be built by hand using a program called Chiron.exe that is installed as a part of the SDK in the following directory on the developer workstation:

C:\Program Files\Microsoft SDKs\Silverlight\v2.0\Tools\Chiron\Chiron.exe.

The Syntax for building XAP using Chiron: 

Chiron.exe /xap:InventoryManager.xap /directory:InventoryManager

Please keep in mind that Chiron does not compile XAML; it just packages the content into a .XAP file. Chiron will be useful if you need to combine more than one Silverlight IDE project outputs into a single XAP file. However, if you don't need to combine multiple projects, you can be content with the IDE build process.

In beta1, IDE is the only way to build the Silverlight project; the automated team builds will be supported in subsequent beta releases.

Deployment

Here are a few simple steps to deploy the Silverlight package to a target web server:

  1. Create ClientBin directory if doesn't exist in the target virtual directory and copy XAP file.
  2. Add application/x-silverlight-app MIME type to the virtual directory's MIME Types list.
  3. Modify and copy the HTML/aspx page(that was generated when the project was created using Silverlight Application VS2008 template to the target virtual directory. 

If the target web server is not IIS, the steps pretty much remain same except the format of the hosting web page. The web page may contain HTML or other platform specific web markup.

Having covered some fundamentals, we will look at our first main topic of application partitioning in the next post. We will compose UI from multiple XAPs with the help of PackageUtil (shown above) and SLPackage shown below:

 

    //code not meant for production use

public class SLPackage

    {

        private Uri _packageUri;

        public class PackageEventArgs:EventArgs

        {

            private Stream _packageStream;

            private string _packageUri;

            public PackageEventArgs(Stream packageStream, string packageUri)

            {

                this._packageStream = packageStream;

                this._packageUri = packageUri;

            }

            public Stream PackageStream { get { return _packageStream; } }

            public String PackageUri { get { return _packageUri; } }

        }

        public delegate void PackageEventHandler(object sender, PackageEventArgs e);

        public event PackageEventHandler PackageDownloaded;

        public SLPackage(Uri uri)

        {

            _packageUri = uri;

        }

        public void LoadPackage()

        {

            WebClient webClient = new WebClient();

            webClient.OpenReadCompleted += new

                        OpenReadCompletedEventHandler(webClient_OpenReadCompleted);

            webClient.OpenReadAsync(_packageUri);

        }

        private void webClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)

        {

            PackageEventArgs pe = new PackageEventArgs(e.Result,this._packageUri.OriginalString);

            PackageDownloaded(this, pe);

        }

    }

PackageUtil and SLPackage will hide the XAP downloading from the application code. We will add more code to the above two classes and use reflection to create instances of UserControl, load the controls into the visual tree and transfer state information to complete the composition.

 

Cheers,

Hanu