Home > Articles > Web Development > ASP.NET

This chapter is from the book

Connecting Web Parts

A cool feature of SharePoint web parts is the ability to connect them together. This allows business users to compose their own mash-ups and dashboards of related information. For example, a master/detail display could allow users to select an item in one web part and then see details and related information in other web parts on the page. The only thing is that SharePoint's web part connections run on the server, so a page refresh is required to update the connected web parts.

In this section, you will learn to build Silverlight web parts that can be connected, but since Silverlight runs on the client, the update will be immediate with no need for a page refresh. The strategy to do this is to use a SharePoint server-side web part connection to broker a direct Silverlight connection on the web page. Figure 5.15 shows the web parts in the ConnectedWebParts sample in the code download. When the web parts are connected, anything that's typed into the source web part also appears in one or more connected target web parts.

Figure 5.15

Figure 5.15 Connected web parts

You can try this on your development machine if you place the two web parts on the page. Edit either web part; then pull down the same drop-down next to the web part title you used to edit the web part. This time, a Connections choice appears to let you connect the web parts as shown in Figure 5.16.

Figure 5.16

Figure 5.16 Connecting SharePoint web parts

Fortunately, SharePoint allows developers to create any kind of connection they like. In this case the connection is called ISilverlightConnection, and it defines a simple registration method for web parts that wish to connect. Listing 5.10 shows the interface.

Listing 5.10. The ISilverlightConnection Interface

    public interface ISilverlightConnection
    {
        void RegisterReceiver(string receiverName);
    }

The ConnectionSource Web Part implements the ISilverlightConnection, and ConnectionTarget consumes it. The strategy is for each ConnectionTarget to register a unique receiver name by calling the RegisterReceiver() method in the source. Both web parts then pass the receiver name to their corresponding Silverlight applications, which can then use Silverlight's messaging API to send messages. The ConnectionSource web part is capable of handling several receiver names if multiple target web parts are connected; go ahead and try this if you like. This is shown in Figure 5.17.

Figure 5.17

Figure 5.17 Brokering Silverlight communication with a server-side connection

Using Silverlight in Composite Controls

The sad truth is that sandboxed solutions don't allow web part connections, and the Silverlight SharePoint Web Parts used earlier in this chapter use a sandboxed solution. To handle this, the web parts are written from scratch. A Visual Web Part would work, but this is a good opportunity to show you how to use Silverlight in composite controls, as explained in Chapter 2, "Introduction to SharePoint Development." These concepts are used in other web parts later in the book as well as in editor parts, where a visual solution is not available. It's also used in a navigation control in Chapter 13, "Creating Silverlight Navigation," and a field control in Chapter 15, "Creating a Silverlight Field Control," where, again, a composite control is the only option.

Beginning with a farm solution, each web part was added as a simple, nonvisual web part. As you recall from Chapter 2, instead of using a design surface containing ASP.NET controls and HTML, child controls are added in code by overriding a method called CreateChildControls().

To facilitate placing Silverlight on the page, a new SilverlightPlugin web control has been provided in the code download. It contains the same Javascript error handler and <object> tag as the standard Silverlight test page, which you might have noticed in the Custom Silverlight Visual Web Part. This time they're in string constants that contain tokens such as {0} and {1} that hold values for the source, InitParams, and other properties. CreateChildControls() fills in the tokens and adds both the Javascript and <object> tag to the page, as shown in Listing 5.11.

Listing 5.11. CreateChildControls() in the SilverlightPlugin Control

private const string SILVERLIGHT_EXCEPTION_SCRIPT_BLOCK = @"
    <script type=""text/javascript"">
    function {0}Error (sender, args) {{

    // Boilerplate error handler goes here, same as in any Silverlight
    // web page. The full code is in the code download.

    </script>";

private const string SILVERLIGHT_OBJECT_TAG = @"
  <div style=""overflow-x: hidden; position:relative; width:{0};
       height:{1}"">
    <object data=""data:application/x-silverlight-2,""
       type=""application/x-silverlight-2"" width=""{0}"" height=""{1}"">
       <param name=""source"" value=""{2}""/>
       <param name=""onError"" value=""{3}Error"" />
       <param name=""background"" value=""white"" />
       <param name=""minRuntimeVersion"" value=""4.0.50401.0"" />
       <param name=""initparams"" value=""{4}"" />
       <param name=""autoUpgrade"" value=""true"" />
        <!-- Rendering for browsers without Silverlight follows -->
       <!-- The code download contains the full code for this →
    </object>
    <iframe id=""_sl_historyFrame""
      style=""visibility:hidden;height:0px;width:0px;border:0px"">
    </iframe>
  </div>";

protected override void CreateChildControls()
{
    base.CreateChildControls();

    if (Source != null && Source != "")
    {
        // Ensure we have set the height and width
        string width = (this.Width == Unit.Empty)
                           ? "100%" : this.Width.ToString();
        string height = (this.Height == Unit.Empty)
                           ? "100%" : this.Height.ToString();

        // Render error handling script
        this.Controls.Add(new LiteralControl(
        String.Format(SILVERLIGHT_EXCEPTION_SCRIPT_BLOCK,
            this.ClientID)));

        this.Controls.Add(new LiteralControl(
        String.Format(SILVERLIGHT_OBJECT_TAG, width, height, this.Source,
            this.ClientID, this.InitParameters)));
    }
}

It's important to ensure the Height and Width properties are set on the Silverlight <object> tag, as they both default to zero. Leaving them out will result in a 0x0 pixel Silverlight application that won't show on the page at all.

It would be typical to add Javascript to the page by calling Page.RegisterClientScriptBlock(), but this would preclude using the SilverlightPlugin control in sandboxed solutions in the future because the sandbox does not allow access to the Page object. Instead, the web part's clientID property, which is guaranteed to be unique on the page, is used to make the error handler's method name unique, and the script is generated inline, as in the Silverlight Custom Visual Web Part.

The SilverlightPlugin control shows up in other solutions later in this book in standard (nonvisual) web parts as well as editor parts and navigation and field controls. It makes writing composite controls with Silverlight easy and encapsulates the details about placing Silverlight on the page.

Making the Connection

Listing 5.10 shows the ISilverlightConnection interface used to connect the web parts in this example. The provider (ConnectionSource) web part implements the interface, and the consumer (ConnectionTarget) web part makes use of the interface. In SharePoint the connection provider always implements the interface; in this case, the consumer calls the provider's RegisterReceiver() method, but event handlers are often used to allow information to flow from provider to consumer.

Listing 5.12 shows the ConnectionSource web part. The [ConnectionProvider] attribute tells SharePoint that the connection is available, and the ConnectionInterface() method hands SharePoint an object that implements the ISilverlightConnection interface. Because this web part only supports one kind of connection, the easiest approach is for the web part itself to implement the interface and pass itself back in this method. If you ever want to implement more than one kind of connection provider in a single web part, you'll find yourself having to implement a separate class for each interface and manage them in your web part.

Listing 5.12. ConnectionSource Web Part Implements a Connection Provider

public class ConnectionSource : WebPart, ISilverlightConnection
{
    // Register with SharePoint as a connection provider
    // The provider name will appear in the connection message, as
    // in, "Send Keystrokes To"
    [ConnectionProvider("Keystrokes")]
    public ISilverlightConnection ConnectionInterface()
    {
        return this;
    }

    // ISilverlightConnection members
    void ISilverlightConnection.RegisterReceiver(string receiverName)
    {
        EnsureChildControls();

        if (silverlightPlugin.InitParameters == null ||
            silverlightPlugin.InitParameters == "")
        {
            silverlightPlugin.InitParameters = "SendOn=" + receiverName;
        }
        else
        {
            silverlightPlugin.InitParameters += "" + receiverName;
        }
    }

    private SilverlightPlugin silverlightPlugin;
    protected override void CreateChildControls()
    {
        base.CreateChildControls();

        silverlightPlugin = new SilverlightPlugin();
        silverlightPlugin.Source = SPContext.Current.Site.Url +
            "/ClientBin/SLConnectionSource.xap";

        this.Controls.Add(silverlightPlugin);
    }
}

The RegisterReceiver() method begins by calling EnsureChildControls(), which is a method in all ASP.NET controls that checks to see if CreateChildControls() has been called and calls it if it wasn't. That way, the code that follows can be sure that the SilverlightPlugin control has been created.

The code passes the receiver name to its Silverlight application using its InitParam property. This is standard operating procedure in Silverlight: If you want to pass one or more values to Silverlight, place them in the InitParam property in the format name1=value1, name2=value2 and the Silverlight application is presented with a dictionary object containing the name-value pairs in its application startup event. In later chapters you learn how to pass more complex data in a hidden form field on the web page and to pass a reference to the form field in InitParam; for now the receiver name(s) can go in directly. The code uses the convention of a semicolon to separate receiver names, so as more target web parts register themselves the receiver names are simply appended to the InitParam value.

Listing 5.13 shows the ConnectionTarget web part, which registers as a connection consumer. Instead of implementing a method decorated with the [ConnectionProvider] attribute, this web part includes a [ConnectionConsumer] attributed method. As you can see, it uses its own client ID, which is sure to be unique and HTML-safe, as the receiver name, and it registers with the provider and also passes the same ID to its Silverlight application.

listing 5.13. ConnectionTarget Web Part Implements a Connection Consumer

public class ConnectionTarget : WebPart
{
    // Register with SharePoint as a connection consumer
    // The consumer name will appear in the connection message, as
    // in, "Get Keystrokes From"
    [ConnectionConsumer("Keystrokes")]
    public void GetConnectionInterface
        (ISilverlightConnection providerPart)
    {
        providerPart.RegisterReceiver(this.ClientID);
        EnsureChildControls();
        silverlightPlugin.InitParameters = "ReceiveOn=" +
            this.ClientID;
    }
    SilverlightPlugin silverlightPlugin;

    protected override void CreateChildControls()
    {
        base.CreateChildControls();

        silverlightPlugin = new SilverlightPlugin();
        silverlightPlugin.Source = SPContext.Current.Site.Url +
            "/ClientBin/SLConnectionTarget.xap";

        this.Controls.Add(silverlightPlugin);
    }
}

Now both the source and target Silverlight applications have the receiver name, so they can communicate directly on the client. Listing 5.14 shows the Application_Startup event in the SLConnectionTarget application; as you can see it simply retrieves the list of receiver names from InitParams and passes them to the main page by setting a public property.

listing 5.14. The Application_Startup Event Passes InitParams to Main Page

private void Application_Startup(object sender, StartupEventArgs e)
        {
            MainPage page = new MainPage();
            this.RootVisual = page;

            if (e.InitParams.ContainsKey("SendOn"))
            {
                page.SendOnConnectionNames = e.InitParams["SendOn"];
            }
        }

The main page is extremely simple. It consists of a textbox, whose KeyUp event is hooked as shown in Listing 5.15. Each time the event fires, the content of the text box is sent to all receivers.

Listing 5.15. SLConnectionSource Sends Information on the KeyUp Event

internal string SendOnConnectionNames { get; set; }

private void messageTextBox_KeyUp(object sender, KeyEventArgs e)
{
    foreach (string receiverName in SendOnConnectionNames.Split(';'))
    {
        LocalMessageSender msgSender =
            new LocalMessageSender(receiverName);
        msgSender.SendAsync(messageTextBox.Text);
    }
}

The SLConnectionTarget Silverlight application's job is to listen on its receiver and display messages sent to it in a text box. It uses the same Application_Startup code to pass in the receiver name, but instead of sending the main page, it receives as shown in Listing 5.16.

Listing 5.16. SLConnectionTarget Receives and Displays Text

LocalMessageReceiver msgReceiver;

internal void SetupReceiver(string receiverName)
{
    msgReceiver = new LocalMessageReceiver(receiverName);

    msgReceiver.MessageReceived += (s, e) =>
        {
            Dispatcher.BeginInvoke(() =>
                {
                    this.messageTextBox.Text = e.Message;
                });
        };

        msgReceiver.Listen();
        this.StatusTextBlock.Text = "This web part is connected.";
}

The MessageReceived event handler is called whenever a new message is received and is implemented as an anonymous function as discussed in Chapter 3. In Silverlight, the user interface always needs to be updated on the UI thread, so a second anonymous function is passed Dispatcher.BeginInvoke(), which runs it on the UI thread. Anonymous functions are a big help with all the asynchronous activity in a Silverlight application.

The last thing to do is to listen on the event, by calling the Listen() method. Now any time a user types into the ConnectionSource web part, all connected ConnectionTargets are updated immediately with every key stroke.

InformIT Promotional Mailings & Special Offers

I would like to receive exclusive offers and hear about products from InformIT and its family of brands. I can unsubscribe at any time.

Overview


Pearson Education, Inc., 221 River Street, Hoboken, New Jersey 07030, (Pearson) presents this site to provide information about products and services that can be purchased through this site.

This privacy notice provides an overview of our commitment to privacy and describes how we collect, protect, use and share personal information collected through this site. Please note that other Pearson websites and online products and services have their own separate privacy policies.

Collection and Use of Information


To conduct business and deliver products and services, Pearson collects and uses personal information in several ways in connection with this site, including:

Questions and Inquiries

For inquiries and questions, we collect the inquiry or question, together with name, contact details (email address, phone number and mailing address) and any other additional information voluntarily submitted to us through a Contact Us form or an email. We use this information to address the inquiry and respond to the question.

Online Store

For orders and purchases placed through our online store on this site, we collect order details, name, institution name and address (if applicable), email address, phone number, shipping and billing addresses, credit/debit card information, shipping options and any instructions. We use this information to complete transactions, fulfill orders, communicate with individuals placing orders or visiting the online store, and for related purposes.

Surveys

Pearson may offer opportunities to provide feedback or participate in surveys, including surveys evaluating Pearson products, services or sites. Participation is voluntary. Pearson collects information requested in the survey questions and uses the information to evaluate, support, maintain and improve products, services or sites, develop new products and services, conduct educational research and for other purposes specified in the survey.

Contests and Drawings

Occasionally, we may sponsor a contest or drawing. Participation is optional. Pearson collects name, contact information and other information specified on the entry form for the contest or drawing to conduct the contest or drawing. Pearson may collect additional personal information from the winners of a contest or drawing in order to award the prize and for tax reporting purposes, as required by law.

Newsletters

If you have elected to receive email newsletters or promotional mailings and special offers but want to unsubscribe, simply email information@informit.com.

Service Announcements

On rare occasions it is necessary to send out a strictly service related announcement. For instance, if our service is temporarily suspended for maintenance we might send users an email. Generally, users may not opt-out of these communications, though they can deactivate their account information. However, these communications are not promotional in nature.

Customer Service

We communicate with users on a regular basis to provide requested services and in regard to issues relating to their account we reply via email or phone in accordance with the users' wishes when a user submits their information through our Contact Us form.

Other Collection and Use of Information


Application and System Logs

Pearson automatically collects log data to help ensure the delivery, availability and security of this site. Log data may include technical information about how a user or visitor connected to this site, such as browser type, type of computer/device, operating system, internet service provider and IP address. We use this information for support purposes and to monitor the health of the site, identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents and appropriately scale computing resources.

Web Analytics

Pearson may use third party web trend analytical services, including Google Analytics, to collect visitor information, such as IP addresses, browser types, referring pages, pages visited and time spent on a particular site. While these analytical services collect and report information on an anonymous basis, they may use cookies to gather web trend information. The information gathered may enable Pearson (but not the third party web trend services) to link information with application and system log data. Pearson uses this information for system administration and to identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents, appropriately scale computing resources and otherwise support and deliver this site and its services.

Cookies and Related Technologies

This site uses cookies and similar technologies to personalize content, measure traffic patterns, control security, track use and access of information on this site, and provide interest-based messages and advertising. Users can manage and block the use of cookies through their browser. Disabling or blocking certain cookies may limit the functionality of this site.

Do Not Track

This site currently does not respond to Do Not Track signals.

Security


Pearson uses appropriate physical, administrative and technical security measures to protect personal information from unauthorized access, use and disclosure.

Children


This site is not directed to children under the age of 13.

Marketing


Pearson may send or direct marketing communications to users, provided that

  • Pearson will not use personal information collected or processed as a K-12 school service provider for the purpose of directed or targeted advertising.
  • Such marketing is consistent with applicable law and Pearson's legal obligations.
  • Pearson will not knowingly direct or send marketing communications to an individual who has expressed a preference not to receive marketing.
  • Where required by applicable law, express or implied consent to marketing exists and has not been withdrawn.

Pearson may provide personal information to a third party service provider on a restricted basis to provide marketing solely on behalf of Pearson or an affiliate or customer for whom Pearson is a service provider. Marketing preferences may be changed at any time.

Correcting/Updating Personal Information


If a user's personally identifiable information changes (such as your postal address or email address), we provide a way to correct or update that user's personal data provided to us. This can be done on the Account page. If a user no longer desires our service and desires to delete his or her account, please contact us at customer-service@informit.com and we will process the deletion of a user's account.

Choice/Opt-out


Users can always make an informed choice as to whether they should proceed with certain services offered by InformIT. If you choose to remove yourself from our mailing list(s) simply visit the following page and uncheck any communication you no longer want to receive: www.informit.com/u.aspx.

Sale of Personal Information


Pearson does not rent or sell personal information in exchange for any payment of money.

While Pearson does not sell personal information, as defined in Nevada law, Nevada residents may email a request for no sale of their personal information to NevadaDesignatedRequest@pearson.com.

Supplemental Privacy Statement for California Residents


California residents should read our Supplemental privacy statement for California residents in conjunction with this Privacy Notice. The Supplemental privacy statement for California residents explains Pearson's commitment to comply with California law and applies to personal information of California residents collected in connection with this site and the Services.

Sharing and Disclosure


Pearson may disclose personal information, as follows:

  • As required by law.
  • With the consent of the individual (or their parent, if the individual is a minor)
  • In response to a subpoena, court order or legal process, to the extent permitted or required by law
  • To protect the security and safety of individuals, data, assets and systems, consistent with applicable law
  • In connection the sale, joint venture or other transfer of some or all of its company or assets, subject to the provisions of this Privacy Notice
  • To investigate or address actual or suspected fraud or other illegal activities
  • To exercise its legal rights, including enforcement of the Terms of Use for this site or another contract
  • To affiliated Pearson companies and other companies and organizations who perform work for Pearson and are obligated to protect the privacy of personal information consistent with this Privacy Notice
  • To a school, organization, company or government agency, where Pearson collects or processes the personal information in a school setting or on behalf of such organization, company or government agency.

Links


This web site contains links to other sites. Please be aware that we are not responsible for the privacy practices of such other sites. We encourage our users to be aware when they leave our site and to read the privacy statements of each and every web site that collects Personal Information. This privacy statement applies solely to information collected by this web site.

Requests and Contact


Please contact us about this Privacy Notice or if you have any requests or questions relating to the privacy of your personal information.

Changes to this Privacy Notice


We may revise this Privacy Notice through an updated posting. We will identify the effective date of the revision in the posting. Often, updates are made to provide greater clarity or to comply with changes in regulatory requirements. If the updates involve material changes to the collection, protection, use or disclosure of Personal Information, Pearson will provide notice of the change through a conspicuous notice on this site or other appropriate way. Continued use of the site after the effective date of a posted revision evidences acceptance. Please contact us if you have questions or concerns about the Privacy Notice or any objection to any revisions.

Last Update: November 17, 2020