Chapter 14. Connecting Web Parts – SharePoint 2010 Web Parts in Action

Chapter 14. Connecting Web Parts

 

This chapter covers

 

Up to now you’ve focused on one Web Part at a time, but in this chapter I’ll show you how to get your Web Parts to work together. By creating connections, you ensure that one Web Part can communicate with other Web Parts using specific contracts. For instance, say you have a Web Part containing a list of orders; when a user selects one of the orders, another Web Part shows its details. Connected Web Parts are often used in dashboards and reporting scenarios in which you’d like to “slice and dice” the information. You can configure the connections in code or directly in the user interface without any coding (which allows end users to create their own applications or mashups using different Web Parts).

Nearly all out-of-the-box Web Parts in SharePoint support connections in one way or another. In addition, if you’re fortunate to be working with the Server edition of SharePoint, you get a whole bunch of filter Web Parts that you can use to filter the information in your Web Part pages.

In this chapter, you’ll learn how to create both Web Part connection providers and consumers using custom connection contracts as well as the default connection types defined in SharePoint. I’ll show you how to combine Web Part connections with ASP.NET Ajax techniques to make the connections and updates more dynamic. In addition, you’ll look at filter Web Parts, specialized Web Parts that you can use to filter the contents of other Web Parts.

14.1. Introducing Web Part connections

Web Part connections are one of the core fundamentals of the Web Part infrastructure. Connecting Web Parts allows your end users to build rich and advanced applications using the various Web Parts that exist in their SharePoint installation.

A Web Part connection always has one provider side and one consumer side. The providers send information to one or more consumers that use this information to filter or show more information. Here’s an example: You can connect one Web Part containing data read from a database to another Web Part showing a chart representing that data. The chart isn’t directly connected to the database; instead, that Web Part retrieves the data through the connection.

The concept of connecting Web Parts is built on the principle that there are providers and consumers. A provider Web Part is one that provides information to consumers. A Web Part can have either of these roles, or both. Not all consumers can consume information from all providers—each connection needs a contract that both the consumer and provider understand. This contract is defined using an interface that’s implemented by the provider and used by the consumer, as you can see in figure 14.1.

Figure 14.1. The provider Web Part implements an interface that acts as a contract for the connection. The consumer Web Part uses this interface to retrieve or exchange information with the provider.

A provider Web Part can provide its interface to multiple consumers, and consumers can use connections from several providers, as figure 14.2 illustrates. But a consumer can’t consume the same interface from multiple providers. In advanced scenarios where a consumer is both a consumer and a provider, the Web Part can forward the information to a second consumer that’s chaining the result.

Figure 14.2. Web Parts can be connected in many ways, depending on how the connection endpoints are configured.

Web Part connections aren’t specific to SharePoint; they’re defined in ASP.NET 2.0. Web Parts were a part of SharePoint prior to ASP.NET 2.0, and connections existed during the pre–ASP.NET 2.0 era. The technique was similar and used an interface as the contract, but otherwise the actual connection was very unlike the method used today. The pre–ASP.NET 2.0 Web Part connection had one thing that ASP.NET 2.0 connections don’t have: client-side connections using JavaScript. Client-side connections can be replaced using ASP.NET 2.0 Ajax, which you’ll learn about in section 14.3.3.

Connections can only be made between Web Parts with compatible interfaces on the same Web Part page and if both the consumers and providers exist in Web Part zones (including the Wiki Web Part zone). Previous versions of SharePoint allowed Web Parts to be connected across page boundaries. The ASP.NET implementation of Web Part connections didn’t implement this feature out of the box.

14.2. Connecting Web Parts

One of the great things with Web Part connections is that end users can make the connections themselves. They can use the SharePoint web interface or use a rich client application such as SharePoint Designer. Web Part connections in the SharePoint interface are designed to be easy to use and configure.

Connected Web Parts can be used in many different scenarios. Let’s return to our earlier example in which you have a list of orders in one Web Part and a second Web Part that shows the details of a specific order. By connecting your Web Parts, you build a dynamic interface. You can have even more Web Parts involved in your connections. In this example, you could connect to another Web Part that shows customer details so that when a user selects an order both the details of the order and information about the customer are shown.

14.2.1. Connecting using the web interface

Web Parts can be connected using the web interface in SharePoint. You do so by selecting Edit Web Part in the Web Part options menu to enter edit mode and open the Web Part’s property pane. Click the options menu again and select the Connections option. The Connections submenu is dynamic and depends on what consumer and provider endpoints the current Web Part exposes and whether there are compatible Web Parts on the page (see figure 14.3).

Figure 14.3. Using the Web Part options menu, you can create Web Parts connections.

By selecting a connection type and then the target Web Part, you’ll connect your Web Parts. Depending on the type of the connection, an optional pop-up window will ask you to provide the connection with further details, such as which parameter or property to retrieve or send values to. You’ll see this in action a bit later in the chapter. Once the connection is established, a check mark appears beside the current connection. Depending on the implementation of the Web Parts, there might be multiple connections.

To disconnect Web Parts from one another, you use the same procedure. Select the current connection (the one with the check mark). If the connection is configurable, the pop-up window will allow you to change the settings, or you can choose to remove the connection. If you can’t configure the connection, you’ll simply see a dialog box asking you to confirm the disconnect.

14.2.2. Connecting using SharePoint Designer

SharePoint Designer is another option available to you when you’re working with Web Part pages and configuring Web Parts and connections. When you’re editing a page in SharePoint Designer and you select a Web Part, the Ribbon menu will display the contextual Web Part Tools tab. This tab contains a group called Connections that you can use to add new connections or manage existing ones. Figure 14.4 shows the dialog box that appears when you click Manage Connections. This dialog box lets you add, modify, and remove connections of the selected Web Part.

Figure 14.4. SharePoint Designer 2010 can be used to configure Web Part connections. The rich interface in SharePoint Designer makes the connection experience easier.

The SharePoint Designer interface is a great complement to the web interface, especially when you’re building complex dashboards with a lot of connections. The connections configuration wizards in SharePoint Designer are more helpful and intuitive than the corresponding ones in the web interface.

14.2.3. Connection permissions

If for some reason you don’t want to allow users to create Web Part connections, an administrator can disable that capability. Web Part connections might slow the performance down somewhat, due to the extra processing needed when transferring information between Web Parts and filtering them. But most often you don’t want to prohibit users from using Web Part connections.

You configure these permissions on a per–web application basis in Central Administration. Click Application Management and then select Manage Web Applications. Choose your web application and then click Web Part Security in the Ribbon. This opens the dialog box shown in figure 14.5. The first option, Web Part Connections, allows you to turn on or off your users’ ability to create connections for the specified web application.

Figure 14.5. The Security For Web Part Pages dialog box in Central Administration lets you enable or disable the functionality for connecting Web Parts.

14.3. Creating connectable Web Parts

Building Web Parts that can be connected requires that you either create a provider Web Part or a consumer Web Part—and in many cases you create both ends. Each provider–consumer connection has a contract that tells the consumer what it can expect to receive from the provider. The provider and consumer communicate using an interface, the contract, which the provider Web Part exposes. The consumer Web Part uses this interface to retrieve information from the provider.

You can create custom interfaces for your own providers and consumers or use any of the default connection interfaces. There’s a huge benefit to using the default interfaces because they’re compatible with several of the out-of-the-box Web Parts in SharePoint. (See appendix A for a comprehensive list of Web Parts and their connection interfaces.) In this section, I’ll show you both ways: custom interfaces and the default interfaces.

In addition, I’ll describe how to combine the ASP.NET Ajax framework with Web Part connections. This approach allows you to make your dashboards perform better without reloading the page completely.

14.3.1. Connect using custom interfaces

The first technique you’ll explore is creating a custom connection defined by a custom interface. You use this type of connection when you don’t need to connect your Web Parts with Web Parts from SharePoint or third-party applications. To create a custom connection, you need to

.  Define a connection interface, which is the connection contract

.  Create a provider Web Part, implementing the interface

.  Create a consumer Web Part, using the interface

For this example, you’ll continue to build on the RSS Web Part used in previous chapters and make it into a consumer Web Part. The RSS Web Part will be connected to a provider Web Part that provides a URL to the RSS Web Part. You’ll create a new Web Part that will serve as the provider.

Define the Connection Interface

To build this solution, you need to create a new SharePoint project based on the Empty SharePoint Project template. Be sure to select to deploy the project as a farm solution; Web Part connections can’t be used with sandboxed solutions. First, Add a new Web Part to the project and give it the name FeedInputWebPart.

The connection interface you’ll create must be able to send a URL from one Web Part to another. The URL will be exposed from the interface as a property with the string type. Add an interface item to the newly created Web Part and name the interface IUrlConnection. This interface will be the contract of the connection, and it will have a single property called Url, like this:

public interface IUrlConnection {
    string Url {
        get;
    }
}

Note that the interface is defined as public. This is necessary so that SharePoint (the Web Part Manager) and other Web Parts outside your project can access it. This interface has a single property that will contain the URL and is read-only; there’s no need to be able to write back the value in this case.

Create the Provider

When you’ve defined the interface, it’s time to build the provider Web Part. This Web Part will have a text input control and a button, as shown in figure 14.6.

Figure 14.6. A provider Web Part that accepts a text input—in this example a URL to an RSS feed—and sends the value of the text box to any connected Web Part consumers

The user interface for this Web Part is built in the CreateChildControls method. You can build this Web Part using a Visual Web Part if you prefer, but doing so would require the extra plumbing between the user control and the Web Part. The code that generates the interface should look like this in a standard Web Part:

protected TextBox url;

protected override void CreateChildControls() {
    HtmlGenericControl fieldset = new HtmlGenericControl("fieldset");
    HtmlGenericControl legend = new HtmlGenericControl("legend") {
        InnerText = "Enter feed URL:"
    };
    fieldset.Controls.Add(legend);

    url = new TextBox();
    fieldset.Controls.Add(url);

    Button button = new Button() {
        Text = "Submit"
    };

    fieldset.Controls.Add(button);

    this.Controls.Add(fieldset);
}

The TextBox containing the URL is defined as a protected class property. You’ll need that property later when you add the connection interface to this Web Part. This Web Part uses the fieldset and legend HTML elements to encapsulate the text box and button. All these controls are then added to the controls collection.

Once you’ve built the user interface, it’s time to let the provider Web Part implement the connection interface. Do so by adding the interface to the provider class definition:

public class FeedInputWebPart : WebPart, IUrlConnection

Now that the interface is defined for the class, you need to implement the property. You can either right-click on IUrlConnection in the class definition and select Implement Interface or you can write the code yourself. The Url property implementation should return the value of the text box:

public string Url {
    get {
        return url.Text;
    }
}

There’s one more thing that you need to do in order to turn this into a provider Web Part: create a method in the Web Part that returns the connection interface and mark that method as a connection provider endpoint:

[ConnectionProvider("Feed url")]
public IUrlConnection SetFeedConnection() {
    return this;
}

The attribute ConnectionProvider informs the Web Part Manager on the page that this Web Part has a provider connection endpoint and that the parameter is the name for it, which will be shown in the interface when connecting the Web Part. You can give the method any name, but it must return the interface; because the Web Part implements the interface, the current object (this) is returned.

The ConnectionProvider attribute always requires that you specify a name for the connection point. This name will be used in the SharePoint user interface to identify the connection. If you have multiple connection provider endpoints in your Web Part, you also have to supply an ID parameter that uniquely identifies the endpoint.

By default, a provider connection point can be used to connect to multiple consumers. You can change this by setting the named property called AllowsMultiple-Connections to false in the ConnectionProvider attribute.

Build the Consumer

As the consumer Web Part in this sample, you’ll build a new RSS Web Part. This Web Part is similar to the RSS Web Part that you built in chapter 5. First, add a new Web Part to the project and give it the name RssWebPart. Add two properties, as you did for the Web Part in chapter 5. These properties are the default URL and the default number of items retrieved from the feed:

[WebBrowsable]
[Personalizable(PersonalizationScope.Shared)]
[WebDisplayName("RSS feed Url")]
[WebDescription("Enter the Url to the RSS feed")]
public string RssFeedUrl {
    get;
    set;
}
[WebBrowsable]
[Personalizable(PersonalizationScope.Shared)]
[WebDisplayName("Items to show")]
[WebDescription("The number of RSS feed items to show")]
public int ItemCount {
    get;
    set;
}

These properties are used as default values for the RSS feed and the number of items to retrieve. The RssFeedUrl will be used when the Web Part isn’t connected to a provider Web Part. To initialize the value of the ItemCount property, use the following constructor:

public RssWebPart() {
    this.ItemCount = 5;
}

This constructor will ensure that the default value for the number of items retrieved is 5. You could set the default value in the .webpart file instead, if you prefer.

To render the feed items as links in the Web Part, you’ll implement a separate method. The method is declared as private and looks like this:

private void renderFeed() {
    if (string.IsNullOrEmpty(this.RssFeedUrl)) {
        return;
    }
    XElement feed = XElement.Load(this.RssFeedUrl);

    var items = feed.Descendants("item").Take(this.ItemCount);

    BulletedList bulletedList = new BulletedList();
    bulletedList.DisplayMode = BulletedListDisplayMode.HyperLink;

    foreach (var item in items) {
        bulletedList.Items.Add(new ListItem(
            item.Descendants("title").First().Value,
            item.Descendants("link").First().Value));
    }
    this.Controls.Add(bulletedList);
}

The renderFeed method is essentially just a copy of what you used in chapter 5 in the CreateChildControls method. If the RssFeedUrl property isn’t set, it quits the method; otherwise, it creates a BulletedList object, which shows a link for each feed item, and then adds the bulleted list to the Web Part child controls collection.

The consumer Web Part needs a consumer connection endpoint, and you implement that in a similar way. First add a new method that takes the connection interface as a parameter and mark it with the ConnectionConsumer attribute. The code should look like this:

IUrlConnection _provider;

[ConnectionConsumer("Feed Url", "feed")]
public void GetFeedConnection(IUrlConnection provider) {
    _provider = provider;
}

internal bool IsConnected() {
    return _provider != null;
}

First, a local property called _provider is defined and used to store a reference to the connection interface. The instance of that connection interface is set in the GetFeed-Connection method, which is the connection consumer endpoint. The attribute has two parameters; the first one is the display name for the connection and the second one an ID for the connection. The ID is optional at this point, but it’s required if the Web Part will have more than one connection consumer endpoint (and you’ll soon add more). Finally, you add an internal method that checks whether the Web Part is connected. This method will be used to ensure that the Web Part doesn’t use the connection if it’s not set.

If you deployed this project now, the provider and consumer can be connected, but because you haven’t as yet added any code in the RSS Web Part that uses the connection, you won’t see any results of the connection. To use the connection interface, you have to consider the order of events in a Web Part (see chapter 4). Figure 14.7 shows a part of the event flow of the Web Part when connections are involved.

Figure 14.7. The Web Part Manager connects Web Parts during a page load (HTTP GET) immediately after the OnLoad event and before the CreateChildControls event.

During an HTTP GET request, the provider connection method is called after the OnLoad events of both the consumer and provider. Directly after retrieving the provider connection, the connection consumer method is called to establish the connection. Once the connection is established, the CreateChildControls method is invoked.

For a postback event, when an event is triggered in the provider Web Part, the event flow differs just as discussed in chapter 4 (see figure 14.8). The CreateChild-Controls method is now invoked before the OnLoad event and the connection methods are invoked after the postback events.

Figure 14.8. Web Part connections are established after the postback events during a postback (HTTP POST) and immediately before the OnPreRender event.

The Web Part connections aren’t connected until just before the OnPreRender method. This means that you can’t use CreateChildControls to render the links of the feed. Instead you use the OnPreRender method to render the parts of the interface that are dependent on the connection. Before rendering the interface, the URL has to be retrieved from the connection:

protected override void OnPreRender(EventArgs e) {

    if (IsConnected()) {
        this.RssFeedUrl = this._provider.Url;
    }

    renderFeed();

    base.OnPreRender(e);
}

The OnPreRender method checks whether the Web Part is connected to a provider by using the IsConnected method. If it’s connected, then the method sets the RssFeedUrl property to the value of the Url property of the interface. The list of links to the feed items is then rendered using the renderFeed method.

The ConnectionConsumer attribute that defines the consumer connection point must have a name. As in the previous sample, an ID must be used if the Web Part has more than one connection consumer point. Just as with the ConnectionProvider attribute, the AllowsMultipleConnections property can be used to specify whether the connection point supports multiple providers. For a connection consumer point, the default value is false, which means it supports only a single provider.

Now it’s time to build, deploy, and connect the Web Parts. Once you’ve deployed the solution to SharePoint, navigate to a page or create a new one and then add both the provider Web Part and the consumer Web Part to the page. Then click Edit Web Part in the Web Part options menu so that the Web Part enters Edit mode. To connect the Web Parts, you can use either the consumer or the provider. Click the provider Web Part options menu and select Connections > Send Feed Url To > RSS Web Part, as shown in figure 14.9. Then click OK in the property pane of the Web Part.

Figure 14.9. To connect the Feed Input connection provider with the RSS Web Part, select Connections in the Web Part options menu, and then select the name of the connection and finally the name of the Web Part.

If you now enter an RSS feed URL in the provider Web Part and click the Submit button in the provider Web Part, the page will reload and the feed URL will be sent to the consumer. If you enter another URL and click the Submit button, the consumer Web Part will again reload and show the new feed.

14.3.2. Connect using standard connections

To be able to connect to the out-of-the-box Web Parts in SharePoint, you can’t use custom interfaces. Fortunately there’s a set of standard Web Part connection provider interfaces defined in ASP.NET 2.0 that the SharePoint Web Parts use. Table 14.1 lists the connection interfaces defined by ASP.NET. When you can, use the default Web Part connection interfaces because they allow you to connect to the SharePoint Web Parts, such as List View Web Parts or even third-party Web Parts.

Table 14.1. Standard connection provider interfaces

Interface

Usage

IWebPartField Transfers a single field of data
IWebPartRow Transfers one row of data (multiple fields)
IWebPartTable Transfers one table of data (multiple rows)
IWebPartParameters Transfers a single field of data based on a parameter

 

Note

You might see references to interfaces such as ICellProvider, ICell-Consumer, and IFilterConsumer when looking at Web Part connections. These are interfaces used by the SharePoint implementation of Web Part connections before ASP.NET 2.0. These interfaces are now obsolete and shouldn’t be used.

 

I’ll show you how to use some of these connection provider interfaces by modifying the RSS Web Part and then connecting it to a standard list Web Part that shows a Links list, where the Links list will be the provider. When a link in the Web Part is selected, that link will be used to retrieve the feed in the RSS Web Part, as shown in figure 14.10.

Figure 14.10. By using the built-in connection interfaces, you can connect custom Web Parts to the out-of-the-box Web Parts such as List Web Parts. Notice the Select column in the List Web Part; it appears when a List Web Part is acting as a provider Web Part.

Connect Using IWebPartRow

The IWebPartRow default connection provider interface allows a provider Web Part to send a row of data to a consumer Web Part. There’s a benefit to using this interface in a Web Part. For instance, say the SharePoint XSLT List View Web Part provides that interface, inherited from the Data Form Web Part. Using an XSLT List View Web Part (which is used to display lists in SharePoint), you can easily retrieve feeds from a Links list into the RSS Web Part.

First you need to add the consumer connection endpoint to the RSS Web Part. You can use the endpoint you created in the previous section; remember that you set an ID on it that allows for more than one endpoint. The IWebPartRow consumer connection endpoint is implemented as follows:

IWebPartRow _row;

[ConnectionConsumer("Row", "row")]
public void GetRowData(IWebPartRow row) {
    _row = row;
}

This endpoint is marked with the ConnectionConsumer attribute, and it takes the IWebPartRow interface as the parameter. The connection interface is stored in a local variable. You also need to update the IsConnected method so that the Web Part can be connected through this endpoint:

internal bool IsConnected() {
    return _provider != null || _row != null;
}

The updated IsConnected method checks whether the Web Part is connected to the custom interface or if it uses the IWebPartRow connection.

The default connection interfaces in ASP.NET don’t use properties to transfer the data between Web Parts, as in our example custom connection. Instead, they use callback methods. The provider interfaces contain methods that you send in a callback method from the consumer. You have to modify the OnPreRender method as follows:

After you’ve made those changes, OnPreRender will first check whether the Web Part is connected to the custom interface , and if that’s the case, it will use that connection. Otherwise, it will check whether it’s connected using the IWebPartRow connection . If that’s the case, the method calls the GetRowData method of the provider with a callback method getRowData, defined here:

private void getRowData(object rowData) {
    DataRowView dataRow = rowData as DataRowView;
    if (dataRow != null) {
        foreach (PropertyDescriptor property in this._row.Schema) {
            if (property.Name == "URL") {
                SPFieldUrlValue value =
                    new SPFieldUrlValue(dataRow[property.Name].ToString());
                this.RssFeedUrl = value.Url;
                return;
            }
        }
    }
    this.RssFeedUrl = null;
}

The getRowData callback method accepts an object that’s converted into an object of the type DataRowView. If the cast is successful, it’ll iterate over all property descriptors found in the Schema property of the IWebPartRow interface. The Schema contains information, such as the name and type, about all columns in the row. When a column with the name “URL” is found in the row, this Web Part assumes that it’s a URL column. The column is transformed into a SharePoint SPFieldUrlValue object. From this object the Url property is retrieved and put into the Web Part RssFeedUrl property. If no column called “URL” is found, it sets the feed URL to null.

That’s all you need to connect the custom RSS Web Part to a standard SharePoint Links list. Deploy the solution and go to your site. Use an existing Links list or add a new one, and then fill the list with a few links to RSS feeds. When you’ve done that, create a new page and add the Links list to that page and then the RSS Web Part. Click Edit Web Part on the Links list options menu; then once again in the options menu of the Web Part, select Connections > Send Row of Data To > RSS Web Part. Click OK in the edit pane of the Web Part. Now the Links list is connected to the RSS Web Part and you can see that the Links list has a new column called “Select.” If you click the Select icon on any of the rows, the RSS Web Part displays the contents from the URL of that selected row in the Lists Web Part, as shown previously in figure 14.10.

Connect Using IWebPartParameters

The third connection type that I’ll show you is an alternative to the IWebPartRow when you need to select a list column to send to the consumer during the connection. The interface you’ll use for this is called IWebPartParameters. This approach is better than iterating over the columns in the row as in the previous sample because it doesn’t depend on a specific hardcoded name of the column.

The connection provider interface requires that the consumer tell the provider which field or fields to send to the consumer. You must add the connection endpoint to the RSS Web part and mark it as a connection consumer endpoint:

This implementation differs from the previous ones because it’s not just storing the value of the connection endpoint. In this case you need to inform the provider Web Part about the property (or properties) that you’d like it to provide to your consumer. You do so by creating a PropertyDescriptorCollection that consists of Property-Descriptor objects. In this example, the property you need is a string to set the feed URL. You create that property description using the CreateProperty method of the TypeDescriptor object , using the current Web Part type, the name (RssUrl), and the type of property. The collection of property descriptors is then used with the Set-ConsumerSchema method of the connection provider interface before the connection instance is stored to a local variable.

Using the property descriptors and the configuration of the connection, the provider Web Part will know which property to send to the consumer. The connection configuration is determined when the connection is established in the user interface.

Before modifying the OnPreRender method to support this new connection endpoint, you have to update the IsConnected method once again. It’ll now check whether the Web Part is connected to any of the three connection endpoints:

internal bool IsConnected() {
    return _provider != null || _row != null || _parameters != null;
}

You then update the OnPreRender method so that it’ll retrieve the feed URL from the new parameterized connection:

Just as with the IWebPartRow connection, the IWebPartParameters connection calls a method in the provider, passing a local callback method called getParametersData . This callback method now knows the name of the property to retrieve and the correct feed URL can safely be retrieved:

private void getParametersData(object rowData) {
    IDictionary dictionary = rowData as IDictionary;
    if (dictionary != null) {
        SPFieldUrlValue value =
            new SPFieldUrlValue(dictionary["RssUrl"].ToString());
        this.RssFeedUrl = value.Url;
        return;
    }
    this.RssFeedUrl = null;
}

The getParametersData method takes an object as an argument and that argument is cast into an IDictionary object containing the parameters. Using the SPField-UrlValue class, the “RssUrl” parameter is retrieved and the value of that parameter is set into the Web Part RssFeedUrl property. This implementation is easier and safer because you can specify the property that you need. Note that this sample requires that the parameter passed have the name “RssUrl”; in your implementations you should check for the correct parameter names.

To connect the Links list and the RSS Web Part, you deploy the solution and go back to the page where you previously added the Links Web Part and the RSS Web Part. Remove the current (IWebPartRow) connection by editing one of the Web Parts, and then select Connections > Send Row of Data To > RSS Web Part. SharePoint will display a pop-up window that asks you if you’d like to remove the connection. Click OK to remove it.

To connect the Web Parts using the IWebPartParameters interface, start with the consumer Web Part. Select Connections > Get Parameters From > Links from the options menu of the RSS Web Part. In the resulting dialog box, select URL from the Provider Field Name drop-down list and RssUrl from the Consumer Field Name drop-down list, as shown in figure 14.11. Click Finish to configure the connection and then click OK to save and close the edit pane of the Web Part.

Figure 14.11. Some Web Part connection interfaces require that you configure the connections. If necessary, SharePoint will show a dialog box that asks you to configure the connection.

If you instead choose to create the connection using the provider, select Connections > Send Row of Data To > RSS Web Part. SharePoint will then detect that there’s both an IWebPartRow connection and an IWebPartParameters connection available. The Configure Connection dialog box will appear and you must choose the connection type; Get Row From or Get Parameters From, as previously shown in figure 14.3. If you select the latter of the two, you’ll then be required to choose the fields.

14.3.3. Ajax and Web Part connections

When you use a connected Web Part to filter a consumer, the page will make a post-back to update the values for just the consumer. Because SharePoint now supports ASP.NET Ajax out of the box, you can use update panels in the Web Parts. That’s a simple way to improve the performance of the page or dashboard: it makes SharePoint update only the Web Parts instead of the whole page.

Provider and Interface Changes

To learn how to use Ajax and dynamically updating Web Parts, you’ll take the consumer and provider Web Parts, update the connection interface, and add an update panel to the consumer. First, let’s update the connection interface. The provider must be able to send information to the consumer (in addition to the URL) indicating that it contains a control that can be used for asynchronous operations:

public interface IUrlConnection {
    string Url {
        get;
    }

    Control AsyncTrigger {
        get;
    }
}

This version has a new property called AsyncTrigger that returns a Control object. This object is the trigger of the asynchronous update. You must modify the original provider Web Part so that it supports this new property from the interface:

public Control AsyncTrigger {
    get {
        return _button;
    }
}

The implementation of the AsyncTrigger property returns the current _button object. This object will then be used by the consumer Web Part for asynchronous operations. By supplying it as a property without modifications to the provider Web Part, you make it optional for the consumer Web Part to use the property.

Consumer Changes

In the consumer Web Part, there are three changes you must include to make it update asynchronously. The first change is to override the CreateChildControls method and add an UpdatePanel object to the consumer:

protected UpdatePanel updatePanel;

protected override void CreateChildControls() {
    updatePanel = new UpdatePanel();
    this.Controls.Add(updatePanel);
    base.CreateChildControls();
}

The UpdatePanel is declared as a protected property in the Web Part class. In the CreateChildControls it’s created and added to the child controls collection. This UpdatePanel object is then used by the renderFeed method in the consumer. Instead of adding the BulletedList (which shows the RSS feed items) to the Web Part child controls collection, it’s added to the template container of the UpdatePanel, like this:

BulletedList bulletedList = new BulletedList();
bulletedList.DisplayMode = BulletedListDisplayMode.HyperLink;

foreach (var item in items) {
    bulletedList.Items.Add(new ListItem(
        item.Descendants("title").First().Value,
        item.Descendants("link").First().Value));
}
updatePanel.ContentTempalteContainer.Controls.Add(bulletedList);

This allows the feed items to be updated when the UpdatePanel is asynchronously updated. All that you’ve changed is that the RSS feed items are now contained within an update panel. Any clicks on the button will still invoke a full postback.

The final modification is to edit the OnPreRender so that it registers the Control object provided from the connection interface as an asynchronous postback control. You accomplish this by using the ScriptManager object in the OnPreRender method:

If the consumer Web Part is connected using the IUrlConnection interface, the current ScriptManager is retrieved. If the ScriptManager is found, it’s used to register the control (AsyncTrigger) from the connection interface as an asynchronous post-back control. This operation converts the functionality of the button into an asynchronous operation.

If you deploy the solution now, connect the Web Parts using the custom connection interface, enter a URL to a feed, and click the Submit button, you’ll see that the consumer Web Part updates without refreshing the whole page. This simple change to the Web Parts and the connection interface is a small but efficient way to make the user interface of connected Web Parts and SharePoint faster.

14.4. Filter Web Parts

Filter Web Parts are provider Web Parts used to filter the information in other Web Parts. For instance, a filter Web Part might define a date range that’s used by another Web Part to filter its contents. SharePoint Server Enterprise is delivered with a set of filter Web Parts that you can use with your consumer Web Parts. Or you might create custom filter Web Parts to add new filtering functionality to your SharePoint installation. If you’re working with SharePoint Foundation or SharePoint Server, you have no filter Web Parts at all by default, and you might find it worth your time to add your own.

14.4.1. Default filter Web Parts

A filter Web Part is a special kind of provider. Its sole purpose is to serve as a filter for another Web Part. Only the Server version of SharePoint 2010 contains filter Web Parts out of the box. Most of them are quite easy to implement on your own, if you need them in SharePoint Foundation. Table 14.2 shows the filter Web Parts in SharePoint Server.

Table 14.2. Out-of-the-box filter Web Parts in SharePoint Server Enterprise 2010

Name

Description

Business Data Connectivity Filter Filters a Web Part using values from the Business Data Connectivity service
Choice Filter Filters a Web Part using a list of values entered by the page author
Current User Filter Sends a user id to a Web Part
Date Filter Filters a Web Part with a selected date
Filter Actions Synchronizes two or more filter Web Parts
Page Field Filter Filters a Web Part based on metadata of the Web Part Page
PerformancePoint Filter Filters PerformancePoint Web Parts
Query String Filter Filters a web part using Query String parameters
SharePoint List Filter Filters a Web Part using a list of values
SQL Server Analysis Server Filter Filters a Web Part with values from a SQL Server Analysis Server cube
Text Filter Filters a Web Part using a value entered by the user

All of these Web Parts (except the Business Data Connectivity and PerformancePoint filter Web Parts) are defined in the Microsoft.Office.Server.FilterControls.dll assembly, which is installed in the global assembly cache in a SharePoint Server installation.

14.4.2. Web Part transformers

Before you dig into how the filter Web Part works, I want to explain the concept of Web Part transformers. Web Part transformers are used to connect two Web Parts with incompatible connection endpoints and translate the data. For instance, a transformer can be used to transform an IWebPartRow provider endpoint to an IWebPart-Field consumer endpoint.

The transformers derive from the abstract WebPartTransformer class defined in the System.Web.dll assembly and are a part of the ASP.NET framework. To create a Web Part transformer, you need to create a new class that derives from the transformer base class and returns the connection interface for the type you’re transforming to. Listing 14.1 shows how to implement a transformer that transforms an IWebPartField connection provider to our custom IUrlConnection interface.

Listing 14.1. Transforming IWebPartField endpoint to IUrlConnection endpoint
[WebPartTransformer(typeof(IWebPartField), typeof(IUrlConnection)]
public class FieldToUrlTransformer:
    WebPartTransformer, IUrlConnection {

    protected IWebPartField _provider;
    protected string _url;

    public override object Transform(object providerData) {
        _provider = (IWebPartField)providerData;
        return this;
    }

    public string Url {
       get {
            this._provider.GetFieldValue(getFieldValue);
            return _url;
       }
    }

    private void getFieldValue(object fieldValue) {
      _url = fieldValue.ToString();
    }
}

The FieldToUrlTransformer class inherits from WebPartTransformer and the IUrlConnection interface is marked with the WebPartTransformer attribute. This attribute defines which connection type the transformer can transform from and which connection type the transformation results in. To transform the interfaces, the Transform method must be overridden; in this case it stores the from provider in the local variable. The Url method of the IUrlConnection interface uses the provider callback method to get the value from the IWebPartField provider, thus converting from IWebPartField to the IUrlConnection provider.

To use a transformer, you must register it in the web.config of the web application. You do so in the webParts section using the transformers element. Add each transformer using an add element:

<webParts>
    <transformers>
        <add name="FieldToUrlTransformer"
            type="WebPartsInAction.FieldToUrlTransformer, ... "/>
    </transformers>
</webParts>

The name attribute is a unique name for the transformer and the type attribute contains the transformer type. Creating custom transformers is rarely done, especially if you’re using SharePoint Server, but using them can simplify development when building advanced dashboards. Transformers can be useful if you’re working with third-party Web Parts with incompatible connection contracts.

 

Note

Don’t manually make changes to the web.config files. Use the SPWeb-ConfigModification classes or a similar approach to provision your changes throughout your farm.

 

SharePoint Server 2010, by default, adds all the needed transformers for the filter Web Parts in the web.config file. The following are the default transformers registered in a SharePoint 2010 Server installation. The assembly where the transformer is defined appears within parentheses:

  • TransformableFilterValuesToFilterValuesTransformer (Microsoft.SharePoint)
  • TransformableFilterValuesToParametersTransformer (Microsoft.SharePoint)
  • TransformableFilterValuesToFieldTransformer (Microsoft.SharePoint)
  • TransformableFilterValuesToEntityInstanceTransformer (Microsoft.SharePoint.Portal)

For an Enterprise installation of SharePoint, the following transformers are also added:

  • TransformableBIDataProviderToFilterValuesTransformer (Microsoft.PerformancePoint.Scorecards.WebControls)
  • TransformableBIDataProviderToWebPartParametersTransformer (Microsoft.PerformancePoint.Scorecards.WebControls)
  • TransformableBIDataProviderTransformer (Microsoft.PerformancePoint.Scorecards.WebControls)

These transformers are used by PerformancePoint Services Web Parts, and by building custom filter Web Parts, you can enhance the feature set of PerformancePoint Services dashboards.

14.4.3. The ITransformableFilterValues interface

All filter Web Parts in SharePoint use the ITransformableFilterValues interface. This interface was specifically created for Web Part transformers in SharePoint. The default transformers are used to transform from this interface to the interfaces used by the default consumer Web Part in SharePoint. If you build your Web Parts using the default interfaces, which I discussed earlier, you can take advantage of the filter Web Parts. This interface is defined in Microsoft.SharePoint.dll in the Microsoft.SharePoint.WebPartPages namespace.

To build your own filter Web Part that could be used by the default SharePoint Web Parts, you need to make your provider Web Part implement the ITransformableFilterValues interface. In the project with the connectable RSS Web Part, add a new Web Part project item called CustomFilter. This will be a filter Web Part with a drop-down list containing a few RSS feeds (see figure 14.12). By selecting an item from the drop-down list, you can update the RSS Web Part.

Figure 14.12. Using the SharePoint defined interfaces for connections allows you to create filter Web Parts that can be connected to almost any Web Part.

Listing 14.2 shows the full implementation of the filter Web Part. Notice that the ITransformableFilterValues interface is prefixed with SPWPP. This is because the interface exists in the same namespace in which the SharePoint WebPart class is declared. To avoid conflicting class names, you employ a using statement:

using SPWPP=Microsoft.SharePoint.WebPartPages;

This custom filter implements the five different properties of the interface and exposes the interface as a connection provider.

Listing 14.2. A filter Web Part that uses the ITransformableFilterValues interface
public class CustomFilter : WebPart, SPWPP.ITransformableFilterValues {
    protected DropDownList _dropDown;

    protected override void CreateChildControls() {
        _dropDown = new DropDownList();
        _dropDown.Items.Add(new ListItem("Wictor Wilén",
           "http://feeds.feedburner.com/WictorWilen"));
        _dropDown.Items.Add(new ListItem("SharePoint Team Blog",
           "http://blogs.msdn.com/sharepoint/rss.xml"));
        _dropDown.AutoPostBack = true;
        this.Controls.Add(_dropDown);
    }

    public bool AllowAllValue {
        get { return true; }
    }
    public bool AllowEmptyValue {
        get { return false; }
    }

    public bool AllowMultipleValues {
        get { return false; }
    }

    public string ParameterName {
        get { return "Url"; }
    }

    public ReadOnlyCollection<string> ParameterValues {
        get {
            EnsureChildControls();
            string[] values = new string[] {_dropDown.SelectedValue};
            return new ReadOnlyCollection<string>(values);
        }
    }
    [ConnectionProvider("Feed filter",
        "ITransformableFilterValues",
        AllowsMultipleConnections = true)]
    public SPWPP.ITransformableFilterValues SetConnectionInterface() {
        return this;
    }
}

The CreateChildControls method of the filter Web Part adds a DropDown control to the controls collection. This drop-down list is filled with two different RSS feeds. To avoid adding a button to apply the filter, you set the drop-down to AutoPostBack when it’s changed. The AllowAllValue, AllowEmptyValue, and AllowMultipleValues properties are set to default values in this implementation. The ParameterName property returns the parameter name of this filter, and ParameterValues returns a single value in this case, which is the value of the selected item in the drop-down. To make the Web Part into a provider, the ITransformableFilterValues interface is returned by the SetConnectionInterface method. Notice how it’s also set to support multiple consumers.

Once you deploy the project, you can connect the custom filter Web Part to the RSS Web Part and see how the feed item changes when you switch feeds using the drop-down list. Using this technique with filter Web Parts, you can enhance the use of your Web Parts as well as the out-of-the-box ones.

14.5. Summary

Web Part connections are powerful and can enhance the user experience. They can make different Web Parts interact with one another, and users can filter and customize potentially large amounts of information. Connectable Web Parts can be used to provide new functionality to existing and even the out-of-the-box Web Parts. Web Part connections allow power users to use existing Web Parts in combination with other Web Parts to build new applications. In the next, and last, chapter, you’ll build full configurable dashboards.