The Personal Website Starter Kit is a great resource for getting up and running with asp.net 2.0 beta. I’ve been using it to check out some features while waiting for other projects to get to a point where I feel like I can contribute more than just criticism (sorry y’all :) That said, the default.aspx page comes with a FormsView that rotates pictures from your PSKit albums, but everything else is static content! That is, you’re greeted on the front page with something like:

Welcome to my Website!

On this site you will find lorem ipsum dolor sit amet...

Earlier, I had tried using one of the new data controls in asp.net - namely the FormView. I ran into a few issues with this control, mostly having to do with having to know what ID I was using in the database to set or edit the FormView’s contents - I’m sure I could have worked out a way to set the ID to use in some clever way, but then I looked at the actual content that comes stock with the PSKit and it hit me…

A DataList.

It’s already separated by a horizontal rule - all I really need is to bind a good old DataList to a couple of database entries and I’ve got something that I can update, oh, say twice a year or whatever. heh.

I used a similar table structure to the one from before:

Content
ContentID
Heading
Content
IsVisible

I had to actually write code (gasp!) to get it working the way I wanted it to, but it was pretty stock stuff thankfully. I just set up a SqlDataSource pointing to this table’s CRUD procedures:

                
	<asp:SqlDataSource ID="SqlDataSource1" 
runat="server"
ConnectionString="<%$ ConnectionStrings:Personal %>"
ProviderName="System.Data.SqlClient" SelectCommand="GetContents"
SelectCommandType="StoredProcedure"
DeleteCommand="RemoveContent"
DeleteCommandType="StoredProcedure"
InsertCommand="AddContent"
InsertCommandType="StoredProcedure"
UpdateCommand="EditContent"
UpdateCommandType="StoredProcedure"> <DeleteParameters> <asp:Parameter Name="Content_ID" Type="Int32" /> </DeleteParameters> <UpdateParameters> <asp:Parameter Name="Content_ID" Type="Int32" /> <asp:Parameter Name="Heading" Type="String" /> <asp:Parameter Name="Content" Type="String" /> <asp:Parameter Name="IsVisible" Type="Boolean" /> </UpdateParameters> <InsertParameters> <asp:Parameter Direction="InputOutput" Name="Content_ID" Type="Int32" /> <asp:Parameter Name="Heading" Type="String" /> <asp:Parameter Name="Content" Type="String" /> <asp:Parameter Name="IsVisible" Type="Boolean" /> </InsertParameters> </asp:SqlDataSource>

Then the DataList itself:

			<asp:DataList ID="DataList1" 
runat="server"
DataSourceID="SqlDataSource1"
Width="100%"
OnCancelCommand="DataList1_CancelCommand"
OnEditCommand="DataList1_EditCommand"
OnUpdateCommand="DataList1_UpdateCommand"
OnDeleteCommand="DataList1_DeleteCommand"
OnItemCommand="DataList1_ItemCommand"
RepeatLayout="Flow" > <ItemTemplate> <asp:Panel ID="contentPanel"
runat="server"
Visible='<%# Eval("IsVisible") %>'> <h3><asp:Label ID="HeadingLabel"
runat="server"
Text='<%# Eval("Heading") %>'></asp:Label></h3> <asp:Label ID="ContentLabel"
runat="server"
Text='<%# Eval("Content") %>'></asp:Label>
<asp:HiddenField ID="hdnContentID"
runat="server"
Value='<%# Eval("Content_ID") %>' /> </asp:Panel> <asp:Panel ID="Panel1"
Visible='<%# User.IsInRole("Administrators") %>'
runat=
"server" Height="50px" Width="125px"> <asp:LinkButton ID="LinkButton3"
runat="server"
CommandName="edit">Edit</asp:LinkButton>&nbsp;&nbsp;
<asp:LinkButton ID="LinkButton4"
runat="server"
CommandName="delete">Delete</asp:LinkButton></asp:Panel> </ItemTemplate> <SeparatorTemplate> <hr /> </SeparatorTemplate> <EditItemTemplate> <asp:TextBox ID="txtHeading"
runat="server"
Text='<%# Bind("Heading") %>'></asp:TextBox> <asp:CheckBox ID="chkVisible"
runat="server"
Checked='<%# Bind("IsVisible") %>'
Text=
"Visible" />
ContentID:
<asp:Label ID="lblContentID"
runat="server"
Text='<%# Eval("Content_ID") %>'></asp:Label> <asp:TextBox ID="txtContent"
runat="server"
Columns="40" Rows="20"
Text='<%# Bind("Content") %>' TextMode="MultiLine"></asp:TextBox>
<br /> <br /> <asp:LinkButton ID="LinkButton1"
runat="server"
CommandName="update">Update</asp:LinkButton>&nbsp;&nbsp; <asp:LinkButton ID="LinkButton2"
runat="server"
CausesValidation="False"
CommandName="cancel">Cancel</asp:LinkButton>&nbsp;&nbsp; <asp:LinkButton ID="LinkButton5"
runat="server"
CommandName="add">Create as New</asp:LinkButton> </EditItemTemplate> </asp:DataList>

Several points of interest in the DataList declaration:

  • No more pesky DataBinder.Eval(Container.DataItem, "field") syntax - much leaner and meaner Eval() syntax for one-way binding.
  • Two-way binding happens via the Bind() syntax - notice that Bind() only happens in the EditItemTemplate, since the ItemTemplate is readonly.
  • I'm only showing the edit/delete buttons based on what role the current user is in. I wasn't sure if this (# User.IsInRole("Administrators")) would work at first because it's deceptively simple. But yeah, it does work. Works great!
  • I did most of this visually - there is no longer a reason to fear the designer in asp.net (thanks Venus team!)
  • I had to disable Page input validation because I want the Content to contain html, and by default, it don't like that.

As for the codebehind, I guess I could have refactored it a little bit, but since this is not a mission-critical application (it is just a personal site, after all!) I just went the easy route and duplicated a lot of code. Probably the best thing to do would be to handle just the ItemCommand because there is no default handler for add and use a clever mix of a switch statement and defaulting the value of EditItemIndex to -1. But this isn’t about best practices, it’s about getting the stuff to work, ya know? Anyway, here’s the code:

  1 	protected void DataList1_CancelCommand(object source, DataListCommandEventArgs e)
  2 	{
  3 		this.DataList1.EditItemIndex = -1;
  4 		this.DataList1.DataBind();
  5 	}
  6 	protected void DataList1_UpdateCommand(object source, DataListCommandEventArgs e)
  7 	{
  8 		string heading = ((TextBox)e.Item.FindControl("txtHeading")).Text;
  9 		string content = ((TextBox)e.Item.FindControl("txtContent")).Text;
 10 		string isvisible = ((CheckBox)e.Item.FindControl("chkVisible")).Checked.ToString();
 11 		string id = ((Label)e.Item.FindControl("lblContentID")).Text;
 12 
 13 		this.SqlDataSource1.UpdateParameters["Content_ID"].DefaultValue = id;
 14 		this.SqlDataSource1.UpdateParameters["Heading"].DefaultValue = heading;
 15 		this.SqlDataSource1.UpdateParameters["Content"].DefaultValue = content;
 16 		this.SqlDataSource1.UpdateParameters["IsVisible"].DefaultValue = isvisible;
 17 
 18 		this.SqlDataSource1.Update();
 19 
 20 		this.DataList1.EditItemIndex = -1;
 21 		this.DataList1.DataBind();
 22 	}
 23 	protected void DataList1_DeleteCommand(object source, DataListCommandEventArgs e)
 24 	{
 25 		string id = ((HiddenField)e.Item.FindControl("hdnContentID")).Value;
 26 		this.SqlDataSource1.DeleteParameters["Content_ID"].DefaultValue = id;
 27 
 28 		this.SqlDataSource1.Delete();
 29 
 30 		this.DataList1.EditItemIndex = -1;
 31 		this.DataList1.DataBind();
 32 	}
 33 	protected void DataList1_ItemCommand(object source, DataListCommandEventArgs e)
 34 	{
 35 		switch (e.CommandName)
 36 		{
 37 			case "add":
 38 				string heading = ((TextBox)e.Item.FindControl("txtHeading")).Text;
 39 				string content = ((TextBox)e.Item.FindControl("txtContent")).Text;
 40 				string isvisible = ((CheckBox)e.Item.FindControl("chkVisible")).Checked.ToString();
 41 
 42 				this.SqlDataSource1.InsertParameters["Heading"].DefaultValue = heading;
 43 				this.SqlDataSource1.InsertParameters["Content"].DefaultValue = content;
 44 				this.SqlDataSource1.InsertParameters["IsVisible"].DefaultValue = isvisible;
 45 
 46 				this.SqlDataSource1.Insert();
 47 
 48 				this.DataList1.EditItemIndex = -1;
 49 				this.DataList1.DataBind();
 50 				break;
 51 		}
 52 	}

This is the quickest way I could figure out to make things work, and yeah, it does work. So, there you have it - even though there are only two items currently in the table, it’s very easy to add content via in-place editing and change what is currently there as well. You can view it live over at www.bluefenix.net.

[ Currently Playing : Voices - Godsmack - Other Side (3:44) ]