Portal Framework

 <  Day Day Up  >  

The need for a structured framework is not something new. Over the years , departments in many companies have been developing their own homegrown solutions to problems they encountered . They purchased off-the-shelf software to solve other problems they had. Although these applications solved most of the problems that they were intended to solve, they also introduced other problems into the workplace. The homegrown solutions became harder and harder to maintain and, with all of the independent solutions within the company, almost none of them knew how to "talk" to each other.

Many companies started implementing IT departments, and many of the smaller solutions were turned over to the IT department for continued development and maintenance. Purchasing of applications moved from a per-department basis to a company-wide basis. Nevertheless, the advent of the IT department did not solve one of the most important problems ”communication between the applications. The IT departments began to see the power in consolidating many of the singleton applications into larger company-wide systems and so a new trend began. Although consolidation of these small applications was seen as a positive step in the right direction, not all applications can or should be consolidated. For off-the-shelf products and for applications that could not be included in the consolidated systems, the IT departments began to develop application integration solutions. This allowed more applications to be able to communicate with each other.

Define Portal Framework Goals

A portal in general and specifically a portal framework can be looked upon as the natural evolution of the consolidation and integration of disparate enterprise systems. One of the main goals of the portal framework is to achieve a high degree of organizational integration. Here is a more complete listing:

  • Extensibility. During the design phase of a portal framework, extensibility is the principal goal. Allowing users to build and use individual portal modules to view, manage, and manipulate data is the basis for the extensibility of the framework.

  • Common infrastructure. The portal framework needs to act as a common infrastructure for all of the modules that make up the portal. While each module may extract data from a different source, this common infrastructure should act as the plumbing for the portal. Users should not need to have to think about implementation of the infrastructure and should be able to focus on the design and development of the specific portal modules.

  • Security. Security is of utmost importance within the portal and therefore the portal's framework needs to incorporate a security layer that will deal with authentication and authorization of the end user. Authentication is the process of obtaining credential information from a user , and then validating those credentials against some sort of authority. The process ensures that users are who they say they are. Authorization is the process of validating permissions using a user's credentials and either granting or denying access to operations or resources.

  • Authentication. This task needs to be done at the time of initial login, while authorization can occur throughout the system, depending on user roles and the type of action that they are attempting to perform.

  • Scalability and performance. Without the ability to scale to the required number of users, the portal would be useless. Performance is also a factor that comes into play because a portal, or any web application, that performs poorly will produce a bad user experience and thereby discourage users from returning to the portal. The scalability and performance factors need to be taken into account from day one of the portal framework design.

Identify Framework Benefits

There are numerous benefits associated with using a portal framework. This list summarizes the benefits gained by using the portal framework:

  • Shorter development schedule/shorter time to market: Development projects no longer have to solve the many problems related to web applications. They simply reuse the code provided by the framework. Project developers don't have to design, develop, or test these framework services; they take them for granted.

  • Reduced development risk: With a complex programming model like .NET, the risk of project failure is initially high. The portal framework significantly reduces the risk by serving as a reliable proven base.

  • Consistent application architectures: Using a framework results in all applications having similar application architectures, which makes them easier to learn, support, and maintain.

These benefits boil down to design savings, code savings, and test savings.

Figure 5.3 shows a conceptual view of a portal page, which consists of multiple regions known as panes . Each pane has a specific location within the page. While some panes, like the header, footer, and navigation panes, are only intended to host a single module, all panes can contain zero or more modules. Portal modules provide the actual content of the portal and allow users to customize the portal depending on their preferences.

Figure 5.3. Conceptual View of a Portal Page

graphics/05fig03.gif


Define the Portal Module Object Model

Portal modules provide the actual content for the portal. The modules are ASP.NET user controls that inherit from the ModuleControl base class. The ModuleControl class provides functionality common to all modules, enforces behavior common to all modules, creates hooks necessary to control and position each ModuleControl from the portal page, and provides communication between the module and the underlying portal framework.

The ModuleControl itself inherits from the UserControl class that is part of the .NET Framework. While this second generation of inheritance gives the module functionality shared by all portal modules, it also gives the module all of the functionality exposed by the UserControl class.

Figure 5.4 shows a partial object model for the ModuleControl base class as well as modules that inherit from the ModuleControl . The portal module object model has been designed in such a way that each module type inherits the exact amount of code needed for the implementation of a control of this type. In the diagram you can see that ModuleControl inherits from the System.Web.UI.UserControl, which means that the ModuleControl is a type of UserControl.

Figure 5.4. Partial Object Model

graphics/05fig04.gif


Figure 5.5 demonstrates a potential design for a portal module. The portal page controls the modules through two interfaces implemented by each module: IPlacement and ITheme. IPlacement interface contains methods used by the page to position a module in a required location on the selected pane. The ITheme interface contains methods used to control the appearance of each module. The mode of inheritance used in this scenario is called implementation inheritance , which allows each module to use the default implementation of both interfaces implemented in a BaseModule control or to override the default implementation with control-specific implementation.

Figure 5.5. BaseModule with Interfaces

graphics/05fig05.gif


The portal framework exposes a set of objects that build on the .NET functionality and offer a set of services consumed by portal modules. The portal framework consists of the following services:

  • Security

  • Encryption

  • Data

  • SharePoint connector service

  • Commerce Server Catalog connector

  • BizTalk 2002 WebService connector

Figure 5.6 illustrates the relationship between portal modules, the portal framework, and .NET Framework.

Figure 5.6. Portal Framework Layers

graphics/05fig06.gif


Develop the Data Model

Now, after we have familiarized ourselves with the .NET Framework and with the design goals and practices of portal framework architecture, let's roll up our sleeves and develop a minimal portal framework. Our ultimate goal is to make the framework extensible, easily manageable, and dynamic. To achieve this goal, we first develop the data model for the object that will comprise the portal framework. The data model will provide necessary containers and operations to enable the creation of the dynamic page shown in Figure 5.3.

This section describes the tables, their use, and descriptions for each of the fields. The data structure is designed to give the framework a high degree of extensibility. In Figure 5.7, you can see the framework's data model. This diagram shows the tables that make up the data model as well as the relationships between each of the tables. The data model consists of four "nouns" that can be seen as the main entities of the framework: Page, Template, Control, and Area.

Figure 5.7. Portal Framework Data Model

graphics/05fig07.jpg


As you will see later in the chapter, a template is made up of a number of areas and each page is a specific instance of a template. A common analogy used within object-oriented design can be seen here within the data model. If you think of a template as a blueprint for a house, then a page can be seen as a finished house. In other words, a template defines the structure of the page and each page can be seen as a concrete, implemented instance of that template. Each page can contain one or more controls within each of its areas. For a visual example of the page layout, see Figure 5.3.

Template

tblTemplate contains data that is used to define a template. The template is used to define a page layout. Table 5.1 briefly explains the data that is stored in the tblTemplate table.

Table 5.1. Structure of the tblTemplate Table

Field Name

Data Type

Description

TemplateID

Integer

Identity column for the table

Name

Alphanumeric (25)

A descriptive name for the template

Description

Alphanumeric (100)

A description of the purpose of the template

FileName

Alphanumeric (100)

The fully qualified filename of the template file (ASPX file)

ImageFileName

Alphanumeric (100)

The fully qualified filename of a graphic image that will be used to display what the template will look like


Area

tblArea contains data that is used to describe an area, which is a section of page used to hold one or more controls. Table 5.2 briefly describes the data that is stored in the tblArea table.

Table 5.2. Structure of the tblArea Table

Field Name

Data Type

Description

AreaID

Integer

Identity column for the table

Description

Alphanumeric (100)

A description of the area


Template Areas

tblTemplateArea contains data that is used to define the relationships between a template and an area. A collection of template-area records, grouped by a single template identifier, defines the areas that make up a single template. Table 5.3 briefly explains the data that is stored in the tblTemplateArea table.

Table 5.3. Structure of the tblTemplateArea Table

Field Name

Data Type

Description

TemplateAreaID

Integer

Identity column for the table

TemplateID

Integer

A template identifier ”this is a reference to the template that will contain the area

AreaID

Integer

An area identifier

CanBeConfigured

Bit

Flag used to denote if the template area configuration can be overridden within a page


Page

tblPage contains data that is used to define each page within the portal. The page table is the central table of the data model. Table 5.4 briefly explains the data that is stored in the tblPage table.

Table 5.4. Structure of the tblPage table

Field Name

Data Type

Description

PageID

Integer

Identity column for the table

Title

Alphanumeric (255)

A descriptive title for the page

ShortTitle

Alphanumeric (100)

A shortened version of the page title; this data is used in various situations in which screen real estate is expensive

ShowInNav

Boolean

A Boolean used to indicate whether this page should be shown within any of the navigation mechanisms

ShowInMainNav

Boolean

A Boolean used to indicate whether this page should be shown within the main navigation mechanism

TemplateID

Integer

A template identifier; this is a reference to the template that defines this page

PageTypeID

Integer

A page type identifier; this is a reference to the page type that specifies what type of page this is


Page Type

tblPageType contains data that is used to define each page within the portal. The page table is the central table of the data model. Table 5.5 briefly explains the data that is stored in the tblPage table.

Table 5.5. Structure of the tblPageType Table

Field Name

Data Type

Description

PageTypeID

Integer

Identity column for the table

Description

Alphanumeric (50)

A description of the page type

The page types that can exist within the portal are:

  • Portal page

  • External page (a page belonging to an external application or web site)

  • External page “new browser (this is similar to an external page, but thepage is opened in a separate browser window)


Page Relations

tblPageRelation contains data that is used to define relationships between pages. By maintaining relationship information, the framework can expose functionality that will provide dynamic links between these pages, thus allowing the end users to navigate between them.

The extraction of data from this table should take into account that relationships between pages are bidirectional; therefore, there should not be a need to store links in both directions for each of the pages in question. Table 5.6 briefly explains the data that is stored in the tblPageRelation table.

Table 5.6. Structure of the tblPageRelation Table

Field Name

Data Type

Description

PageID

Integer

Identity of the page

RelatedPageID

Integer

Identity of the related page


Page Hierarchy

tblPageHeirarchy contains data that is used to define the hierarchy of pages within the portal. The navigation within the portal is generated by recursively "walking" the page hierarchy programmatically and thus building a site map. Table 5.7 briefly explains the data that is stored in the tblPageHierarchy table.

Table 5.7. Structure of the tblPageHierarchy Table

Field Name

Data Type

Description

ParentPageID

Integer

Identity of the parent page

ChildPageID

Integer

Identity of the child page


Control

tblControl contains data that is used to describe controls, which are modular pieces of code that are used to define a specific set of functionality. A control can be placed into any of the areas on one or more pages. Table 5.8 briefly explains the data that is stored in the tblControl table.

Table 5.8. Structure of the tblControl Table

Field Name

Data Type

Description

TemplateID

Integer

Identity column for the table

Name

Alphanumeric (25)

A descriptive name for the control

FileName

Alphanumeric (100)

The fully qualified filename of the control file (ASCX file)


Page Controls

tblPageControl contains data that is used to describe the relationship between a page and a control. The page-control relationship defines more than just the appearance of a control on a page; it also defines the location of the control and how it should appear in that location.

A collection of page-control records, grouped by a single page identifier, defines the controls that will appear on a single page. Table 5.9 briefly explains the data that is stored in the tblPageControl table.

Table 5.9. Structure of the tblPageControl Table

Field Name

Data Type

Description

PageControlID

Integer

Identity column for the table

PageID

Integer

A page identifier; this is a reference to the page being defined

ControlID

Integer

A control identifier; this is a reference to the control being defined

AreaID

Integer

An area identifier; this is a reference to the area in which the control will be placed

OrderID

Integer

The order in which the control will be placed within the area, used for instances in which more than one control will be placed in the same area

Size

Integer

An optional value used to indicate the requested maximum height for the control


Control Properties

tblControlProperty contains data that is used to describe a property that will be exposed by a control. Control properties are used to dynamically configure a control. By describing each of a control's exposed properties, the framework can change the properties based on the specific instance of a control. Table 5.10 briefly explains the data that is stored in the tblControlProperty table.

Table 5.10. Structure of the tblControlProperty Table

Field Name

Data Type

Description

ContolPropertyID

Integer

Identity column for the table

ControlID

Integer

A control identifier; this is a reference to the control to which this property belongs

Name

Alphanumeric (100)

A descriptive name for the property

Required

Bit

A Boolean field used to indicate whether the specific property must have a corresponding value for each instance of the control


Page Control Properties

tblPageControlProperty contains data that is used to define a control property's value. A single page-control-property specifies the value of a property for an instance of a control property where it appears on a specific page. Table 5.11 briefly explains the data that is stored in the tblPageControlProperty table.

Table 5.11. Structure of the tblPageControlProperty Table

Field Name

Data Type

Description

ContolPropertyID

Integer

Identity column for the table

ControlID

Integer

The identifier of the control to which this property belongs

ContolPropertyID

Integer

A control property identifier; this is a reference to the control property whose value is being set by this record

Value

Alphanumeric (255)

The value for the specified control property


Create SQL Server Stored Procedures

With the data model in place, we can now proceed to defining the data retrieval operations. We create SQL Server stored procedures to retrieve the information necessary to display the hierarchy within a site and to create a page based on a page template and sets of controls contained within its panes.

SQL Server stored procedures represent a compiled SQL code stored within the SQL Server. Stored procedures offer the benefits of additional speed, security and code encapsulation, and reuse, and they are always preferable to the inline SQL statements.

The first stored procedure retrieves the information about the page. Because each page is a specialized page template, we return the template and template area information in this stored procedure as well.

Listing 5.1. Complete Code Listing for the Stored Procedure Page Data
 /*  Purpose:  Stored procedure for retrieving portal page data  Inputs:   @PageID - numeric ID of the page for which the data is _            retrieved */ Create  PROCEDURE spFetchPageInformation    @PageID INT  AS SET NOCOUNT ON Select P.PageID, P.Title, P.ShortTitle,        P.ShowInNav, P.ShowInMainNav,        P.TemplateID, P.PageTypeID,        PT.Description as PageTypeDescription,        T.Name as TemplateName,        T.Description as TemplateDescription,        T.FileName, T.ImageFileName FROM      tblPage P        INNER JOIN tblPageType PT           ON P.PageTypeID = PT.PageTypeID        INNER JOIN tblTemplate T           ON P.TemplateID = T.TemplateID WHERE    P.PageID = @PageID RETURN @@ERROR SET NOCOUNT OFF 

With the stored procedure in Listing 5.1, we can now retrieve the page information. The next stored procedure tells us which controls to load into each pane defined for the page. Because we are allowing each control to persist its properties in a table in SQL Server, the same stored procedure retrieves the list of properties for each control and the list of values set for these properties (if any) as well.

Listing 5.2. Complete Code Listing for the Stored Procedure Retrieving Control Data for All Controls Within a Page
 /*  Purpose:  Stored procedure for retrieving control data for all _            controls within a page  Inputs: @PageID - numeric ID of the page for which the data is _          retrieved          @ControlID - ID of the control whose information we retrieve */ CREATE   PROCEDURE spFetchPageControlInformation     @PageID INT,     @ControlID INT = NULL  AS SET NOCOUNT ON SELECT  PC.PageControlID, PC.PageID, PC.ControlID,     PC.AreaID, PC.OrderID, PC.[Size],     C.[Name] as ControlName, C.[FileName] FROM    tblPageControl PC     INNER JOIN tblControl C         ON PC.ControlID = C.ControlID WHERE    PC.PageID = @PageID    AND PC.ControlID = CASE WHEN IsNull(@ControlID, 0) = 0                   THEN PC.ControlID                   ELSE @ControlID                   END ORDER BY     PC.AreaID, PC.OrderID RETURN @@ERROR SET NOCOUNT OFF 

The last stored procedure required for our framework implementation retrieves values for all control properties saved in the database based on the PageControlID parameter.

Listing 5.3. Complete Code Listing for the Stored Procedure Retrieving Control Data for All Controls Within a Page
 /*  Purpose:  Stored procedure for retrieving the properties, stored in _            the database, for a specific instance of a control within a _            page.  Inputs:   @ControlID - ID of the control whose information we retrieve */ CREATE   PROCEDURE spFetchControlProperties     @PageControlID INT  AS SET NOCOUNT ON SELECT     CP.ControlPropertyID,     CP.[Name] as ControlPropertyName, CP.Required,     PCP.Value FROM   tblPageControl PC    INNER JOIN tblControlProperty CP       ON PC.ControlID = CP.ControlID    INNER JOIN tblPageControlProperty PCP       ON PC.PageControlID = PCP.PageControlID           and CP.ControlPropertyID = PCP.ControlPropertyID WHERE    PC.PageControlID = @PageControlID ORDER BY    CP.[Name] RETURN @@ERROR SET NOCOUNT OFF 

Create Code for Minimal Portal Framework

Armed with these stored procedures, we can finally start creating the code for the minimal portal framework. In this example, we omit such advanced portal features as authentication, maintenance of user profiles, personalization, and advanced caching techniques.

Here are the steps:

  1. Open Visual Studio .NET and create a Visual Basic web project called PortalFramework . Visual Studio creates a project and adds a new blank page to the project.

  2. Rename the page TemplatePage.aspx . This page will serve as our main framework template page.

  3. With the page opened in design mode, add a few HTML elements to the page. Provide container areas for left, right, top, and bottom portions of the page according to the layout shown in Figure 5.3. For the purposes of this example, we use an HTML table to break our portal page in the required area. Listing 5.4 shows the HTML for the prototype portal page.

Listing 5.4. HTML for the Portal Page Showing Portal Page Panes and Navigation Control Placement
 <%@ Page Language="vb" AutoEventWireup="false" Codebehind="TemplatePage.aspx.vb"     Inherits="PF.TemplatePage"%> <HTML>   <HEAD>     <TITLE id="PageTitle" runat="server">       Portal Framework Template Page     </TITLE>     <LINK href="Portal.css" type="text/css" rel="stylesheet">   </HEAD>   <BODY style="margin:1px">     <FORM id="Form1" method="post" runat="server">       <TABLE width="800" cellspacing="0" cellpadding="0" border="0">         <TR valign="top">           <TD id="TopPane" visible="False" runat="server" align="center">           </TD>         </TR>         <TR valign="top" height="20">           <TD id="NavPane" visible="False" runat="server">           </TD>         </TR>         <TR>           <TD>             <TABLE width="100%" cellspacing="0" cellpadding="4" _             border="0">               <TR height="*" valign="top">                 <TD id="LeftPane" Visible="false" Width="150" _                 runat="server">                </TD>                 <TD id="ContentPane" Visible="false" Width="*" _                 runat="server">                </TD>                 <TD id="RightPane" Visible="false" Width="150" _                 runat="server">                </TD>               </TR>             </TABLE>           </TD>         </TR>         <TR>           <TD id="BottomPane" visible="False" runat="server" _           align="center">          </TD>         </TR>       </TABLE>     </FORM>   </BODY> </HTML> 

The page consists of the HTML table containing four user controls: header, top breadcrumb menu control, left menu control, and the footer control. These standard controls will be used to display site navigation, page information, and general site information. If you were to try to run the solution, now it would fail because we have included forward declarations for our standard controls but have not defined the controls themselves .

The next step is to create four standard controls:

  1. Using Visual Studio Solution Explorer, right-click your solution and select Add New Folder from the popup menu.

  2. Name the new folder Controls . All our user controls will be grouped together in this folder.

  3. To create the header control, right-click the Controls folder and select Add Web User Control from the popup menu.

  4. Name the new control ctrlHeader.ascx . Visual Studio creates a control and opens it in design mode.

  5. Add the ASP.NET Label control with the ID of Header and the text Basic Portal Framework Demonstration in the design area.

  6. Repeat this process three more times to create the breadcrumb, left menu, and footer controls. Name them, respectively, ctrlBreadcrumb.ascx, ctrlMenu.ascx , and ctrlFooter.ascx .

  7. Set the text of the label of the footer control to Building Portals with .NET_Basic Portal Framework Demonstration .

We will use these four controls on the majority of the portal pages. To make a page dynamic, we will need to complete these steps:

  1. Store the database connection information in the Web.config file.

  2. Create a base page object; make it responsible for retrieving page-level information, and inherit all portal pages from the base page.

  3. Create a base control object and derive all portal user controls from the base control. The base control will be responsible for the common operations such as reading control properties during the base control's Load event.

  4. Implement code in the menu and breadcrumb controls to display, respectively, the site menu and the current breadcrumb trail.

  5. Add code to the Page Load event of the portal page. In this code, call the stored procedure spFetchPageInformation , which indicates which controls should be loaded into the page and which areas on the page should contain these controls.

  6. Enter template and page information in SQL Server tables.

  7. Create a generic content control and configure control-related data in SQL Server tables.

Store and Read the Database Connection Information

We need to keep the database connection string in a safe but easily reachable place. One good option is to store it in the Web.config file. Let's add the entry shown in Listing 5.5 to the Web.config file:

Listing 5.5. Storing the Database Connection String in the Web.config File
 <appSettings>        <add key="ConnectionString" value="Persist Security _        Info=True;User ID=sa;Password=password;Initial _        Catalog=Northwind;Data Source=."/> <appSettings> 

Note that you will have to modify the connection string to specify a valid user for your database.

Create the Base Page Object

To create this object:

  1. Create a new ASP.NET page and name it BasePage.aspx .

  2. Add the function shown in Listing 5.6 to the code-behind module of the base page.

    Listing 5.6. Executing Stored Procedure in Base Page Object
     ' GetDataTable() function executes a stored procedure ' and returns a first ADO.NET DataTable object from the ' resulting DataSet Protected Function GetDataTable(ByVal StoredProcName As String, _                             ByVal ParamName As String, _                             ByVal ParamValue As Integer) As DataTable     Dim ds As DataSet, dt As DataTable     Dim SQLParams(1) As SqlClient.SqlParameter     Dim strConn As String = AppSettings("ConnectionString")     Try         SQLParams(0) = New SqlClient.SqlParameter("@ReturnValue", 0)         SQLParams(0).DbType = DbType.Int32         SQLParams(0).Direction = ParameterDirection.ReturnValue         SQLParams(1) = New SqlClient.SqlParameter("@" & ParamName, _                     ParamValue)         ds = SqlHelper.ExecuteDataset(strConn, _             CommandType.StoredProcedure, StoredProcName, SQLParams)         If ds.Tables.Count > 0 Then dt = ds.Tables(0)     Catch ex As Exception         System.Diagnostics.Debug.Write(ex.ToString)     Finally         ds = Nothing     End Try     Return dt End Function 

    This function will be used by all derived template pages to run stored procedures in order to retrieve page-level data. The function uses ADO.NET objects to execute the stored procedure and return the result as the DataTable object.

  3. Change the definition of the template page by modifying its Inherits statement to read: Inherits BasePage . Now all functionality of the base page object will be available to the derived template object.

Create the Base Control Object and Derive All User Controls from the Base Control

Complete these steps:

  1. Add a user control to the Controls folder.

  2. Name the new control BaseControl.ascx .

  3. Add the code shown in Listing 5.7 to the code-behind module of the base control:

    Listing 5.7. Root Object for the User Controls Hierarchy. BaseControl.ascx
     Inherits System.Web.UI.UserControl Protected _PageControlID As Integer = 0 Protected _dtProperties As DataTable Public Property PageControlID() As Integer     Get         Return _PageControlID     End Get     Set(ByVal Value As Integer)         _PageControlID = Value     End Set End Property ' Load the values of the control properties during the Page Load _ event Private Sub Page_Load(ByVal sender As System.Object, ByVal e As _         System.EventArgs) Handles MyBase.Load     Try         _dtProperties = GetControlProperties()     Catch ex As Exception         Debug.WriteLine(ex.Message)     End Try End Sub ' Executes a stored procedure which loads all propeties ' for the given control and the given page. ' Returns the properties as ADO.NET DataTable Protected Function GetControlProperties() As DataTable     Dim ds As DataSet, dt As DataTable     Dim SQLParams(1) As SqlClient.SqlParameter     Dim strConn As String = AppSettings("ConnectionString")     Try         SQLParams(0) = New SqlClient.SqlParameter("@ReturnValue", 0)         SQLParams(0).DbType = DbType.Int32         SQLParams(0).Direction = ParameterDirection.ReturnValue         SQLParams(1) = New SqlClient.SqlParameter("@PageControlID", _                     _PageControlID)         ds = SqlHelper.ExecuteDataset(strConn, _             CommandType.StoredProcedure, _             "spFetchControlProperties", _             SQLParams)         If ds.Tables.Count > 0 AndAlso _             ds.Tables(0).Rows.Count > 0 Then dt = ds.Tables(0)     Catch ex As Exception         System.Diagnostics.Debug.Write(ex.ToString)     Finally         ds = Nothing     End Try     Return dt End Function 

    First, we defined two member variables , _ PageControlID and _ dtProperties , to hold, respectively, the ID of this control as it appears on the current page and the ADO.NET DataTable object to hold all properties for the current control. Next we defined a public property, PageControlID , which will be used by the parent page to set the page control ID value for the given control. And finally we created a function, GetControlProperties() , executed during the Page Load event of the base control. This function uses a stored procedure to query the database for the values of all properties defined for the current control.

  4. Now modify the definitions for all four standard controls to make them children of the base control. Open the code-behind modules for the menu, breadcrumb, header, and footer controls and replace the Inherits System.Web. UI .UserControl line with a Inherits BaseControl line. The new barebones code-behind for the header control should now look like that in Listing 5.8:

    Listing 5.8. Header User Control Deriving from the Base Control. ctrlHeader.ascx
     Public MustInherit Class ctrlHeader     Inherits BaseControl     Private Sub Page_Load(ByVal sender As System.Object, ByVal e As _     System.EventArgs) Handles MyBase.Load         'Put user code to initialize the page here     End Sub End Class 

Implement Breadcrumb and Menu Controls

Easy and convenient navigation is one of the primary objectives of a good portal. Our portal framework will provide two means of navigation: using the site menu displayed on the left side of the page and implemented in the menu control and the breadcrumb trail implemented in the breadcrumb control that shows the user the path traversed to the current page from the top page of the site.

The data for the menu control will be generated in XML format by the SQL Server stored procedure and pushed to the Load event of the menu control, where it will be transformed into the HTML format suitable for the display on a page using an XSL style sheet. Due to space limitations, it is impossible to discuss here in detail the usage of XML and XSL with SQL Server and .NET Framework. Refer to the MSDN site for extensive documentation and code samples for these technologies at http://msdn.microsoft.com.

  1. Create the stored procedure shown in Listing 5.9 to read the site menu information:

    Listing 5.9. Site Menu Stored Procedure. spFetchMenu.sql
     CREATE  PROCEDURE spFetchMenu    @ROOTPAGEID int = 1,    @PAGEID int = 2  AS SET NOCOUNT ON    Select          ROOT.PageID       ,PAGE.PageID       ,PAGE.Title       ,PAGE.ShortTitle       ,PAGE.URL       ,CASE WHEN PAGE.PageID = @PageID THEN 1 ELSE 0 END as _       PAGESELECTED       ,SUBPAGE.PageID       ,SUBPAGE.Title       ,SUBPAGE.ShortTitle       ,SUBPAGE.URL       ,CASE WHEN SUBPAGE.PageID = @PageID THEN 1 ELSE 0 END as _       SUBPAGESELECTED    From vwPages ROOT       LEFT OUTER JOIN vwPages PAGE         ON PAGE.ParentPageID = ROOT.PageID       LEFT OUTER JOIN vwPages SUBPAGE         ON SUBPAGE.ParentPageID = PAGE.PageID    WHERE ROOT.PageID = @ROOTPAGEID      AND PAGE.ShowInMainNav = 1      AND SUBPAGE.ShowInMainNav = 1    FOR XML AUTO RETURN @@ERROR SET NOCOUNT OFF 

    The spFetchMenu stored procedure uses the FOR XML AUTO clause to produce the output in the form of the XML document. Refer to the Microsoft SQL Server documentation for the detailed explanation of this feature.

  2. Implement the Page_Load event handler of the control responsible for the creation of the portal menu. Listing 5.10 shows how the menu control uses the stored procedure spFetchMenu to build and display the portal menu. The stored procedure is being called during the Load event of the control using a .NET XMLReader object.

    Listing 5.10. Page Load Event of the Menu User
     Private Sub Page_Load(ByVal sender As System.Object, _                       ByVal e As System.EventArgs) Handles _                       MyBase.Load  Dim strXMLMainMenuInfo As String = ""  Dim strHTMLMainMenuInfo As String = ""  Dim m_ConnectionString As String '- RECEIVE THE PAGE ID If Not Request.Params("PageID") Is Nothing Then _          _PageID = Int32.Parse(Request.Params("PageID"))  Dim CacheKey As String = "MainMenuInfo_" & _PageID.ToString  Dim sbXML As New System.Text.StringBuilder("")  Dim xrReader As System.Xml.XmlReader  Dim oStringWriter As New System.IO.StringWriter  Dim oXMLDoc As New System.Xml.XmlDocument  Dim oXslTransform As New System.Xml.Xsl.XslTransform  strHTMLMainMenuInfo = Cache.Item(CacheKey)  If strHTMLMainMenuInfo Is Nothing OrElse _  strHTMLMainMenuInfo.Length = 0 Then    Try      '- GET THE CONNECTION STRING      m_ConnectionString = ConfigurationSettings.AppSettings _      ("ConnectionString")      Dim con As New SqlClient.SqlConnection(m_ConnectionString)      '- PACKAGE PARAMETERS      Dim Params(1) As SqlClient.SqlParameter      Params(0) = New SqlClient.SqlParameter("@RootPageID", 1)      Params(0).DbType = DbType.Int32      Params(1) = New SqlClient.SqlParameter("@PageID", _PageID)      Params(1).DbType = DbType.Int32      Try        '- FETCH THE DATA FROM THE DATABASE        con.Open()        xrReader = SqlHelper.ExecuteXmlReader(con, _                   CommandType.StoredProcedure, "spFetchMenu", _                   Params)        ' READ THE CONTENTS OF XML READER        xrReader.MoveToContent()        While Not xrReader.EOF           sbXML.Append(xrReader.ReadOuterXml & vbCrLf)        End While         strXMLMainMenuInfo = sbXML.ToString         xrReader.Close()         con.Close()      Catch ex1 As Exception        System.Diagnostics.Debug.WriteLine(ex1.ToString)        Throw New Exception(ex1.Message)      Finally        xrReader = Nothing        con = Nothing        sbXML = Nothing      End Try       oXMLDoc.LoadXml(strXMLMainMenuInfo)       oXslTransform.Load(Server.MapPath("~/Controls/xslMenu.xsl"))       oXslTransform.Transform(oXMLDoc, Nothing, oStringWriter, _       Nothing)       strHTMLMainMenuInfo = oStringWriter.ToString       Page.Cache.Add(CacheKey, strHTMLMainMenuInfo, Nothing, _                       DateTime.MaxValue, TimeSpan.FromMinutes(60), _                       Caching.CacheItemPriority.High, Nothing)     Catch ex As Exception       'HANDLE ERROR     Finally       oStringWriter = Nothing       oXMLDoc = Nothing       oXslTransform = Nothing     End Try   End If    If strHTMLMainMenuInfo.Length > 0 Then      ctrlLiteral.Text = strHTMLMainMenuInfo    Else      ctrlLiteral.Text = "An error occurred while attempting to _      retrieve the Main Menu"    End If End Sub 

    As you can see in Listing 5.10, because the Menu control data is retrieved from the database in XML format, it needs to be transformed into HTML. Once this step is complete, the data is cached for subsequent requests using the ASP.NET cache object. This reduces the processing time when additional requests are made to the same page.

  3. Create an XSL file used to transform the data returned from the SQL Server into the HTML required to render the actual menu. Detailed explanation of XSL is beyond the scope of this chapter. Listing 5.11 demonstrates the finished XSL file used to transform the Menu data.

    Listing 5.11. XSL File Used to Transform the Menu from Raw XML into HTML
     <?xml version="1.0" ?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" _version="1.0">   <xsl:output method="html" indent="yes" />   <xsl:template match="PAGE">     <xsl:choose>         <xsl:when test="@PAGESELECTED='1'">           <DIV class="SelectedPage">             <B><xsl:value-of select="@Title" /></B>           </DIV>         </xsl:when>         <xsl:otherwise>           <DIV class="NonSelectedPage">               <A class="MenuItem">                 <xsl:attribute name="href">                   <xsl:value-of select="@URL" />                   ?PAGEID=<xsl:value-of select="@PageID" />                 </xsl:attribute>                 <xsl:value-of select="@Title" />                 <xsl:attribute name="alt">                   Go to the "<xsl:value-of select="@Title" />" page                 </xsl:attribute>                 <xsl:choose>                   <xsl:when test="@Target">                     <xsl:attribute name="target">_Blank</xsl:attribute>                   </xsl:when>                 </xsl:choose>               </A>           </DIV>         </xsl:otherwise>       </xsl:choose>       <xsl:apply-templates select="./SUBPAGE" />   </xsl:template>   <xsl:template match="SUBPAGE">     <xsl:choose>         <xsl:when test="@SUBPAGESELECTED='1'">           <DIV class="SelectedPage">             <B>&#160;&#160;<xsl:value-of select="@Title" /></B>           </DIV>         </xsl:when>         <xsl:otherwise>           <DIV class="NonSelectedPage">               &#160;&#160;<A class="MenuItem">                 <xsl:attribute name="href">                   <xsl:value-of select="@URL" />                   ?PAGEID=<xsl:value-of select="@PageID" />                 </xsl:attribute>                 <xsl:value-of select="@Title" />                 <xsl:attribute name="alt">                   Go to the "<xsl:value-of select="@Title" />" page                 </xsl:attribute>                 <xsl:choose>                   <xsl:when test="@Target">                     <xsl:attribute name="target">_Blank</xsl:attribute>                   </xsl:when>                 </xsl:choose>               </A>           </DIV>         </xsl:otherwise>       </xsl:choose>   </xsl:template> </xsl:stylesheet> 

  4. Next we will create the functionality needed to produce the breadcrumb trail user control to enable the display of the breadcrumb trail navigation bar. Create the stored procedure shown in Listing 5.12 to read the page hierarchy data and create the navigation path from the database.

    Listing 5.12. Breadcrumb Trail Stored Procedure. spFetchBreadCrumbTrail.sql
     CREATE PROCEDURE spFetchBreadcrumbTrail    @PageID int  AS SET NOCOUNT ON DECLARE  @tmpPages TABLE    ([Order]       int,     [PageID]      int,     [ParentPageID]         int,     [Title]       nvarchar(255),     [ShortTitle]  nvarchar(100),     [URL]                  varchar(150) ,     [Selected]     bit) DECLARE @Order int SET @Order = 1 DECLARE @Title             nvarchar(255) DECLARE @ShortTitle        nvarchar(100) DECLARE @URL               nvarchar(150) DECLARE @ParentPageID      int DECLARE @CurrentPageID     int DECLARE @PageType  int DECLARE @PageEntity        nvarchar(300) DECLARE @ParentFound       bit INSERT INTO @tmpPages Select 1, PageID, ParentPageID, Title, ShortTitle, URL, 1 FROM   vwPages WHERE  PageID = @PageID Select @ParentPageID = ISNULL(ParentPageID,0) from vwPages where _ PageID = @PageID and ShowInNav = 1 WHILE (@ParentPageID <> 0)     BEGIN    Set @Order = @Order + 1    INSERT INTO @tmpPages    SELECT @Order, PageID, ParentPageID, Title, ShortTitle, URL, 0        FROM vwPages WHERE PageID = @ParentPageID and ShowInNav = 1    Set @CurrentPageID = @ParentPageID    Set @ParentPageID = 0    Select @ParentPageID = ISNULL(ParentPageID,0)        FROM vwPages WHERE PageID = @CurrentPageID and ShowInNav = 1     END SELECT PageID, Title, ShortTitle, URL, Selected FROM @tmpPages PAGE ORDER BY [Order] DESC FOR XML AUTO RETURN @@ERROR SET NOCOUNT OFF 

  5. Implement the code consuming the breadcrumb data retrieved by the stored procedure. The code for the Page Load event of the breadcrumb control displayed in Listing 5.13 is similar to the Page Load event of the Menu control. The data, in XML format, is being loaded from the database using the spFetchBreadCrumbTrail stored procedure. When the data received from the SQL Server is loaded into the XML document, XSL (extensible stylesheet language) transformation is applied using the style sheet stored in the file xslBreadCrumbTrail.xsl. To optimize server load and execution time, the breadcrumb trail XML data is loaded into the .NET cache object.

    Listing 5.13. Breadcrumb Trail User Control
     Private Sub Page_Load(ByVal sender As System.Object, _                       ByVal e As System.EventArgs) Handles MyBase.Load     Dim strXMLBreadCrumbTrailInfo As String = ""     Dim strHTMLBreadCrumbTrailInfo As String = ""     Dim m_ConnectionString As String    '- RECEIVE THE PAGE ID    If Not Request.Params("PAGEID") Is Nothing Then _             _PageID = Int32.Parse(Request.Params("PAGEID"))     Dim CacheKey As String = "BreadCrumbTrailInfo_" & _PageID.ToString     Dim sbXML As New System.Text.StringBuilder("<ROOT>")     Dim xrReader As System.Xml.XmlReader     Dim oStringWriter As New System.IO.StringWriter     Dim oXMLDoc As New System.Xml.XmlDocument     Dim oXslTransform As New System.Xml.Xsl.XslTransform     strHTMLBreadCrumbTrailInfo = Cache.Item(CacheKey)     If strHTMLBreadCrumbTrailInfo Is Nothing _         OrElse strHTMLBreadCrumbTrailInfo.Length = 0 Then       Try         '- GET THE CONNECTION STRING         m_ConnectionString = ConfigurationSettings.AppSettings _         ("ConnectionString")         Dim con As New SqlClient.SqlConnection(m_ConnectionString)         '- PACKAGE PARAMETERS         Dim Params(0) As SqlClient.SqlParameter         Params(0) = New SqlClient.SqlParameter("@PageID", _PageID)         Params(0).DbType = DbType.Int32         Try           '- FETCH THE DATA FROM THE DATABASE           con.Open()           xrReader = SqlHelper.ExecuteXmlReader(con, _           CommandType.StoredProcedure, _                      "spFetchBreadCrumbTrail", Params)           ' READ THE CONTENTS OF XML READER           xrReader.MoveToContent()           While Not xrReader.EOF             sbXML.Append(xrReader.ReadOuterXml & vbCrLf)           End While           sbXML.Append("</ROOT>")           strXMLBreadCrumbTrailInfo = sbXML.ToString           xrReader.Close()           con.Close()         Catch ex1 As Exception           System.Diagnostics.Debug.WriteLine(ex1.ToString)           Throw New Exception(ex1.Message)         Finally           xrReader = Nothing           con = Nothing           sbXML = Nothing         End Try         oXMLDoc.LoadXml(strXMLBreadCrumbTrailInfo)         oXslTransform.Load(Server.MapPath("~/Controls/ _         xslBreadCrumbTrail.xsl"))         oXslTransform.Transform(oXMLDoc, Nothing, oStringWriter, _         Nothing)         strHTMLBreadCrumbTrailInfo = oStringWriter.ToString         Page.Cache.Add(CacheKey, strHTMLBreadCrumbTrailInfo, Nothing, _                        DateTime.MaxValue, TimeSpan.FromMinutes(60),  _                        Caching.CacheItemPriority.High, Nothing)       Catch ex As Exception         'HANDLE ERROR       Finally         oStringWriter = Nothing         oXMLDoc = Nothing         oXslTransform = Nothing       End Try     End If     If strHTMLBreadCrumbTrailInfo.Length > 0 Then       ctrlLiteral.Text = strHTMLBreadCrumbTrailInfo     Else       ctrlLiteral.Text = "An error occurred while attempting to _       retrieve the Bread Crumb Trail"     End If   End Sub 

  6. Use the XSL transformation to create HTML presentation code from the data retrieved from the SQL Server. Listing 5.14 demonstrates an XSL file used to transform the breadcrumb data.

Listing 5.14. XSL File Used to Transform the Breadcrumb Trail from Raw XML into HTML
 <?xml version="1.0" ?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" _ version="1.0">   <xsl:output method="html" indent="yes" />   <xsl:template match="PAGE">     <xsl:choose>         <xsl:when test="@Selected='1'">             <SPAN class="SelectedPage"><xsl:value-of select="@Title" _             /></SPAN>         </xsl:when>         <xsl:otherwise>             <SPAN class="NonSelectedPage">               <A>                 <xsl:attribute name="href">                   <xsl:value-of select="@URL" />                   ?PAGEID=<xsl:value-of select="@PageID" />                 </xsl:attribute>                 <xsl:value-of select="@Title" />                 <xsl:attribute name="alt">                   Go to the "<xsl:value-of select="@Title" />" page                 </xsl:attribute>               </A> >             </SPAN>         </xsl:otherwise>       </xsl:choose>       <xsl:apply-templates select="./PAGE" />   </xsl:template> </xsl:stylesheet> 

Dynamically Load User Controls

Notice that our template page is blank; it does not contain any design-time controls. We will load controls dynamically during the template page's Page Load event by querying the database for the list of all controls belonging to the current page and the area into which the controls should be placed. Our stored procedure will return both the file name of the control and the area name that should contain the control.

  1. Modify the code-behind module of the portal page to read the list of controls belonging to the current page.

  2. Position the controls within the panes on the page.

Listing 5.15 below shows the complete text of the code-behind module of the portal page implementing these two steps.

Listing 5.15. Dynamically Creating User Controls in the Portal Page
 Inherits BasePage ' Inherit template from BasePage ' Define template page's containing area controls Protected PageTitle As HtmlControls.HtmlGenericControl Protected TopPane As System.Web.UI.HtmlControls.HtmlTableCell Protected NavPane As System.Web.UI.HtmlControls.HtmlTableCell Protected LeftPane As System.Web.UI.HtmlControls.HtmlTableCell Protected ContentPane As System.Web.UI.HtmlControls.HtmlTableCell Protected RightPane As System.Web.UI.HtmlControls.HtmlTableCell Protected BottomPane As System.Web.UI.HtmlControls.HtmlTableCell ' define enumerator corresponding to the page areas Enum Pane As Integer     TopPane = 1     NavPane = 2     LeftPane = 3     ContentPane = 4     RightPane = 5     BottomPane = 6 End Enum ' define a class member to hold the database-received ID of ' the current page. Default it to Zero. Actual value will ' be retrieved in the Page Load event handler Private _PageID As Integer = 0 ' Page load event handler will: ' - Receive the ID of the current page from the parameter list ' - Retrieve page information using FetchPageInformation() function ' - Load all controls on the page using LoadPageControls() function Private Sub Page_Load(ByVal sender As System.Object, ByVal e As _                         System.EventArgs) Handles MyBase.Load     If Not Request.Params("PageID") Is Nothing Then         _PageID = CType(Request.Params("PageID"), Integer)     Else         _PageID = 2     ' Assume the first page with data (ignore _                           Root page)     End If     Dim strTitle As String = "", strShortTitle As String = ""     If FetchPageInformation(strTitle, strShortTitle) Then _                         PageTitle.InnerText = strTitle     LoadPageControls() End Sub ' FetchPageInformation() function will call GetDataTable() function ' defined in the BasePage class to receive page's title and short ' title. ' Data is returned as ADO.NET DataTable. Private Function FetchPageInformation(ByRef Title As String, _ ByRef _             ShortTitle As String) As Boolean     Dim retVal As Boolean = False    'ASSUME FAILURE     Dim dt As DataTable     Try         dt = GetDataTable("spFetchPageInformation", "PageID", _         _PageID)         Title = CType(dt.Rows(0).Item("Title"), String)         ShortTitle = CType(dt.Rows(0).Item("ShortTitle"), String)         retVal = True     Catch ex As Exception         retVal = False     Finally         dt = Nothing     End Try     Return retVal End Function ' LoadPageControls() function will: ' - call GetDataTable() function to execute a stored procedure '   which returns the data about controls belonging to the '   current page ' - iterate through the resulting data table; dynamically '   load each control and assign it to the specified area on '   the page Private Function LoadPageControls() As Boolean     Dim retVal As Boolean = False    'ASSUME FAILURE     Dim dt As DataTable, dr As DataRow     Dim ctrl As String = "", intArea As Pane = 0     Dim intOrder As Integer = 0, strFileName As String = ""     Dim theControl As BaseControl     Try         dt = GetDataTable("spFetchPageControlInformation", _         "PageID", _                         _PageID)        For Each dr In dt.Rows             ctrl = dr.Item("ControlName")             intArea = dr.Item("AreaID")             intOrder = dr.Item("OrderID")             strFileName = dr.Item("FileName")             ' Find the containing area control             Dim ParentTableCell As HtmlControls.HtmlTableCell              ParentTableCell = Page.FindControl(intArea.GetName(_                                  intArea.GetType, intArea))             If ParentTableCell.Controls.Count > 0 Then                 Dim ctrlLiteral As New WebControls.Literal                 ctrlLiteral.Text = "<BR>"                 ParentTableCell.Controls.Add(ctrlLiteral)             End If             ' Dynamically load new control              theControl = Page.LoadControl("~/" & strFileName)              theControl.PageControlID = _              CType(dr.Item("PageControlID"), Int32)              ParentTableCell.Controls.Add(theControl)              ParentTableCell.Visible = True         Next         retVal = True     Catch ex As Exception         retVal = False     Finally         dt = Nothing     End Try     Return retVal End Function 

In the code fragment in Listing 5.15, we have defined a set of controls corresponding to the containing panes on the form. We have used a member variable Pane of the Enum data type for easier access to the area controls. Enumerators ( Enum in .NET Framework) let developers supply alternate human-readable names for the underlying primitive types.

The Page Load event handler executes a function to load main page “level information and another function to retrieve the list of controls, instantiate and position each control within its target area, and populate control properties.

Add Template and Page Information to the Database

Our framework is database-driven; but at this point, the database is empty. Let's add the page area definitions and create one generic template and a few pages based on this template. We don't have an administrative module yet, so we will enter the data by hand using SQL Server Enterprise Manager. Note that we need a root page to enable the functioning of the menu and breadcrumb controls. The root page only serves as root of the page hierarchy; it doesn't contain any controls and is never shown to the user. To populate the data, open all portal tables in Enterprise Manager and type in the values for all fields, referring to Figure 5.8. After populating the Area, Template, Template Area, Page, and Page Hierarchy tables, you should see the data as shown in Figure 5.8.

Figure 5.8. Adding Page and Template Definitions to the Database

graphics/05fig08.jpg


We have defined a single template, Framework Template, which contains all six possible areas. We then created three pages; all based on this template, and we created a simple hierarchy with one page, Home Page, at the root of the hierarchy and two sibling pages, Content Page 1 and Content Page 2, one level below the Home Page.

The framework reads the page definition data and loads and displays the page hierarchy. This is great, but the crucial part of any portal ”the content ”is still missing. To display the content, we create a simple content control derived from the base control and we con the framework into displaying it in the content pane of each page.

Create the Content Control

To create this control:

  1. Using Visual Studio .NET, add a new control to the Controls folder.

  2. Name the new control ctrlContent.ascx .

  3. Change the Inherits statement at the top of the code-behind module to inherit the new content control from the base control.

    The Content control works by reading the list of its properties for a given page and displaying them using ASP.NET Label controls. Each of the properties for the control is populated by the content creator and may consist of text, HTML data, or image data. The values and names of the properties are contained in the ADO.NET DataTable object _dtProperties inherited from the BaseControl .

  4. To display the values of the properties, create two label controls, Header and Content . Later we configure the database to match these content properties. Add the code shown in Listing 5.16 to ctrlContent.ascx:

    Listing 5.16. ctrlContent.ascx
     <asp:Label id="Header" runat="server" Font-Size=16 _ Font-Bold=True>Header for content control</asp:Label> <br> <asp:Label id="Content" runat="server" >Content data</asp:Label> 

  5. Add the code shown in Listing 5.17 to the code-behind module of the ctrlContent object:

    Listing 5.17. Code Module for the Content Control ctrlContent.ascx.vb
     Protected Header As System.Web.UI.WebControls.Label Protected Content As System.Web.UI.WebControls.Label ' Go through all properties for the Content control ' and load them Private Sub Page_Load(ByVal sender As System.Object, ByVal e As _         System.EventArgs) Handles MyBase.Load     If _dtProperties Is Nothing Then Exit Sub     Dim i As Integer, DisplayControl As Label     With _dtProperties         For i = 0 To .Rows.Count - 1             Select Case .Rows(i).Item("ControlPropertyName")                 Case "Content"                      Content.Text = .Rows(i).Item("Value")                 Case "Header"                      Header.Text = .Rows(i).Item("Value")             End Select         Next     End With End Sub 

We have defined two label objects and have implemented a Page Load handler event that uses the DataTable object inherited from the parent BaseControl object to loop through the list of property names and property values and populate both label controls with the values defined for them.

Finally we can configure our three portal pages to display the content control in its content areas. In a full-blown portal framework implementation, this data is entered by using Administration and Content Management modules. In this stripped-down version, you enter the data by hand using SQL Server Enterprise Manager. If you follow along, you can enter the data shown in Figure 5.9 or create your own content.

Figure 5.9. Adding Control Definitions and Content to the Database

graphics/05fig09.jpg


Let's review the steps completed so far. We have associated header, breadcrumb trail, menu, footer, and content controls with the header, top, left, footer, and content areas, respectively, on each of our three portal pages using tblPageControl . Next we created two properties, Content and Header, for the content control (ControlID = 2) and a single property, Content, for the inventory control (ControlID = 6) using the tblControlProperty table. Finally we set up some content to be displayed by the content and inventory controls on each of the three portal pages using the tblPageControlProperty table.

Run the Portal

If you have followed this exercise closely, you should be able now to successfully compile and run the project. With control content specified as shown in Figure 5.8 and Figure 5.9, the first page of the portal should look like that shown in Figure 5.10.

Figure 5.10. First Portal Page

graphics/05fig10.gif


Where to Go from Here

At this point we have a functioning (albeit rather simple) site. We can navigate the site using menu and the breadcrumb trail controls; and we can modify data in SQL Server tables to change the page composition as well as add or delete pages or change control placement within the page.

Follow these steps to take your work in this exercise closer to a full-blown portal framework implementation:

  1. Add the administration module to allow portal administrators to manage user, page, and content information.

  2. Add login, logout, and authentication mechanisms.

  3. Add the authorization mechanism to provide the ability to restrict content based on the current login (refer to Chapter 6 for a detailed review of .NET-related security, authentication, and authorization options).

  4. Add the logging and usage statistics gathering and management modules.

  5. Add caching to support better performance.

  6. Add the content management module to allow content authors to create, edit, and manage portal content.

 <  Day Day Up  >  


Building Portals, Intranets, and Corporate Web Sites Using Microsoft Servers
Building Portals, Intranets, and Corporate Web Sites Using Microsoft Servers
ISBN: 0321159632
EAN: 2147483647
Year: 2004
Pages: 164

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net