Thursday, 17 February 2011

SharePoint 2010 Silverlight Web Part JavaScript Bridge

SharePoint 2010 Silverlight Web Part JavaScript Bridge

Overview
This template contains base classes and scripts enabling Silverlight web parts (and ASP.Net web parts) to be created enabling client-side interaction with other Silverlight Web Parts. A JavaScript file is injected into the page automatically and allows Web Parts to register themselves for interaction with the bridge. If only Silverlight to Silverlight communication is required, local messaging could be used as an alternative mechanism, however this technique allows interaction from both Silverlight and ASP.Net web parts which is more flexible for SharePoint applications.  A Web Part using the base classes has the following properties required for JS Bridge connection:

  • JSClientID - Used to pass the JavaScript Bridge ClientID from the SharePoint UI to the Web Part. JSClientID is a simple identifier for components connecting to the JS Bridge.
  • JSClientSourceID - Used to pass the JavaScript Bridge ClientSourceID from the SharePoint UI to the Web Part. JSClientSourceID indicates to the JS Bridge where a components connection is sourced.
  • JSUniqueClientID - JSClientSourceID indicates to the JS Bridge the real ID of the component on the page. It is derived from the WebParts’s ClientID with an ‘SL’ suffix.
 
Registering Clients
When a JS Bridge Web Part loads, it registers itself with the JS Bridge using the registerClient method, this allows the bridge to locate the WebPart on the page and lets it know where to route data.

Installing
The package can be deployed straight to a local SharePoint 2010 server from Visual Studio 2010. The feature should appear in the default site collection features list:


Testing
To test the functionality, simply place 2 instances of the demo web part on a page. The demo web part is designed so one instance can talk to another instance of itself but normally different web parts would talk to each other.
The first web part can be configured as follows:

    The second web part can be configured as follows:


    Using the Silverlight UserControlBase Class
    Obviously the contents of the base class can be copied to a user control, but to implement it as a base for a user control the following steps must be taken:

    Application Manifest
    The ‘ExternalCallersFromCrossDomain’ attribute must be set to ‘ScriptableOnly’ to allow applications hosted on a different site to the SharePoint site (cross-domain) to access the DOM; otherwise the JSBridge will not work. This can be a security risk particularly for public facing sites, so it's best to host the XAP in SharePoint.


    <Deployment xmlns="http://schemas.microsoft.com/client/2007/deployment"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            ExternalCallersFromCrossDomain="ScriptableOnly" >
        <Deployment.Parts>
        </Deployment.Parts>
    </Deployment>

    AssemblyInfo
    The following attribute must be included in the AssemblyInfo file so that the UserControlBase can be implemented. The ‘System.Windows.Markup’ namespace needs referencing for this.


    [assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "WebberCross.JavaScriptBridge.SilverlightApplication11")]



    Calling  JSBridgeSend
    The example shows how an object can easily be JSON serialized then sent to the JS Bridge where it will be multi-cast to all registered web parts with a matching JavaScriptClintSourceID

                            
    // Send a message to the bridge
    DemoMessage msg = new DemoMessage("Hello from Silverlight Application", base._jsClientID.ToString());
    string jsonMsg = JSONHelper.Serialize(msg);
    base.JSBridgeSend(jsonMsg);


    Overriding JSBridgeReceive
    The example shows how to override the 'JSBridgeReceive' method to deserialize the sent object:

                            
    // Override base JSBridgeReceive method
    public override void JSBridgeReceive(string arg)
    {
        try
        {
            // Deserialize message
            DemoMessage msg = JSONHelper.Deserialize<DemoMessage>(arg);

            // Write message to label
            this.lbl3.Text = string.Format("{0}, from JSBridge Client {1}", msg.Message, msg.JSClientID);
        }
        catch (Exception ex)
        {
             MessageBox.Show(ex.ToString());
        }
    }



    Conclusion
    The JavaScript Bridge is a great way of enabling Silverlight web parts to interact with each other in the browser, it also allows Silverlight web parts to be communicated with from a web page. The base classes provide a quick way of getting standard behavior in sets of web parts.

    8 comments:

    1. Hi, your javascript bridge solution is looking really promising for a problem I am facing with communication between a Silverlight and ASP.NET web part on a Sharepoint 2010 site. But I can't figure out how to implement your solution correctly. I've downloaded the source from Codeplex and ran the project with the JSBridgeDemoApp as the startup project but when I click the button in the web part I just get an error.

      Could you give me a few steps to follow on what to do with the source to get it up and running.
      Thanks!
      Anthony

      ReplyDelete
    2. You need to deploy the package to SharePoint, then add 2 of the deployed web parts to a page, then configure them as described in this article. Let me know how you get on.

      Cheers

      ReplyDelete
    3. I get as far as adding the web parts to the page. For the configuration of the web parts, I have set the ID the same way you have in the images, for the XAP source are you setting that to point at the JSBridgeDemoControl? Do you have to upload it separately?

      ReplyDelete
    4. The XAP source is the XAP's url, it could be in a website, but I put it in a list (I can't remember whether the feature puts it in a list for you?) so it's the url of the xap in the list.

      ReplyDelete
      Replies
      1. <?xml version="1.0" encoding="utf-8"?>
        <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
        <Module Name="XAP" Url="Lists/WebberCross.JavaScriptBridge" >
        <File Path="XAP\JSBridgeDemoApp.xap" Url="JSBridgeDemoApp.xap" Type="GhostableInLibrary" IgnoreIfAlreadyExists="True" />
        </Module>
        </Elements>

        ...XAP should be here: Url="Lists/WebberCross.JavaScriptBridge"

        Delete
    5. I went to that url on my server and it showed the JSBridgeDemoApp XAP file alright. So I put the url to it in the XAP source. Both web parts now display the silverlight Loading image that is at 100% but the control does not actually load and if I click the "Call JS Bridge from Web Part" button I get a null control error in the JSBridgeSend function.

      ReplyDelete
    6. are you using localhost or the server dns name in the url? What version of SL are you using? There might be compatibility issues with sp2010 and sl5

      ReplyDelete
    7. I'm using the server dns name. Its silverlight 4. I'll look into it more, I'm probably missing something small along the way.
      Thanks for all the help so far Geoff

      ReplyDelete