Peter McGrattan’s Weblog

Silverlight, WCF, ASP.NET, AJAX, Graphics, RIA

Silverlight Initialization via the ASP.NET Silverlight Server Control

Posted by petermcg on July 16, 2008

Edited on 20/October/2008 : Code download updated to support Silverlight 2 RTW

(Code download)

This post takes a look at the ASP.NET Silverlight server control and what it renders as markup in response to a web request when added to an ASP.NET page.  It then digs deeper to explore how this markup describes the Silverlight plug-in and how this rendered plug-in is itself initialized in the Microsoft ASP.NET AJAX client framework.  This post also shows how to specify and retrieve Silverlight initialization parameters when using the server control.

The ASP.NET Silverlight Server Control

The Silverlight control is one of two ASP.NET server controls included in the Silverlight 2 Beta 2 SDK; the other is the MediaPlayer control which actually inherits from the Silverlight control.  The control provides an easy way to include Silverlight content in a new or existing ASP.NET Web page using the familiar ASP.NET server control model.  The control is available in the System.Web.Silverlight.dll assembly located under %ProgramFiles%\Microsoft SDKs\Silverlight\v2.0\Libraries\Server in the System.Web.UI.SilverlightControls namespace.  The Silverlight content to be executed by the plug-in this control ultimately renders can be specified by setting the value of the Source property to a URI either to a XAML file or in Silverlight 2 a compiled Silverlight application (a .xap file):

<asp:Silverlight ID="Xaml1" runat="server" Source="~/ClientBin/InitParameters.xap"
                 MinimumVersion="2.0.30523" Width="100%" Height="100%" />

The Silverlight server control requires access to a ScriptManager control (generally on the same page) otherwise an InvalidOperationException will be thrown at runtime when the control initializes.

Rendered Markup and the ASP.NET AJAX Client Framework

When rendered to the output stream as part of an ASP.NET page it is declared in, the Silverlight server control delivers four additions to the markup eventually interpreted by the browser.  The first addition the control renders is a JavaScript script block under the html <body> tag with it’s src property set to a path that includes the string "ScriptResource.axd":

<script src="/InitParametersWeb/ScriptResource.axd?d=wMEjThkBoZWGT...;t=633481889860000000"
        type="text/javascript"></script>

This resource is requested by the Silverlight server control in it’s implementation of the IScriptControl interface.  When this script block is encountered as the html page loads a GET request is made to resolve the path assigned to the src property; because the path includes the string "ScriptResource.axd", the request is handled by an instance of the ScriptResourceHandler class as mapped in the default web.config file under the httpHandlers element:

<httpHandlers>
    <add verb="GET,HEAD"
       path="ScriptResource.axd"
       type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0,
             Culture=neutral, PublicKeyToken=31BF3856AD364E35"
       validate="false"/>
</httpHandlers>

The ScriptResourceHandler class implements the IHttpHandler interface in a way that handles request processing for script files that are embedded as resources in an assembly.  In this case the handler eventually resolves the path to a gzip compressed version of either the SilverlightControl.js or SilverlightControl.debug.js JavaScript file (depending on the ScriptMode property of the required ScriptManager control and in turn on the compilation mode in web.config) embedded in the System.Web.Silverlight.dll assembly:

System.Web.Silverlight Resources

It’s the JavaScript code in this file that (amongst other things) registers the Sys.UI.Silverlight ASP.NET AJAX client namespace, the definition of the Sys.UI.Silverlight.Control client component class (with Sys.UI.Control as the base class) and the definition of a method called createObject.

The second addition to the markup is a html <span> element:

<span id="Xaml1_parent"></span>

This <span> element is referenced in the third piece of markup the Silverlight server control renders. Another JavaScript script block, this time with some in-line code that calls the previously defined createObject method:

<script type="text/javascript">

//<![CDATA[

Sys.UI.Silverlight.Control.createObject('Xaml1_parent', '<object 
type="application/x-silverlight-2-b2" data="data:application/x-silverlight-
2-b2," id="Xaml1" style="height:100%;width:100%;">\r\n\t<param
name="MinRuntimeVersion" value="2.0.30523">\r\n\r\n\t</param><a
href="http://go2.microsoft.com/fwlink/?LinkID=114576&amp;v=2.0"><img
src="http://go2.microsoft.com/fwlink/?LinkID=108181" alt="Get Microsoft
Silverlight" style="border-width:0;" /></a>\r\n</object>'
); //]]> </script>

The createObject method takes two parameters here, the first is a string specifying the id of a parent element (the <span>) the second parameter is a string containing html markup for the Silverlight plug-in using the <object> element. The body of the createObject method finds the parent element on the page using the id in the first parameter and sets it’s innerHtml property to be the second parameter. When the innerHTML property is set, the <object> element becomes the content of the <span> element resulting in the object tag describing the Silverlight plug-in becoming part of the browser’s DOM.

The fourth and final markup snippet rendered by the ASP.NET Silverlight server control is the in-line JavaScript script statement shown below:

Sys.Application.add_init(function() {
    $create(Sys.UI.Silverlight.Control, {"source":"ClientBin/InitParameters.xap"},
            null, null, $get("Xaml1_parent"));
});

This script statement adds an anonymous JavaScript function as an event handler for the init event of the Sys.Application client object defined by ASP.NET AJAX. Handlers for this init event are executed after the DHTML window object’s onload event and after the ASP.NET AJAX runtime has been initialized.  The body of this anonymous function contains a single statement that invokes the $create alias defined by the Microsoft ASP.NET AJAX library in the MicrosoftAjax.js or MicrosoftAjax.debug.js JavaScript file embedded in the System.Web.Extensions.dll assembly.

The $create alias is just an convenience for calling the Sys.Component.create function which performs a number of steps.  It creates an instance of the Sys.UI.Silverlight.Control client class within the ASP.NET AJAX client framework as a visual component associated with the span element (this association is required for visual controls) returned as the last parameter from the call to the $get alias. Crucially it sets the value of the ‘source’ property on this component instance to the .xap file using the key/value object literal generated from the server control ‘Source’ property and passed as the second parameter.  It calls the initialize method inherited from the base Sys.UI.Control class on the component instance and finally stores a reference to the instance as a child component of the global Sys.Application object via it’s addComponent method.

At this stage I believe the Silverlight-plug-in, now part of the browser DOM and registered as a visual component in the Microsoft ASP.NET AJAX client framework with it’s source property set to the .xap file, performs the following steps outlined in the Silverlight 2 Beta 2 documentation:

"…starts the common language runtime (CLR) and creates an application domain for the Silverlight application to run in. Downloads the application package, works with the Silverlight runtime to create an execution environment for the Silverlight application, and loads the assemblies and resource files included in the application package. The next step is to instantiate the application class to start the application running."

The Silverlight Application Class

Several of Microsoft’s API’s follow a similar pattern of having an instance of an Application type as the entry point into the program. The client-side ASP.NET AJAX framework, the ASP.NET server-side framework, WPF and Silverlight 2 all employ this pattern. The Application class is the one class that every Silverlight application must implement.  When you create a ‘Silverlight Application’ using the default Visual Studio 2008 template, the Application class is inherited by the ‘App’ class defined in the App.xaml and App.xaml.cs files.  It’s the instance of this App class that initializes and starts the main UI of the Silverlight Application by creating an instance of the Page class (defined in Page.xaml and Page.xaml.cs) and assigning it to the RootVisual property.

Initialization Parameters

To specify initialization parameters to Silverlight from a basic Html page the options are to either set the initParams parameter to a correctly formatted string using JavaScript against the Silverlight plug-in’s object model, or to set the value of a <param> element named InitParams to the same formatted string under the Silverlight plug-in’s <object> tag using Html.  The formatted string should match the pattern : "key1=value1,key2=value2,key3=value3".

The same functionality can be achieved when hosting Silverlight using the ASP.NET Silverlight server control by setting the server-side InitParameters property to the exact same formatted string.  The InitParameters server control property is of type string, is stored in ViewState, and can be set in markup and code-behind; it’s important that this string is in the expected format to ensure the parameters make it to Silverlight.  When a Silverlight server control with it’s InitParameters property set ultimately renders itself, the string is appropriately escaped and passed on to become the value of a <param> element named InitParams inside the generated Silverlight plug-in <object> element.

The key/value pairs in this formatted string are parsed into an IDictionary<string, string> and are able to be retrieved in Silverlight 2 in the StartupEventArgs.InitParams property (e.InitParams) in an event handler for the Application.Startup event:

Application Startup with Parameters

The sample visual studio solution available for download above demonstrates how to specify initialization parameters in both markup and code behind on a Silverlight ASP.NET server control and how to retrieve those parameters in an event handler for the Silverlight Application.Startup event.  The sample also demonstrates passing the parameters on to an instance of the Page class to be displayed in a DataGrid.

Advertisements

14 Responses to “Silverlight Initialization via the ASP.NET Silverlight Server Control”

  1. Hello Peter,

    thanks for the great post !

    About the Silverlight Server Control, is there a way to let it render Silverlight 2.0 XAML without using a .xap file ? When I use :

    asp:Silverlight Source=”~/InlineButton.xaml” ID=”Silverlight1″ runat=”server” MinimumVersion=”2.0.30523″ Width=”200″ Height=”100″

    I get an error : “Invalid XAML for control …: Unknown element:Button.”

    When I limit the content of InlineButton.xaml to Silverlight 1.0 XAML everything works fine.

    greetings, Stefaan

  2. Peter McGrattan said

    Hi Stefaan,

    The default programming model available to XAML in absence of a specified ‘x:Class’ is unmanaged script (Silverlight 1.0) which is why ‘everything works fine’ when you stick to Silverlight 1.0 XAML code even though you’ve set MinimumVersion=”2.0.30523″.

    To use Silverlight 2 you would need to specify a ‘x:Class’ in the XAML file that points to a type that derives from the managed Application class to be used as the entry point. This type would however exist in a complied managed assembly and would need to be deployed to the client via a .xap package specified in the Source property when using the server control.

    To use Silverlight 2 types such as Button (in the System.Windows.dll managed assembly), set the Source property on the Silverlight server control to a .xap package. Note also that you should only specify a .xap package as the value for the Source property if the MinimumVersion property is at least 2.0.

    Regards,

    Peter

  3. Thanks Peter,

    that answers my question. It seems that what I was trying to do (use the new SL 2.0 controls but script them with browser javascript, like in the SL 1.0 model) is not possible. Scripting SL 2.0 controls seems only to be possible with the managed DLR-based scripting languages in combination with the .xap packages.

    greetings from Norway, Stefaan

  4. Pete Hurst said

    Obvious question, but one I’ve not seen the answer to.

    How do I place a comma in one of my InitParameter values? Is there an escape sequence for this?

    Thanks in advance.

  5. Peter McGrattan said

    Hi Pete,

    Apologies for the delay in getting back to you, I’ve been on holiday for the last two weeks. I had a quick look at this when I was writing the sample code and the short answer is that I couldn’t find an escape sequence that worked. The easiest option would be to use another character such as a semi-colon.

    Another option for passing startup parameters to Silverlight is using the Query String params accessed via the Html bridge. This post by Tim Heuer may be of interest to you :

    http://timheuer.com/blog/archive/2008/07/17/setting-startup-parameters-for-silverlight.aspx

  6. Frank Patton said

    Am having a hard time with this .. LOL

    Lets say I have a classic ASP Website .. Master page .. 10 separate content pages .. and I want to put a different silverlight control on each of the ten pages (10 different controls in all) and an 11th control for a master page..

    Is it possible?

    Do I need 11 (Total) silverlight projects, each with its own xap file?

  7. Peter McGrattan said

    Hi Frank,

    If only one Silverlight application will be shown to the user at a time, I would advise having one Silverlight control on the Master Page. In the Page_Load event handler of each content page you could then set the Source property of the control on the Master Page to point to a different .xap file if required. You could also manipulate the InitParameters property at this stage to pass any content-page specific settings through to the Silverlight application.

    I have put together a basic demo of this with one content page and one .xap file only here.

    Regards,

    Peter

  8. Goving Rajan said

    I am using SL 1.0 and having a MediaPlayer control playing a video. I am using script manager. this is my aspx code.

    I have a button and need from a javascript code to do a replay, I need reach the media control and call the Play method.

    What the javascript to write to do this? any help would be appreciated thanks…

  9. Goving Rajan said

    re-put back the aspx code, add spaces to the tags so it can be posted.

    let me know if you need more info.
    Thanks
    Govind

  10. Goving Rajan said

    another try removed all the greater and less operators.

    div id=”divPlayer_0″
    asp:ScriptManager ID=”ScriptManager1″ runat=”server”
    asp:MediaPlayer ID=”MyPlayer” runat=”server” Height=”400px” MediaSkinSource=”~/webelements/player.xaml” Width=”480px” AutoPlay=”true” OnClientMediaEnded=”mediaEnded”
    asp:MediaPlayer
    div

    one more try!

  11. Peter McGrattan said

    Hi Goving Rajan,

    The best place to get an answer to your question is the silverlight.net forums.

    Hope this helps,

    Peter

  12. John said

    most helpfull blog.

  13. Bitnbytes said

    You can easily pass commas in values are well. Instead of using comma, just use URL encoded value of it. You can look at this post for more information.
    How to supply startup parameters to Silverlight applications.

  14. nice blog to dig silverlight deeper

Sorry, the comment form is closed at this time.

 
%d bloggers like this: