Ayende @ Rahien

My name is Oren Eini
Founder of Hibernating Rhinos LTD and RavenDB.
You can reach me by phone or email:


+972 52-548-6969

, @ Q c

Posts: 6,007 | Comments: 44,761

filter by tags archive

Fighting the architecture astronaut

time to read 4 min | 665 words

It is surprising how many other things I have to deal with in order to get a product up and running. Right now I am working on the web site for NH Prof, and I found myself tackling a problem in an interesting way.

The problem itself is pretty simple. I need to show a user guide, so people can lookup help topics, view alerts, etc.

My first instinct was to create a HelpTopics table and do a simple data driven help site. Literally just showing a list of the topics and allowing to view them. I got that working, and was busy creating my second help topic when I found out that I had to have some way of referencing another help topic.

Obviously I could just use a link, but that would tie one content of the help topics to the id of another, in a completely non obvious manner. Not to mention that when I deploy, it may very well have a different id.

At the time I was also fighting having to do updates to the content of the site using UPDATE statements (if the content is in the DB, then I need to update it somehow, and I figured that giving UI for that is too much of a hassle). I started thinking about solutions, using the title of the page for a link, wiki style, when I figured out that I was out of breath because I was architecting a trivial FAQ system as if it was Wikipedia.

I decided to take a step back, and try to do it all over again. This time, using such useful tools as HTML and pages. Here is what the current user guide looks like:


<h1>NHibernte Profiler User Guide</h1>
	<li><%=Html.ActionLink<LearnController>(x => x.Topic("ProfileAppWithConfiguration"),
		 "Configuring the application to be profile without changing the application code")%></li>
	<li><%=Html.ActionLink<LearnController>(x => x.Alert("SelectNPlusOne"), 
		"Select N+1")%></li>
	<li><%=Html.ActionLink<LearnController>(x => x.Alert("TooManyDatabaseCalls"), 
		"Too many database calls per session")%></li>
	<li><%=Html.ActionLink<LearnController>(x => x.Alert("UnboundedResultSet"), 
		"Unbounded result set")%></li>
	<li><%=Html.ActionLink<LearnController>(x => x.Alert("ExcessiveNumberOfRows"), 
		"Excessive / Large number of rows returned")%></li>
	<li><%=Html.ActionLink<LearnController>(x => x.Alert("DoNotUseImplicitTransactions"),
		"Use of implicit transactions is discouraged")%></li>
	<li><%=Html.ActionLink<LearnController>(x => x.Alert("LargeNumberOfWrites"), 
		"Large number of individual writes")%></li>

And here is the implementation of Topic and Alert:

public ActionResult Topic(string name)
	return View("~/Views/Learn/Topics/" + name + ".aspx");

public ActionResult Alert(string name)
	return View("~/Views/Learn/Alerts/" + name + ".aspx");

Now, if I want to edit something, I can do it in a proper HTML editor, and managing links between items has turned into a very trivial issue, like it is supposed to be.


Will Shaver

Sounds like a great case of JFHCI. Someone smart came up with that acronym a while back.

John Teague

If you don't want to create actions for each static page, you could route them all to one action with the name of the view as a parameter.

Something like this (from memory, so expect typos):


MapRoute("static_conent", "Learn/{vew}", new {controller = "Learn", action = "DisplayStatic"});

public ActionResult DisplayStatic(string view){

return View(view);





Ya man. KISS always wins.


Why not just use a wiki? Perhaps you will even trust your best end users to add comments and clarifications?

Comment preview

Comments have been closed on this topic.


No future posts left, oh my!


  1. Speaking (3):
    23 Sep 2015 - Build Stuff 2015 (Lithuania & Ukraine), Nov 18 - 24
  2. Production postmortem (11):
    22 Sep 2015 - The case of the Unicode Poo
  3. Technical observations from my wife (2):
    15 Sep 2015 - Disk speeds
  4. Find the bug (5):
    11 Sep 2015 - The concurrent memory buster
  5. Buffer allocation strategies (3):
    09 Sep 2015 - Bad usage patterns
View all series



Main feed Feed Stats
Comments feed   Comments Feed Stats