BlogEngine.NET - Urlrewriting

So the first thing I usually do when reviewing web projects is to find the default entry page that the user would see. When doing this with BlogEngine.NET you find the default.aspx (obviously in most cases). The first thing in the Page_Load of this is the following code:

if (Request.RawUrl.ToLowerInvariant().Contains("/category/")){...}
else if (Request.RawUrl.ToLowerInvariant().Contains("/author/")){...}
else if (Request.RawUrl.ToLowerInvariant().Contains("?tag=")){...}
//a couple of else if's more

So this makes it clear that the default.aspx page handles all listing of posts whether it is all in a category, all by an author or all having a specific tag. All these listings are requested using different URI's, to handle this an UrlRewrite HttpModule is implemented. If we look at some code in this UrlRewriter we will find:

if (context.Request.Path.Contains("/blog.aspx")){...}
else if (url.Contains("/POST/")){...}
else if (url.Contains("/CATEGORY/")){...}
else if (url.Contains("/AUTHOR/")){...}
//a couple of else if's more

So what happens here is we delegate the responsibility for different URL's to be handled on different pages, the responsibilities redirected to the default page is afterwards on the default page once again delegated to different methods handling databinding because presentation is alike. This results in some parsing of the URL's is duplicated in the UrlRewriter and in the default.aspx.cs file. And furthermore the collection of all posts is iterated both in the UrlRewriter and on the pages, that seems silly. Why not let UrlRewriting do what its intended for: to forward information and then keep the processing on simple pages for specific requests to avoid the redundant parsing and iteration?

I read an interview with the BlogEngine.NET founder on InfoQ a while back, and it seems he has some issues with third party dependencies. I don't see the reason for this, if you can use a third party dependency too do a task it does well and have been doing in many projects already, why roll your own. So allow me to introduce UrlRewritingNet.UrlRewrite

UrlRewritingNet basically consists of a generic HttpHandler that rewrites based on rules you set up in a configuration section in your web.config file, so instead of having to change code to change rewrites, we change simple regular expressions in our configuration of UrlRewritingNet. So lets see the rules I set up for BlogEngine.NET:

<configSections>
	<section name="urlrewritingnet"
		restartOnExternalChanges="true"
		requirePermission="false"
		type="UrlRewritingNet.Configuration.UrlRewriteSection, UrlRewritingNet.UrlRewriter"
	/>
</configSections>
<urlrewritingnet xmlns="http://www.urlrewriting.net/schemas/config/2006/07">
	<rewrites>
		<add name="categoryRule" virtualUrl="^~/category/(.*).aspx" destinationUrl="~/category.aspx?name=$1"/>
		<add name="blogRule" virtualUrl="^~/blog.aspx" destinationUrl="~/default.aspx?blog=true"/>
		<add name="authorRule" virtualUrl="^~/author/(.*).aspx" destinationUrl="~/author.aspx?name?=$1"/>
		<add name="postRuleDate" virtualUrl="^~/post/(\d{4})/([0-1]?\d)/([0-3]?\d)/(.*).aspx"
			destinationUrl="~/post.aspx?year=$1&amp;month=$2&amp;day=$3&amp;name=$4"/>
		<add name="postRuleMonth" virtualUrl="~/post/(\d{4})/([0-1]?\d)/(.*).aspx"
			destinationUrl="~/post.aspx?year=$1&amp;month=$2&amp;name=$3"/>
		<add name="postRuleTitle" virtualUrl="~/post/(.*).aspx" destinationUrl="~/post.aspx?name=$1"/>
		<add name="pageRule" virtualUrl="~/page/(.*).aspx" destinationUrl="~/page.aspx?name=$1"/>
		<add name="calendarRule" virtualUrl="~/calendar/.*" destinationUrl="~/calendar.aspx"/>
	</rewrites>
</urlrewritingnet>
<system.web>
	<httpModules>
		<add name="UrlRewriteModule" type="UrlRewritingNet.Web.UrlRewriteModule, UrlRewritingNet.UrlRewriter"/>
	</httpModules>
</system.web>

The above handles rewriting of Url's nothing more, nothing less. The existing BlogEngine.NET UrlRewrite have some business logic built in, for instance to retrieve the identifier of posts and sending them to the page that shows the post. I feel this doesn't belong in an UrlRewriter so I will implement this logic on the pages that actually handles the requests instead of on the UrlRewriter.

So this was the first step, now we can move the if statement out of our default.aspx and let it concentrate on showing the default content which is the frontpage of the blog and the other pages concentrate on their tasks. How to implement the pages referred to in the mapping above will follow in the next post.


Comments

May 13. 2008 09:02 AM

Niels Brinch

If you need a less generic solution, consider simply using the native .NET method System.Web.HttpContext.RewritePath().

Niels Brinch

May 13. 2008 09:55 AM

Jakob Andersen

Thanks for your comment. I generally think custom UrlRewriters is an open invitation to implement features in a component where they don't belong. However there could of course be cases where regular expressions isn't powerful enough to extract the information you want from an Url but i have yet to see an Url scheme so complicated Smile

Jakob Andersen

Comments are closed