Standalone NHaml

Posted by Andrew on April 19, 2008

Quite a few people have asked me how to use NHaml outside of ASP.NET MVC. Here’s how to do it:

1) Create your project and add a reference to MvcContrib.NHamlViewEngine
2) Use code like the following to compile and render a template.

var templateCompiler = new TemplateCompiler();
var viewType = templateCompiler.Compile("MyTemplate.haml");               
var view = (ICompiledView)Activator.CreateInstance(viewType);
 
string output = view.Render();

In this case the haml template is located in the same folder as the application.

As always, a good way to figure this stuff out is to take a look at the unit tests. In this case I copied the code verbatim from the NHaml TestFixtureBase class.

Trackbacks

Use this link to trackback from your own site.

Comments

Leave a response

  1. Igor LoginovNo Gravatar Sun, 20 Apr 2008 15:12:17 CDT

    Andrew,

    Thank you for this example! You are absolutely right, I have already found the code in unit tests. My problem was, that initially I downloaded the contrib package from codeplex but not your original one.

  2. adminNo Gravatar Sun, 20 Apr 2008 16:30:50 CDT

    Hi Igor,

    That should be no problem. I was using the version from the contrib project.

    Cheers,

    Andrew.

  3. Igor LoginovNo Gravatar Mon, 21 Apr 2008 06:06:38 CDT

    Hi Andrew,

    There is another interesting question - exposing variables for evaluation. Is it possible to reference assemblies manually without adding a section in .config file? - Or - Can I expose my variables via genericArguments to get them accessable in template on render?

    Thank you.

  4. AndrewNo Gravatar Mon, 21 Apr 2008 16:32:50 CDT

    Igor,

    Yes, you can add references using the AddReference method on TemplateCompiler.

    You can also specify a custom base class for your compiled template types. This allows you to set up state accessible from your template and is how the view engine does it.

    Cheers,

    Andrew.

  5. Igor LoginovNo Gravatar Mon, 21 Apr 2008 17:50:41 CDT

    Andrew,

    Thank you for advice - exactly what I did. However, as soon as I tried to share public property of my test page class, compiler requested to reference System.Web assembly. Here I failed, so asked you about referencing. OK, it was wrong direction… Finally, I created NHamlView class and got an access to its fields from the template. By the moment I have played with nested templates and different C# code evaluations. Works very stable and looks very flexible! Definitely a great approach (thanks once again!)

    Although one thought is still bothering me. Since NHamlView class is instantiated by the compiler, I am unable to change its state from outside (from page class, for example). And the situation looks not very dynamic then. Have you ever considered an alternative way of parameter sharing? E.g. via CompilationContext?

  6. AndrewNo Gravatar Mon, 21 Apr 2008 18:24:48 CDT

    The idea is to create a view base class that exposes a context setting method and then use this method to set the context before calling Render.

    The view engine does this through the INHamlView interface.

  7. Igor LoginovNo Gravatar Mon, 21 Apr 2008 18:59:59 CDT

    Aha! This is a lost piece of puzzle! Thanks a million! Will check the first time tomorrow. Don’t want to steal your time more (although I have 2 other topics for questions - caching / precompilation and resource embedded templates :)

  8. Igor LoginovNo Gravatar Sat, 26 Apr 2008 06:00:08 CDT

    Hi Andrew,

    This is me again and with the next thoughts…

    I tried to make a simple comparison of NHaml and NVelocity. For sure I can tell that Haml template language is far ahead. It is very effective - like you are doing the same things but with shortcuts. It is rich and has excellent coverage of (X)HTML. But at runtime NVelocity brings results much faster. Pretty easy to understand why - NHaml executes native C# code in templates, like Ruby does. For Ruby, however, it’s natural. Ruby is interpreting language. .NET uses compilation paradigm. So, NHaml generates class code first and then compiles it.

    I am not going to interfere with your plans on NHaml development. But for me a good idea would be to have an external Haml template compiler. The compiler produces a DLL with templates as embedded resources. And the template engine has a mechanism to reference that DLL (mutual compiler-engine config?). So, developer will have a choce - to do everything on-the-fly and to pay its price with lower performance, or to use pre-compiled templates and to boost performance.

    Could you, please, comment that?

    Thank you.

  9. AndrewNo Gravatar Sat, 26 Apr 2008 21:16:14 CDT

    Hi Igor,

    The idea is to cache the NHaml generated types. The view engine supports this through the “production” configuration option. When this option is set to true the view engine will cache the generated template type the first time it is requested.

    When measuring NHaml’s performance there are two things we should be mainly concerned with:

    1) Compilation performance - how long does it take to generate a compiled NHaml type.
    2) Render performance - given a compiled view how long does it take to render.

    I’m interested to see the numbers with view caching enabled.

    Cheers,

    Andrew.

  10. Igor LoginovNo Gravatar Sun, 27 Apr 2008 15:17:34 CDT

    Hi Andrew,

    First of all, I don’t want to drop any shadow to NHaml. Sorry, if the situation looks like this from your prospective. I am just learning step by step, and only “NHaml” and “Tests” folders were explored. We can move to personal email if you want.

    Seems, it’s time for me to proceed with the code from “ViewEngine” directory I hoped to avoid :) Let you know about results.

    Thank you for explanations!

    Igor

  11. DanielNo Gravatar Wed, 26 Aug 2009 17:00:19 CDT

    Hi Andrew,

    I’ve worked out how to render a template in a standalone fashion but I can’t workout how to add objects to the templates. For example if in my haml file I put “= myVal” how do I set myVal?

    Thanks in advance

    Dan

  12. AndrewNo Gravatar Tue, 08 Sep 2009 13:25:31 CDT

    @Daniel,

    Check out the unit tests for examples.

    Cheers,

    Andrew.

Comments