Personalization with ASP.NET 2.0

 

Jayesh Patel, Bryan Acker, Robert McGovern
Infusion Development

June 2006

Summary: Create personalized applications faster and build entirely new classes of applications with the new personalization features in ASP.NET 2.0. (22 printed pages)

Contents

Introduction
Identifying and Managing Users
Creating a Custom User Experience
Storing User Data with Providers
Conclusion

Introduction

The variety of business solutions that can now be serviced by Web based applications is continually increasing. With added functionality and faster network connectivity, the infrastructure of the Internet now supports increasing numbers and types of users. These users access the Internet for varying reasons through many different devices, making the traditional "anonymous" single user Web architecture insufficient.

To keep pace with the new demands for more flexible, user-oriented Web applications, Microsoft ASP.NET 2.0 includes an extensive personalization framework. The ASP.NET 2.0 personalization features include new mechanisms for identifying and registering users, tailoring a Web site to a specific user, and storing user information automatically and transparently. Web Parts empower the user to include the information they deem most valuable. Through layout control and inclusion of relevant tools, users can create a site that streamlines their experience. These customizations can be persisted and made available to those users on subsequent visits to the site.

This white paper provides a technical overview of new features, including Web Parts, authentication controls, and personalization providers. If you are a beginning or mid-level developer, or just interested in the new personalization features of ASP.NET 2.0, you will benefit from the code examples and feature descriptions in this white paper.

The Personalization Process

Web sites have traditionally been used to convey information to interested viewers. A given site would contain related information about a concept or product, and provide the added benefit of links to other sources of relevant information. Web sites today serve a much broader purpose; the term portal, or centralized information point, describes today's Web sites more accurately. It is in these types of sites that personalization features, such as Web Parts and the Profile service, can be leveraged to provide viewers with a configurable and relevant Web experience. As companies grow in size and complexity, information must be delivered in a controlled and secure manner. In order for a Web site to provide a personalized experience, the Web application must perform several distinct tasks:

  • Identify the user—A Web application must have a mechanism for separating the requests of one user from another. Identifying the user and associating the user with specific roles involves three distinct processes: First, the Web site must have a means for allowing a user to identify himself (authentication); second, the Web site must also have a means for identifying the user's requests (session continuity); finally, the Web site must have a mechanism for creating and managing new user identities.
  • Provide a personalized experience—Personalizing a Web experience can range from allowing or disallowing functions for a particular user (authorization), providing a user with a custom display, or keeping track of user information (for example, a shopping cart). All of these tasks leverage the user's identity in a different way, to provide a Web experience that is specific for each user.
  • Store user information—In most cases, a Web application will need to store user information between requests or between sessions. User information can range from the user's identity (login and password) to a complex preference list or historical data (Amazon's "wish list," for example).
  • One of the challenges in developing personalized Web applications has been designing the framework code necessary to support the personalization process. Not only do you have to develop each function, you have to ensure that all of the functions work together in a secure and seamless fashion.

ASP .NET 2.0 introduces a series of new controls and technologies which provide an elegant solution to these issues and if the default functionality is not suitable the provider framework allows for the development of custom solutions which work seamlessly with other aspects of the system.

Personalization in ASP.NET 2.0

ASP.NET 2.0 greatly simplifies and enhances personalization by providing integrated controls and functions designed specifically to support each phase of the personalization process. From an ASP.NET 2.0 perspective, the three main areas of personalization support are membership, profiles and Web Parts. In this white paper, we will examine each of these areas in greater detail.

Membership

ASP.NET 1.x provided authentication and authorization services that relied on external data stores or configuration in the Web.config file. For example, an ASP.NET 1.1 application could provide forms-based authentication, which required that the developer create a login form and associated controls to acquire, validate, and manage user credentials. Once the user was authenticated, authorization was provided through XML configurations in the Web.config file.

ASP.NET 2.0 expands on these services in three distinct ways:

  • Login and User controls—The new suite of login and user management controls reduce the need to rewrite standard user code for each application. You can, for example, create a set of pages for registering a new user, allowing an existing user to login, and even send a forgotten password to a user simply by placing the appropriate controls on the page and setting a few properties.
  • User management—Each ASP.NET 2.0 application can be accessed through a special set of administrative pages which allow an authorized user to create new users, assign users to roles and store user information. If you want to write your own management tools, you can access all of the same features programmatically.
  • Membership Provider—The membership feature creates a link between the front end features (login controls and user management site) and the persistence mechanism. A membership provider encapsulates all of the data access code required to store and retrieve users and roles. Thanks to the provider model, this component can easily be replaced with a provider that supports your particular data source.

These three components work together to reduce the amount of code required to provide membership services and link the membership services to a persistent data store.

Profiles

In ASP.NET 1.x applications, user specific data was often stored in the session and persisted to a database when necessary. This process was often inefficient, and required the development of special framework code.

ASP.NET 2.0 helps solve this problem by providing a new profile service. A profile is simply a set of data that is associated with each user. The profile can contain any serializable data type from basic data types (for examples, string or int) to complex objects. Unlike in ASP.NET 1.x, the management of the profile is automatic. ASP.NET 2.0 takes care of creating and storing the user profile automatically.

The heart of the profile service is the profile provider. The profile provider contains all the code and structure necessary to persist and load user data to a data store. Similar to the membership provider, the profile provider is designed so that you can replace it with a provider that matches your choice of data store.

Web Parts

The Web Parts framework is a highly advanced replacement for portal based Web sites that use HTML frames. Basically, you can use Web Parts to create a multi-component application, where the user can decide which components to display, how to configure the components, and how to arrange the components on the page. Once authenticated users have set up the Web Parts the way they want them, the layout is automatically preserved between sessions. In other words, Web Parts let you build Web applications that look and act like a desktop.

Web Parts rely on a personalization provider to manage the persistence of Web Part layouts between sessions. Once again, the provider is designed as an extensible part of the .NET framework. If you do not want to use the providers available as part of the framework, you can easily create your own.

Identifying and Managing Users

The first step in personalizing a Web site is establishing a mechanism for identifying and managing users. As a Web site user, you have to have a means to identify yourself to the Web site in order to access your personalized content. As a Web site administrator, you have to have a means for registering new users, assigning users to specific roles, deleting users and responding to requests for lost passwords. All of these functions have been greatly simplified with ASP.NET 2.0.

Identifying Users

Traditional Web application systems have leveraged a wide range of mechanisms for identifying a user. In ASP.NET v1.0, for example, you could choose from one of four different authentication mechanisms ranging from Windows authentication to custom forms. However, once you selected an authentication mechanism, you still had to build your own code for support the user base by creating new users, linking users to roles and evaluating the roles in your Web site. Although technologies such as Windows authentication and Active Directory helped solve the problem, the Web developer still had to write a lot of code.

ASP.NET 2.0 builds on the base authentication mechanisms in two distinct ways. First, ASP.NET 2.0 includes a suite of new controls for building login and user management Web forms. Second, ASP.NET 2.0 includes new APIs for creating user accounts and associating users with specific roles.

Table 1 describes controls used to service identity related issues:

NameDescription
<asp:login>Standard login capability that allows users to enter credentials.
<asp:loginname>Display the name of the logged in user.
<asp:loginstatus>Specifies whether the user has been authenticated
<asp:loginview>Provides various login views depending on selected template
<asp:passwordrecovery>Emails a lost password to the user
<asp:CreateUserWizard>User creation wizard with declarative configuration
<asp:ChangePassword>Password change wizard with declarative configuration

Table 1. ASP.NET 2.0 Login Controls

The <asp:login> control creates the appropriate labels, text fields and buttons to gather user credentials. The look and feel of this control can be modified using a built in format or it can be configured using style sheets. The properties window also allows access to the label, value, and validation message as well the login button’s appearance can be modified to suit individual needs.

The <asp:passwordrecovery> control reduces the amount of developer code required to handle situations where a password is lost or forgotten. Using SMTP configured through the Web.config file, the password recovery control will email a user’s password to an email address previously associated with the specified account.

User Management

To simplify the process of managing users, ASP.NET 2.0 and Visual Studio 2005 provide a local host only Web site configuration tool. The Web site Administration Tool is a simple Web site that can only be accessed directly on the localhost and must be launched from Visual Studio 2005. Through this tool an administrator can manage the application, by configuring services such as user management, the personalization providers, security, and profiles. The Web site configuration tool provides a graphical front-end to a number of ASP .NET 2.0 technologies, such as personalization, membership, and providers.

The membership API exposes user-management functionality, while the Profile page property handles user-preference details. The membership API can also be accessed programmatically or through user controls. For cases where a custom user-management interface is required, the Membership and MembershipUser objects should be used to persist and retrieve user details. For most authentication concerns, the login controls provide a very robust and configurable mechanism.

Once you have configured the local version of your application, you can deploy the various configuration files to your production server, modifying them directly as necessary.

Personalization Provider

The personalization provider creates the link between the Web Parts feature that consumes personalization data, and the data store that contains the user information. You can configure a personalization provider and connect it to SQL Server provider.

Although ASP.NET 2.0 ships with providers that work with SQL Server and SQL Server 2005 Express Edition, the provider framework was designed for extensibility. Creating a provider for another database or even an XML file is simply a matter of developing a new provider class and registering it with the administration tool.

Managing User Accounts

Once the provider has been configured and a data store has been created, the next step is to populate the data store with user information. The Web site Administration Tool has a simple create user form that lets an administrator create a new user and send a password to the user via email.

ms379593.person_fin01(en-US,VS.80).gif

Figure 1. User CreationWeb site Administration Tool

Although this Web form is useful for creating small numbers of users, many Web sites support hundreds or thousands of registered users. In addition, the website only functions on the local host and requires an installation of Visual Studio 2005. Fortunately, the Web site Administration Tool is just a Web based shell on top of the administration API. In other words, creating a batch user upload process, or creating a self-registration form for users is simply a matter of leveraging the proper ASP.NET 2.0 classes.

Programmatic User Creation

The membership API encapsulates all user maintenance functionality and can be accessed through a number of classes. The two most important membership classes are Membership and MembershipUser.

The System.Web.Security.Membership class provides methods to create, delete, update and find users. To create a user account from within an application, simply call one of the CreateUser() methods from the Membership class:

try {
    MembershipUser newUser = Membership.CreateUser("Seth",
      "trader", "seth@boilerroom.com", "last name?",
      "Davis", true);
} catch (MembershipCreateUserException mcue) {
    string error = mcue.Message;
}

Listing 1. Programmatically creating a new user

In this case, the CreateUser method attempts to persist the new user using the underlying membership provider. If a failure occurs, the CreateUser() method will throw a MembershipCreateUserException indicating the problem. The exception can be queried for its Message or StatusCode property to determine the exact nature of the failure.

For more functional error handling, you can use an overloaded version of CreateUser that accepts an in/out MembershipCreateStatus enumeration that will provide error codes for different types of failure conditions.

MembershipCreateStatus status;
MembershipUser newUser = Membership.CreateUser(
    "Seth", "trader", "seth@boilerroom.com", "last name?", "Davis", true, out status);
if (status == MembershipCreateStatus.Success) {
    Server.Transfer("WebParts.aspx");
} else {
   //User creation failed, determine the failure type
    string errorcode;
    switch (status) {
     case MembershipCreateStatus.DuplicateUserName:
       errorcode = "Username already exists.";
       //resolve error condition and try again
       break;
     case MembershipCreateStatus.DuplicateEmail:
       // Other 8 conditions omitted for brevity

Listing 2. Advanced user creation

The MembershipCreateStatus enumeration is passed as an output parameter to the CreateUser method. On method completion, the status object can be queried for error codes and the results can be compared against MembershipCreateStatus’s predefined error types.

Once a user is successfully created, the user's details are encapsulated in a System.Web.Security.MembershipUser class. The MembershipUser class can be used to determine the date of last activity, modify a password or a password security question, modify comments on the user, and approve or disable the user account.

Leveraging Roles

Users are often grouped into roles to help simplify provisioning security settings. The ASP.NET membership model includes the role concept in the form of the System.Web.Security.Roles object. A role is simply a higher level container for users. Creating a role is therefore a fairly straight forward process. You can either use the Website administration tool, or write your own code:

Roles.CreateRole("Administrator");

Listing 3. Creating a Role

Once you have the roles created, you can allow or deny access to specific parts of your application for any user assigned to the role. For example, if you had a UserAdmin.aspx page for controlling users, you could add the following to your web.config file to restrict access to the Administrator users:

  <location path="UserAdmin.aspx" >
    <system.web>
      <authorization >
      <allow roles="Administrator"/>
      </authorization>
    </system.web>
  </location>

Listing 4. Leveraging Roles for security

Only users belonging to the Administrator role would be authorized to view the UserAdmin.aspx page.

Programmatic Role Assignment

Once a user has been created, he can be added to an existing role through the System.Web.Security.Roles object. Assigning a Role is as easy as linking the user name to the role name:

Roles.AddUserToRole("Seth", "Administrator");

Listing 5. Assigning a user to a role

Note that ASP.NET users and roles aren't necessarily linked to Windows users and roles.

The Login Controls Revisited

Most of the functionality contained in the Membership, MembershipUser, and Roles classes is encapsulated in the login controls. Using the login controls therefore saves you time and code when developing user management. For example, using the Login controls (specifically CreateUserWizard and its ability to provide a multi-step user creation process), you can create a multi-step user registration process that gathers user information, verifies the information and then automatically creates the new user thanks to the login controls and the membership provider.

Creating a Custom User Experience

Most traditional Web applications offer little in the way of a customized user experience because of the complexities involved with tracking, storing, and using the user's information for anything more than simple text displays. However, with ASP.NET 2.0, you can quickly and easily create a user interface that will display specific content, store user information and allow the user to modify the display according to his or her preferences.

Profiles

Profiles are a configurable mechanism for creating storable buckets of information for a specific user. A profile can be used to store anything from the user's name to complex data objects. Profiles essentially replace the persistence code required to gather user information, persist it to the session (or cookies or database) and ensure that the information was maintained between user sessions.

A profile is configured using an XML Schema stored in the Web.config file as an XML element. Once a well formed profile configuration is saved into the Web.config file, it is immediately available to the IDE and runtime. A profile can be as simple or complex as required by the application.

Defining a Profile

A profile is defined according to a specific set of XML tags in the Web.config file. Each element in a profile must be minimally specified with a name and usually a data type. If no type attribute is included, the default type of string is assumed. Any type of data from primitives to user defined objects can be stored in a profile. Both the name and data type are used by Visual Studio 2005 to provide IntelliSense and perform runtime checking.

<profile>
   <property name="NumberOfApples" type="int" />
</profile>

Listing 6. Simple property definition

The property specified in Listing 6 will be referenced by the name NumberOfApples and will be an integer.

A property can also define additional attributes that define, among other things, how the profile element will be saved and whether the element will be used by anonymous users:

<profile>
<properties>
  <add name="EmailAddresses" type="System.Collections.Specialized.StringCollection"
       serializeAs="Xml" allowAnonymous="false" provider="SQL" /> 
</profile>

Listing 7. Complex property definition

The profile in Listing 7 defines the EmailAddress property which makes use of many of the parameters available for use by properties. Table 2 outlines the complete list of attributes that can be applied to a given property, most are optional.

Attribute NameOptional?Example ValuesDescription
nameRequiredStringA unique identifier for this property.
typeOptionalPrimitive | User Defined typeA .NET primitive type or class. Class names must be fully qualified (e.g. Myapp.UserData.ColorPrefs).
serializeAsOptionalString | Xml | BinaryFormat of value when persisting in datastore.
allowAnonymousOptionaltrue | falseRestrict or allow anonymous access to this value. If set to false, anonymous users won't have access to this profile value.
providerOptionalStringThe provider used to manage this value. Overrides the defaultProvider setting in Web.config or machine.config.
defaultValueOptionalStringValue to return if property has not been explicitly set.
readOnlyOptionaltrue | falseRestrict write access.
customProviderDataOptionalDetermined by custom providersUseful for custom provider authors to store metadata about their profile attributes.

Table 2. Available property attributes

The provider attribute can play a crucial role in situations where different parts of the profile are stored through different providers. The provider attribute allows you to combine data from multiple back end systems but provides a single class that can be used to expose the data. The ASP.NET profile simplifies the data aggregation process by exposing the data through a single class. For example, private user data may be stored through a database provider, whereas less important (or easily reconstructed) data may be stored in an XML file. By assigning specific providers, such scenarios are easily possible.

Grouping properties

In many cases a profile should be made up of a number of properties which are grouped together to convey some type of business concern. For example, a group of related properties may represent user preferences, where another group may represent billing information. In ASP.NET 2.0 properties can be grouped together using the <group> tag.

<profile>
  <properties>
   <group name="Preferences">
    <add name="ShowQuoteOfTheDay" defaultValue="true" type="System.Boolean" />
    <add name="ShowNews" type="System.Boolean" />
   </group>
   <group name="BillingAddress">
    <add name="Street" type="System.String" />
    <add name="City" defaultValue="Toronto" type="System.String" />
    <add name="StateProv" type="System.String" />
    <add name="ZipPostal" type="System.String" />
   </group>
  </properties>
 </profile>

Listing 8. Profile using group tags

Note that each group must have a unique name, and that the elements within the group must be uniquely named. However, elements in different groups may share names because the group association keeps the elements distinct.

Accessing Profile Properties in Code

Once you have defined a profile in the Web.config file, you can access the various profile elements through the Profile property that is available on each page. This property is actually an instance of a special sub-class of System.Web.Profile.ProfileBase that is created during page compilation. The sub-class (called ProfileCommon) automatically contains strongly typed access methods for all of the properties and groups defined in the profile. The ProfileCommon class is therefore a custom class for each Web application. From a developer perspective, however, ProfileCommon class creation is automatic and transparent.

The Profile property available on each page provides read and write access to the properties in the current user's profile. If a property is contained within a group, the group acts like an additional property that in turn has sub-properties. As a developer, you just program against the Profile property, and ASP.NET will automatically handle loading and saving the Profile on your behalf.

ms379593.person_fin02(en-US,VS.80).gif

Figure 2. Strongly typed Web.config properties with IntelliSense support

Visual Studio 2005 reflects changes to the Web.config file immediately. Properties become accessible via IntelliSense as soon as the Web.config file is saved. In other words, if you need to modify a profile during development, Visual Studio 2005 will instantly recognize the change and provide appropriate tool support.

Web Parts

Coupled with a WebPartManager and contained within WebPartZones, Web Parts are modular components that can be included and arranged by the user to create a productive interface that is not cluttered with unnecessary details. The user can:

  • Choose which parts to display
  • Configure the parts in any order or arrangement
  • Save the view from one Web session to the next
  • Customize the look of certain Web Parts.

All of these features are practically impossible to implement with ordinary Web applications.

Web Part Architecture

You can think of Web Parts as modular Web page blocks. Each block can be added or removed from the Web page dynamically, at runtime. Code for organizing and manipulating Web Parts is built in to ASP.NET 2.0. All of the functionality for adding, removing and configuring layout is automatically handled by the Web Parts system. The programmer simply builds Web Parts and assigns them to Web Part Zones. A user can mix and match Web Parts, display them in any order, and expect the configuration to be saved between site visits. All the functionality of Web Parts, including adding, removing, and listing is managed automatically using a WebPartManager.

The key components of the Web Part framework are:

  • The System.Web.UI.WebControls.WebParts.WebPart class – The WebPart is the base class outlining configuration properties that allow sub classes to be members of Web Part Zones. Generally, a custom control will be a subclass of WebPart, or a GenericWebPart will be wrapped around a single user control.
  • The System.Web.UI.WebControls.WebParts.WebPartZone control – The WebPartZone control is a container for a set of Web Parts. The WebPartZone is part of the infrastructure for the Web Parts and is used to define the look and feel of the screen region occupied by the zone.
  • The System.Web.UI.WebControls.WebParts.WebPartManager control – One WebPartManager is placed on each page that uses Web Parts. The WebPartManager controls and maintains the state of all Web Parts on the page.

These three controls combine together to create Web pages that are visually and functionally similar to complex desktop applications.

Building Web Parts

A Web Part can be built in one of three ways. First, you can drop an ordinary user control onto a WebPartZone. The user control will automatically be encapsulated in a GenericWebPart wrapper. This method of Web Part creation is the easiest way to extend personalization to user controls.

Second, you can create a control that extends the WebPart class. You might want to use this approach if you want to modify the behavior of the Web Part or have greater control over Web Part features and properties. However, you have to develop a server control, which requires more complex code and development effort than using a GenericWebPart. Extending the basic WebPart class is often a better choice than implementing the interfaces since you automatically inherit the code for processing verbs and working with a WebPartManager. Once you inherit the class, simply overload the RenderContents() method to generate the content specific to your Web Part.

Third, you can implement the IWebPart and IWebActionable interfaces. The IWebPart interface defines several properties related to how a WebPart looks. The IWebActionable interface defines verbs that a Web Part supports. These interfaces are potentially useful when a custom control derives from an existing control, and thus you cannot directly inherit from the WebPart class. These interfaces also allow you to further customize the behavior of user controls used as web parts. However, you will rarely, if ever, need to implement a WebPart using the interfaces.

A User Control Web Part

The easiest way to create a Web Part is to attribute public properties on any user control with the [Personalizable()] attribute and then drag the user control onto an existing WebPartZone This method allows for rapid development of Web Parts, and is well suited for the development of content. Though simple to create, this method of building Web Parts has some minor limitations. Each control that is added to a WebPartZone gets its own GenericWebPart wrapper which implements some functionality normally found on a WebPart-derived class.

For example, if you created a "Welcome" control to identify the current user, you might have an ASCX that looks like this:

<%@ Control Language="C#" AutoEventWireup="true" 
   CodeFile="WebUserControl.ascx.cs" Inherits="WebUserControl" %>
<script>
  [Personalizable]
  public string CurrentUserName
  {
    get
    {
      if(Label1.Text == null | Label1.Text.Length < 0)
        return String.Empty;
      else
        return Label1.Text;
    }
    set
    {
      Label1.Text = "Hello: " + value;
    }
  }
</script>

<asp:Label ID="Label1" runat="server" Text="Guest" Width="205px"></asp:Label>

Listing 9. A typical User Control

This control is just a basic ASCX with the addition of a "personalizable" name parameter. The [Personalizable] attribute tells the ASP.NET runtime that the CurrentUserName property should be stored with the profile for the currently registered user. This attribute only takes effect if this user control is embedded in a WebPartZone. If the control is in a zone, then it will automatically load up the property for the logged in user each time the user logs into the website.

Note that you won't ever see the GenericWebPart wrapper that actually surrounds the basic control. At runtime, the Web Part framework automatically injects a GenericWebPart wrapper into the control tree for any control that is embedded in a WebPartZone control. In other words, the mechanics of creating this wrapper class around your user control are automatic, and performed behind the scenes by the ASP.NET 2.0 compiler.

A Derived WebPart

To expose the full functionality of Web Parts a custom Web Part can be created by extending the WebPart class. The steps involved in creating a custom Web Part are similar to that required to build a custom user or server control. First, create an object that extends the WebPart class:

using System;
using System.Text;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI;
namespace PartsLibrary {
    public class announcementControl : WebPart {
        public announcementControl() {}
        protected override void RenderContents(HtmlTextWriter writer) {
            writer.Write("Dr. William K Chin discovers new treatment for Ranaud's!");
        }
    }
}

Listing 10. The announcementControl source code

The code in Listing 10 creates a sub class of WebPart and overrides the RenderContents() method to print out a message. For simplicity sake, this example is relatively uneventful. However, an announcementControl could encapsulate complex business logic in a real world scenario. Note that the class is defined in the PartsLibrary namespace and should be compiled into an assembly.

Next add a reference to the assembly in the Web project where you want to use the announcementControl Web Part. The Web part can now be added to the pages of the application by simply dragging and dropping it from the toolbox, or adding code directly to your ASPX page. Listing 11 illustrates the source required to register and instantiate our annoucementControl.

<%@ Register TagPrefix="jc1" Namespace="ClassLibrary1" Assembly="ClassLibrary1" %>
  <asp:WebPartZone ID="BottomZone" Runat="server" Height="45px" Width="760px">
    <PartTitleStyle Font-Bold="True" BackColor="Black" ForeColor="DarkKhaki">
    </PartTitleStyle>
    <RestoreVerb ImageUrl="~/images/RestoreVerb.GIF"></RestoreVerb>
    <HeaderStyle BackColor="Black" ForeColor="DarkKhaki"></HeaderStyle>
    <MinimizeVerb ImageUrl="~/images/MinimizeVerb.GIF"></MinimizeVerb>
    <ZoneTemplate>
      <jc1:announcementControl Runat="server" ID="AnnouncementControl1"
           ForeColor="#C00000" BackColor="Silver" Title="Announcements"
           AllowHide="False" AllowMinimize="False" AllowClose="False" />
    </ZoneTemplate>
  </asp:WebPartZone>

Listing 11. Adding the custom Web Part to an ASPX page

The register directive associates the jc1 prefix with our custom Web Part thus making all controls (the announcementControl) in the assembly available for use in this page. The custom Web Part jc1:announcementControl is fully configurable, and exposes Web Part properties such as AllowHide and AllowMinimize for configuration. These options require a bit more coding when using the simple user-control-as-a-Web-part creation method.

ms379593.person_fin03(en-US,VS.80).gif

Figure 3. Web Part with verb control

Note that the Announcements Web Part in Figure 4 does not make standard verbs available to the user. In Listing 11, those properties were specifically disabled. By disabling certain Web Part features, you can ensure that required page elements are not accidentally removed by the user.

Web Part zones

A Web Part zone is a region of space that contains a collection of Web Parts. The Web Part zone is a container that defines properties that can be manipulated to change the look and feel of the components within its contained scope. Each Web Part zone should contain a related group of WebParts.

Web Part zones are defined within the .aspx page using the <asp:WebPartZone> control tag. Listing 12 shows a typical Web Part zone definition containing the announcements Web Part. Note: the following code is not the complete .aspx page.

<asp:WebPartZone ID="BottomZone" Runat="server" Height="45px" Width="760px">
  <PartTitleStyle Font-Bold="True" BackColor="Black" ForeColor="DarkKhaki">
  </PartTitleStyle>
  <RestoreVerb ImageUrl="~/images/RestoreVerb.GIF"></RestoreVerb>
  <HeaderStyle BackColor="Black" ForeColor="DarkKhaki"></HeaderStyle>
  <MinimizeVerb ImageUrl="~/images/MinimizeVerb.GIF"></MinimizeVerb>
  <ZoneTemplate>
    <jc1:announcementControl Runat="server" ID="AnnouncementControl1"
         ForeColor="#C00000" BackColor="Silver" Title="Announcements"
         AllowHide="False" AllowMinimize="False" AllowClose="False" />
    </ZoneTemplate>
</asp:WebPartZone>

Listing 12. Web Part zone example

A Web Part zone must be configured with a unique id attribute that is used by the Web Part manager control to identify a particular zone within the page. The title is displayed as a header for the Web Part zone when editing page layout.

Web Part Verbs

Web Part verbs are user interface elements that enable users to perform specific Web Part related actions. You can think of Web Part Verbs as being equivalent to the standard commands and icons found on most desktop Windows applications. These verbs are defined by the WebPartZone, which provides a number of standard verbs: Close, Minimize, Restore, Help, Edit, Connect, and Export.

Each verb can be configured as an XML element inside of the Web Part zone:

<asp:WebPartZone id="Zone1"  runat="Server">
  <CloseVerb ImageUrl="images/CloseVerb.jpg"
            Enabled="True"
            Text="Close"
            Description="Closes the WebPart"
            visible="True" />
  <ZoneTemplate>
     <custom:QuoteWebPart title="Quotations" id="QuoteWebPart" runat="Server" />
  </ZoneTemplate>
</asp:WebPartZone>

Listing 13. Web Part verb

A typical verb contains a number of parameters describing its state and visual composition. For example, an image can be associated with the verb using the imageUrl attribute. Typically, the image is a small icon style image that symbolizes the intended action.

Verbs are displayed in the upper right corner of the WebPartZone title bar. By default, the verb displays as simple text. However, by assigning an icon, you can create custom displays of verbs.

ms379593.person_fin04(en-US,VS.80).gif

Figure 4. Web Part Verbs (text on left, icon on right)

Verbs also have an associated tool tip that can be configured to give a textual description of the indented task. Adding iconographic verbs to Web Parts can therefore reduce the amount of screen real-estate used to convey common functionality, while preserving the information necessary to train the user on web part options.

Templates

Throughout ASP.NET 2.0, templates are used to configure common elements of user controls. The Web Parts components also make use of templates to configure the look and feel of the Web Parts on the page. Web Parts are added to a WebPartZone by placing them within the <ZoneTemplate> tag. The ZoneTemplate defines the default layout of its constituent Web Parts.

<ZoneTemplate>
  <custom:DrugWebPart Title="Drugs" bgcolor="#333333" id="DrugWebPart1" runat="server" /> 
  <custom:ScheduleWebPart Title="Schedules" id="QuoteWebPart2" runat="server" />         
  <custom:EventsWebPart Title="Daily Events" id="QuoteWebPart3" runat="server" />
</ZoneTemplate>

Listing 14. Using a ZoneTemplate

All of the parts stored within the same template will use the same look and feel. Note that the CatalogZone and EditorZone also define a ZoneTemplate and that the ZoneTemplate for these zones may use a different look and feel than the standard Web Part zones. You might, for example, want to emphasize the catalog zone by having the look and feel change when the user enters catalog mode. By using template controls, ASP.NET 2.0 allows developers to define the look and feel of Web Parts declaratively. Templates also promote a more consistent UI for controls resulting in an improved user experience with these interactive components.

Web Part manager

One and only one Web Part manager must be added to any page that uses Web Parts. The manager control must be added before any Web Part zone, and is responsible for keeping track of the state of all the Web Parts on the page.

The Web Part manager control’s DisplayMode property is of particular interest because it defines the type of configuration options available to the end user. DisplayMode has several possible values.

  1. Catalog—Displays a list Web Parts and allows parts to be rearranged.
  2. Design—Allows the user to rearrange Web Parts on the page.
  3. Edit—Allows a user to edit specific attributes of individual Web Parts.
  4. Connect—Provides communication between two Web Parts
  5. Browse (default)—Displays the page with user preferences applied.

Using the different modes, developers can expose desired functionality to the user. For example, the catalog mode depicted in Figure 6 lets the user select which Web Parts are displayed. In catalog mode, the WebPartManager’s catalog zone becomes visible to the user. Web Parts can be selected and then added to the one of the page’s zones by using the add button. This is the mode in which Web Parts are usually added to the page. However, you can always programmatically add Web Parts to a page, regardless of the WebPartManager's mode.

ms379593.person_fin05(en-US,VS.80).gif

Figure 5. Catalog modeWeb Parts

A typical catalog will contain several different Web Parts, each of which displays specific information or allows the user to access specific functions. For example, the catalog in Figure 6 is part of a Web Portal for a hospital. Doctors, nurses and administrators all use this portal to access scheduling information, daily events, announcements and patient status. Because the portal contains patient information, security is a definite concern. The portal therefore relies on the membership service to identify each user and determine which information to display.

Once the user has selected which parts to add to the zone, he can click the close button to switch back to browse mode and see the resulting layout:

ms379593.person_fin06(en-US,VS.80).gif

Figure 6. Browse modeWeb Parts

For example, Figure 7 shows a Web Part layout for Dr Jayesh Patel. Dr Patel has chosen to display Web Parts for current patient list (upper left), drug lookup (lower left), and billing information (right).

A Web Part can be moved from one Web Part zone to another using ASP .NET built in drag and drop functionality. Dr Patel might decide, for example, to group the patient list and billing information on the right hand side of the page.

ms379593.person_fin07(en-US,VS.80).gif

Figure 7. Drag and DropWeb

Figure 8 shows a Web Part being dragged from the leftzone to the mainzone. Any available Web Part can be placed in any Web Part zone. Once the part is relocated by the user, the state of the page is persisted to secondary storage. On subsequent visits to the Web site the user’s Web Part layout is recalled.

The Personalization Provider

Web Part layouts and configuration are stored by the personalization provider. This provider is similar to the membership provider and profile provider, in that it transparently manages persisting user information. The personalization provider stores Web Part personalization data for each user, however.

Storing User Data with Providers

The provider model is used throughout ASP.NET 2.0 as a mechanism to extend and enhance the framework. The provider is therefore both a pattern and a point where developers can extend the ASP.NET 2.0 framework to meet specific needs. For example, a developer can create a new provider to support the user identification system, or to store personalization data in an alternate data store.

Most custom providers will interact with database backend systems. However, the programmer is free to implement the required provider methods and classes using any medium or algorithm so long as it meets the models required interface specification.

The Provider Model

The provider model is derived from a number of widely accepted patterns. The model defines a set of classes and hooks to the data persistence layer that provides storage and retrieval for specified requests. In this way the provider model acts as a programming specification that allows ASP.NET 2.0 to service unique client concerns.

With respect to personalization, ASP.NET 2.0 uses three different providers:

  • Membership—The membership provider manages supports user authentication and user management.
  • Profile—The profile provider supports storage and retrieval of user specific data linked to a profile.
  • Personalization—The personalization provider supports persistence of Web Part configurations and layouts for each user.

Each type of provider acts independently of the other providers. You can therefore replace the profile provider without causing problems with the membership provider.

Developing custom providers

Creating a new provider is as easy as implementing a new class that meets the functional requirements of the provider. Once the class has been developed, it can be registered using the Web site Maintenance Tool, thus enabling it as a provider of the correct type.

Custom provider solutions should be considered in cases where personalization data already exists or becomes too complex to manage using the default providers. If an application requires personalization data that spans multiple datasources, such as user data in an LDAP directory and personal information in a backend human resources repository, a custom provider could be used to interface with the homogeneous data system.

Custom Membership Provider

Creating a custom membership provider involves several steps:

  1. Write a new class that derives from System.Web.Security.MembershipProvider.
  2. Use the Web Configuration Tool to register the provider. You can register the provider manually by adding a new <connectionStrings> element and a <membership> element.
    <configuration>    
      <connectionStrings>
        <add name="MembershipProviderConnection" connectionString="DATA\mydb.mdb" />
      </connectionStrings>
      <system.Web>
        <membership defaultProvider="FlatFileProvider">
          <providers>
            <add connectionStringName="MembershipProviderConnection"
                 applicationName="/DoctorPortal"
                 description="Flat file membership provider"
                 requiresUniqueEmail="true"
                 enablePasswordRetrieval="false"
                 enablePasswordReset="true"
                 requiresQuestionAndAnswer="false"
                 passwordFormat="Hashed"
                 name="catdog"
                 type="MyCode.Membership.FlatFileProvider, MyCode.Membership,
                   Version=1.1.1300.0, Culture=neutral, PublicKeyToken=xxxxxxxxxxxxxxxx" />
                </providers>
            </membership>
    
    //other configuration pieces
        </system.Web>
    

    Listing 15. Manually Configuring a Membership Provider

    Note that whichever way you register the provider, you can declare whether the provider supports the various membership features such as automatic password retrieval or the actual password format.

  3. Make the datastore (database or other data source) available to the application.

Once the membership provider has been created, you can use your own data store to organize and maintain users and roles.

Custom Profile Provider

Developing a custom profile provider requires a similar process; however the implementation class must derive from the System.Web.Profile.ProfileProvider class. The ProfileProvider class is derived from System.Configuration.SettingsProvider which in turn inherits from System.Configuration.Provider.ProviderBase. As a result any custom profile provider should implement all of the methods required by the ProfileProvider, SettingsProvider and ProviderBase abstract classes.

The profile feature can then be configured to use the custom provider by adding a new entry in the Web.config file.

<profile defaultProvider="OdbcProvider">
  <providers>
    <add name="OdbcProvider" type="Samples.AspNet.Profile.OdbcProfileProvider"
               connectionStringName="OdbcProfile" />
  </providers>
</profile>

Listing 16. Custom Profile Provider entryWeb.config

Listing 16 illustrates the profile section of the Web.config file. A custom profile provider named OdbcProvider is added to the provider list. The profile tag has its defaultProvider attribute set to the OdbcProvider. The above configuration along with a valid implementation of the ProfileProvider class is all that is required for a custom provider implementation.

Custom Personalization Provider

Creating a custom personalization provider also follows the same basic process. However, a personalization provider has to derive from System.Web.UI.WebControls.WebParts.PersonalizationProvider. Once created, the provider can be registered by adding an entry to the <providers> section of the <personalization> tag (which can be found nested within the <WebParts> element of the Web.config file).

As with other custom providers, you are responsible for creating a valid data source and making it available to the applications. Your personalization data source might be an XML file or entries in a database.

Conclusion

Personalizing a Web site has always involved a large amount of complex supporting code. However, with the new personalization features in ASP.NET 2.0, developers can not only create personalized applications faster, they can also build entirely new classes of applications. The user management system and login controls make recognizing a user even easier than before, and the profile features help store user data in a fast and efficient manner. The Web Parts framework, however, provides a revolutionary new design paradigm for Web sites. Thanks to Web Parts, a Web site is no longer constrained to the linear document format that formed the basis for the HTML standard. Web Parts offer much greater flexibility and allow developers to create Web applications that are almost indistinguishable from the most powerful desktop systems.

 

About the authors

Jayesh Patel—Jay Patel is a developer in both .NET and Java Technologies. Jay's research focuses on pattern-based programming and agile methodologies.

Bryan Acker—Bryan Acker is a technical writer for Infusion Development. Bryan has a strong background in ASP and ASP.NET Web development and Web hosting.

Robert McGovern—Rob McGovern is a senior writer, developer, and project manager for Infusion Development. Rob has worked on several different ASP.NET projects, including CodeNotes for ASP.NET and the JSP to ASP.NET migration guide. Rob is also a Microsoft MVP for Virtual Earth.

Infusion Development Corporation is a Microsoft-Certified Solutions Provider offering customized software-development, training, and consulting services for Fortune 1000 Corporations, with an emphasis on the financial-services industry. With offices in New York and Toronto, Infusion Development has established an international client base, including some of the world's largest companies in the financial service, securities brokerage, and software development industries.

Show: