Making better use of the UrlFormatter in SUB
Categories
As Brendan pointed out in his recent post, I got pretty slack with implementing the UrlFormatter class in SUB. Basically, every data type in SUB inherits from a base class known as "ApplicationDataObject" which gives each item enough properties to be displayed within an RSS feed. One of the classes that I implemented quite early on in the piece was the UrlFormatter whose job it was to take an instance of a generic ApplicationDataObject class and to produce a suitable URL from it. Internally the code looks something like this:
public class UrlFormatter {
public static string FormatUri(ApplicationDataObject item) {
if (item is Post) {
return string.Format("{0}Posts/Post.aspx?postId={1}", Globals.UrlStartPath, item.Id);
}else if( ... ) {
...
}else{
return Globals.UrlStartPath;
}
}
}
Here we can see that the UrlFormatter is passed an ApplicationDataObject and then uses an if statement to determine the type of the object and then returns the URL for that particular instance.
Over the weekend I went through the SUB source code and identified several of the Repeater that Brendan mentioned in his post that were using independent logic for displaying the URL's for posts. What I ended up doing was to remove the ItemTemplate code from each of the main display Repeaters that are used to display Posts on the Home Page, the Posts By Category page, and the Posts By Month Page and I put the HTML that was within those ItemTemplates into a User Control and I load that as the ItemTemplate of the Repeaters. The code for the User Control looks like this:
<div class="post">
<h5><a href='<%# UrlFormatter.FormatUri((Post) ((RepeaterItem)Container).DataItem) %>'>
<%# ((Post)((RepeaterItem)Container).DataItem).DisplayName%></a></h5>
<p><asp:literal runat="server" text='<%# ((Post) ((RepeaterItem)Container).DataItem).Description %>' id="Label4"/></p>
<p class="postfoot">posted on <%# ((Post)((RepeaterItem)Container).DataItem).DateCreated.ToString()%>
( <a href="<%# UrlFormatter.FormatUri((Post) ((RepeaterItem)Container).DataItem) %>#Feedback">
<%# ((Post)((RepeaterItem)Container).DataItem).CommentCount.ToString()%> Comments</a> )
</p>
</div>
You can see that the Container must now be cast to a RepeaterItem before it is cast to a Post. The code in the hosting Repeaters now looks like this:
<asp:repeater id="PostList" runat="server" enableviewstate="False">
<separatortemplate>
<hr />
</separatortemplate>
</asp:repeater>
… and I simply put in some code to load the template at runtime:
protected override void OnInit(EventArgs e) {
base.OnInit(e);
this.PostList.ItemTemplate = Page.LoadTemplate("~/UserControls/PostItemTemplate.ascx");
}
Now I can easily implement Brendan's cool idea for using the FormatUri function of the UrlFormatter as an abstraction for implementing friendly formatted Url's for posts in SUB.