Provisioning Web Part instances in a structured and repeatable way
SharePoint 2007 introduces various approaches to provisioning Web Parts instances in Publishing Pages. A few of them are:
- using custom code inside the FeatureActivated event of a Feature Receiver,
- using custom code inside an Event Handler attached to the ItemAdded event on a Pages Library,
- defining the Web Part instances outside Web Part Zone directly in the Page Layout,
- provisioning Web Parts using Features using the AllUsersWebPart element
While each of these techniques results in creating an instance of a Web Part they aren't equally suitable for provisioning Web Parts in a structured and repeatable way.
Looking at the deployment process in SharePoint 2007 I distinguish two kind of Web Part deployments: provisioning a Web Part definition (.webpart or .dwp depending on the base class; asset deployment) to the Web Part Gallery and creating an instance of a Web Part on a Publishing Page (eg. Content Query Web Part which displays on the home page 10 last press releases; configuration deployment). It is not always required to deliver a Web Part definition prior to provisioning Web Part instances. You need Web Part definitions only if you want to allow the end-users to reuse these Web Parts themselves.
Earlier in this article I have presented a few possible approaches for deploying Web Part instances. All of them have their pros and cons. Yet I believe that there are particular scenario's when you might tend to choose one before another depending on the requirements. Below I present each of these concepts in detail and focus on the pros and cons of using it.
Custom code inside the FeatureActivated event of a Feature Receiver
Using custom code inside the FeatureActivated event of a Feature Receiver is the first approach you could use to provision instances of your Web Parts onto Publishing Pages. During the activation process of a Feature scoped to a Web you obtain a reference to the SPLimitedWebPartManager of the target page and add the Web Parts. While you are in control of the provisioning process and can extend it with some custom logic, there are some serious drawbacks to this approach. First of all the target pages must exist prior to provisioning the Web Parts. This means that either you have to create them using a Site Definition or create them programmatically using custom code. Furthermore you need to include the Web Part definition in the code behind. While this can be avoided if you're adding Web Part which exist in the Web Part Gallery, you either have to include the complete Web Part XML or set the particular settings in your code. Each modification to your Web Parts means recompiling the assemblies and deploying them to the web server. Another important drawback is being able to provision the Web Parts only initially during the Feature activation. If a user would create a Publishing Page later on it wouldn't have the Web Parts as defined the Feature Receiver. In spite of being fully in control of the deployment process and having access to the SPContext object this approach is far from optimal due to its lack of overview and flexibility.
Custom code inside an Event Handler attached to the ItemAdded event on a Pages Library
A slightly similar approach is instantiating Web Parts using an Event Handler. Comparing to the Feature-based approach it allows you to provision Web Parts not only during the initial deployment but also during the whole life cycle of a web site. Just as the Feature-based approach, your custom Event Handler will use custom code to obtain the required references and provision the Web Parts. While still fully controlling the provisioning process you are not limited to the initial deployment anymore. Event Handler is active during the whole life cycle of a web site and can instantiate Web Parts whenever required. The biggest drawback to this approach, as it still works using custom code, is the inclusion of Web Parts definition in your code behind. Depending on how many various Page Layout are allowed within a Page Library this approach might decrease your performance during the page creation.
Defining the Web Part instances outside Web Part Zone directly in the Page Layout
Defining Web Parts outside Web Part Zones is a totally different approach. It leans toward design work as it's a part of creating Page Layouts. Instead of or next to creating Web Part Zone you paste the Web Part XML as defined by the Web Part definition and configure your properties. In spite of its name it likes more like working with Custom Controls: once embedded in the Page Layout, Web Parts outside Web Part Zones cannot be either configured or removed using the SharePoint Web UI. Any change to these Web Parts requires either delivering new Features or customizing the Page Layout using SharePoint Designer. This approach might be ideal when permanent Web Parts are required on particular Page Layouts. The lack of flexibility makes it however of little use from the maintenance point of view.
Provisioning Web Part instances using Features using the AllUsersWebPart element
Probably most commonly used approach is provisioning Web Part instances using the AllUsersWebPart element in the Feature definition. The Web Parts can be provisioned together with the corresponding Page Layouts and the whole is described using XML. The provisioning process is being taken care of by SharePoint and you don't have do anything else besides creating a Feature and provide the information about Web Parts. As you provide the Web Part definition you don't have to worry whether it exists in the Web Part Gallery or not. Provisioning Web Part instances using the AllUsersWebPart element seems like the perfect approach: it doesn't require any custom development and the definitions can be easily modified using intellisense for the Feature XML files. There is however one thing you should consider. Web Parts provisioned using this approach are being instantiated not only during the initial activation of the Feature but each time you activate it. And it actually doesn't matter whether you deactivate the Feature first or just reactivate it using the -force parameter. All Web Parts, as defined by the Feature definition will get added again to the Page Layout resulting in multiple instances of the same Web Part. There are many scenario's to think of when you might need to reactivate your Features. Because overwriting assets provisioned by Feature A using Feature B is not possible using the standard SharePoint functionality you have to keep the ability to activate and reactivate the Features without any negative impact on the existing configuration. Although it is possible to remove the duplicate Web Parts upon the Feature activation, it is not covered by the SharePoint framework, it is not straightforward and requires either manual modifications or developing custom code: not really something you want in structured and repeatable deployment scenario's. Provisioning duplicate Web Parts upon Feature reactivation makes this approach difficult to use in some scenario's. It turns out to be extremely problematic when you either haven't though on deployment in a early stage of your project or weren't able to do so. Novice SharePoint developers in particular should try this approach out in various scenario's before using it in the projects. Understanding the Web Parts provisioning framework will save you a lot of frustration.
SharePoint 2007 provides many approaches to provision Web Parts in a structured and repeatable way. While none of them is flawless it is important for you to know the pros and cons of each one of them and to make an educated choice depending on your requirements.