(This is an update of the Blog article from ASP.NET 1.0 to ASP.NET 2.0). It also corrects the problem of displaying the most recent blog entry first)
Introduction
I still haven't gotten used to the name Blog. I can't even find it in the dictionary. For all I know its a coined word from the phrase "blind hog" or "blue fog". More likely it's coined from the words "bland pedagogue" or "blabbering monologue". If someone knows where this word originates, kindly add it to the blog you create from this article. Anyway, blogs seem to becoming pervasive and there is no end to people spilling their stream of consciousness onto the internet. This can make for some entertaining reading. If you want to search for a blog in a particular area of interest, check out Google's new blog search.
Figure 1 - ASP.NET Blog
Design
This is a very simple blog design consisting of two aspx web pages. BlogList.aspx contains the blogs, and BlogEntry.aspx allows you to enter your own blog comments. The blogs are persisted through a XML file which is read and written by a data set. Upon reading the data set, the codebehind builds the blogs dynamically using a System.Web.UI.WebControls.Table.
Figure 2 - UML Diagram of Blog Design Reverse Engineered using WithClass
Code
When the BlogList.aspx page starts, it calls the Page_Load method and initializes the page from the Comments.XML file and reads it into a data set. The Session["Changed"] hash is used to track where the Page_Load originated from. If the Page_Load was triggered by a hyperlink, you don't need to append anything to the data set. If the Page_Load was triggered by a redirect from the BlogEntry.aspx page, then the data set will append the Session["Title"], Session["Blog"], and Session["Name"] data to a new data set row.
Listing 1 - Upon initial entry into the BlogList.aspx page, load the Blog
private void Page_Load(object sender, System.EventArgs e) { // Put user code to initialize the page here if (IsPostBack) {
} else {
// initialize Blog and read it into a data set
data set ds = ReadBlogIntoTable();
// if we created a new entry, append it to the BlogList // and save it to the xml file
if ( (bool)Session["Changed"]) { AppendComments(ds); WriteXmlComments(ds); Session["Changed"] = false; }
// Dynamically build the blog into a WebControls.Table
RebuildTableView(ds);
}
} |
The ReadBlogIntoTable method, reads the data set and data set structure from the Comments.Xml file. If there is no file to read, then it simply constructs the data set structure.
Our blog data set structure consists of 4 columns: Name, Time, Title, and Blog.
Listing 2 - Reads the Blog into a DataSet or creates an empty DataSet structure if the File doesn't exist
private DataSet ReadBlogIntoTable() { // construct the DataSet DataSet ds = new DataSet();
// form the server path of the blog database string filename = Server.MapPath(".\\") + "comments.xml";
// if the file exists, read the blog database into the data set if (File.Exists(filename)) { ds.ReadXml(filename); } else { // otherwise we need to create a new new in-memory // database table from scratch
DataTable theTable = new DataTable("Comments"); ds.Tables.Add(theTable);
// add a name, time, title, and blog columns to our mock-up blog database
theTable.Columns.Add("Name", Type.GetType("System.String")); theTable.Columns.Add("Time", Type.GetType("System.DateTime")); theTable.Columns.Add("Title", Type.GetType("System.String")); theTable.Columns.Add("Blog", Type.GetType("System.String")); }
return ds;
} |
If someone just entered a blog, we need to append it to the DataSet. This is accomplished by the AppendComments method. This method simply creates a new DataRow and assigns the new blog values to each column in the row. The row is then added into the DataSet. Finally the DataSet is written out to the Comments.XML file.
Listing 3 - Appending a Blog to the DataSet
/// <summary> /// Append comments to xml file /// </summary> /// <param name="ds"></param> void AppendComments(DataSet ds) { // create a new DataRow
DataRow dr = ds.Tables["Comments"].NewRow();
// Populate the row from the text boxes filled by the user
dr[0] = Session["Name"]; dr[1] = DateTime.Now; dr[2] = Session["Title"]; dr[3] = Session["Blog"];
// add the row to the DataSet
ds.Tables["Comments"].Rows.Add(dr);
// persist the blog in an xml file
WriteXmlComments(ds);
} |
Once the data set is updated, we can render the contents of the data set onto the web page. We use the RebuildTableView method to create and populate the WebControls.Table dynamically from the data set. In this method, we loop through each row of the DataTable in the data set and create a new table row on the page. We can then copy the data row data into the individual cells of the web table row.
Listing 4 - Building the Blog on the Web Page
void RebuildTableView(DataSet ds) { string previousUser = ""; // track previous
// loop through each row in the data set and create // the row on the web page in a web table
foreach (DataRow dr in ds.Tables[0].Rows) { // add title (use a single column) TableRow tr = new TableRow(); tr.Cells.Add(new TableCell());
// change title color slightly tr.Cells[0].ForeColor = Color.Navy; tr.Cells[0].Width = 400;
// make the text title big and purple tr.Cells[0].Text = "<FONT SIZE=5 COLOR=purple FACE=Rockwell><B>" + dr[2].ToString() + "</B></FONT>"; this.BlogTable.Rows.Add(tr);
// add blog in a single column and span 2 columns tr = new TableRow(); tr.Cells.Add(new TableCell()); tr.Cells[0].Width = 550; tr.Cells[0].ColumnSpan = 2; tr.Cells[0].Text = dr[3].ToString(); this.BlogTable.Rows.Add(tr);
// add user who posted and date (use two columns in the row - one for poster, one for date) tr = new TableRow(); tr.Height = 50; tr.HorizontalAlign = HorizontalAlign.Left; tr.VerticalAlign = VerticalAlign.Bottom; tr.Cells.Add(new TableCell()); tr.Cells.Add(new TableCell()); tr.Cells[0].Text = "Posted by " + dr[0].ToString();
DateTime postTime = DateTime.Parse(dr[1].ToString()); tr.Cells[1].HorizontalAlign = HorizontalAlign.Right; tr.Cells[1].Text = String.Format("<i>{0}</i>", postTime.ToString("MMM dd, 2005 @ hh:mm"));
this.BlogTable.Rows.Add(tr);
// add separator graphic and span 2 columns
tr = new TableRow(); tr.Cells.Add(new TableCell()); tr.Cells.Add(new TableCell()); tr.Cells[0].ColumnSpan = 2;
this.BlogTable.Rows.Add(tr);
string imageFile = this.ResolveUrl( @".\images\separator.jpg"); System.Web.UI.WebControls.Image separator = new System.Web.UI.WebControls.Image();
separator.ImageUrl = imageFile; separator.Width = 600; separator.Height = 32; separator.Visible = true;
tr.Cells[0].Controls.Add(separator); tr.Cells[0].HorizontalAlign = HorizontalAlign.Center;
}
} |
Blog Entry
Figure 3 illustrates the blog entry screen (BlogEntry.aspx) which is activated by hitting the Comments button on the BlogList.aspx web page. This allows the user to enter their blog and append it to the main blog page.
Figure 3 - Blog Entry Web Page
Upon hitting the Submit button, the Session map is filled with the values entered and then we redirect the page to the BlogList.aspx page. We also set a Changed boolean flag in the Session to indicate that we came from the BlogList.aspx page rather than from some other page.
Listing 5 - Submitting your blog
private void btnSubmit_Click(object sender, System.EventArgs e) { // record the blog data in the Session State
Session["Title"] = this.txtTitle.Text; Session["Blog"] = this.txtBlog.Text; Session["Name"] = this.txtName.Text; Session["Changed"] = true;
// redirect back to the main blog page
this.Response.Redirect("BlogList.aspx"); } |
Conclusion
Blogs are an interesting way to share your thoughts with the rest of the world. This blog application should get you started for your own web site in ASP.NET. One additional feature that you may want to add would be a user login page that allows someone to become a 'member' of your blog. Also, note that I turned off the validation request switch in this application so that you can post html tags to your blog. However, be forewarned that this may not be the most secure choice, so you can turn the validation back on by changing this line in the config file.
<pages validateRequest="false" />
to
<pages validateRequest="true" />
Enjoy creating your blogs, but don't get blogged down in the details, simply use this web application compliments of the power of ASP.NET!