Web Parts
Use Windows SharePoint Services as a Platform for Building Collaborative Apps, Part 2
Jason Masterman and Ted Pattison
This article discusses:
- The WSS and SPS object models
- Web Part Page anatomy
- Creating and deploying Web Parts
- Web Part security
|
This article uses the following technologies:
SharePoint, ASP.NET, C#
|
Code download available at:
WebParts.exe
(204 KB)
Browse the Code Online

Contents
In the first installment of this article in the July 2004 issue, we examined the architecture of SharePoint® Products and Technologies. You saw that Windows® SharePoint Services (WSS) supplies a facility for building collaborative Web sites. Microsoft® Office SharePoint Portal Server (SPS) 2003, which is part of the Office System, complements WSS by adding features designed to assist users in navigating through the otherwise disconnected WSS-delivered SharePoint sites, as well as vast amounts of information, documents, people and application resources within an organization. SPS also supplies additional functionality to enhance portal sites using indexing, searching, audience targeting, and single sign-on (SSO).
In this second of two parts, we will start by examining the WSS and SPS object models, before moving into a detailed discussion of Web Part infrastructure where we will show how to create custom Web Parts. (For a look at the first part of this series, see
SharePoint: Use Windows SharePoint Services as a Platform for Building Collaborative Applications.)
WSS provides the underlying infrastructure that lets you generate user interfaces by including Web Part Page and Web Part technology. Web Part Pages and Web Parts offer lots of power because they allow each WSS site and SPS portal site to have a browser-based user interface that is extensible and fully customizable. Web Parts also allow you to track personalization information on a user-by-user basis.
The WSS and SPS Object Models
WSS and SPS each expose their own object model. The WSS object model allows you to develop administrative applications that can create and manage virtual servers, site collections, sites, workspaces, and users. You can also use the WSS object model to design and implement user-targeted applications that manage lists and document libraries as well as the items they contain. The SPS object model allows you to programmatically manipulate areas and listings and automate other features such as the SPS services for search and SSO. Moreover, since every SPS portal site is an extension of the WSS site technology, SPS also exposes and makes use of the WSS object model.
The WSS and SPS teams have exposed their object models through class library DLLs as well as through a set of built-in Web services. Thus, when you want to program against the WSS object model using the class library you should add a reference to Microsoft.SharePoint.dll. If you want to program against the WSS object model using Web services, you should add a Web reference to one of the built-in Web services such as http://AcmeServer/_vti_bin/Lists.asmx.
There are a few things to consider when deciding if you will use the class libraries or Web services. The class libraries are easier to use and they support more features. However, a custom application that uses one of the class library DLLs can only run on a server within a WSS or SPS deployment. Programming against the object model of WSS and SPS using the Web services doesn't provide as much functionality and often requires you to program in terms of XML. If you build your application using Web services, however, it can be run on an administrator's desktop computer or even a user's laptop. The whole point of using the built-in Web services is that it allows you to write a custom application to communicate with a WSS or SPS deployment from across the network.
When you begin to program against the WSS object model, you may find that the changes in terminology between WSS and its predecessor, SharePoint Team Services (STS), cause some confusion. For example, the new WSS term "Site Collection" is the equivalent of the old STS term "Site." The new WSS term "Site" is the equivalent of the old STS term "Web" and the new WSS term "Top-level Site" is the equivalent of the old STS term "Root Web."
While the use of the new WSS terminology in the product documentation has been consistent, the names of classes in the WSS object model are based on the old STS terms. For example, you program against a site collection using an SPSite object. You program against a site using an SPWeb object. An SPSite object provides a public property named RootWeb that returns an SPWeb object representing the site collection's top-level site. Once you understand this somewhat confusing terminology, the WSS object model becomes much easier to learn.
The WSS object model exposed by the class library provides a top-level GlobalAdmin class that serves as an entry point into a WSS deployment. You can use a GlobalAdmin object to enumerate through the virtual servers, site collections, and sites within a WSS or SPS deployment, as shown in Figure 1. Within each site, you can then inspect its lists, document libraries, users, and child sites.

Figure 1 Enumerating the Lists of a Virtual Server
// get GlobalAdmin object for current WSS deployment
SPGlobalAdmin globalAdmin = new SPGlobalAdmin();
// enumerate through IIS Virtual Servers
foreach(SPVirtualServer vServer in globalAdmin.VirtualServers)
{
// determine which IIS Virtual Servers are extended with WSS
if(vServer.State == SPVirtualServerState.Ready)
{
// enumerate through Site Collections of each Virtual Server
foreach(SPSite siteCollection in vServer.Sites)
{
// enumerate through Sites of each Site Collection
foreach(SPWeb site in siteCollection.AllWebs)
{
// enumerate through Lists of each Site
foreach(SPList list in site.Lists)
{
Console.WriteLine(list.Title);
}
}
}
}
}
Two sample applications accompany this article. The first, SharePoint Site Browser, illustrates how you can program against the WSS object model using the class library. We wrote this Windows Forms application to demonstrate the techniques required for enumerating through virtual servers, site collections, sites, lists, document libraries, and users. A screen shot of the application is shown in Figure 2.

Figure 2 SharePoint Site Browser
We wrote a second sample application named the Portal Area Browser that demonstrates how to program against the SPS object model. It shows how to program against the SPS class library DLLs to navigate through areas and inspect their listings. Both of these applications, complete with full source code, can be downloaded from the MSDN®Magazine Web site.
Web Part Infrastructure
As we mentioned earlier, Web Part Pages provide each site with an extensible HTML-based user interface. You can customize a Web Part Page by adding and configuring Web Parts. Users can further personalize them by modifying existing Web Parts and adding new ones. The fact that the Web Part Page and Web Part technologies created for WSS are being carried over as a major new feature in ASP.NET 2.0 is a testament to their power.
So how do Web Part Pages differ from standard ASP.NET pages? A standard ASP.NET page is stored as a text file on the file system of the Web server. The pieces that make up a Web Part Page, on the other hand, are stored in multiple tables inside the SharePoint content database. WSS constructs Web Part Page objects on the fly by retrieving data from these tables. This dimension of the Web Part architecture makes it possible to customize and personalize sites.
Let's take a moment and examine a Web Part Page from the perspective of a Web Part user. If you are a site owner or you have Web designer permissions, you can view and modify a Web Part Page in either shared view or personal view. Using the browser, you can switch back and forth using the Modify Shared Page menu, as shown in Figure 3. Once you have switched over to your personal view, the menu caption in the upper right-hand corner of the Web Part Page changes to Modify My Page.

Figure 3 Modify Shared Page
To customize the Web Parts on a Web Part Page, you should enable the "Design this Page" option. You can also add new Web Parts to a Web Part Page using the Add Web Parts menu. If you are working in a Web Part Page in shared view, the customizations you apply to Web Parts are seen by all users. If you switch from shared view to personal view, your modifications are only seen by you. WSS is smart enough to store the shared customization data and private personalization data separately in the content database.
You must be a site owner or have Web designer permissions to modify a Web Part Page in shared view. When a Web Part Page is generated for a user who is neither the site owner nor a Web designer, that user will not be allowed to switch over to a shared view. Instead, the page only provides a "Modify My Page" menu. However, the user can still enable the "Design this Page" option and, consequently, add and customize Web Parts. Any modifications made by the user using these features will be stored as personalized data rather than shared data.
A Web Part Page is laid out in terms of Web Part Zones. You add a Web Part to a Web Part Page by placing it in a Web Part Zone. WSS allows a site owner or Web designer to create new Web Part Pages using one of the templates provided. With the browser, you can use one of these Web Part Page templates to create a new Web Part Page with a predefined layout of zones. If you use Microsoft Office FrontPage® 2003 to create and design Web Part Pages, you have even more flexibility because you can add, remove, and reposition zones on a Web Part Page using the FrontPage page designer.
WSS provides a rendering engine for Web Part Pages by leveraging and extending the underlying ASP.NET infrastructure. WSS routes each Web Part Page request to an instance of the SharePointHandler class—a custom ASP.NET handler. This handler class is defined in the Microsoft.SharePoint.ApplicationRuntime namespace and resides in the Microsoft.SharePoint.dll assembly.
For each Web Part Page request, the SharePointHandler object is responsible for retrieving all the necessary data from the content database. This includes the Web Part Page document which defines a layout of Web Part Zones. The SharePointHandler object must also retrieve data from other tables within the content database to determine how Web Parts have been customized and personalized within specific zones. WSS optimizes the retrieval of all the data it needs for a Web Part Page by obtaining it in a single round-trip to SQL Server™.
Figure 4 Assembling a Web Part Page
After retrieving the data associated with a Web Part Page, the SharePointHandler object is responsible for assembling the HTML page to be returned to the user as shown in Figure 4. The SharePointHandler object creates an object for each Web Part and initializes it with the appropriate customization and personalization data. Finally, the SharePointHandler object enters the rendering phase where it steps through all the Web Part objects in sequence, giving them an opportunity to contribute HTML for the output of the page.
Writing a Custom Web Part
With your newfound understanding of Web Part infrastructure, let's turn our attention to the creation of custom Web Parts using Visual Studio
® .NET. To get started with Web Part development, you should download and install the Web Part Templates for Visual Studio .NET. These templates are distributed in an installer file (.msi) that can be found at
SharePoint Products and Technologies. After you have installed the Web Part Templates, Visual Studio .NET will provide a new project template for creating a Web Part library DLL, along with various other templates for creating files related to Web Part development, such as a source file with the starting point for a Web Part class.
You create a Web Part by authoring a class that inherits from the WebPart class defined inside the Microsoft.SharePoint.dll assembly. The WebPart class exists within the Microsoft.SharePoint.WebPartPages namespace. You are required to override methods of the WebPart class to take advantage of many Web Part features. To create the traditional "Hello, World" Web Part class, you simply need to override a single method named RenderWebPart:
using Microsoft.SharePoint.WebPartPages;
using System.Web.UI;
namespace AcmeWebParts {
public class TedsWebPart : WebPart {
protected override void RenderWebPart(HtmlTextWriter output) {
output.Write("Hello, World");
}
}
}
Figure 5 shows how custom Web Part classes fit into a larger inheritance hierarchy. As you can see, the WebPart class created by the Microsoft WSS team inherits from the Control class created by the ASP.NET team. Therefore, a Web Part is really a specialized type of ASP.NET control. If you have experience developing ASP.NET Web applications or server-side controls, many of the programming techniques you already use can be readily applied when developing Web Parts.
Figure 5 Web Part Class Inheritance Hierarchy
When it comes to providing the code to render HTML, however, there's an important difference between developing ASP.NET controls and developing Web Parts. When you author an ASP.NET control, you render HTML by overriding the Render method. When you author a Web Part, you override the RenderWebPart method instead. Why is this?
The Render method defined in the WebPart class contains generic code to generate the Web Part's title bar and borders. In SharePoint Products and Technologies terminology, this is known as the "chrome" around a Web Part. You should not override the Render method provided by the WebPart class because your resulting Web Part class will not render the standard Web Part chrome correctly. Instead, you should override the RenderWebPart method because this allows you to generate HTML that is displayed properly inside the chrome.
The RenderWebPart method provides the same HtmlTextWriter parameter as the Render method. This means that you can generate HTML for a Web Part in the RenderWebPart method using the same techniques you use for a custom ASP.NET control in the Render method. For example, you can generate an HTML table by calling the RenderBeginTag method and the RenderEndTag method of the HtmlTextWriter parameter, as shown in Figure 6.

Figure 6 Rendering in a Custom Web Part
override void RenderWebPart(ByVal output As HtmlTextWriter) {
// create HTML table with custom attributes
output.AddAttribute(HtmlTextWriterAttribute.Cellpadding, "5");
output.AddAttribute(HtmlTextWriterAttribute.Border, "2");
output.RenderBeginTag(HtmlTextWriterTag.Table);
// create new row
output.RenderBeginTag(HtmlTextWriterTag.Tr);
// create new cell
output.RenderBeginTag(HtmlTextWriterTag.Td);
output.Write("Name:");
output.RenderEndTag(); // </td>
// create new cell
output.RenderBeginTag(HtmlTextWriterTag.Td);
output.Write("Bob Smith");
output.RenderEndTag(); // </td>
output.RenderEndTag(); // </tr>
output.RenderEndTag(); // </table>
}
A Web Part, like other ASP.NET controls, can be designed to be a composite control containing child controls. If you base your custom Web Parts on familiar ASP.NET server-side controls, you can create detailed views and polished data-entry screens without getting bogged down generating DHTML and JavaScript. For example, you can create sophisticated-looking Web Parts quickly using some ASP.NET controls including the DataGrid control, the Calendar control, and the ASP.NET validation controls.
You must override the CreateChildControls method to create a custom Web Part with child controls. Your implementation of CreateChildControls should create and initialize child control objects and then add them to the Web Part object's Controls collection. A simple example that creates a TextBox object and a Button object is shown in the definition for JasonsWebPart in Figure 7.

Figure 7 Custom Web Part with Child Controls
public class JasonsWebPart : WebPart {
// fields to hold child controls
protected TextBox txtName;
protected Button btnSubmit;
// create child control
protected override void CreateChildControls() {
txtName = new TextBox();
this.Controls.Add(txtName);
btnSubmit = new Button();
btnSubmit.Text = "Submit Name";
this.Controls.Add(btnSubmit);
}
// render HTML for Web Part
protected override void RenderWebPart(HtmlTextWriter output) {
txtName.RenderControl(output);
output.RenderBeginTag(HtmlTextWriterTag.Br);
btnSummit.RenderControl(output);
}
}
Examine the implementation of the RenderWebPart method in the JasonsWebPart class and see how it calls the RenderControl method on each child control. When you call RenderControl on a child control and pass it the HtmlTextWriter parameter, the child control responds by writing its HTML into the output stream that will be returned to the user. This example illustrates how a Web Part's implementation of the RenderWebPart method is written to combine the HTML output of all the child controls into a single HTML element.
Web Part Customization and Personalization
One of the most powerful aspects of Web Part technology is its ability to track customization and personalization data. Thankfully, it's also relatively easy to implement. You simply add properties to a Web Part class and mark these properties with special attributes that have been defined by the WSS team. This strategy represents a great example of the power of declarative programming made possible by the .NET Framework. You are not required to write any code for storing or retrieving either customization data or personalization data. All of this is handled by Windows SharePoint Services behind the scenes.
Imagine a scenario in which you are required to develop a custom Web Part that displays the user's local weather report. Since different users live in different places, your Web Part must be designed to track a personalized ZIP code for each user. You can design a Web part to track personalized ZIP codes by defining a ZipCode property with a special set of attributes. It's the presence of these attributes in your compiled code that tells WSS how you would like the property value to be customized or personalized.
Examine the WeatherReportWebPart class definition in Figure 8. This Web Part class defines a public ZipCode property together with a protected _ZipCode field to track the required personalization data. As you can see, the ZipCode property definition contains the WebPartStorage attribute which has been parameterized for personal storage. The presence of the WebPartStorage attribute tells WSS that it should automatically store and retrieve personalization data for this property.

Figure 8 Persisting Personalization Settings
[XmlRoot(Namespace="AcmeWebParts")]
public class WeatherReportWebPart : WebPart {
// Web Part property attributes
[WebPartStorage(Storage.Personal),
DefaultValue(""),
Browsable(true),
FriendlyName("Zip Code"),
Category("User Info")]
public string ZipCode {
get { return _ZipCode; }
set { _ZipCode = value; }
}
// field used as backing store for ZipCode property
protected string _ZipCode = string.Empty;
}
When the SharePointHandler object initializes a Web Part object from the WeatherReportWebPart class, it checks to see if there is customization or personalization data for the Web Part in the content database. If WSS finds a preexisting ZipCode property value, it assigns this value to the ZipCode property while it is initializing the Web Part object. Since the ZipCode property's set block assigns the personalized value to the _ZipCode field, the user's ZIP code is available to all other methods in the WeatherReportWebPart class throughout the lifetime of the Web Part object. This example demonstrates a common technique in which a protected or private field is used to provide a backing store for the public property value.
When you define a persistent property like ZipCode in a Web Part class, WSS automatically supplies user interface elements that allow users to customize property settings. When a user runs a menu command on a Web Part Page to modify a Web Part, WSS displays a Task Pane containing Tool Parts on the right-hand side of the browser window.
A Tool Part is a WSS user interface element that allows a user to examine and modify Web Part property values in the Task Pane. When in shared view, a Tool Part allows the user to work with customized values. When in personal view, a Tool Part allows the user to work with personalized values.
WSS provides standard Tool Parts that allow users to inspect and modify Web Part properties. If you don't like the generic user interface elements created by these standard Tool Parts, WSS makes it possible for you to create your own, and you can take control of how the user interface is generated when a user wants to customize or personalize your custom Web Part properties. Authoring a Tool Part is similar to authoring a Web Part because you can build it as a composite control containing child ASP.NET controls.
Web Part technology is powerful because it provides a sophisticated facility for tracking customization and personalization data. Your sites can be customized and personalized by different users in different ways. All the while, you never have to write any code to manage user membership or to store and retrieve property values inside the content database, so you can spend all of your time writing your business logic instead.
Other Web Part Development Features
When you are writing code for a Web Part, you can program against the WSS object model to access the data for a list or a document library. You can also create a custom Web Part that allows a user to inspect or configure the various security settings for a site. However, it doesn't usually make sense to use the GlobalAdmin object as the entry point into the WSS object model as was shown earlier. Instead, you should acquire an entry point using the SPControl class.
The SPControl class provides two static methods: GetContextSite and GetContextWeb. These two methods allow you to hook into the WSS object model within the context of the current request. The GetContextSite method returns an object that represents the current site collection and the GetContextWeb method returns an object that represents the current site. Both methods require you to pass the ASP.NET HttpContext object associated with the current request. Here's an example that uses the GetContextWeb method from within a custom Web Part to enumerate through the lists of the current site:
SPWeb currentSite = SPControl.GetContextWeb(this.Context);
foreach(SPList list in currentSite.Lists) {
this.ListBox1.Items.Add(list.Title);
}
Another important aspect of Web Parts development is communicating across the network with Web services and other back-end systems. Web Parts are often used to give SPS portal sites and standard WSS sites the ability to act as gateways into enterprise-level applications. Microsoft and other companies have already built Web Parts that act as adapters into popular line-of-business applications such as such as BizTalk®, SAP, and PeopleSoft. You can follow suit and build custom Web Parts that will allow your users to access any of your back-end systems.
A set of security credentials are typically required by Web Parts that are written to communicate with Web services and line-of-business applications. Given this common requirement, SPS was designed with a built-in SSO service for storing and retrieving security credentials. The SSO service can cache security credentials on a user-by-user basis. Alternatively, it can store a common set of security credentials used by all the members of an Active Directory® group. The SSO service does the work required to track the Windows security ID (SID) of the current user when storing or retrieving a set of security credentials from the SSO database. The SSO service also employs the necessary encryption so that security credentials are never stored in the SSO database as clear text.
The Web Part infrastructure supports a feature known as Web Part connections, which represent an extensible customization model by which two or more Web Parts can be joined in a provider/consumer relationship. A user can manually create a connection between Web Parts using either the browser or FrontPage 2003. This makes it possible to create Web Part Pages that display sophisticated views of data with features like master/detail and parent/child relationships.
The WSS infrastructure for connecting Web Parts is based on a loosely coupled model. That means two Web Parts do not require knowledge of each other to be connected on a page. The loose coupling of this model provides the flexibility to connect Web Parts created by different development teams or even by different companies. For example, you can create your own custom Web Parts and connect them to standard Web Parts that are distributed by Microsoft or a third party.
Web Part Deployment and Distribution
You can deploy a Web Part library DLL on a Web server in one of two places: inside a virtual server's \bin directory just like you would deploy assembly DLLs for a standard ASP.NET application, or in the Global Assembly Cache (GAC). A Web Part library DLL in the GAC can be loaded into any virtual server on the hosting Web server machine.
While you are developing and testing Web Parts, it's convenient to configure your Web Part library project to compile its output DLL directly into the \bin directory of the virtual server you will be using for your testing. By following this approach, you will instantly be able to test your Web Parts using the browser after you recompile the Web Part library project.
The fact that Web Part Pages are stored inside the content database poses a security risk. Imagine a scenario in which some malicious individual is able to access the content database and modify the table that holds all the Web Part Page documents. What would happen if this person attempted to mount an attack by placing in-line code within the body of the Web Part Page? You can see the potential problem here.
Fortunately, WSS can defend itself against this kind of attack by processing Web Part Pages in safe mode. When the SharePointHandler object processes the request for a Web Part Page, it will never execute any inline code it finds within the body of the page. Furthermore, the SharePointHandler object will only load Web Parts and ASP.NET controls that have been explicitly configured as "safe controls." You can configure Web Parts and ASP.NET controls using the <SafeControls> section of the hosting virtual server's web.config file.
You will experience an error whenever you run a Web Part Page that attempts to load a Web Part or an ASP.NET control that has not been properly configured as a safe control. Clearly, there must be a set of standard Web Part and ASP.NET controls that WSS marks as safe by default. Whenever you extend a virtual server with WSS, the web.config file that is automatically copied to the root directory contains a <SafeControls> element that includes a set of standard Microsoft Web Parts and ASP.NET server-side controls.
When you deploy a custom Web Part library DLL onto a front-end Web server running WSS, you must modify the web.config file for each virtual server where you plan to run these Web Parts. The <SafeControls> entry in the web.config file should be modified to look like the following code:
<!–- in web.config of hosting virtual server -->
<configuration>
<SharePoint>
<SafeControls>
<SafeControl Assembly="AcmeWebParts" Namespace="AcmeWebParts"
TypeName="*" Safe="True" />
</SafeControls>
</SharePoint>
</configuration>
Note that the preceding example of a <SafeControl> element identifies an assembly using its friendly name (AcmeWebParts). When you deploy a strongly named assembly DLL, you should not use the simple friendly name. Instead, you should use the fully qualified, four-part assembly name which, by the way, you will always be required to use when you deploy a Web Part library DLL in the GAC (the GAC only contains strongly named assemblies).
The security layer provided by the Web Part architecture goes beyond requiring that Web Part and ASP.NET controls be configured as safe controls. A Web Part library DLL running inside the \bin directory is further restricted in what actions it can perform by the <trust> element defined in the web.config file, as shown here:
<configuration>
</system.web>
<!-- set level to (1) WSS_Minimal (2) WSS_Medium or (3) Full -->
<trust level="WSS_Minimal" originUrl="" />
</system.web>
</configuration>
The trust element contains an attribute named level. The value of this attribute configures Code Access Security (CAS) permissions that restrict Web Part library DLLs from performing potentially dangerous actions such as connecting to a SQL Server database or accessing the local file system. The trust element's level attribute is set to WSS_Minimal by default, which severely restricts what a Web Part library can do. This default setting often makes it difficult or impossible to test and debug custom Web Parts during the development cycle.
You can adjust the trust level to WSS_Medium if you want to relax the CAS restrictions. A setting of WSS_Medium usually allows you to test and debug a Web Part without security-related problems. Occasionally, you might have to adjust the trust level setting to Full in order to grant your part full trust. Note that you should run the IISRESET command after adjusting the trust level inside a web.config file.
Remember that the trust level defined in a web.config file only affects Web Part library DLLs running within the \bin directory. The trust-level setting does not affect Web Part library DLLs that have been installed in the GAC. Web Part library DLLs in the GAC are considered to be fully trusted and always run without any CAS restrictions. This factor can influence your decision to deploy a Web Part library DLL in the \bin directory or in the GAC.
Importing Web Parts
The final aspect of Web Part deployment centers on importing description information about the Web Part into a Web Part gallery. WSS supports Web Part galleries at the site-collection level as well as at the virtual-server level. However, before you can import a Web Part's description information into a Web Part gallery, you must first create a Web Part description file.
A Web Part description file is an XML file with a .dwp extension (see Figure 9). The Title and Description elements provide friendly text that is displayed to Web Part consumers as they are browsing through the list of Web Parts that can be added to a Web Part Page. The Assembly and TypeName elements provide WSS with the information it needs to load the associated Web Part class at run time. It's important to remember to use the fully qualified, four-part assembly name when creating a .dwp file for a Web Part library DLL with a strong name.

Figure 9 Web Part Description File
<?xml version="1.0" encoding="utf-8"?>
<WebPart xmlns="http://schemas.microsoft.com/WebPart/v2" >
<!-- display information for Web Part consumers -->
<Title>Weather Report</Title>
<Description>Acme Weather Report Web Part</Description>
<!-- type information for loading Web Part at run time -->
<Assembly>AcmeWebParts</Assembly>
<TypeName>AcmeWebParts.WeatherReportWebPart</TypeName>
<!-- property initialization values -->
<ZipCode xmlns="AcmeWebParts">98052</ZipCode>
</WebPart>
A .dwp file can optionally contain initialization values for one or more Web Part properties. The .dwp file in Figure 9 shows how to use a custom <ZipCode> element to provide an initial default value for the Web Part's ZipCode property. The default ZIP code that's being used in this example is 98052, for Redmond, WA. This means that after being placed on a Web Part Page, this Web Part will initially show the weather report for the Microsoft campus. However, this initial ZipCode property value will be overwritten once it has been customized or personalized by a user.
Once you have created the Web Part description file, you can import the associated Web Part into WSS and use it on a Web Part Page. The simplest way to import it is to choose the Import command from the "Add Web Part" menu while customizing or personalizing a Web Part Page in the browser. The Add Web Parts menu is available as a sub menu of the "Modify Shared Page" menu and the "Modify My Page" menu in the upper right-hand corner of the browser window.
You can also import a Web Part description file into the Web Part gallery of a site collection to make it available to all sites in that site collection. To do this, navigate to the top-level site administration page and scroll down to the Site Collection Galleries section. Next, click the link with the caption "Manage Web Part Gallery." That will bring you to the site collection's Web Part Gallery page. This page provides the option of importing .dwp files.
In addition to importing a Web Part at the site-collection level, you can also import a Web Part into the Web Part Gallery for a virtual server. The process for doing this, however, is more complex because you must first build a Web Part Package. Once you have built the Web Part Package, you can install it using the STSADM.EXE administration tool.
A Web Part Package is a CAB file that contains a Web Part library DLL and all its associated .dwp files. You can easily build a Web Part Package with Visual Studio .NET by creating a new CAB project. When you create a Web Part Package, you must add a special header file named manifest.xml because it contains information that STSADM.EXE needs to properly install and configure a Web Part library DLL.
An example of manifest.xml is shown in Figure 10. As you can see, it contains the file name of the Web Part library DLL and a list of .dwp files. It isn't necessary to add the fully qualified, four-part assembly name of a Web Part library DLL to a manifest.xml file because the STSADM.EXE administration utility is able to discover the assembly name at run time when it loads the Web Part library DLL.

Figure 10 manifest.xml
<?xml version="1.0"?>
<WebPartManifest xmlns="http://schemas.microsoft.com/WebPart/v2/
Manifest">
<Assemblies>
<Assembly FileName="AcmeWebParts.dll">
<SafeControls>
<SafeControl Namespace="AcmeWebParts" TypeName="*" />
</SafeControls>
</Assembly>
</Assemblies>
<DwpFiles>
<DwpFile FileName="TedsWebPart.dwp"/>
<DwpFile FileName="JasonsWebPart.dwp"/>
<DwpFile FileName="WeatherReportWebPart.dwp"/>
</DwpFiles>
</WebPartManifest>
Once you have built a Web Part Package that contains a manifest.xml file, the Web Part library DLL and all the associated .dwp files, you can then install it using the STSADM.EXE administration tool. For example, if you have built a Web Part Package named AcmeWebPartsPack.cab, you can install it using the following command-line instruction:
STSADM.EXE -o AddWPPack -filename AcmeWebPartsPack.cab
When you run this command, the STSADM.EXE utility copies the Web Part library DLL into the \bin directory of each virtual server within the current WSS deployment. You can add the -url parameter to the preceding command-line instruction if you would like to install the Web Part library into only one specific virtual server within the current WSS deployment.
Installing a Web Part Package with STSADM.EXE provides the convenience of adding the required <SafeControl> elements to web.config files to configure each Web Part that is being installed as a safe control. This certainly eases large-scale deployment when you are rolling a new Web Part library DLL out into a Web farm environment.
When installing a Web Part Package with the STSADM.EXE utility, you have the option of installing Web Part library DLLs in the GAC. This can be accomplished by using the -globalInstall parameter, as shown here:
STSADM.EXE -o AddWPPack -filename AcmeWebPartsPack.cab -globalInstall
Using this technique makes it possible to install a Web Part library DLL only once per machine, no matter how many virtual servers use it. As mentioned earlier, Web Part library DLLs installed in the GAC are not restricted by the trust level defined inside the web.config file. Therefore, you should not install Web Part library DLLs into the GAC casually. You should only do that when you know that the DLL has come from a trusted source and that it poses no security risk whatsoever.
If you need to provide CAS settings as part of your Web Part installation, a CAB file installed with STSADM.EXE will not be sufficient. There is, however, a Web Part Packager tool and accompanying white paper that can be downloaded from
SharePoint Products and Technologies. This tool creates .msi installation files that can contain CAS instructions in addition to all of the facilities common to CAB file deployments.
Conclusion
WSS and SPS are two different offerings that have been designed to work well together. WSS provides the foundation for creating collaborative Web sites that support customization and personalization and SPS complements WSS by playing the role of a content aggregator. Because SPS is fully dependent on the underlying infrastructure of WSS, the more you know about WSS, the easier it will be to master SPS.
On one hand, SharePoint Products and Technologies decrease the need for custom software development because WSS and SPS provide so much functionality right out of the box. Yet they also provide valuable opportunities to write custom applications and Web Parts. Now that you have a roadmap, it's time to get started on your SharePoint development.
Jason Masterman and Ted Pattison have both been working in the software industry for over a decade writing software, consulting, and educating developers. In 2003, Jason and Ted founded Barracuda .NET, a leading-edge consulting and training company that focuses on Microsoft collaboration technologies. Go to
http://Barracuda.net to find out more about their training classes and online events.