Update: I changed from using MarkdownSharp to MarkdownDeep.NET and pushed the helper to NuGet to make it easier to use. Sure, it's only a few lines of code, but this way one command will import the MarkdownDeep.NET library and add the namespace to your views Web.config easily. It'll also make updates much simpler if you use it in many places :-)


One of the goals for my new blogging engine in ASP.NET MVC/Razor is to store all of my articles using Markdown instead of HTML. If you don't know what Markdown is, go read. I'll wait... If you've used StackOverflow much, you're probably already familiar with it, even if you didn't know it by name.

Since I first started working on content management systems many moons ago, there was something I disliked about using HTML to store content. Even with strides towards semantic markup, HTML felt a little clunky as a storage format. I wanted something better.

I tried many things to "solve" this problem, including creating my own XML markup for content, which I could transform into HTML for displaying on the website (or plain text, if required). This was totally stupid, and I permit for you to laugh at me (just this once, mind). My XML was 95% the same as HTML. Duh. It made more sense to just store HTML, and convert that into other formats if required, but this still didn't feel right.

As years went by, I really learned to hate rich HTML editors. They usually generate crap markup (why are there 50 divs wrapped around my content?!), and often destroyed relative paths in links and images. They also didn't work on mobile versions of most browsers, meaning I couldn't even fix simple typos when away from my computer. I was sure there had to be a better way, but unfortunately at the time of building this blog, I couldn't find one. As a result, all of the articles currently on this blog are hand-typed HTML in a <textarea>! This has an advantage of working on my iPad, but it kinda sucks. It makes me cry a little inside every time I create a post.

Enter, Markdown

Over the past few years, I've been using StackOverflow quite a lot and I've really grown to love the editor they use, which uses Markdown for formatting. The more I use it, the more I think it's what I should be using for my blog. Not only is the markup much simpler than hand-crafting HTML, it's 100% human-readable in text format and also editable on my iPad!

To test out how this could work, I decided to knock up a quick prototype in ASP.NET MVC/Razor. The code used to transform StackOverflow's content server-side was opensourced under the name MarkdownSharp, so I grabbed that. The project includes a lot of files, but these are mostly tests. The file Markdown.cs is all you need to transform text. I didn't expect it to be difficult, but it still turned out to be far simpler and far more elegant than I was expecting!

Creating an HtmlHelper Extension Method

The best way to use Markdown in an MVC view would be by creating an extension method on the Html property (an instance of HtmlHelper of a view. This will allow us to transform text very easily, like this:

@Html.Markdown(Model.Body)

To do this, we need to create an extension method on HtmlHelper. We do this by using the class we'd like to extend as the first argument, but prefixing it with the keyword "this":

/// <summary>
/// Helper class for transforming Markdown.
/// </summary>
public static class MarkdownHelper
{
	/// <summary>
	/// An instance of the Markdown class that performs the transformations.
	/// </summary>
	static Markdown markdownTransformer = new Markdown();

	/// <summary>
	/// Transforms a string of Markdown into HTML.
	/// </summary>
	/// <param name="helper">HtmlHelper - Not used, but required to make this an extension method.</param>
	/// <param name="text">The Markdown that should be transformed.</param>
	/// <returns>The HTML representation of the supplied Markdown.</returns>
	public static IHtmlString Markdown(this HtmlHelper helper, string text)
	{
		// Transform the supplied text (Markdown) into HTML.
		string html = markdownTransformer.Transform(text);

		// Wrap the html in an MvcHtmlString otherwise it'll be HtmlEncoded and displayed to the user as HTML :(
		return new MvcHtmlString(html);
	}
}

It's important to note that you need to wrap the resulting string in an MvcHtmlString (or other IHtmlString) to stop the framework from HtmlEncoding the output, since in this case the result is deliberately HTML that should be rendered by the browser.

In order to be able to use this method in our views without having to import namespaces, we can add the namespace to the web.config file, like this:

<pages>
	<namespaces>
		<add namespace="DanTup.Web" />
	</namespaces>
</pages>

Now in our view, we'll see our Markdown method in the intellisense once we've typed "Html.", allowing us to pass in the string we'd like to transform.

<div id="content">
	<h2>@Model.Title</h2>
	@Html.Markdown(Model.Body)
</div>

In addition to transforming data in your model, you could also pass a string in directly if you wish to keep your markup a little clearer:

<div id="sidebar">
	@Html.Markdown(@"
	Links
	---

	* [Danny Tuppeny](http://blog.dantup.com/)
	* [Andrew Nurse](http://vibrantcode.com/)
	")
</div>

Unfortunately if you add indenting you'll get strange issues (since indenting means something in Markdown), but for a simple hard-coded list of links/etc. this might be more elegant than ahrd-coding UL/Hyperlinks!