Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

SharpDOM, a new view engine for ASP.NET MVC

0.00/5 (No votes)
6 May 2010 1  
IntroductionSharp DOM is a view engine for ASP.NET MVC platform allowing developers to design extendable and maintenable dynamic HTML layouts using

This articles was originally at wiki.asp.net but has now been given a new home on CodeProject. Editing rights for this article has been set at Bronze or above, so please go in and edit and update this article to keep it fresh and relevant.

Introduction

Sharp DOM is a view engine for ASP.NET MVC platform allowing developers to design extendable and maintenable dynamic HTML layouts using C# 4.0 language. It is also possible to use Sharp DOM project to generate HTML layouts outisde 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.

Sharp DOM project allows you to develop HTML layout as C# code using all the power of modern object-oriented C# 4.0 language. You can use features of C# 4.0 like inheritance, polymorphism, etc. In other words, designing of HTML layout can be transformed into the development of strongly typed HTML code :-)

Usage of Sharp DOM

  1. Simply download DLL files from the Downloads page of CodePlex site - http://sharpdom.codeplex.com/releases
  2. Reference SharpDom.dll file and SharpDom.Mvc.dll file in your ASP.NET MVC project.
  3. Create a class inherited from SharpDomView<> class (where generic parameter is view model).
  4. Override CreateTagTree() method of this newly created class and write HTML layout inside this method in the form of C# code.
  5. In the controller, create view model and populate it with proper data.
  6. Write some plumbing code to embed Sharp DOM view engine into MVC platform:
public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        RegisterRoutes(RouteTable.Routes); 
        RegisterViewEngines(ViewEngines.Engines);
    }
    public static void RegisterViewEngines(ViewEngineCollection viewEngines)
    {
        viewEngines.Clear();
        viewEngines.Add(new SharpDomViewEngine());    }
}

Example of transformation

Let's look at source HTML layout we are going to transform from old plain HTML into strongly typed HTML:

<html>
    <head>
        <title>Title of the page</title>
        <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
        <link href="css/style.css" rel="stylesheet" type="text/css">
        <script href="/JavaScripts/jquery-1.4.2.min.js" type="text/javascript">
    </head>
    <body>
        <div>
            <h1>Test Form to Test</h1>
            <form id="Form1" type="post">
                <label>Parameter</label> =
                <input type="text">Enter value</input>
                <input type="submit" text="Submit !" />
            </form>
            <div>
                <p>Textual description of the footer</p>
                <a href="http://google.com">
                    <span>You can find us here</span>
                </a>
                <div>
                    Another nested container
                </div>
            </div>
        </div>
    </body>
</html>

This could be rewritten using C# 4.0 language as:

html[
    head[
        title[ "Title of the page" ],
        meta.attr(http-equiv: "contenttype", content: "html", charset: "utf-8"),
        link.attr(href: "css/style.css", rel: "stylesheet", type: "css"),
        script.attr(href:"/JavaScripts/jquery-1.4.2.min.js", type: "javascript")
    ],
    body[
        div[
            h1[ "Test Form to Test" ],
            form.attr(id: "Form1", type: "post")[
                label[ "Parameter" ], "=",
                input.attr(type:"text", value: "Enter value"), br,
                input.attr(type: "submit", value: "Submit !")
            ],
            div[
                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.

Advanced topics

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.

Maintenability
In the case when your HTML code expressed in C# is supported by another developer, she can use all features of C# to extend/override/modify tree of generated HTML tags before tags are shipped to the browser. Open/close approach is in action.

See an example of using each concrete feature in the Documentation on CodePlex site - http://sharpdom.codeplex.com/documentation

What C# 4.0 artefacts are used?

C# artefacts

The mostly used thing is indexer - each time you see square brackets, you see an indexer of certain C# object, and this C# object has the same name as name of corelated HTML tag. So if you see code like:

    h1[ "Test Form to Test" ]

you know, that there is C# object named "h1" and this object corelates to H1 tag of HTML specification. Next, you can notice that there are used optional named parameters, in sentences like:

    form.attr(id: "Form1", type: "post")

Also params parameters are used (all parameters are of the same base type - Tag):

    body[ h1[...], form[...], div[...], div[...] ]

also there is overloaded implicit convertion operator from string type to Tag class:

    label[ "Parameter" ], "=", input.attr(type: "text", value: "Enter value")

Advantages

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 Sharp DOM 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.

Maintenability

Extendablity and maintenability of the HTML layout is one of the main reasons why Sharp DOM project was developed. During our programming lives we have came accross many situations when we had HTML layout as ASPX file, but:

  • we weren't able to alter ASPX layout directly - because there was a possibility that in near future the layout would be reverted back to source state,
  • we weren't able to extend code-behind code - because it was obfuscated or sealed or not properly architectured not allowing desired changes.

That's why we spent a lot of time thinking over the architecture of Sharp DOM project trying to find the optimal form of the code from the point of view of maintenability. That's why we did following things inside the code:

  • Practically each and every method/property is public and virtual. It allows to use class inheritance for future maintenance (in case when subscribing to events is not enough).
  • Template Method design pattern is widely used (and sequence steps are virtual methods).
  • Each tag has unique internal id which can be reused for the maintenance benefits.
  • Each tags has some events - OnPreRender and OnPostRender. Each builder (master page builders, content page builders, user control builders) has the same events plus OnPre/PostCreateTags and some other, Also all these events are propagated up through tag tree. So it is possible to subscribe only to the root tag to listen to all events.
  • The whole tree of generated HTML tags is split into nested areas - areas where different builders have worked. So it is possible to easily recognize what code generates what HTML. It could simplify the life of developers working in support departments and who have to improve somehow already designed HTML code in order to fullfil changed bussiness requirements.

Authors

Please, leave your comments and other feedback on the Discussion page on CodePlex site - http://sharpdom.codeplex.com/Thread/List.aspx

We quite hope the project is helpful for you!

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here