Microsoft SharePoint Products and Technologies Resource Kit

 

This chapter is taken from Microsoft SharePoint Products and Technologies Resource Kit published by Microsoft Press; ISBN 073561881X; copyright Microsoft Press 2005; all rights reserved. The author, Bill English, MCSE, Microsoft Certified Trainer, is a Microsoft MVP for Microsoft SharePoint Products and Technologies, a member of the Microsoft SharePoint Beta team, and the author and coauthor of eight computer books. The Microsoft SharePoint Team develops and supports Microsoft Office SharePoint Portal Server 2003 and Microsoft Windows SharePoint Services.

No part of these chapters may be reproduced, stored in a retrieval system, or transmitted in any form or by any means—electronic, electrostatic, mechanical, photocopying, recording or otherwise—without the prior written permission of the publisher, except in the case of brief quotations embodied in critical articles or reviews.

Chapter 37: Using Visual Studio .NET to Create Web Parts

Contents

Web Part Architecture
Strong-Naming Assemblies
Code Access Security
Creating a Web Part
Debugging Web Parts
Creating Child Controls on a Web Part
Web Part Tools
Summary

Microsoft SharePoint Products and Technologies offers a managed object model that can be used to create your own custom solutions in a developer-friendly way using Microsoft Visual Studio .NET. This chapter and Chapter 31, "Working with Web Parts," introduce you to the basic things you need to know to be successful in Web Part development.

Web Part Architecture

To understand how the Web Part architecture works, you need to look at the smallest piece within the architecture, the Web Part itself, and then zoom out gradually to less granular levels. This is the approach that is taken by this section.

Web Parts

Web Parts are the basic building blocks of a Web Part Page, each one providing its own specific set of features. For example, a news Web Part is responsible for showing news items. You are responsible for deciding how many and which Web Parts should be placed on a Web Part Page.

SharePoint Products and Technologies comes with several Web Parts that users can use right away, and many more are available in the online Web Part gallery. For more information about these Web Parts, see Chapter 31, "Working with Web Parts" Several other software vendors offer free or commercial Web Parts that you can use. In addition, you can create your own Web Parts using Microsoft Visual Studio .NET, which is the topic of this chapter.

Every Web Part derives from the Microsoft.SharePoint.WebPartPages.WebPart class. Because the Web Part base class derives from System.Web.UI.Control, every Web Part is a Microsoft ASP.NET Web control. This means Web Parts, like all controls, participate in page rendering, property settings, post-back events, and state management.

Placing Web Parts

Web Parts can be placed on Web Part zones. A Web Part zone is a server control that derives from the Microsoft.SharePoint.WebPartPages.WebPartZone class. Web Part zones are located on a Web Part Page, and every Web Part zone can contain one or more Web Parts.

At this point, you might assume that every Web Part should be placed within a Web Part zone, which is not the case. Placing a Web Part within a Web Part zone has its advantages. By doing this, you tap into the power of the customization and personalization services offered by the SharePoint Products and Technologies framework, discussed in Chapter 23, "Personalization Services in SharePoint Products and Technologies."

You can also place a Web Part on a Web Part Page outside of a Web Part zone. The advantage of doing this is that you ensure the properties of such a Web Part are static. Because the Web Part properties cannot be customized or personalized, the Web Part will always have the same set of properties. The properties of a static Web Part are not stored in the database but are stored in the page itself.

Finally, because a Web Part is an ASP.NET Web control, it can also be used outside a Web Part Page as a standard Web form control. A Web Part can be placed directly on any .aspx page in the same way you would place any other custom control. Essentially, this is very similar to placing a Web Part outside of a Web Part zone.

Web Part Pages

Every SharePoint site consists of Web Part Pages. A Web Part Page is a special type of Web page that can contain one or more Web Part zones. Every Web Part Page derives from the Microsoft.SharePoint.WebPartPages.WebPartPage class, which in turn is derived from the System.Web.UI.Page class.

When you work with Web Part Pages, it's important to realize that a Web Part Page can be in one of two states: ghosted or unghosted. This concept can be confusing when you're new to SharePoint Products and Technologies, but basically, ghosted pages are Web Part Pages that are stored on the file system, and unghosted pages are stored in the SharePoint database.

Ghosted pages are all Web Part Pages that are rendered from the root virtual directory main application root and its subfolders, as well as Web Part Pages stored in SharePoint document libraries. Ghosted pages do not include pages that come from the child virtual directories _layouts and _vti_bin. Examples of ghosted pages are the default home page and the new Web Part Pages. A ghosted page becomes unghosted after the page or one of its properties has been modified, for example, using Microsoft Office FrontPage 2003 or Web folders. The state of a Web Part Page has significant consequences during Web Part Page rendering.

Web Part Page Rendering

In a SharePoint Products and Technologies environment, each page request that hits Microsoft Internet Information Services (IIS) is handed over to the ASP.NET HTTP pipeline. The HTTP pipeline is a chain of managed objects that sequentially processes the request and makes the transition from a URL to plain HTML text.

At installation time, the SharePointHandlerFactory registers itself as the IHttp-Handler for all .aspx requests. This association between types of resources and types of handlers is stored in the configuration file of the SharePoint site. More exactly, the default set of mappings is defined in the <httpHandlers> section of the web.config file. The following shows the code that defines the HTTP handler for .aspx resources after Microsoft Windows SharePoint Services is installed.

<add verb="*" path="*.aspx"
   type="Microsoft.SharePoint.ApplicationRuntime
   .SharePointHandlerFactory"/>

The SharePointHandlerFactory IHttpHandler requires that all page requests are Web Part Pages, that is they derive from the Microsoft.SharePoint.WebPartPages. WebPartPage class. The following code shows the **@Page** directive that ensures that the Web page is a Web Part Page.

<%@ Page language="C#"
   Inherits="Microsoft.SharePoint.WebPartPages.WebPartPage" %>

If the **@Page** directive is missing, it defaults to a Web Part Page type and the request is passed to the Web Part infrastructure for rendering. Any requests whose **@Page** directives identify Web Part Page types are also passed to the Web Part infrastructure. If an **@Page** directive identifies a page that is not a Web Part Page, the following error is returned: "To run as a WebPartPage, this page must derive from a class which is derived from the Microsoft.SharePoint.WebPartPages.WebPartPage object."

After the request is passed to the Web Part infrastructure, Windows SharePoint Services determines whether the page is ghosted or unghosted. For ghosted pages, the request is handed off to the ASP.NET infrastructure for rendering; otherwise, the page is rendered by the SafeMode parser that is part of the Web Part infrastructure. The following steps are taken during this page rendering process:

  • Retrieval of the page's collection of Web Parts, and a determination whether the page is in personal or shared view; personalization and customization considerations are resolved.
  • Verification that every part in a Web Part zone is in the SafeControls list. If a page is parsed by the SafeMode parser, all server controls, even those that are not a part of a Web Part zone, are validated against the SafeControls list, which is located in the web.config file.

The infrastructure then creates each Web Part until all the parts are rendered on the page and the page is returned to the requestor.

Web Part Rendering

Rendering a Web Part is handled by the standard ASP.NET rendering process. The Render method of the WebPart class is inherited from the System.Web.UI.Control class and is used by the Microsoft.SharePoint.WebPartPages.WebPart base class to add the frame around the content provided by the Web Part. The Render method also calls the RenderWebPart method so the Web Part can generate the HTML that is rendered inside the Web Part frame. Although the Render method on the base class is defined as overridable, it is not recommended that you do so. Instead, implement any rendering for the Web Part in the RenderWebPart method. The entire rendering process is shown in Figure 37-1.

Rendering Web Part Pages and Web Parts

Figure 37-1. Rendering Web Part Pages and Web Parts

Page States Explained

We have seen that Web Part Pages can be in different states. The main reasons for SharePoint Products and Technologies to store some templates in the file system (ghosted) and some in the database (unghosted) have to do with security and scalability.

When a client requests an unghosted page, the Web Part Page is rendered by the SafeMode parser. The SafeMode parser ensures unghosted pages are not allowed to run untrusted code. This security feature prevents a user from injecting code into Web Part Pages that might, maliciously or unintentionally, bring down a server or hijack data. After a page is transitioned from a ghosted to unghosted state, the SharePoint administrator knows that page cannot influence the behavior of the server in such ways. Remember, a ghosted page becomes unghosted after the page or one of its properties has been modified, for example, using FrontPage 2003 or Web folders. Pages that are created through the SharePoint user interface are ghosted, but pages that are newly uploaded will be unghosted. In other words, if you upload a new file to a SharePoint folder or document library, the page is automatically and permanently considered unghosted.

Additionally, without the SafeMode parser, all pages would have to be routed through ASP.NET, which would mean all pages would be compiled and their associated assemblies would be loaded into memory. On a site with thousands of operational pages, the memory requirement would be huge. In the current design, using the SafeMode parser, page compilation is limited to a very small number of pages relative to the actual number of pages within a SharePoint–extended virtual server.

Another benefit of unghosted pages becomes clear in Web farm scenarios. SharePoint Products and Technologies do not offer any features that replicate physical files or data from one front-end Web server to another. This means if you change a Web Part Page on front-end Web server A, you should make the same change on front-end Web server B. Unghosting a page allows only one copy of the page to exist for any given number of front-end Web servers.

Strong-Naming Assemblies

Every Web Part exists within an assembly. The Web Part assembly, a dynamic-link library (DLL) file, contains one assembly manifest that describes the assembly itself and contains several global attributes. Assemblies are referenced by using their names. An assembly name consists of a text name, which is usually the name of the assembly without the file extension. In addition to this name, the assembly name can consist of an assembly version number and a culture reference. The assembly name can be further qualified by using a public key token. The assembly name, version number, culture, and public key token of an assembly are called the assembly's full name, also known as the strong name.

The next XML fragment is taken from the web.config file located in the Windows SharePoint Services extended virtual server root directory.

<SafeControl Assembly="ResKitLibrary, Version=1.0.0.0, Culture=neutral, 
   PublicKey-Token=3fab337e00400dc5" Namespace="ResKitLibraryNamespace" 
   TypeName="*" Safe="True" />

The web.config file is used to specify the settings for the specific virtual server where Windows SharePoint Services or Microsoft SharePoint Portal Server 2003 is installed. It clearly shows how the Web Part assembly name consists of several parts. The first part refers to the name of the assembly, followed by the assembly version number and the culture. It also includes a public key token related to the strong name of the assembly. The <SafeControl> element also contains a Namespace attribute referring to one of the namespaces used within the assembly and a TypeName attribute referring to the simple type name. For example, if a control is named MyControl and the namespace is MyNamespace, the TypeName attribute would contain MyControl and not MyNamespace.MyControl.

Note   This differs from the type name described in Web Part description files (.dwp). Web Part description files require the full type name for the TypeName node. A SafeControl entry only requires the simple type name. For detailed information about Web Part description files, see Chapter 31 "Working with Web Parts."

If you specify a wildcard (*), every type name is selected. You can also explicitly specify the type name. Finally, the <SafeControl> element can contain a Safe attribute. If the Safe attribute is omitted, the SafeControl entry defaults to true. If a Web Part fails to meet the SafeControl validation, you will get an error message informing you that "A Web Part or Web Form Control on this Web Part Page cannot be displayed or imported because it is not registered on this site as safe."

The Safe attribute indicates whether a server control is considered to be safe to be executed. This attribute can be set to false if you temporarily want to disable a Web Part. This provides fine-grained control to the administrator of what is running on the server. Suppose you have installed an assembly from company A that contains a set of ten Web Parts. And suppose that one of the Web Parts contains a critical error that can bring down the server. By setting the Safe attribute to false, the administrator can prevent this Web Part from running on the server without having to remove the entire assembly. Therefore, business functionality involving all other Web Parts can remain intact.

If you want to import and place a Web Part on a Web Part Page, you should register the Web Part as a safe control. Failing to do so will prevent the Web Part import and rendering. You can register the Web Part as a safe control by adding a <SafeControl> element to the web.config file

Web Part library assemblies can be installed in one of two locations. First, you can place the DLL in the bin directory of the Windows SharePoint Services extended virtual server root directory. In this case, the Web Part is available only to the virtual server containing this directory. Second, you can place the DLL in the global assembly cache. This makes the assembly accessible to all applications on the server. Assemblies installed in the global assembly cache are granted Full Trust by the policy files used by either Windows SharePoint Services or ASP.NET. A Web Part library can only be placed in the global assembly cache if it is signed. For more information about this topic, see the procedure "To create a strong name key pair file," later in this chapter.

Code Access Security

The Microsoft .NET Framework provides a security mechanism called code access security. Code access security is a process that helps limit the access code has to protected resources. This could be code from a third party or code that you have written yourself. Although code access security is something that has been around for quite some time, SharePoint Products and Technologies are the first technologies to really bring it to the forefront. SharePoint Products and Technologies use .NET code access security to control access to protected resources. With code access security, you can assign to an assembly a configurable level of trust that corresponds to a predefined set of permissions.

Note   For more information about code access security, see Microsoft Windows SharePoint Services and Code Access Security.

To allow the administrator to easily switch the levels of trust that are assigned to an application, Windows SharePoint Services includes code groups of its own in addition to the default policies that are installed by ASP.NET. Windows SharePoint Services includes two security policy files: WSS_Minimal and WSS_Medium. You can specify a level of trust that corresponds to a predefined set of permissions for ASP.NET applications, ranging from "Minimal" to "Full." SharePoint Products and Technologies define two additional trust levels: "WSS_Minimal" and "WSS_Medium." The exact location of the security policy files can be found in the <securityPolicy> section in the web.config file, as shown here:

<securityPolicy>
   <trustLevel name="WSS_Medium" 
   policyFile="C:\Program Files\Common Files\Microsoft Shared\
   Web Server Extensions\60\config\wss_mediumtrust.config" />
   <trustLevel name="WSS_Minimal"
   policyFile="C:\Program Files\Common Files\Microsoft Shared\
   Web Server Extensions\60\config\wss_minimaltrust.config" />
</securityPolicy>

The default trust level is WSS_Minimal, but you can change this using the level attribute of the <trust> element, as shown here:

<trust level="WSS_Minimal" originUrl="" />

The SharePoint Products and Technologies class libraries use code access security to protect certain resources and operations by specifying the permissions that they require to run. The members of the SharePoint class libraries require a reference to the SharePointPermission class with the ObjectModel property set to true. You should ensure that any assemblies you create that use the Windows SharePoint Services object model have this permission.

Note   If you look at the .NET Framework Class Library information, which can be found on MSDN, you will notice a Requirements section that outlines the permissions required in order to execute a method.

If the default permission level does not suit your needs, you can ensure that your code has the required permissions in other ways: You can:

  • Consider installing the assembly in the global assembly cache because the code in it, by default, has Full trust. Installing assemblies in the global assembly cache is not recommended; it's best to assign to the assembly the lowest level of permissions possible.
  • Consider raising the trust level for the virtual server extended with SharePoint Products and Technologies.
  • Create a custom security policy and assign the needed permissions to the specific assembly or set of assemblies.

Note   For more information about raising the trust level for assemblies, see Microsoft Windows SharePoint Services and Code Access Security.

Your code may also need the following permissions in these circumstances:

  • If your code tries to write data to the SharePoint configuration database on an HTTP Get, or if the code needs to enable Web Part to Web Part connections, your code might need two permissions that are specific to SharePoint Products and Technologies: SharePointPermission.UnsafeSaveOnGet and WebPartPermission.Connections.
  • If you want to use the classes and members in the Microsoft.SharePoint.Portal.SingleSignOn namespace, your code will need SingleSignOnAccess permission
  • If your code tries to perform an action or access a resource that is protected by the common language runtime, your code might need one or more of the default .NET Framework permissions.

Changing trust levels for the virtual server is an easy approach to granting or revoking permissions. Changing the trust level is a global change affecting all assemblies. For example, an administrator might want to either grant more permissions or reduce the number of permissions granted to specific assemblies. To do this, the administrator must create a custom code group and add it to the security policy file.

To customize one of the built-in policy files, you should make a copy of it and change the copy to ensure that you can reuse the original file, if necessary. The following procedure describes how to give access to the SharePoint Products and Technologies object model to a specific assembly.

To create a custom security policy

  1. Copy the wss_minimaltrust.config file, which is located by default at <Local Drive>:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\60\config\wss_minimaltrust.config.

  2. Rename the file new_file_name.config.

  3. Use a text editor to open new_file_name.config.

  4. Under the <SecurityClasses> element, add a reference to the SharePointPermission class, as follows:

    <SecurityClasses>
    ..
       <SecurityClass Name="SharePointPermission"
       Description="Microsoft.SharePoint.Security.SharePointPermission,
       Microsoft.SharePoint.Security,Version=11.0.0.0, Culture=neutral,
       PublicKeyToken=71e9bce111e9429c "/>
    </SecurityClasses>
    
  5. Search in your .config file for the <PermissionSet> element where the name attribute equals ASP.Net.

  6. Copy this entire tag and all of its children, and paste a copy of it immediately following the one you copied.

    <PermissionSet 
       class="NamedPermissionSet" 
       version="1" 
       Name="new_permission_set_name">
    </PermissionSet>
    
  7. Add the following <IPermission> element to the <PermissionSet> element where the name attribute equals New_Permission_Set_Name:

    <IPermission class="SharePointPermission" version="1" ObjectModel="True" />
    
  8. Create a code group to specify when the common language runtime should apply the permission set. By default, the AllCode code group is a FirstMatchCodeGroup in ASP.NET policy files. Therefore, the common language runtime stops assigning permissions to an assembly after the first match to a specific code group. To apply the custom permissions, you must declare the specific code group assigning the custom permissions to your assembly as the first code group within the AllCode group. This ensures that the common language runtime assigns your New_Permission_Set_Name permission set and stops without proceeding to the default $AppDirUrl$/* code group that is used to assign permissions based on whether the assembly is located in bin directory.

    To do this, add the <CodeGroup> element to your .config file. In the following example, the membership condition for the new code group is based on strong-named membership. Therefore, the <IMembershipCondition> element contains a PublicKeyBlob attribute. The next step discusses how to obtain the public key binary large object (BLOB).

    <CodeGroup class="UnionCodeGroup" version="1" Permission-
       SetName="New_Permission_Set_Name">
       <IMembershipCondition class="StrongNameMembershipCondition"
          version="1" PublicKeyBlob="..  .." ="[see the next step]" Name="
             MyAssemblyName " /> </CodeGroup>
    
  9. To retrieve the public key BLOB for an assembly, use the Secutil.exe tool as follows: secutil.exe -hex -s MyAssemblyName.dll

  10. The Secutil tool extracts strong name information or the public key for an X.509 certificate from an assembly and converts this information into a format that can be incorporated into code.

    Note   The Secutil tool returns a string in the form of

    ""0X

    . . .

    ".

    . . .

    "

    . You should not include the 0X notation marker when copying the public key BLOB to the policy file.

  11. Save and close your .config file.

  12. Open the web.config file for your Windows SharePoint Services virtual server, and add the following <trustLevel> element:

    <trustLevel name="MyCustomTrustLevel"
                 policyFile="new_file_name.config" /&gt
    
  13. Go to the <trust> element in the web.config file, and adjust it so that it refers to your custom trust level.

    <trust level="MyCustomTrustLevel" originUrl="" />
    
  14. Save and close the web.config file, and run iisreset.

    Caution   Failing to run iisreset can result in the display of the following error message**: "Assembly AssemblyName security permission grant set is incompatible between app domains."** In ASP.NET programs, strong-named assemblies are loaded in a neutral domain. These assemblies are not unloaded until the process is stopped.

    Therefore, if the security policy for a strong-named assembly is altered, the common language runtime will cause an error message to appear when it detects that differing grant sets have been applied to the same assembly. This behavior typically occurs in scenarios where the trust level for a strong-named assembly has been changed.

    Another way to resolve this is to manually recycle the site's associated application pool in the Internet Services Manager for IIS. To do this, in IIS Manager, expand the local computer, expand Application Pools, right-click the application pool, and then click Recycle.

Creating a Web Part

In Web Part Architecture, you learned that a Web Part is a special kind of Web control that derives from the Microsoft.SharePoint.WebPartPages.WebPart class. If you first start developing Web Parts with Visual Studio .NET, you should download the Web Part template from the Microsoft Developer Network (MSDN). The installation of this template isn't mandatory, but it makes Web Part development a lot easier. The Web Part template provides support for both C and Microsoft Visual Basic .NET development.

Note   For more information about Web Part templates, see Web Part Templates for Microsoft Visual Studio .NET.

After installing the Web Part template the creation of a Web Part is easy. You can use Visual Studio .NET to create a new Web Part library project. Web Part libraries contain Web Parts.

To create a new Web Part library project

  1. Start Visual Studio .NET.

  2. On the File menu, point to New and then click Project.

  3. In the New Project dialog box, click Visual C Projects and then select the Web Part Library template.

    Tip   If you want to create a Visual Basic .NET project, select the Web Part Library template from Visual Basic Projects instead.

Now a reference to the Microsoft.SharePoint DLL is added and a WebPart class and a .dwp file are created. The default name of the WebPart class is WebPart1.cs. This class does not need much work before it can be used; just locate the RenderWebPart method and replace SPEncode.HtmlEncode(Text) with SPEncode.HtmlEncode("Hello World!"). Then you will be ready to create your first Web Part. The RenderWebPart method is shown below (in C).

/// <summary>
/// Render this Web Part to the output parameter specified.
/// </summary>
/// <param name="output"> The HTML writer to write out to </param>
protected override void RenderWebPart(HtmlTextWriter output)
{
   output.Write("SPEncode.HtmlEncode("Hello World!"));
}

Note   In this example, the use of SPEncode.HtmlEncode is superfluous, but in general you should HTML encode your strings so that script injection bugs are avoided at all times.

Next you should create a name for the Web Part so that it can be identified uniquely. Strong naming the Web Part library assembly is a crucial step in accomplishing this.

The first step you need to take if you want to strong name an assembly is generating a strong name key pair file, which can be done using the Strong Name tool (sn.exe), which is installed with the .NET Framework SDK.

To create a strong name key pair file

  1. Create a file containing the key pair. From a command prompt on the drive where you installed Visual Studio .NET, type the following: cd \Program Files\Microsoft Visual Studio .NET\FrameworkSDK\Bin\ or \Program Files\Microsoft Visual Studio.NET 2003\SDK\v1.1\Bin if you are using Visual Studio .NET 2003.

  2. Type the following: sn.exe -k c:\mykey.snk

  3. Next open the AssemblyInfo.cs file to set the version number of the assembly. Remember, the version number is also a part of the assembly name. The following code shows how to use the AssemblyVersion property to set the version number of the assembly to 1.0.0.0.

    [assembly: AssemblyVersion("1.0.0.0")]
    

It is best to set the version number to a known value instead of using a wildcard (*) for the minor parts. When a Web Part is added to the page, Windows SharePoint Services uses the assembly's full name to determine the Web Part type. As long as the version number does not change, Windows SharePoint Services will always be able to find Web Part X, version V, from assembly Y. This information is stored in the SharePoint database. If you are using a wildcard the version number is changed the next time you compile your assembly. At that point, you will have Web Part X, version Q, from assembly Y, which does not match to the record in the SharePoint database. This results in a mismatch stating that the Web Part is not safe.

Adjust the AssemblyKeyFile property so that it refers to the strong name key pair file to make sure the name of the assembly is unique after compilation.

[assembly: AssemblyKeyFile(@"c:\mykey.snk")]

There are two default locations where the .NET common language runtime will look for .NET assemblies when operating within the context of a Windows SharePoint Services extended server. One of them is the global assembly cache, and the other one is the bin directory of your Windows SharePoint Services extended virtual server root directory (for example, the c:\inetpub\wwwroot\bin folder).

During Web Part development, changing the build output path to the bin folder of your SharePoint virtual server is recommended so that you don't have to copy the assembly file every time after compilation.

To specify the build output path

  1. In Solution Explorer, right-click your project name, and then click Properties.
  2. Under Configuration Properties\Build\Outputs, set the Output Path to the bin folder within the root folder of the Windows SharePoint Services extended virtual server, for example: c:\inetpub\wwwroot\bin.

Deploying a Web Part

Now you are ready to compile the Web Part. However, before you're able to use the Web Part, there are a couple more things you need to do. The <SafeControls> section of the web.config file specifies which Web Parts are trusted. So, you need to register your own Web Part as a safe control. The following code shows an example of the <SafeControls> section:

<SafeControls>
..
   <SafeControl Assembly="Microsoft.SharePoint.Solutions.GreatPlains,
      Version=11.0.0.0, Culture=neutral, 
      PublicKeyToken=71e9bce111e9429c" Namespace="Microsoft.SharePoint
      .Solutions.GreatPlains" TypeName="*" Safe="True" />
   <SafeControl Assembly="Microsoft.SharePoint.WebParts.QuickQuote,
      Version=11.0.0.0, Culture=neutral,
      PublicKeyToken=71e9bce111e9429c" Namespace="Microsoft.SharePoint
      .WebParts.QuickQuote" TypeName="*" Safe="True" />
</SafeControls>

The Assembly attribute of the <SafeControl> element shows the assembly name of the Web Part assembly, and optionally a version number, a culture reference, and a public key token. Now you should determine the public key token of your Web Part library assembly so that you can create a safe control entry for your Web Part in the web.config file. The easiest way to accomplish this is to copy the assembly DLL file into the global assembly cache. Locate the DLL file, right-click the DLL, and copy the public key token. After this, don't forget to remove the assembly .DLL file from the global assembly cache. You could also use the Strong Name tool (sn.exe) to obtain the public key token.

To use sn.exe to obtain the public key token

  1. From a command prompt on the drive where you installed Visual Studio .NET, type the following: cd \Program Files\Microsoft Visual Studio .NET\FrameworkSDK\Bin\ or \Program Files\Microsoft Visual Studio.NET 2003\SDK\v1.1\Bin if you are using Visual Studio .NET 2003.

  2. Type the following: sn.exe -T [MyAssemblyPath\MyAssemblyName.dll]

    Note   The –T flag is case sensitive. Only the –T (in uppercase) will give you the correct public key token.

  3. Next, create your own <SafeControl> element. The following example shows a Web Part library named ResKitLibrary in the ResKitLibrary namespace.

    <SafeControl Assembly="ResKitLibrary, Version=1.0.0.0, 
       Culture=neutral, Public-KeyToken=3fab337e00400dc5"
       Namespace="ResKitLibraryNamespace" TypeName="*"
       Safe="True" />
    

Before you can import your Web Part on a Web Part Page, you need to create a Web Part Definition (.dwp) file. The .dwp file is an XML file that contains property settings for a Web Part. The most important properties when installing a Web Part in the .dwp file are the <Assembly> and <TypeName> elements. The <Assembly> element contains the assembly name, simple or full, of the Web Part assembly; the <TypeName> element contains the full type name for the Web Part. The following code shows the content of an example .dwp file:

<?xml version="1.0" encoding="utf-8"?>
<WebPart xmlns="http://schemas.microsoft.com/WebPart/v2" >
   <Title>TestPart</Title>
   <Description>Our TestPart</Description>
   <Assembly>ResKitLibrary, Version=1.0.0.0, Culture=neutral,
      PublicKeyToken=3fab337e00400dc5</Assembly>
   <TypeName>ResKitLibrary.TestPart</TypeName>
</WebPart>

Now, for the final stage, you're ready to import the Web Part into a Web Part Page.

To import your Web Part into a Web Part Page, simply upload the .dwp file. After uploading the Web Part, you can display the Web Part by dragging it into one of the zones of the Web Part Page.

To import your Web Part into a Web Part Page

  1. Open a Web Part Page on your server.

  2. Click Modify My Page or Modify Shared Page (depending on whether you are in Personal View or Shared View) in the upper-right corner of the page, and click Add Web Parts from the menu.

  3. Click Import.

  4. Browse to the location of your .dwp file and click the Upload button. After uploading, the page will refresh and your Web Part should be displayed under Imported Web Part.

  5. Drag the icon next to your Web Part to a zone on the Web Part Page.

    The end result is shown in Figure 37-2.

    Custom Web Part imported into Web Part Page

    Figure 37-2. Custom Web Part imported into Web Part Page

More Info   If you want to know more about Web Part Deployment, you can also refer to Using Wppackager to Package and Deploy Web Parts for Microsoft SharePoint Products and Technologies and Packaging and Deploying Web Parts for Microsoft Windows SharePoint Services.

Debugging Web Parts

The previous "Hello, World!" Web Part example was simple to create in terms of code. As soon as you start doing serious Web Part development, you will need the available Web Part debugging techniques.

When debugging Web Parts, there are two important questions to ask. The first question concerns how you want to attach to the process that runs your Web Part: either manually or automatically. The other question depends on who is generating the symbol table (.pdb), to which the debugger must have access to debug the code: you or ASP.NET.

If you want to start the debugging process manually and you already have code-behind assemblies and a symbol table in place, you do not have to change any settings within Visual Studio .NET. In this scenario, you will not be able to debug inline code.

If you want to debug code within the .aspx page itself and you want ASP.NET to generate the symbol table, for any pages that it compiles you need to set the trust level in the web.config file to at least WSS_Medium.

If you want Visual Studio .NET to automatically attach itself to the process that runs your Web Part, you need to set the debugging settings to true. You can do this by setting the debug attribute of the <compilation> element in the web.config file to true, like this: <compilation batch="false" debug="true" />. You should also make sure that debugging is enabled for your Web Part library project. You can do this by right-clicking the project name in Solution Explorer and choosing Properties. Then choose Configuration Properties | \Debugging, and set Enable ASP.NET Debugging to True.

The next step in the debugging process, regardless of the scenario that applies to you, is to set breakpoints in your code. For example, the RenderWebPart method would be a good place to set a breakpoint. You can set breakpoints by opening your Web Part assembly in Visual Studio .NET, going to the line of code where you want to enter a breakpoint, right-clicking the line, and then clicking Insert Breakpoint.

You can manually attach to the ASP.NET debugging process, W3wp.exe, to debug your Web Part. This method is less useful in situations where you are in the middle of a repeated development and debugging cycle. However, this method is extremely helpful in situations where you are attempting to debug code access security–related problems. In a scenario in which you are automatically attaching to a process, you might have to artificially raise the trust level (to at least WSS_Medium). This could possibly hide security exceptions that might be encountered only at lower trust levels.

To manually attach to the ASP.NET debugging process

  1. Set up a Web Part Page with the Web Part you want to debug on your local server running SharePoint Products and Technologies.
  2. Attach the debugger to the ASP.NET process: W3wp.exe.
    1. On the Debug menu, click Processes.
    2. Select the Show system processes and Show processes in all sessions check boxes.
    3. In the Available Processes list, select W3wp.exe and then click Attach.
    4. In the Attach to Process dialog box, select Common Language Run-time and then click OK.
    5. Click Close.

You are now ready to step through your code.

You can automatically attach to the W3wp.exe process for debugging purposes. This method is probably the one you will use most often during Web Part development.

To use a startup page and automatically attach to the process

  1. Right-click the project name in Solution Explorer, and then click Properties.
  2. Click Configuration Properties, and then click Debugging.
  3. Under Start Action, set Debug Mode to URL and then set Start URL to the URL of the Web Part Page that uses your Web Part.
  4. Click OK, and then save your project.
  5. On the Debug menu, click Start. The debugger should launch the browser with your Web Part Page, attach to the process, and allow you to debug automatically.

After attaching to the W3wp.exe process, you are now ready to step through the code. Request the Web Part Page with the target Web Part in it. As the Web Part Page and the Web Part render, depending on where the breakpoint is set you will notice that the control switches to the Visual Studio debugger. After the control is in the debugger, you can step through the code and identify the problem by using the debugger's available functionality.

Using the CallStack Attribute

Windows SharePoint Services overrides the CallStack attribute. This attribute is located in the web.config file. The CallStack attribute controls whether a call stack and an exception message are displayed when a system-level exception occurs while ASP.NET processes a request to send a page to all local and remote clients. By default, Windows SharePoint Services disables the CallStack attribute and displays a limited set of exceptions to prevent information disclosure.

To receive a call stack and an exception message when an exception occurs, enable the CallStack attribute.

To enable the CallStack attribute

  1. In Windows Explorer, browse to the root folder of the Windows SharePoint Services extended virtual server, for example: local_drive:\InetPub\wwwroot\bin\.
  2. Double-click the web.config file.
  3. In the web.config file, search for the <SharePoint> element.
  4. In the <SharePoint> element, locate the <SafeMode MaxControls="50" CallStack= "false"/> tag and change it to <SafeMode MaxControls="50" CallStack="true"/>.
  5. Save and close the file.

When exceptions occur, you now receive ASP.NET exception messages with stack trace information.

Note   The CallStack attribute enables this functionality for all local and remote clients.

Using Tracing in ASP.NET

You can use the tracing feature in ASP.NET to monitor the environment of the server on which you are programming. You can use tracing on a specific page or for an entire application.

You can use tracing on a local server without enabling it for remote clients.

To enable ASP.NET tracing on a local server

  1. In Windows Explorer, browse to the root folder of the Windows SharePoint Services extended virtual server, for example: local_drive:\InetPub\wwwroot\bin\.

  2. Double-click the web.config file.

  3. In the web.config file, search for the <system.web> element.

  4. In the <system.web> element, add the following line:

    <trace enabled="true" pageOutput="true"/>
    
  5. Save and close the file.

The environment information now appears at the bottom of the test page that includes the Web Part.

Creating Child Controls on a Web Part

Now that you've seen how to create a simple Web Part and debug it, you're ready for the next level: creating child controls on a Web Part. This provides you with the possibility to create more sophisticated Web Parts. This section describes how to add TextBox and Button controls to a Web Part.

First you need to declare two member variables named myTextBox and myButton at the top of the WebPart class, as follows:

private TextBox myTextBox;Button myButton;

Tip   Make sure you have added the System.Web.UI.WebControls namespace.

Next you need to override the CreateChildControls method, which is the place to instantiate child controls, initialize them, and add them to the control tree. The CreateChildControls method is called automatically by the framework. The following code example shows a CreateChildControls method that can be copied into a WebPart class. The method adds two controls to the control tree: a TextBox control and a Button control. The Click event of the button control is associated with an event handler named myButton_Click.

protected override void CreateChildControls ()
{        
   myTextBox = new TextBox();
   myTextBox.Text = "hi!";   
   Controls.Add(myTextBox);
   myButton = new Button();
   myButton.Text = "Push the button!";
   myButton.Click += new System.EventHandler(myButton_Click);
   Controls.Add (myButton);
}

The implementation of the event handler depends very much on your specific needs. The following example can be copied into a WebPart class and shows how to retrieve the value of the TextBox control:

private void myButton_Click(object sender, System.EventArgs e)
{
   string strValue = myTextBox.Text;
}

Do not override the Render method of the WebPart class because it is responsible for adding the frame around the content provided by the Web Part. Instead, you should override the RenderWebPart method, which is called by the Render method. The RenderWebPart method is called whenever the Web Part needs to be displayed, so it is called every time the Web Part Page that contains your Web Part is called.

If you are not sure about the control execution life cycle, you can call the EnsureChildControls method from any code that needs to access a child control. The EnsureChildControls method checks whether the child controls have been created. If the child controls have not been created, it invokes the CreateChildControls method.

Note   For more information about the control execution life cycle, see Control Execution Lifecycle.

The RenderWebPart method is also where you call the RenderChildren method, which renders the children of a Web Part control into an HtmlTextWriter object. The following code shows a basic RenderWebPart implementation that ensures that the TextBox and Button controls are rendered.

protected override void RenderWebPart(HtmlTextWriter output)
{
   EnsureChildControls();
   RenderChildren(output);
}

A Web Part with child controls

Figure 37-3. A Web Part with child controls

This concludes the section about creating child controls on a Web Part. A Web Part is a special kind of ASP.NET Web control. You can find more information about ASP.NET Web controls on MSDN.

Web Part Caching

One of the factors that distinguishes a great Web Part from an average Web Part is performance. You can enhance performance by caching data. You should not use the ASP.NET Session state in Web Parts because the current implementation of the SafeMode parser does not allow Session state to be defined at the page level as is possible with the ASP.NET parser. This means the administrator can enable Session state for all Web Part Pages or for none of them. Enabling Session state for all pages degrades server performance.

Instead you can use the Web Part cache to store data to enhance performance. The Web Part cache can be used in different modes: None, Database, and CacheObject. The None mode disables caching. In the Database mode, all data is stored in the SharePoint database. In this mode, Shared and Personal cache entries are limited to 2 MB. If this limit is exceeded, the cache entry will be lost, and no error will be displayed. Personal storage data will be charged against the user's quota. The final Web Part cache mode, the CacheObject mode, uses the ASP.NET cache object to store data. This is also the default mode of the Web Part cache object. Only administrators—not developers—can set the cache type using the <WebPartCache> element in the <SharePoint> section of the web.config file, as follows:

<SharePoint>
 ..
   <WebPartCache Storage="CacheObject" />
</SharePoint>

You can use the CacheType property of the WebPart class to determine the type of caching used by the Web server. This property is read-only, so it cannot be used to change the type of caching. Developers can retrieve the cache type at run time using the following code:

if ( CacheType == CacheType.None )
{
   output.Write("Caching is disabled.");
}
{
   output.Write("Caching is enabled.");
}

The PartCacheWrite method of the WebPart class stores a value in the Web Part cache. You need to provide this method with a storage type (None, Personal, or Shared) and a key-value pair, and determine how long you want to keep a value stored in the Web Part cache. The following code example shows how to write data to the Web Part cache:

PartCacheWrite(Storage.Shared, "mykey", "myvalue", 
   TimeSpan.FromMinutes(5));

You can use the PartCacheRead method of the WebPart class to retrieve values from the Web Part cache again. This is shown in the following code example:

String strValue = PartCacheRead(Storage.Shared, "mykey").ToString();

You can use the PartCacheInvalidate method of the WebPart class to mark data in the Web Part cache as outdated. You can mark as outdated all contents of the Web Part cache, contents of a specific storage type, or only a specified cache value of a specified storage type. The following code example shows how to mark a specific cache value and storage type as outdated:

PartCacheInvalidate(Storage.Shared, "mykey");

Web Part Tools

Several tools already exist that can help you during Web Part development. MSDN and the Resource Kit CD-ROM contain valuable aids. The tools that are most relevant to this chapter are discussed briefly in this section.

  • GhostHunter   The GhostHunter Web Part identifies all ghosted pages on a site and can optionally revert unghosted pages back to their original form.
  • InstallAssemblies   This is an assembly installation tool for Windows SharePoint Services. It is designed for use within development environments. The tool can be used to deploy packages using the AddWPPack functionality of the Stsadm.exe tool, which is discussed in detail in Chapter 31, "Working with Web Parts." The tool can also install assemblies using traditional XCopy methods.
  • Plex.exe   This tool is useful when using the backward-compatible document library. Plex.exe can be used for Web Storage System–based document libraries to view document properties.
  • SharePoint Configuration Analyzer (sca.exe)   SharePoint Configuration Analyzer is a diagnostic tool that verifies settings on your server that are critical to running Windows SharePoint Services or SharePoint Portal Server and to hosting Web Parts on your server. SharePoint Configuration Analyzer also reports on Web Part usage on your server and retrieves a set of log files, configuration files, and Web Part packages used by Windows SharePoint Services and IIS.
  • SharePoint Explorer (spex.exe)   If you come from a SharePoint Portal Server 2001 background, you will be familiar with this tool, which is known under different names: Platinum Explorer, plex.exe, WSS Explorer, or Exchange Explorer. SharePoint Explorer is the first cousin of this tool, and it can be used to view Web Part and Web Part Page properties.
  • UberConnector   The UberConnector Web Part offers a flexible way of exposing and hooking into various connection interfaces. This tool is valuable when creating connectable Web Parts.
  • WebPartDeployment tool   This tool can be used to import and delete Web Part packages.
  • Wppackager   Use Wppackager to package and deploy Web Parts for use with SharePoint Products and Technologies. To download Wppackager, see SharePoint Products and Technologies Tool: WPPackager for Packaging and Deploying Web Parts in the Microsoft Download Center.

Summary

This chapter shows the basics you need to be aware of to be successful in Web Part development. It discusses the Web Part architecture. After that, the chapter explains what strong naming is and the role it plays in doing Web Part development. Next, the chapter details how to adjust the trust policy so that code identity-based security allows your Web Parts to do what they need to do—nothing more, nothing less. Then, the chapter shows how to build a basic "Hello, world!" Web Part and how to import this Web Part into a Web Part Page. It also shows how to create Web Parts that are more sophisticated by showing how to create Web Part child controls. The chapter concludes with an explanation of Web Part caching.