| |   Skin:   
      User: Not logged in 
Newsletter Signup
XSLT Library
Latest XML Blogs
Featured Examples
Featured Articles
Book Chapters
Training Courses
Sign In
My Profile
My Articles
My Examples
My Favorites
My Resources
Add a Resource
About Me
My Blog
HeadGeek Articles
Talking Portfolio
World Trip Pics

Showthread.aspx example
Author: Malinda Ng
Published: 11/28/2006 9:52 PM
Category: ADO.NET, ASP.NET, Datagrid, Namespace
Summary: This is a Showthread.aspx example to go with the Forum Stored Procedures of m-aatechsources.

Check it out:


<asp:TemplateField ItemStyle-Width="120px" ItemStyle-CssClass="postinfo">


<div class="posttitle" style="text-align:right;">

<asp:HyperLink runat="server" ID="lnkEditPost" ImageUrl="~/Images/Edit.gif" NavigateUrl="~/AddEditPost.aspx?ForumID={0}&ThreadID={1}&PostID={2}" /> 

<asp:ImageButton runat="server" ID="btnDeletePost" ImageUrl="~/Images/Delete.gif"

OnClientClick="if (confirm('Are you sure you want to delete this {0}?') == false) return false;"/>  


<asp:Literal ID="lblAddedDate" runat="server" Text='<%# Eval("AddedDate", "{0:D}<br/><br/>{0:T}") %>' />

<hr />

<asp:Literal ID="lblAddedBy" runat="server" Text='<%# Eval("AddedBy") %>' /><br /><br />

<small><asp:Literal ID="lblPosts" runat="server"

Text='<%# "Posts: " + GetUserProfile(Eval("AddedBy")).Forum.Posts.ToString() %>' />


Some of the information(such as the post's title, body, author, and date/time) is retrieved by the GridView's companion ObjectDataSources(Which uses Post.GetThreadBuID as its SelectMethod, and GetPostCountByThread as its SelectCountMethod to support pagination)

<asp:Literal ID="lblPosterDescription" runat="server"

Text='<%# "<br />" + GetPosterDescription(GetUserProfile(Eval("AddedBy")).Forum.Posts) %>'

Visible='<%# GetUserProfile(Eval("AddedBy")).Forum.Posts >= Globals.Settings.Forums.BronzePosterPosts %>'/></small><br /><br />

<asp:Panel runat="server" ID="panAvatar" Visible='<%# GetUserProfile(Eval("AddedBy")).Forum.AvatarUrl.Length > 0 %>'>

<asp:Image runat="server" ID="imgAvatar" ImageUrl='<%# GetUserProfile(Eval("AddedBy")).Forum.AvatarUrl %>' />

<br /><br />




The second column renders the Post's title, the body, and then the user's signature profile property.  Because the signature is in plain text, though, it first passes through a helper method named ConvertToHTML, which transforms the signature into simple HTML(it replaces carriage returns with <br/> tags, replaces multiple spaces and tabs with "  ", etc).   At the bottom it had a hyperlink to the AddEditPost.aspx page.  Which creates a new reply by quoting the current post's body.



<div class="posttitle"><asp:Literal ID="lblTitle" runat="server" Text='<%# Eval("Title") %>' /></div>

<div class="postbody">

<asp:Literal ID="lblBody" runat="server" Text='<%# Eval("Body") %>' /><br /><br />

<asp:Literal ID="lblSignature" runat="server"

Text='<%# Helpers.ConvertToHtml(GetUserProfile(Eval("AddedBy")).Forum.Signature) %>' /><br /><br />

<div style="text-align: right;">

<asp:HyperLink runat="server" ID="lnkQuotePost"

NavigateUrl="~/AddEditPost.aspx?ForumID={0}&ThreadID={1}&QuotePostID={2}">Quote Post</asp:HyperLink>









using System;

using System.Data;

using System.Configuration;

using System.Collections;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Web.UI.HtmlControls;

using System.Collections.Generic;

using MB.maatechources;

using MB.maatechources.BLL.Forums;

namespace MB.maatechources.UI


public partial class ShowThread : BasePage


int threadPostID = 0;

Hashtable profiles = new Hashtable();

protected void Page_Init(object sender, EventArgs e)


gvwPosts.PageSize = Globals.Settings.Forums.PostsPageSize;


The variables are set in the page'load event handler, which also has code that loads the body of the post to edit or quote, sets the link to go back to the previous page, and check whether the current user is allowed to perform the requested function.   Example code:

protected void Page_Load(object sender, EventArgs e)


threadPostID = int.Parse(this.Request.QueryString["ID"]);

if (!this.IsPostBack)


threadPostID = int.Parse(this.Request.QueryString["ID"]);

Post post = Post.GetPostByID(threadPostID);


this.Title = string.Format(this.Title, post.Title);

lblPageTitle.Text = string.Format(lblPageTitle.Text, post.ForumID, post.ForumTitle, post.Title);

ShowCommandButtons(post.Closed, post.ForumID, threadPostID, post.AddedBy);



private void ShowCommandButtons(bool isClosed, int forumID, int threadPostID, string addedBy)


if (isClosed)


lnkNewReply1.Visible = false;

lnkNewReply2.Visible = false;

btnCloseThread1.Visible = false;

btnCloseThread2.Visible = false;

panClosed.Visible = true;




lnkNewReply1.NavigateUrl = string.Format(lnkNewReply1.NavigateUrl, forumID, threadPostID);

lnkNewReply2.NavigateUrl = lnkNewReply1.NavigateUrl;

btnCloseThread1.Visible = (this.User.Identity.IsAuthenticated &&

(this.User.Identity.Name.ToLower().Equals(addedBy) ||

(this.User.IsInRole("Administrators") || this.User.IsInRole("Editors") || this.User.IsInRole("Moderators"))));

btnCloseThread2.Visible = btnCloseThread1.Visible;



protected void gvwPosts_RowDataBound(object sender, GridViewRowEventArgs e)


if (e.Row.RowType == DataControlRowType.DataRow)


Post post = e.Row.DataItem as Post;

int threadID = (post.IsFirstPost ? post.ID : post.ParentPostID);

// the link for editing the post is visible to the post's author, and to

// administrators, editors and moderators

HyperLink lnkEditPost = e.Row.FindControl("lnkEditPost") as HyperLink;

lnkEditPost.NavigateUrl = string.Format(lnkEditPost.NavigateUrl, post.ForumID, threadID, post.ID);

lnkEditPost.Visible = (this.User.Identity.IsAuthenticated &&

(this.User.Identity.Name.ToLower().Equals(post.AddedBy.ToLower()) ||

(this.User.IsInRole("Administrators") || this.User.IsInRole("Editors") || this.User.IsInRole("Moderators"))));

// the link for deleting the thread/post is visible only to administrators, editors and moderators

ImageButton btnDeletePost = e.Row.FindControl("btnDeletePost") as ImageButton;

btnDeletePost.OnClientClick = string.Format(btnDeletePost.OnClientClick,

post.IsFirstPost ? "entire thread" : "post");

btnDeletePost.CommandName = (post.IsFirstPost ? "DeleteThread" : "DeletePost");

btnDeletePost.CommandArgument = post.ID.ToString();

btnDeletePost.Visible = (this.User.IsInRole("Administrators") || this.User.IsInRole("Editors") || this.User.IsInRole("Moderators"));

// if the thread is not closed, show the link to quote the post

HyperLink lnkQuotePost = e.Row.FindControl("lnkQuotePost") as HyperLink;

lnkQuotePost.NavigateUrl = string.Format(lnkQuotePost.NavigateUrl,

post.ForumID, threadID, post.ID);

lnkQuotePost.Visible = !(post.IsFirstPost ? post.Closed : post.ParentPost.Closed);



protected void gvwPosts_RowCommand(object sender, GridViewCommandEventArgs e)


if (e.CommandName == "DeleteThread")


int threadPostID = Convert.ToInt32(e.CommandArgument);

int forumID = Post.GetPostByID(threadPostID).ID;


this.Response.Redirect("BrowseThreads.aspx?ForumID=" + forumID.ToString());


else if (e.CommandName == "DeletePost")


int postID = Convert.ToInt32(e.CommandArgument);


gvwPosts.PageIndex = 0;




protected void btnCloseThread_Click(object sender, EventArgs e)



ShowCommandButtons(true, 0, 0, "");



// Retrieves and returns the profile of the specified user. The profile is cached once

// retrieved for the first time, so that it is reused if the profile for the same user

// will be requested more times on the same request


There's some interesting code in the code behind class.   In the preceding code you can see that the GetUserProfile method called six times for every single post.   This can cause performance problems when you consider how many times this might execute in one page cycle.   The same thread will likely have multiple posts by the sam user.   In a typical thread of 20 posts, four of them might be from the same user.   This means we make 24 calls to GetUserProfile for the same user.   This methods uses ASP.NET's profile.GetProfile Method to retrieve a ProfileCommon Object to be a query to SQL Server to retrieve the user's profile, and then build the ProfileCommon object to be returned.    In this situation, this would be an incredible waste of resources.  because after the first query to a specific user, the next 23 querries for that user would produce the same result.    To prevent this kind of waste, we use the GetUserProfile method to wrap the call to Profile.GetProfile by adding simple caching support that will last as long as the pages' lifeTime.

protected ProfileCommon GetUserProfile(object userName)


string name = (string)userName;

if (!profiles.Contains(name))


ProfileCommon profile = this.Profile.GetProfile(name);

profiles.Add(name, profile);

return profile;



return profiles[userName] as ProfileCommon;


// Returns the poster level description, according to the input post count

There's another helper method on the page, GetPosterDescription, which returns the user's status description according to user's number of posts.   It compares the number with the values of the GoldPosterPosts, SilverPosterPost, and BeowzePosterPosts configuration settings, and returns the approriate description.

protected string GetPosterDescription(int posts)


if (posts >= Globals.Settings.Forums.GoldPosterPosts)

return Globals.Settings.Forums.GoldPosterDescription;

else if (posts >= Globals.Settings.Forums.SilverPosterPosts)

return Globals.Settings.Forums.SilverPosterDescription;

if (posts >= Globals.Settings.Forums.BronzePosterPosts)

return Globals.Settings.Forums.BronzePosterDescription;


return "";




To see the entire Forums examples goto the last post name


Fans of "The Office"
Dwight Bobbleheads are here!
  “It's me! I'm the bobblehead! Yes!”

Advertise on XMLPitstop

Advertise on XMLPitstop

EggHead Cafe
Web Servicee development
Buy text ads here!
internet laptop backup
Color Laser Printer
Prada sunglasses
Skype vs. sipcall
VoIP Internettelefonie
Buy text ads here!

Interested in Text ads?
2,222 Total Members
35 members(last 30 days)
7 members(last 7 days)
1 members(today)

1,609 Total Discussions
12 Posts(last 30 days)
0 Posts(last 7 days)
0 Posts(today)

17,169 Total Blog Posts
1,748 Blogs(last 30 days)
251 Blogs(last 7 days)
0 Blogs(today)

8,699 Newsgroup Posts
0 Posts(last 30 days)
0 Posts(last 7 days)
0 Posts(today)

13,786 Total Resources
5 Resources(last 30 days)
1 Resources(last 7 days)
0 Resources(today)


David Silverlight's| 2801 Florida Ave #225|Miami, FL 33133|Ph:305-447-1139