The Comment Tracking Control

The comment tracking control is intended to track comments about ASP.NET pages that are under development. Because the comments need to be associated with the different people making them, each user needs to be able to log in. In this control, there is a registration page where anyone can register to make comments on the page. After registering, users will be able to log in at anytime.

Using a module such as this is important in a number of situations. One in particular that I recall is when a client wanted to have staff submit comments for a newly developed Web application. This control provided the perfect mechanism for them to do so.

Because this control is not intended to be used on a production site, the people with knowledge of the URL are likely to be the ones evaluating the site implementation, or the site will be hosted on a development server that is not accessible to the public. In either case, security is not too big of an issue for allowing anyone to register; but if this control were adapted for use on a pubic site, further study of the security issues involved would be necessary. For more discussion of security issues, read the section in Chapter 18 entitled "Security" (page 657).

Control Overview

The comment control handles all facets of commenting. They are the login state, the register state and the comment viewing state. In reality, each state is implemented by a separate server control. Because none of these embedded controls is intended to be used separately, I will just consider them different states of the comment control until I get into the implementation details.

Login State

When a user first accesses a page that has a comment control on it, the comment control is in the login state. Reviewers are required to log in or register prior to seeing other comments. This was intended to get everyone to register and log in. Figure 15.1 shows the comment control when it is first displayed for login.

Figure 15.1. Comment Control in Login Mode

graphics/15fig01.jpg

As you can see, to the left of the control data there is a button, Hide Comments. If this button is pressed, instead of displaying the comment control, only a button, Show Comments, is displayed. This allows the person viewing the page to hide the comments if they cover part of the page being evaluated. This feature is available no matter what state the comment control is in, and it will persist across different pages.

The comment control in the login state has two buttons, the Login button, and the Register button. These buttons do pretty much what you would expect them to. The Login button submits the username and password for authentication, and the Register button changes what is displayed in the comment control to a registration page.

Registration State

The first time someone is evaluating a page, he will need to register. Figure 15.2 shows the comment control in its registration state.

Figure 15.2. Comment Control in Registration Mode

graphics/15fig02.jpg

Because this control is intended to be used during the development of the site before it is live, security of the comments being made was less of an issue than making it easy for the reviewers to register and log in. Because of this, the username is the only required field. If the reviewer wants to display a name other than the username with his comments, he should fill in the display name.

Commenting State

Once a reviewer has logged in, he will see the comment control in its most common state, the commenting state. Figure 15.3 shows the comment control in its commenting state.

Figure 15.3. Comment Control in Commenting Mode

graphics/15fig03.jpg

Once a reviewer has logged in, the commenting control has three areas. At the top is a page note. If the person logging in has developer rights, she will see a small Edit button here. The developer can add or modify the note by clicking the Edit button. All other users can only read the note.

Following the note is a list of the comments. A user can edit but not delete any of his own comments. At the bottom is an entry field to enter new comments into. The developer has some additional functionality. The developer can reply to any of the comments and have the reply immediately below the comment. All others can only enter new comments. The comments are listed in order of entry. The developer can reply to comments so that if the comment is an action item, such as fixing the color on the page or something, the developer can reply that it has been done, or why it wasn't done, and anyone reading the comments can see whether or not an issue was resolved.

User Types

The comment control has three different kinds of users: developers, local users, and customers. Developers are the people who are implementing the site. A developer has the ability to edit the page notes and reply to any comment. A local user would be like an in-house site reviewer or tester. Comments entered by this type of user could not be seen by the customer users. This way, in-house testers can add comments/suggestions without the final customer being able to see them. Figure 15.4 shows the comment control as the developer sees it.

Figure 15.4. Comment Control for the Developer

graphics/15fig04.jpg

Implementation

To implement the control, I actually used four different custom controls. There is one control each for each of the states, and a master control that determines which of the other three controls is displayed. Following is a list of the controls that make up the commenting control:

  • CommentCtl This is the master control that you use. It displays one of the following controls, depending upon the current state.

  • CommentLoginCtl This control displays the initial login.

  • CommentRegisterCtl This control displays the registration form.

  • CommentDisplayCtl This control displays the actual comments once the user has logged in.

Now let's look at each of these controls in detail.

CommentCtl

The first thing to look at is the public interface because that is what a user of the control will need to understand. Table 15.1 shows the public interface methods and properties.

Even though CommentCtl is the only one of the controls that has a truly public interface that can be set by the user, the contained controls also have some of the same properties. The contained controls' interface values are set by this control. The way the control is structured, you can't use the contained controls independently from CommentCtrl.

Next, let's look at the methods that are called to create the control. Table 15.2 shows the private and protected methods used to create the control.

Next we will look at the private properties used by the control. Table 15.3 shows the private properties used in this control.

Table 15.1. Public Interface

Name

Type

Description

ConnectionString

Property

This property is a string that contains the OleDb connection string to the data source containing the comment data.

Revision

Property

This property is an integer containing the revision. The comments are displayed by revision, and only the comments for the indicated revision are displayed.

CssFile

Property

This property contains the name of the .css file that contains the css classes necessary to format the control. Using a separate .css file (rather than relying on the styles of the surrounding page) gives you much more control over the appearance.

Table 15.2. Control Creation Methods

Name

Type

Description

CreateChildControls()

Method

This method starts the process of creating the control. All other methods are called from this one.

HandleState()

Method

This method is called to determine which of the other controls will be displayed.

DisplayShowButton()

Method

This method is called when the main portion of the control is hidden and only a button with the label Show Comments is displayed. If this button is pressed, the main portion of the control will be displayed.

DisplayHideButton()

Method

This method is called when the main portion of the control is displayed with the addition of a button labeled Hide Comments. If this button is pressed, the main portion of the control will be hidden so that any portion of the page behind the control can be seen.

DisplayLogin()

Method

This method displays the CommentLoginCtl control.

DisplayRegister()

Method

This method displays the CommentRegisterCtl control.

DisplayStd()

Method

This method displays the CommentDisplayCtl control, which is where the actual comments are displayed.

AddLiteral()

Method

This method adds a LiteralControl to the Controls collection. The text to be added is passed in an argument.

Finally, we will look at the event handlers used in this control. These events are generated by the contained control being displayed. With this control, each of the events fired results in a change of state, which changes the control that is currently being displayed. Table 15.4 shows the event handlers used in this control.

Now let's look at the actual implementation of this control. Listing 15.3 provides a complete source listing of the control.

Table 15.3. Private Properties

Name

Type

Description

State

Property

This property is an enumation that contains the state of the control.

Compact

Property

This is a Boolean value that indicates whether the control is to be rendered in its compact mode, which displays only a button labeled Show Comments, or whether it is to be rendered normally.

Reload

Property

This is a Boolean value that indicates whether the page needs to be immediately reloaded. The page is normally reloaded every time there is a post back. This property indicates that the page is to be reloaded without resubmitting the previous data.

Table 15.4. Event Handlers

Name

Type

Description

OnShowButton_Click()

Event Handler

This method is used to handle the Click event of the button that shows or hides the main portion of the control.

OnLoggedin()

Event Handler

This method handles the Loggedin event from the CommentLoginCtl control. This event is raised when the user has successfully logged in.

OnRegister

Event Handler

This method handles the Register event from the CommentLoginCtl control. This event is raised when the Register button is pressed when the CommentLoginCtl is displayed.

OnRegistered

Event Handler

This method handles the Registered event from the CommentRegisterCtl control. This event is fired when a new user has successfully registered.

OnCancel

Event Handler

This method handles the Cancel event from the CommentRegisterCtl control. This event is fired when the Cancel button is pressed on the registration form.

Listing 15.3 Comment control CommentCtl.cs
 using System; using System.Web.UI; using System.Web.UI.WebControls; using System.ComponentModel; using System.Configuration; using System.Collections.Specialized; namespace Comment {     ' State enumerations.     enum enumState     {         stateLogin=1,         stateRegister=2,         stateStd=3     };     /// <summary>     /// This is the main comment control, it manages which of     ///  the other controls are displayed     /// </summary>     [DefaultProperty("DataSource"),         ToolboxData             ("<{0}:CommentCtl runat=server></{0}:CommentCtl>")]     public class CommentCtl : WebControl,INamingContainer     {         private String m_sUsername;         private string m_sConnectionString;         private string m_sCssFile;         private int m_nRevision;         // Control Creation Methods         protected override void CreateChildControls()         {             if(Reload)             {                 Reload=false;                 ' Adding script allows client-side interaction.                 AddLiteral("<script>");                 AddLiteral("window.navigate('"+                     Page.Request.RawUrl+"')");                 AddLiteral("</script>");             }             else if(Compact)             {                 DisplayShowButton();             }             else             {                 ' Attempt to retrieve state data.                 if(Page.Request.Cookies["CommentUser"]!=null)                 {                     m_sUsername=                         Page.Request.Cookies["CommentUser"]                         .Value;                     ' There are times when this is not explicitly know.                     State = enumState.stateStd;                 }                 HandleState();             }         }         private void HandleState()         {             // Add stylesheet if necessary.             if(CssFile!="")             {                 AddLiteral("<link href=\""+CssFile+                     "\" type=\"text/css\" rel=\"stylesheet\">");             }             switch (State)             {                 case enumState.stateLogin :                     DisplayLogin();                     break;                 case enumState.stateRegister :                     DisplayRegister();                     break;                 case enumState.stateStd :                     DisplayStd();                     break;                 default :                     throw new Exception("Invalid State");             }         }         private void DisplayShowButton()         {             // Add stylesheet if necessary.             if(CssFile!="")             {                 AddLiteral("<link href=\""+CssFile+                     "\" type=\"text/css\" rel=\"stylesheet\">");             }             Button objCompactButton=new Button();             objCompactButton.Text="Show Comments";             objCompactButton.Css;             objCompactButton.CausesValidation=false;             objCompactButton.CommandName="Show";             objCompactButton.;             objCompactButton.Click+=                 new EventHandler(OnShowButton_Click);             Controls.Add(objCompactButton);         }         private void DisplayHideButton()         {             // Display Hide Button             Button objCompactButton=new Button();             objCompactButton.Text="Hide Comments";             objCompactButton.Css;             objCompactButton.CausesValidation=false;             objCompactButton.CommandName="Show";             objCompactButton.;             objCompactButton.Click+=                 new EventHandler(OnShowButton_Click);             Controls.Add(objCompactButton);         }         private void DisplayLogin()         {             CommentLoginCtl objCommentLoginCtl=                 new CommentLoginCtl();             objCommentLoginCtl.ConnectionString=                 ConnectionString;             objCommentLoginCtl.Loggedin+=                 new EventHandler(OnLoggedin);             objCommentLoginCtl.Register+=                 new EventHandler(OnRegister);             Controls.Add(objCommentLoginCtl);             DisplayHideButton();         }         private void DisplayRegister()         {             CommentRegisterCtl objCommentRegisterCtl=                 new CommentRegisterCtl();             objCommentRegisterCtl.ConnectionString=                 ConnectionString;             objCommentRegisterCtl.Registered+=                 new EventHandler(OnRegistered);             objCommentRegisterCtl.Cancel+=                 new EventHandler(OnCancel);             Controls.Add(objCommentRegisterCtl);             DisplayHideButton();         }         private void DisplayStd()         {             CommentDisplayCtl objCommentDisplayCtl=                 new CommentDisplayCtl();             objCommentDisplayCtl.ConnectionString=                 ConnectionString;             objCommentDisplayCtl.Revision=Revision;             objCommentDisplayCtl.Username=m_sUsername;             Controls.Add(objCommentDisplayCtl);             DisplayHideButton();         }         private void AddLiteral(String sText)         {             Controls.Add(new LiteralControl(sText));         }         // Private properties start here.         private enumState State         {             get             {                 if(Page.Session["State"]==null)                     Page.Session["State"]=enumState.stateLogin;                 return (enumState) Page.Session["State"];             }             set             {                 Page.Session["State"]=value;             }         }         private bool Compact         {             get             {                 if(Page.Session["Compact"]==null)                     Page.Session["Compact"]=false;                 return (bool) Page.Session["Compact"];             }             set             {                 Page.Session["Compact"]=value;             }         }         private bool Reload         {             get             {                 if(Page.Session["Reload"]==null)                     Page.Session["Reload"]=false;                 return (bool) Page.Session["Reload"];             }             set             {                 Page.Session["Reload"]=value;             }         }         // Public properties start here.         public string ConnectionString         {             get             {                 return m_sConnectionString;             }             set             {                 m_sConnectionString = value;             }         }         public int Revision         {             get             {                 return m_nRevision;             }             set             {                 m_nRevision = value;             }         }         public string CssFile         {             get             {                 return m_sCssFile;             }             set             {                 m_sCssFile = value;             }         }         // Event handlers go here         private void OnShowButton_Click             (Object sender, EventArgs e)         {             Compact=!Compact;             Reload=true;             Controls.Clear();             CreateChildControls();         }         private void OnLoggedin(Object sender, EventArgs e)         {             CommentLoginCtl objLoginCtl=                 (CommentLoginCtl) sender;             State=enumState.stateStd;             m_sUsername=objLoginCtl.m_ctlEditUsername.Text;             // Add the User cookie             System.Web.HttpCookie objCookie =                 new System.Web.HttpCookie("CommentUser");             objCookie.Value = m_sUsername;             Page.Response.Cookies.Add(objCookie);             Controls.Clear();             HandleState();         }         private void OnRegister(Object sender, EventArgs e)         {             State=enumState.stateRegister;             Controls.Clear();             HandleState();         }         private void OnRegistered(Object sender, EventArgs e)         {             CommentRegisterCtl objRegisterCtl=                 (CommentRegisterCtl) sender;             State=enumState.stateStd;             m_sUsername=objRegisterCtl.m_ctlEditUsername.Text;             // Add the User cookie             System.Web.HttpCookie objCookie =                 new System.Web.HttpCookie("CommentUser");             objCookie.Value = m_sUsername;             Page.Response.Cookies.Add(objCookie);             Controls.Clear();             HandleState();         }         private void OnCancel(Object sender, EventArgs e)         {             State=enumState.stateLogin;             Controls.Clear();             HandleState();         }     } } 

This control is basically a state management engine with two different unrelated sets of states. One set of states manages which of the contained controls is being rendered. The other set of states is whether the controls should be rendered as a button or a complete control.

RECOMMENDED PRACTICE: One thing to note here is that the control is positioned absolutely on the page using a style sheet. This means that this control can hide portions of the page. Normally this would be fine becasue we can hide the comment control. The one case in which unexpected results may occur is if the page has a list box, either a drop-down list box or a standard list box. In this case, the list box will render on top of the comment control rather then being hidden by it. This is an inherent problem with Internet Explorer. Before allowing others to review the application, you should go through every page and verify that you have positioned the comment control on the page such that this does not occur.


CommentLoginCtl

The CommentLoginCtl is the control that is displayed by the main CommentCtl control prior to the user logging in. It displays a Username and a Password entry field, and Login and Register buttons. This represents the initial state of our comment control.

Table 15.5. Public Interface

Name

Type

Description

ConnectionString

Property

This property is a string that contains the OleDb connection string to the data source containing the comment data.

m_ctlEditUsername

TextBox

This is a variable that holds a reference to the contained control that contains the username of the user logging in.

M_ctlEditPassword

TextBox

This is a variable that holds a reference to the contained control that contains the password of the user logging in.

Table 15.6. Control Creation Methods

Name

Type

Description

CreateChildControls()

Method

This method starts the process of creating the control. For this control, all this method does is call the CreateLogin() method.

CreateLogin()

Method

This method creates this control.

AddLiteral()

Method

This method adds a LiteralControl to the Controls collection. The text to be added is passed in an argument.

Table 15.7. Event Handlers

Name

Type

Description

OnLoginButton_Click()

Event Handler

This method is used to handle the Click event of the Login button.

OnRegisterButton_Click()

Event Handler

This method is used to handle the Click event of the Register button.

Table 15.8. Events

Name

Type

Description

Loggedin

Event

This event is fired after the Username and Password entered by the user have been confirmed.

Register

Event

This event is fired when the Register button is pressed.

The public interface portion of this control is intended to be used only by the CommentCtl control. Table 15.5 shows the public interface of this control.

Table 15.6 shows the control creation methods.

Table 15.7 shows the event handlers used in this control.

Table 15.8 shows the events generated by this control.

Listing 15.4 contains the source listing for the CommentLoginCtl control.

Listing 15.4 Comment Login Control CommentLoginCtl.cs
 using System; using System.Web.UI; using System.Web.UI.WebControls; using System.ComponentModel; using System.Configuration; using System.Collections.Specialized; namespace Comment {     public class CommentLoginCtl : WebControl,INamingContainer     {         private string m_sConnectionString;         // Variables that hold references to child controls         public TextBox m_ctlEditUsername;         public TextBox m_ctlEditPassword;         private Label m_ctlLabelLoginError;         // Public Properties Start Here         public string ConnectionString         {             get             {                 return m_sConnectionString;             }             set             {                 m_sConnectionString = value;             }         }         // Generated events start here.         public event EventHandler Loggedin;         public event EventHandler Register;         // Control Creation functions start here.         protected override void CreateChildControls()         {             CreateLogin();         }         private void AddLiteral(String sText)         {             Controls.Add(new LiteralControl(sText));         }         protected void CreateLogin()         {             String sTemp;             // Begin Comment Wrapping Div element             sTemp="<div align=\"center\"";             if(CssClass!="")                 sTemp+=" class=\""+CssClass+"\"";             else                 sTemp+=" class=\"Comment\"";             if(Width!=Unit.Empty)                 sTemp+=" width=\""+Width.ToString()+"\"";             if(Height!=Unit.Empty)                 sTemp+=" height=\""+Height.ToString()+"\"";             sTemp+=">\n";             AddLiteral(sTemp);             // Login Message             AddLiteral("Please login or register to add and "+                 "view comments about    this page.<br><br>");             // Create Login table             AddLiteral("<table class=\"LoginTable\" align="+                 "\"center\" border=\"0\" width=\"250\">");             //Username Field             AddLiteral("<tr>");             AddLiteral("<td>Username</td>");             AddLiteral("<td>");             m_ctlEditUsername= new TextBox();             m_ctlEditUsername.;             Controls.Add(m_ctlEditUsername);             AddLiteral("</td>");             AddLiteral("</tr>");             //Password Field             AddLiteral("<tr>");             AddLiteral("<td>Password</td>");             AddLiteral("<td>");             m_ctlEditPassword= new TextBox();             m_ctlEditPassword.;             m_ctlEditPassword.TextMode=TextBoxMode.Password;             Controls.Add(m_ctlEditPassword);             AddLiteral("</td>");             AddLiteral("</tr>");             //Login / Registration Buttons             AddLiteral("<tr>");             AddLiteral("<td colspan=\"2\" align=\"center\">");             // Login Button             Button objLoginButton=new Button();             objLoginButton.Text="Login";             objLoginButton.Css;             objLoginButton.CausesValidation=false;             objLoginButton.CommandName="Login";             objLoginButton.;             objLoginButton.Click+=                 new EventHandler(OnLoginButton_Click);             Controls.Add(objLoginButton);             AddLiteral("&nbsp;&nbsp;");             // Register Button             Button objRegisterButton=new Button();             objRegisterButton.Text="Register";             objRegisterButton.Css;             objRegisterButton.CausesValidation=false;             objRegisterButton.CommandName="Register";             objRegisterButton.;             objRegisterButton.Click+=                 new EventHandler(OnRegisterButton_Click);             Controls.Add(objRegisterButton);             AddLiteral("</td>");             AddLiteral("</tr>");             AddLiteral("</table><br><br>");             // Add error Message Label             m_ctlLabelLoginError=new Label();             m_ctlLabelLoginError.Text=                 "Invalid username or password.";             m_ctlLabelLoginError.Visible=false;             m_ctlLabelLoginError.Css;             Controls.Add(m_ctlLabelLoginError);             // End Div element             AddLiteral("</div>");         }         private void OnLoginButton_Click             (Object sender, EventArgs e)         {             //Load Data Objects             bool bLoggedIn=false;             CommentDataMgr objCommentDataMgr=                 new CommentDataMgr(ConnectionString);             bLoggedIn=objCommentDataMgr.Login                 (m_ctlEditUsername.Text,m_ctlEditPassword.Text);             if(bLoggedIn)                 Loggedin(this,EventArgs.Empty);             else                 m_ctlLabelLoginError.Visible=true;         }         private void OnRegisterButton_Click             (Object sender, EventArgs e)         {             Register(this,EventArgs.Empty);         }     } } 
CommentRegistrationCtl

The CommentRegistrationCtl is the control that is displayed by the main CommentCtl control if the user pressed the Register button on the CommentLoginCtl control. It displays a registration form.

The public interface portion of this control is intended to be used only by the CommentCtl control. Table 15.9 shows the public interface of this control.

Table 15.9. Public Interface

Name

Type

Description

ConnectionString

Property

This property is a string that contains the OleDb connection string to the data source containing the comment data.

m_ctlEditUsername

TextBox

This is a variable that holds a reference to the contained control that contains the username of the user logging in.

m_ctlEditPassword

TextBox

This is a variable that holds a reference to the contained control that contains the password of the user logging in.

Table 15.10. Control Creation Methods

Name

Type

Description

CreateChildControls()

Method

This method starts the process of creating the control. For this control, all this method does is call the CreateRegistration() method.

CreateRegistration()

Method

This method creates this control.

AddLiteral()

Method

This method adds a LiteralControl to the Controls collection. The text to be added is passed in an argument.

Table 15.11. Event Handlers

Name

Type

Description

OnRegisterButton_Click()

Event Handler

This method is used to handle the Click event of the Register button.

OnCancelButton_Click()

Event Handler

This method is used to handle the Click event of the Cancel button.

Table 15.12. Events

Name

Type

Description

Registered

Event

This event is fired after a valid registration form is submitted.

Cancel

Event

This event is fired when the Cancel button is pressed.

Table 15.10 shows the control creation methods.

Table 15.11 shows the event handlers used in this control.

Table 15.12 shows the events generated by this control.

Listing 15.5 contains the source listing for the CommentRegistrationCtl control.

Listing 15.5 Comment Registration Control CommentRegistrationCtl.cs
 using System; using System.Web.UI; using System.Web.UI.WebControls; using System.ComponentModel; using System.Configuration; using System.Collections.Specialized; namespace Comment {     public class CommentRegisterCtl :         WebControl,INamingContainer     {         // private variables         public TextBox m_ctlEditUsername;         public TextBox m_ctlEditPassword;         private TextBox m_ctlEditPassword2;         private TextBox m_ctlEditEmail;         private TextBox m_ctlEditDisplayName;         private Label m_ctlLabelUsernameError;         private Label m_ctlLabelPasswordError;         private Label m_ctlLabelEmailError;         private Label m_ctlLabelDisplayNameError;         private CommentDataMgr m_objCommentDataMgr;         private string m_sConnectionString;         protected override void CreateChildControls()         {             //Load Data Objects             m_objCommentDataMgr=                 new CommentDataMgr(ConnectionString);             CreateRegistration();         }         // Public Properties Start Here         public string ConnectionString         {             get             {                 return m_sConnectionString;             }             set             {                 m_sConnectionString = value;             }         }         // Generated events start here.         public event EventHandler Registered;         public event EventHandler Cancel;         private void AddLiteral(String sText)         {             Controls.Add(new LiteralControl(sText));         }         protected void CreateRegistration()         {             String sTemp;             // Begin Comment Wrapping Div element             sTemp="<div align=\"center\"";             if(CssClass!="")                 sTemp+=" class=\""+CssClass+"\"";             else                 sTemp+=" class=\"Comment\"";             if(Width!=Unit.Empty)                 sTemp+=" width=\""+Width.ToString()+"\"";             if(Height!=Unit.Empty)                 sTemp+=" height=\""+Height.ToString()+"\"";             sTemp+=">\n";             AddLiteral(sTemp);             AddLiteral("<h1>User Registration:</h1>");             // Registration Message             AddLiteral("Please fill out the following "+                 "information.<br><br>");             // Create table             AddLiteral("<table class=\"RegistratonTable\" "+                 "align=\"center\" border=\"0\" width=\"500\">");             //Username Field             AddLiteral("<tr>");             AddLiteral("<td width=\"150\">Username</td>");             AddLiteral("<td width=\"150\">");             m_ctlEditUsername= new TextBox();             m_ctlEditUsername.;             Controls.Add(m_ctlEditUsername);             AddLiteral("</td>");             AddLiteral("<td  width=\"200\">");             //Username Error Label             m_ctlLabelUsernameError=new Label();             m_ctlLabelUsernameError.Text=                 "Username already exists.";             m_ctlLabelUsernameError.Css;             m_ctlLabelUsernameError.Visible=false;             Controls.Add(m_ctlLabelUsernameError);             AddLiteral("</td>");             AddLiteral("</tr>");             //Password Field             // Table entries have been added via HTML rather             //   than via objects. This was done in this case             //   because of the table simplicity.             AddLiteral("<tr>");             AddLiteral("<td>Password</td>");             AddLiteral("<td>");             m_ctlEditPassword= new TextBox();             m_ctlEditPassword.;             m_ctlEditPassword.TextMode=TextBoxMode.Password;             Controls.Add(m_ctlEditPassword);             AddLiteral("</td>");             AddLiteral("<td>");             //Password Error Label             m_ctlLabelPasswordError=new Label();             m_ctlLabelPasswordError.Text=                 "Passwords must match.";             m_ctlLabelPasswordError.Css;             m_ctlLabelPasswordError.Visible=false;             Controls.Add(m_ctlLabelPasswordError);             AddLiteral("</td>");             AddLiteral("</tr>");             //Password2 Field             AddLiteral("<tr>");             AddLiteral("<td>Re-enter Password</td>");             AddLiteral("<td>");             m_ctlEditPassword2= new TextBox();             m_ctlEditPassword2.;             m_ctlEditPassword2.TextMode=TextBoxMode.Password;             Controls.Add(m_ctlEditPassword2);             AddLiteral("</td>");             AddLiteral("<td></td>");             AddLiteral("</tr>");             //Email Field             AddLiteral("<tr>");             AddLiteral("<td>Email Address</td>");             AddLiteral("<td>");             m_ctlEditEmail= new TextBox();             m_ctlEditEmail.;             Controls.Add(m_ctlEditEmail);             AddLiteral("</td>");             AddLiteral("<td>");             //Email Error Label             m_ctlLabelEmailError=new Label();             m_ctlLabelEmailError.Text=                 "Email address cannot be blank.";             m_ctlLabelEmailError.Css;             m_ctlLabelEmailError.Visible=false;             Controls.Add(m_ctlLabelEmailError);             AddLiteral("</td>");             AddLiteral("</tr>");             //DisplayName Field             AddLiteral("<tr>");             AddLiteral("<td>Display Name</td>");             AddLiteral("<td>");             m_ctlEditDisplayName= new TextBox();             m_ctlEditDisplayName.;             Controls.Add(m_ctlEditDisplayName);             AddLiteral("</td>");             AddLiteral("<td>");             //DisplayName Error Label             m_ctlLabelDisplayNameError=new Label();             m_ctlLabelDisplayNameError.Text=                 "Display Name cannot be blank.";             m_ctlLabelDisplayNameError.Css;             m_ctlLabelDisplayNameError.Visible=false;             Controls.Add(m_ctlLabelDisplayNameError);             AddLiteral("</td>");             AddLiteral("</tr>");             //Register / Cancel Buttons             AddLiteral("<tr>");             AddLiteral("<td colspan=\"3\" align=\"center\">");             // Register Button             Button objRegisterButton=new Button();             objRegisterButton.Text="Register";             objRegisterButton.Css;             objRegisterButton.CausesValidation=false;             objRegisterButton.;             objRegisterButton.Click+=                 new EventHandler(OnRegisterButton_Click);             Controls.Add(objRegisterButton);             AddLiteral("&nbsp;&nbsp;");             // Cancel Button             Button objCancelButton=new Button();             objCancelButton.Text="Cancel";             objCancelButton.Css;             objCancelButton.CausesValidation=false;             objCancelButton.;             objCancelButton.Click+=                 new EventHandler(OnCancelButton_Click);             Controls.Add(objCancelButton);             AddLiteral("</td>");             AddLiteral("</tr>");             AddLiteral("</table><br><br>");             // End Div element             AddLiteral("</div>");         }         // Event Handlers         private void OnRegisterButton_Click             (Object sender, EventArgs e)         {             // Validate Data. This code is used             //   instead of validation controls because             //   the complexity of the data validation makes             //   this a more straightforward approach.             bool bIsValid=true;             if(m_ctlEditUsername.Text=="")             {                 bIsValid=false;                 m_ctlLabelUsernameError.Text=                     "Username cannot be blank.";                 m_ctlLabelUsernameError.Visible=true;             }             bool bValid=m_objCommentDataMgr.CheckLogin                 (m_ctlEditUsername.Text);             if(!bValid)             {                 m_ctlLabelUsernameError.Text=                     "Username already exists.";                 m_ctlLabelUsernameError.Visible=true;                 bIsValid=false;             }             if(m_ctlEditPassword.Text!=m_ctlEditPassword2.Text)             {                 m_ctlLabelPasswordError.Visible=true;                 bIsValid=false;             }             if(m_ctlEditEmail.Text=="")             {                 m_ctlLabelEmailError.Visible=true;                 bIsValid=false;             }             if(m_ctlEditDisplayName.Text=="")             {                 m_ctlLabelDisplayNameError.Visible=true;                 bIsValid=false;             }             // Done Validating             if(bIsValid)             {                 try                 {                     m_objCommentDataMgr.AddUser(                         m_ctlEditUsername.Text,                         m_ctlEditPassword.Text,                         m_ctlEditEmail.Text,                         m_ctlEditDisplayName.Text,                         CommentLoginType.Customer);                     //Fire the Registered event                     Registered(this,EventArgs.Empty);                 }                 catch(Exception err)                 {                 }             }         }         private void OnCancelButton_Click             (Object sender, EventArgs e)         {             // Fire the Cancel event.             Cancel(this,EventArgs.Empty);         }     } } 
CommentDisplayCtl

The CommentDisplayCtl control is the control that is displayed by the main CommentCtl control after the user has logged in.

The public interface portion of this control is intended to be used only by the CommentCtl control. Table 15.13 shows the public interface of this control.

Table 15.13. Public Interface

Name

Type

Description

ConnectionString

Property

This property is a string that contains the OleDb connection string to the data source containing the comment data.

Username

Property

This property contains the username of the currently logged in user.

Revision

Property

This property contains the revision of the comments being displayed.

Table 15.14. Control Creation Methods

Name

Type

Description

CreateChildControls()

Method

This method starts the process of creating the control.

CreateStdComments()

Method

This method is the main method for generating the comments.

CreateDeveloperNote()

Method

This method displays the developer note. If the user has developer permissions, then the user will be able to edit this note.

CreateCommentSection()

Method

This method displays the comment section of the comment control.

CreateComments()

Method

This method is called to create the comments.

CreateComment()

Method

This method creates each individual comment as well as the Edit, Reply, and Delete buttons for each comment. The Reply and Delete buttons are displayed only for the users with developer permissions.

CreateReplyBox()

Method

This method is called to create an inline edit control to enter the reply.

CreateEditBox()

Method

This method is called to create an inline edit control to edit the comment. Comments can be edited only by the user who initially created it.

CreateCommentButtons()

Method

This method displays the Reply, Delete, and Edit buttons for each comment.

CreateEntryField

Method

This method displays the edit control for new comments.

AddLiteral()

Method

This method adds a LiteralControl to the Controls collection. The text to be added is passed in an argument.

Table 15.15. Event Handlers

Name

Type

Description

SubmitButton_Click()

Event Handler

This method handles the submission of comment text, either an update or a new comment.

EditButton_Click()

Event Handler

This method is called when the Edit button next to a comment is pressed.

EditNote_Click()

Event Handler

This method is called when the Edit button next to the note is pressed. Only a user with developer permissions will have this button.

DeleteButton_Click()

EventHandler

This method is called when the Delete button next to a comment is pressed. Only a user with developer permissions will have this button.

ReplyButton_Click()

EventHandler

This method is called when the Reply button next to a comment is pressed. Only a user with developer permissions will have this button.

Table 15.14 shows the control creation methods.

Table 15.15 shows the event handlers used in this control.

Listing 15.6 contains the source listing for the CommentDisplayCtl control.

Listing 15.6 Comment Display Control CommentDisplayCtl.cs
 using System; using System.Web.UI; using System.Web.UI.WebControls; using System.ComponentModel; using System.Configuration; using System.Collections.Specialized; using System.Data; namespace Comment {     public class CommentDisplayCtl : WebControl,INamingContainer     {         // Private member data.         private CommentDataMgr m_objCommentDataMgr;         private DataRow m_objLoginRow;         private string m_sUsername;         private string m_sConnectionString;         private int m_nRevision;         private TextBox m_objTextBox;         protected override void CreateChildControls()         {             //Load Data Objects             m_objCommentDataMgr=                 new CommentDataMgr(ConnectionString);             m_objLoginRow=                 m_objCommentDataMgr.LoadLogin(Username);             // Call the helper method to create the comments.             CreateStdComments();         }         // Public Properties Start Here         // The Username property.         public string Username         {             get             {                 return m_sUsername;             }             set             {                 m_sUsername = value;             }         }         // This property holds the connection string for the database.         public string ConnectionString         {             get             {                 return m_sConnectionString;             }             set             {                 m_sConnectionString = value;             }         }         // The revision number may be important at a later         //   date and is supported.         public int Revision         {             get             {                 return m_nRevision;             }             set             {                 m_nRevision = value;             }         }         // The ID is stored in a session variable in order to         //   use in other pages.         private int EditCommentID         {             get             {                 if(Page.Session["EditCommentID"]==null)                     Page.Session["EditCommentID"]=0;                 return (int) Page.Session["EditCommentID"];             }             set             {                 Page.Session["EditCommentID"]=value;             }         }         private int EditNoteID         {             get             {                 if(Page.Session["EditNoteID"]==null)                     Page.Session["EditNoteID"]=0;                 return (int) Page.Session["EditNoteID"];             }             set             {                 Page.Session["EditNoteID"]=value;             }         }         private int ReplyCommentID         {             get             {                 if(Page.Session["ReplyCommentID"]==null)                     Page.Session["ReplyCommentID"]=0;                 return (int) Page.Session["ReplyCommentID"];             }             set             {                 Page.Session["ReplyCommentID"]=value;             }         }         // Private helper functions start here.         private void AddLiteral(String sText)         {             Controls.Add(new LiteralControl(sText));         }         private String FormatForHTML(String sStr)         {             String sTemp="";             for(int i=0;i<sStr.Length;++i)             {                 if(sStr[i]=='\n')                     sTemp+="<br>\n";                 else                     sTemp+=sStr[i];             }             return sTemp;         }         private void CreateReload()         {             AddLiteral("<script>");             AddLiteral("window.navigate('"+                 Page.Request.RawUrl+"')");             AddLiteral("</script>");         }         // Functions to create the child controls are here.         protected void CreateStdComments()         {             String sTemp;             // Begin Comment Wrapping Div element             sTemp="<div";             if(CssClass!="")                 sTemp+=" class=\""+CssClass+"\"";             else                 sTemp+=" class=\"Comment\"";             if(Width!=Unit.Empty)                 sTemp+=" width=\""+Width.ToString()+"\"";             if(Height!=Unit.Empty)                 sTemp+=" height=\""+Height.ToString()+"\"";             sTemp+=">\n";             AddLiteral(sTemp);             CreateDeveloperNote();             CreateCommentSection();             CreateEntryField();             // End Div element             AddLiteral("</div>");         }         private void CreateDeveloperNote()         {             DataRow objNoteRow=m_objCommentDataMgr.GetNote                 (Page.Request.FilePath,Revision);             if(EditNoteID==0)             {                 AddLiteral("<div>");                 AddLiteral("<h1>Developer Note:</h1>");                 AddLiteral("<blockquote>");                 AddLiteral(FormatForHTML                     (objNoteRow["NoteText"].ToString()));                 if((int)m_objLoginRow["LoginType"]==                     (int)CommentLoginType.Developer)                 {                     AddLiteral("&nbsp;");                     //Edit                     Button objEditButton=new Button();                     objEditButton.Text="Edit";                     objEditButton.Css;                     objEditButton.CausesValidation=false;                     objEditButton.CommandName="Edit";                     objEditButton.+                         objNoteRow["ID"].ToString();                     objEditButton.CommandArgument=                         objNoteRow["ID"].ToString();                     objEditButton.Command+=                         new CommandEventHandler(EditNote_Click);                     Controls.Add(objEditButton);                 }                 AddLiteral("</blockquote>");                 AddLiteral("</div>");             }             else             {                 AddLiteral("<div>");                 AddLiteral("<h1>Developer Note:</h1>");                 AddLiteral("<blockquote>");                 //Edit Note HTML                 // Text Box                 m_objTextBox= new TextBox();                 m_objTextBox.Height=Unit.Point(100);                 m_objTextBox.Width=Unit.Point(300);                 m_objTextBox.TextMode=TextBoxMode.MultiLine;                 m_objTextBox.;                 m_objTextBox.Text=                     objNoteRow["NoteText"].ToString();                 Controls.Add(m_objTextBox);                 AddLiteral("<br>");                 // Submit Button                 Button objSubmitButton=new Button();                 objSubmitButton.Text="Update Note";                 objSubmitButton.Css;                 objSubmitButton.CausesValidation=false;                 objSubmitButton.CommandName="Submit";                 objSubmitButton.;                 objSubmitButton.Click+=                     new EventHandler(SubmitButton_Click);                 Controls.Add(objSubmitButton);                 AddLiteral("</blockquote>");                 AddLiteral("</div>");             }         }         private void CreateCommentSection()         {             DataTable objCommentTable;             objCommentTable=m_objCommentDataMgr.GetComments                 (Page.Request.FilePath,Revision);             // Write Initial HTML             AddLiteral("<div>");             AddLiteral("<h1>Comments:</h1>");             // Process Individual Comments             CreateComments(objCommentTable);             // Write Final HTML             AddLiteral("</div>");         }         private void CreateComments(DataTable objCommentTable)         {             int count=objCommentTable.Rows.Count;             for(int i=0;i<count;++i)             {                 CreateComment(objCommentTable.Rows[i]);             }         }         private void CreateComment(DataRow objCommentRow)         {             // Write Begin of comment html             String sTableClass="";             String sSpacingClass="";             String sAuthorClass="";             String sTextClass="";             String sEditClass="";             String sButtonClass="";             if((int)objCommentRow["ReplyToID"]==0)             {                 sTable;                 sSpacing;                 sAuthor;                 sText;                 sEdit;                 sButton;             }             else             {                 sSpacing;                 sTable;                 sAuthor;                 sText;                 sEdit;                 sButton;             }             AddLiteral("<table border=\"0\" "+                 "class=\""+sTableClass+"\">");             AddLiteral("<tr>");             //Spacing cell             AddLiteral("<td class=\""+sSpacingClass+                 "\" valign=\"top\"></td>\n");             //Write Author's Name             AddLiteral("<td class=\""+sAuthorClass+                 "\" valign=\"top\">\n");             AddLiteral(objCommentRow["DisplayName"].ToString()+                 ": \n");             AddLiteral("</td>\n");             if(EditCommentID!=(int) objCommentRow["ID"])             {                 AddLiteral("<td class=\""+sTextClass+"\" "+                     "valign=\"top\">\n");                 //Write Comment                 AddLiteral(FormatForHTML                     (objCommentRow["Comment"].ToString()));                 if(ReplyCommentID==(int)objCommentRow["ID"])                     CreateReplyBox(objCommentRow);                 AddLiteral("</td>");             }             else // show edit box             {                 AddLiteral("<td class=\""+sEditClass+                     "\" valign=\"top\">\n");                 CreateEditBox(objCommentRow);                 AddLiteral("</td>");             }             //Add Edit/Delete/Reply buttons based on             //user Level and ID             AddLiteral("<td class=\""+sButtonClass+                 "\" valign=\"top\">\n");             if(ReplyCommentID!=(int) objCommentRow["ID"])                 CreateCommentButtons(objCommentRow);             AddLiteral("</td>");             // Write Replies             CreateComments(m_objCommentDataMgr.GetReplies                 ((int) objCommentRow["ID"]));             //Write End of comment html             AddLiteral("</tr></table>");         }         private void CreateReplyBox(DataRow objCommentRow)         {             // Initial HTML             AddLiteral("<div>");             //Edit Comment HTML             // Text Box             m_objTextBox= new TextBox();             m_objTextBox.Height=Unit.Point(100);             m_objTextBox.Width=Unit.Point(300);             m_objTextBox.TextMode=TextBoxMode.MultiLine;             m_objTextBox.;             Controls.Add(m_objTextBox);             AddLiteral("<br>");             // Submit Button             Button objSubmitButton=new Button();             objSubmitButton.Text="Add Reply";             objSubmitButton.Css;             objSubmitButton.CausesValidation=false;             objSubmitButton.CommandName="Submit";             objSubmitButton.;             objSubmitButton.Click+=                 new EventHandler(SubmitButton_Click);             Controls.Add(objSubmitButton);             // Final HTML             AddLiteral("</div>");         }         private void CreateEditBox(DataRow objCommentRow)         {             //Edit Comment HTML             // Text Box             m_objTextBox= new TextBox();             m_objTextBox.Height=Unit.Point(100);             m_objTextBox.Width=Unit.Point(300);             m_objTextBox.TextMode=TextBoxMode.MultiLine;             m_objTextBox.;             m_objTextBox.Text=                 objCommentRow["Comment"].ToString();             Controls.Add(m_objTextBox);             AddLiteral("<br>");             // Submit Button             Button objSubmitButton=new Button();             objSubmitButton.Text="Update Comment";             objSubmitButton.Css;             objSubmitButton.CausesValidation=false;             objSubmitButton.CommandName="Submit";             objSubmitButton.;             objSubmitButton.Click+=                 new EventHandler(SubmitButton_Click);             Controls.Add(objSubmitButton);         }         private void CreateCommentButtons(DataRow objCommentRow)         {             if(EditCommentID==(int)objCommentRow["ID"])                 return;             AddLiteral("&nbsp;");             if((int)objCommentRow["AuthorID"]==                 (int)m_objLoginRow["ID"])             {                 // Can edit or delete own message.                 //Edit                 Button objEditButton=new Button();                 objEditButton.Text="Edit";                 objEditButton.Css;                 objEditButton.CausesValidation=false;                 objEditButton.CommandName="Edit";                 objEditButton.+                     objCommentRow["ID"].ToString();                 objEditButton.CommandArgument=                     objCommentRow["ID"].ToString();                 objEditButton.Command+=                     new CommandEventHandler(EditButton_Click);                 Controls.Add(objEditButton);                 //Delete                 if(((CommentLoginType)                     (int)m_objLoginRow["LoginType"])==                     CommentLoginType.Developer)                 {                     Button objDeleteButton=new Button();                     objDeleteButton.Text="Delete";                     objDeleteButton.Css;                     objDeleteButton.CausesValidation=false;                     objDeleteButton.CommandName="Delete";                     objDeleteButton.+                         objCommentRow["ID"].ToString();                     objDeleteButton.CommandArgument=                         objCommentRow["ID"].ToString();                     objDeleteButton.Command+=                         new CommandEventHandler(DeleteButton_Click);                     Controls.Add(objDeleteButton);                 }             }             else if(((CommentLoginType)                 (int)m_objLoginRow["LoginType"])==                 CommentLoginType.Developer)             {                 // Can Reply to a message                 //Reply                 Button objReplyButton=new Button();                 objReplyButton.Text="Reply";                 objReplyButton.Css;                 objReplyButton.CausesValidation=false;                 objReplyButton.CommandName="Reply";                 objReplyButton.+                     objCommentRow["ID"].ToString();                 objReplyButton.CommandArgument=                     objCommentRow["ID"].ToString();                 objReplyButton.Command+=                     new CommandEventHandler(ReplyButton_Click);                 Controls.Add(objReplyButton);             }         }         protected void CreateEntryField()         {             if(EditCommentID==0 && EditNoteID==0 &&                 ReplyCommentID==0)             {                 // Initial HTML                 AddLiteral("<div align=\"center\">");                 AddLiteral("<h1>Add Comment:</h1>");                 AddLiteral("<blockquote>");                 //New Comment HTML                 // Text Box                 m_objTextBox= new TextBox();                 m_objTextBox.Height=Unit.Point(150);                 m_objTextBox.Width=Unit.Point(400);                 m_objTextBox.TextMode=TextBoxMode.MultiLine;                 m_objTextBox.;                 Controls.Add(m_objTextBox);                 AddLiteral("<br>");                 // Submit Button                 Button objSubmitButton=new Button();                 objSubmitButton.Text="Add Comment";                 objSubmitButton.Css;                 objSubmitButton.CausesValidation=false;                 objSubmitButton.CommandName="Submit";                 objSubmitButton.;                 objSubmitButton.Click+=                     new EventHandler(SubmitButton_Click);                 Controls.Add(objSubmitButton);                 // Final HTML                 AddLiteral("</blockquote>");                 AddLiteral("</div>");             }         }         // Event handlers         private void SubmitButton_Click             (Object sender, EventArgs e)         {             // New Comment             if(EditCommentID==0 && EditNoteID==0)             {                 if(m_objTextBox.Text!="")                 {                     m_objCommentDataMgr.AddComment(                         (int)m_objLoginRow["ID"],                         DateTime.Now,                         ReplyCommentID,                         Revision,                         Page.Request.FilePath,                         m_objTextBox.Text);                     ReplyCommentID=0;                 }             }             else if(EditCommentID!=0)             {                 if(m_objTextBox.Text!="")                 {                     m_objCommentDataMgr.UpdateComment(                         EditCommentID,                         m_objTextBox.Text);                 }                 EditCommentID=0;             }             else if(EditNoteID!=0)             {                 m_objCommentDataMgr.UpdateNote                     (EditNoteID,m_objTextBox.Text);                 EditNoteID=0;             }             Page.Session["RELOAD"]=true;             m_objTextBox.Text="";             Controls.Clear();             CreateReload();         }         private void EditButton_Click             (Object sender, CommandEventArgs e)         {             Button objButton=(Button)sender;             int nID=Convert.ToInt32                 (objButton.CommandArgument,10);             EditCommentID=nID;             EditNoteID=0;             ReplyCommentID=0;             Controls.Clear();             CreateReload();         }         private void EditNote_Click             (Object sender, CommandEventArgs e)         {             Button objButton=(Button)sender;             int nID=Convert.ToInt32                 (objButton.CommandArgument,10);             EditCommentID=0;             EditNoteID=nID;             ReplyCommentID=0;             Controls.Clear();             CreateReload();         }         private void DeleteButton_Click             (Object sender, CommandEventArgs e)         {             // Get the comment ID associated with             // the button that was pushed.             Button objButton=(Button)sender;             int nID=Convert.ToInt32                 (objButton.CommandArgument,10);             // Delete the comment             m_objCommentDataMgr.DeleteComment(nID);             Controls.Clear();             CreateReload();         }         private void ReplyButton_Click             (Object sender, CommandEventArgs e)         {             Button objButton=(Button)sender;             int nID=Convert.ToInt32                 (objButton.CommandArgument,10);             EditCommentID=0;             EditNoteID=0;             ReplyCommentID=nID;             Controls.Clear();             CreateReload();         }     } } 


ASP. NET Solutions - 24 Case Studies. Best Practices for Developers
ASP. NET Solutions - 24 Case Studies. Best Practices for Developers
ISBN: 321159659
EAN: N/A
Year: 2003
Pages: 175

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