SharpDOM is a view engine for ASP.NET MVC platform allowing developers to design HTML layouts using C# 3.5/4.0. It is also generic internal DSL for generating HTML that can be used outside of MVC framework.
Nowadays, there are a lot of Web frameworks (in PHP, Java, .NET, etc) allowing to generate HTML layout with the help of certain template engines. Indeed, sometimes, these frameworks are quite powerful and amazing. The only problem is that these template engines introduce their own external DSLs which are not native for the .NET developers. It makes the usage of such template engines a little bit difficult, not to say more.
SharpDOM project allows you to develop HTML layout
as C# code
using all the power of modern object-oriented C# language. You can use features of C# like inheritance, polymorphism, etc to design your HTML layouts. In other words, designing of HTML layout can be transformed into the development of strongly typed HTML
code. SharpDOM is not the only project for it, there are some more sophisticated projects like WebSharper
. But SharpDOM is the only project oriented for common C# developers.
and CityLizard Framework
. Good luck for them!
Example of transformation
Let me start introduction of SharpDOM by converting a simple piece of HTML code into compilable C# code. It will allow you to quickly understand the central meaning of SharpDOM project - what it targets and what advantages it brings. Let's look at source HTML layout we are going to transform into strongly typed HTML:
<title>Title of the page</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<link rel="stylesheet" type="text/css" href="css/style.css">
<h1>Test Form to Test</h1>
<form id="Form1" method="post">
<input type="text">Enter value</input> <br />
<input type="submit" text="Submit !" />
<p>Textual description of the footer</p>
<span>You can find us here</span>
Another nested container
This could be rewritten using C# language as:
title[ Model.Title ],
meta.attr(httpequiv: HttpEquiv.content_type, content: "text/html;charset=utf-8"),
link.attr(rel: LinkType.stylesheet, type: MimeType.text.css, href: "css/style.css"),
h1[ "Test Form to Test" ],
form.attr(id: "Form1", method: Method.post)[
label[ "Parameter" ], Code.nbsp,
input.attr(type: InputType.text, value: "Enter value"), br,
input.attr(type: InputType.submit, value: "Submit !")
p[ "Textual description of the footer" ],
a.attr(href: "http://google.com" ) [ span[ "You can find us here"] ]
div[ "Another nested container" ]
As you can see, both the listings are very corelating each other - each line in HTML layout unambigiously corelates to the only line in C# code and vica verse. In other words, HTML-to-C# mismatch impedance is quite small. On the other hand, a developer having some skills in C# language could easily write strongly typed HTML code. And all the benefits of using the C# compiler are available now: compile-time checks, tight control over generated HTML by using embedded C# code, etc.
As you can see, there are some very interesting points in C# code:
- Title tag (inside head tag) has value = Model.Title - it means that a view model is sent to this view from the controller and the vew model contains a property named "Title" of string type. So some values could come from outside of the view (from the controller, as in this exampe), and the other values could be independant of the controller (example - resource text that could be localized) - such independant values could be calculated inside the view, not inside the controller.
- Some attributes has enum-based value - it helps developers to find appropriate possible values for such attributes. The rule of the tumb, when an attribute is not string based (mainly, they are not string based), then you could just look at the type of the attribute and then type the name of the attribute type and press "." - then IntelliSense will give you possible options.
ASP.NET MVC integration
The example above doesn't show how we can use ASP.NET MVC artefacts inside C# code. Let's take a look at the other small example concentrated on using such artefacts:
form.attr(action:Url.Action("LogOn"), method: Method.post)
Html.ValidationSummary(true, "Login was unsuccessful. Please correct the errors and try again.").ToLiteral(),
Html.LabelFor(m => m.LogOnModel.UserName).ToLiteral(),
Html.TextBoxFor(m => m.LogOnModel.UserName).ToLiteral(),
Html.ValidationMessageFor(m => m.LogOnModel.UserName).ToLiteral()
p[ input.attr(type: InputType.submit, value:"Log On") ]
- ViewModel You can embed into HTML code the values coming from your view model (that you pass from the controller to the view).
- View Logic Besides HTML tags expressed in the form of C#, you can embed some logic into HTML code using so-called "operators".
- User Controls You can divide HTML layout into small pieces using a-la WebForms' UsersContorls.
- Master Pages You can use master-page approach similar to the same approach existing in WebForms. It is also possible to dynamically (at run-time) choose what master page to use with current content page.
- Templated User Controls You can use templated user controls. In WebForms, the nearest analogy is Repeater's TemplateItem tag in layout.
- Extensibility Also there is possibility to traverse the generated tree of HTML tags and alter it with the help of LINQ. Not only traverse, but also alter.
See an example of using each concrete feature in the Documentation - http://sharpdom.codeplex.com/documentation
There are some advantages of switching from plain HTML code to C# code:
- Compile-time checks.
- Freedom for you as developer to use any presentation-level helper classes/constants, etc directly inside the view.
- Possibilty to maintain already written HTML layout (expressed in such C# manner) using features of C# like inheritance (all methods of SharpDOM are public and virtual).
- Presence of all generated HTML tags in the form of tree - so amount of possibilities are open now: a) possibility to use LINQ to Objects to find certain elements in the tree, b) possibility to change/alter/extend found items in your sub-class - and even in the inherited classes. Rather good things for maintenability.
Please, leave your comments and other feedback on the Discussion page - http://sharpdom.codeplex.com/Thread/List.aspx