Introducing NHaml - An ASP.NET MVC View Engine
NHaml (pronounced enamel) is a pure .NET implementation of the popular view engine. From the Haml website:
“Haml is a markup language that‘s used to cleanly and simply describe the XHTML of any web document, without the use of inline code. Haml functions as a replacement for inline page templating systems such as PHP, ERB, and ASP. However, Haml avoids the need for explicitly coding XHTML into the template, because it is actually an abstract description of the XHTML, with some code to generate dynamic content.”
In other words, NHaml is an external for XHTML. It’s primary qualities are it’s simplicity, terseness, performance and that it outputs nicely formatted XHTML. Additionally, the NHaml view engine provides support for Rails style layouts and partials – more on that below.
An example is the best way to grok how NHaml works. Below we have a typical view targeting the default Web Forms view engine. Observe the proliferation of angle-brackets, closing tags and general cruft.
~/Views/Products/List.aspx
<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="true" CodeBehind="List.aspx" Inherits="MvcApplication5.Views.Products.List" Title="Products" %> <asp:Content ContentPlaceHolderID="MainContentPlaceHolder" runat="server"> <h2><%= ViewData.CategoryName %></h2> <ul> <% foreach (var product in ViewData.Products) { %> <li> <%= product.ProductName %> <div class="editlink"> (<%= Html.ActionLink("Edit", new { Action="Edit", ID=product.ProductID })%>) </div> </li> <% } %> </ul> <%= Html.ActionLink("Add New Product", new { Action="New" }) %> </asp:Content>
Now, let us bask in the glory of the NHaml version:
~/Views/Products/List.haml
%h2= ViewData.CategoryName %ul - foreach (var product in ViewData.Products) %li = product.ProductName .editlink = Html.ActionLink("Edit", new { Action="Edit", ID=product.ProductID }) = Html.ActionLink("Add New Product", new { Action="New" })
There are a couple of things going on here. First, NHaml uses indentation (2 spaces) as an alternative to closing tags. Second, the first non-whitespace character in a line can describe how the line should be processed. For example, the first line in the example above starts with a ’%’, which directs NHaml to process that line as an XHTML tag. These directives are called Markup Rules and are discussed in detail in the Reference section below.
Download & License
NHaml is open source and released under the MIT license so go ahead and download the source, kick the tires and let me know what you think. Oh, and if/when you find an issue let me know or submit a patch.
Using NHaml
Configuring the ASP.NET MVC framework to use NHaml is as simple as referencing Mindscape.NHaml.ViewEngine.dll and putting the following line at the end of the Application_Start method in the Global.asax.cs file.
ControllerBuilder.Current.SetDefaultControllerFactory(typeof(NHamlControllerFactory));
NHaml view templates should have a .haml extension and are placed under the Views project folder in the normal manner.
Partials & Layouts
Currently, unlike Rails, the ASP.NET MVC framework delegates layout and partial handling to the view engine. Therefore, NHaml provides it’s own layout & partial system.
Partials
Partials are small reusable sub-views available within a single controller context. NHaml implements a Rails-like partial system. Any view template beginning with an ‘_’ is considered a partial. To use a partial simply use the NHaml ‘_’ markup rule like so:
~/Views/Products/List.haml
- foreach (var product in ViewData.Products) %li _ Product
In this example NHaml will replace the line ”_ Product” with the contents of the file _Product.haml in the current controller”s view folder (~/Views/Products)
~/Views/Products/_Product.haml
= product.ProductName %span.editlink = Html.ActionLink("Edit", new { Action="Edit", ID=product.ProductID })
At compile-time, both layouts and partials are merged into a single view and so any ViewData context is available.
Layouts
Layouts are the NHaml equivalent of master pages. NHaml provides a Rails-like layout system. Layouts are applied automatically based on the following conventions:
- If a layout is specified through the masterName argument of RenderView then that layout is applied. Or,
- If a layout with the same name as the controller exists in Views/Shared then it is applied. Or,
- If a layout called Application.haml exists in the Views/Shared folder then it is applied.
Here is an example layout targeting the Products controller (Views/Shared/Products.haml)
~/Views/Products/Products.haml
!!! %html{xmlns="http://www.w3.org/1999/xhtml"} %head %title My Sample MVC Application %link{href="../../Content/Sites", rel="stylesheet", type="text/css"} %body #inner #header %h1 My Store Manager - Products Section #menu %ul %li %a{href="/"} Home %li = Html.ActionLink("About Us", "About", "Home") %li = Html.ActionLink("Products", new { Controller = "Products", Action = "Category", ID = 1 }) #maincontent _ #footer
A layout file uses the ’_’ partial operator with no arguments to signify where view content should be inserted into the layout.
Compilation Model
NHaml views are compiled. The first time an NHaml view is requested it is parsed and compiled into a .NET Type capable of rendering the view. This Type is then cached. The view engine can run in two modes: development or production. In development mode, the view engine will automatically recompile a cached view if any of it”s constituent haml files are modified. Production mode may be enabled through the web.config file like so:
<configuration> <configSections> <section name="nhamlViewEngine" type="Mindscape.NHaml.ViewEngine.Configuration.NHamlViewEngineSection, Mindscape.NHaml.ViewEngine" /> </configSections> <nhamlViewEngine production="true" /> </configuration>
ViewData & Helpers
NHaml views inherit from an NHamlView base class that makes available the standard ASP.NET MVC helpers: AjaxHelper, HtmlHelper and UrlHelper along with a
ViewData property. These can be accessed and used in the same way as per the Web Forms view engine. For example,
%li = Html.ActionLink("About Us", "About", "Home")
results in:
<li> <a href="/Home/About">About Us</a> </li>
NHaml Language Reference
Disclaimer: Most of this reference was lifted from the main Haml site.
Tags %
The ’% character is placed at the beginning of a line. It‘s followed immediately by the name of an element, then optionally by modifiers (see below), a space, and text to be rendered inside the element. It creates an element in the form of <element></element>. For example:
%one %two %three Hey there
is compiled to:
<one> <two> <three>Hey there</three> </two> </one>
Any string is a valid element name; NHaml will automatically generate opening and closing tags for any element.
Attributes {}
Braces represent a C# 3 anonymous type object initializer statement that is used for specifying the attributes of an element. It is evaluated as an anonymous type, so
logic will work in it and local variables may be used. The braces are placed after the tag is defined. For example:
%head %title My Sample MVC Application %link{ href="../../Content/Sites", rel="stylesheet", type="text/css" }
is compiled to:
<head> <title>My Sample MVC Application</title> <link href="../../Content/Site.css" rel="stylesheet" type="text/css" /> </head>
Self-closing Tags /
The ’/’ character, when placed at the end of a tag definition, causes the tag to be self-closed. For example:
%br/ %meta{ http_equiv" = "Content-Type", content = "text/html"}/
is compiled to:
<br /> <meta http-equiv="Content-Type" content="text/html" />
Some tags are automatically closed, as long as they have no content. meta, img, link, script, br, input and hr tags are closed by default.
%br %meta{ http_equiv = "Content-Type", content = "text/html" }
is also compiled to:
<br /> <meta http-equiv="Content-Type" content="text/html" />
Class and Id . and #
The ’.’ and ’#’ are borrowed from CSS. They are used as shortcuts to specify the class and id attributes of an element, respectively. Multiple class names can be specified in a similar way to CSS, by chaining the class names together with periods. They are placed immediately after the tag and before an attributes hash. For example:
%div#things %span#rice Chicken Fried %p.beans{ food = "true" } The magical fruit %h1.class.otherclass#id La La La
is compiled to:
<div id="things"> <span id="rice">Chicken Fried</span> <p class="beans" food="true">The magical fruit</p> <h1 class="class otherclass" id="id">La La La</h1> </div>
And,
#content .articles .article.title Doogie Howser Comes Out .article.date 2006-11-05 .article.entry Neil Patrick Harris would like to dispel any rumors that he is straight
is compiled to:
<div id="content"> <div class="articles"> <div class="article title">Doogie Howser Comes Out</div> <div class="article date">2006-11-05</div> <div class="article entry"> Neil Patrick Harris would like to dispel any rumors that he is straight </div> </div> </div>
Implicit Div Elements
Because the div element is used so often, it is the default element. If you only define a class and/or id using the . or # syntax, a div element is automatically
used. For example:
#collection .item .description What a cool item!
is the same as:
%div{ id = "collection" } %div{ class = "item" } %div{ class = "description" } What a cool item!
and is compiled to:
<div id="collection"> <div class="item"> <div class="description">What a cool item!</div> </div> </div>
Evaluate C# Output =
’=’ is placed at the end of a tag definition, after class, id, and attribute declarations. It‘s just a shortcut for inserting C# code into an element. It works the same as = without a tag: it inserts the result of the C# code into the template.
%p= string.Join(" ", new string[]{"He", "braid", "runner!"})
Results in:
<p>He braid runner!</p>
No Special Character
If no special character appears at the beginning of a line, the line is rendered as plain text. For example:
%gee %whiz Wow this is cool!
is compiled to:
<gee> <whiz> Wow this is cool! </whiz> </gee>
DOCTYPES !!!
When describing XHTML documents with NHaml, you can have a document type or XML prolog generated automatically by including the characters !!!. For example:
!!! XML !!! %html %head %title Myspace %body %h1 I am the international space station %p Sign my guestbook
is compiled to:
<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head> <title>Myspace</title> </head> <body> <h1>I am the international space station</h1> <p>Sign my guestbook</p> </body> </html>
You can also specify the version and type of XHTML after the !!!. XHTML 1.0 Strict, Transitional, and Frameset and XHTML 1.1 are supported. The default version is 1.0 and the default type is Transitional. For example:
!!! 1.1
is compiled to:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
and
!!! Strict
is compiled to:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
If you‘re not using the UTF-8 characterset for your document, you can specify which encoding should appear in the XML prolog in a similar way. For example:
!!! XML iso-8859-1
is compiled to:
<?xml version="1.0" encoding="iso-8859-1" ?>
XHTML Comments /
The ’/’ character, when placed at the beginning of a line, wraps all text after it in an HTML comment. For example:
%billabong / This is the billabong element I like billabongs!
is compiled to:
<billabong> <!-- This is the billabong element --> I like billabongs! </billabong>
The forward slash can also wrap indented sections of code. For example:
/ %p This doesn"t render... %div %h1 Because it"s commented out!
is compiled to:
<!-- <p> This doesn"t render...</p> <div> <h1>Because it"s commented out!</h1> </div> -->
You can also use Internet Explorer conditional comments (about) by enclosing the condition in square brackets after the /. For example:
/[if IE] %a{ :href = "http://www.mozilla.com/en-US/firefox/" } %h1 Get Firefox
is compiled to:
<!--[if IE]> <a href="http://www.mozilla.com/en-US/firefox/"> <h1>Get Firefox</h1> </a> <![endif]-->
Escape Sequence \
The backslash character escapes the first character of a line, allowing use of otherwise interpreted characters as plain text. For example:
%title = @title \- MySite
is compiled to:
<title> MyPage - MySite </title>
Line Continuation |
The pipe character designates a multiline string. It‘s placed at the end of a line and means that all following lines that end with | will be evaluated as though they were on the same line. For example:
%whoo %hoo I think this might get | pretty long so I should | probably make it | multiline so it doesn"t | look awful. | %p This is short.
is compiled to:
<whoo> <hoo> I think this might get pretty long so I should probably make it multiline so it doesn"t look awful. </hoo> <p>This is short</p> </whoo>
Partials & Layouts _
Use an ’_’ to render a partial or the content of a layout. For a partial, specify the name of the partial after the underscore like so:
%p _ Customer
will render the _Customer.haml partial file.
An ’_’ on it”s own is used to specify where the content within a layout will be inserted:
%p _
Evaluate Output =
The ’=’ character is followed by C# code, which is evaluated and the output inserted into the document as plain text. For example:
%p = "hi" + " there" + " reader!" = "yo"
is compiled to:
<p> hi there reader! yo </p>
Evaluate Silent -
The ’-’ character makes the text following it into “silent” code: C# code that is evaluated, but not output.
It is not recommended that you use this widely; almost all processing code and logic should be restricted to the Controller, Helpers, or partials.
For example:
- string foo = "hello" - foo += " there" - foo += " you!" %p= foo
is compiled to:
<p> hello there you! </p>
Code Blocks
C# code blocks, like XHTML tags, don‘t need to be explicitly closed in NHaml. Rather, they‘re automatically closed, based on indentation. A block begins whenever the indentation is increased after a silent script command. It ends when the indentation decreases.
- for (int i=42; i<47; i++)
%p= i
%p See, I can count!
is compiled to:
<p> 42 </p> <p> 43 </p> <p> 44 </p> <p> 45 </p> <p> 46 </p> <p>See, I can count!</p>
Silent Comments -//
The hyphen followed immediately by a C# comment has the effect of a silent comment. Any text following this isn‘t rendered in the resulting document at all.
For example:
%p foo -// This is a comment %p bar
is compiled to:
<p> foo </p>
Trackbacks
Use this link to trackback from your own site.
Introducing NHaml - An ASP.NET MVC View Engine…
You’ve been kicked (a good thing) - Trackback from DotNetKicks.com…
[...] Original post by Andrew [...]
Very nice, thank you.
This seems very wrist friendly.
What if I dont want to use xhtml but HTML 4.01. My front end dev has a whole slew of reasons why he doesnt like xhtml(Don’t even get him started). So can I generate a doctype like this:
I guess the doctype tag got stripped above. sorry.
DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01//EN” “http://www.w3.org/TR/html4/strict.dtd”
Very cool AP. Pity I can’t inflict this on my designer just yet (although she took to MonoRail like the proverbial duck so there is hope) =)
Nice work :) I know Peter B was looking for just thus very thing a while ago … hopefully I’ll get some time to take it for a test drive!
@Jesse - I’ll look at making this change.
@Jacques, @Neal, @Alex - Thanks!
And another view engine for ASP.NET MVC has been born…
And another view engine for ASP.NET MVC has been born…
I was able to compile with C# express as I could not download VS yet (Too big)
I noticed that the hard coded path for the style sheet and home link to not work when you run the application under a virtual path.
Using:
%a{href=Html.ResolveUrl(”~/”)} Home for the home link seems to work better
I think there is a bug in ResolveUrl though, the the stylesheet link, I had to use a double’/’ like this:
%link{href=Html.ResolveUrl(”~//Content/Site.css”), rel=”stylesheet”, type=”text/css”}
Do you know of a better editor than VS to edit the views?
The indentation is not very obvious, maybe a Python or Ruby editor?
Hi Jacques,
Yeah, the test app is just a clone of Scott Gu’s MVC sample - I’ll take a look at ironing out any wrinkles.
For editing make sure you configure you’re editor to use 2 spaces instead of tabs for haml files. You could try SciTE, Notepad++, Notepad2 or maybe the e text editor.
Cheers,
Andrew.
This is sweet man! Why not put it up on google code or codeplex?
I’m creating a google project for it as we speak :-)
Back to BRAIL horror. What use has a language that has no support in the ide? Where is intellisense?
Common guys…
[...] Andrew has created a rather lengthy blog post about the engine as well as how to write in Haml, Check out the NHaml View Engine here. [...]
Found a syntax highlighter for Vim, screen shot here:
It seems to works with your implementation with minor modifications.
Cool, there is also one for Textmate that targets Rails.
[...] Peter has created NHaml, a new view engine for MS MVC based on the ruby Haml dsl. Sweet!! Maybe we can get Andrew to drop [...]
Any thoughts about putting this in the MVC Contrib project? We would love to have it.
Very cool! Noticed one minor quibble in one of the examples.
Should
<span id=”rice”>Chicken Fried
Have been
<span id=”rice”>Chicken Fried</span>
?
@Haacked,
Thanks, I’ve fixed this now.
@Jesse,
I’ve added the HTML 4.01 doc types. You use them like this:
!!! HTML
!!! HTML Strict
!!! HTML Frameset
Grab the source here:
Do you plan on porting Sass too?
I guess one could use Ruby to compile Sass templates manually in an ASP.NET MVC site.
No plans at this stage.
Yep, you could definitely do that.
Yeeeees, but why… It just adds an other level of complexity. And its another chain piece where it can break.
It looks more like a nice ‘hypothetical’ project: Yes it can be done.
And these kinds of this will be overshadowed by the new MVC controls that probably will be added to the namespace.
This looks fantastic. Good stuff.
@michaud,
How is this another level of complexity when you are substituting one view engine for another? I suspect Web Forms has an order of magnitude more moving parts than NHaml.
“new MVC controls”? I think you’re missing the big picture. ASP.NET MVC is about laying a solid architectural foundation - not about building more controls.
Hey Andrew,
I’d like to discuss your thoughts on incorporating the NHaml view engine into the MVC Contrib project. Can you shoot me an email so I can make my pitch?
-Bill
Hi Andrew,
I got Sass to work with 5 lines of ruby code.
I could not make it work with IronRuby though.
It is really a nice complement to NHaml as the structure of the Sass files parallels the one of the NHaml views.
It can also compile multiple sass files into a single compacted css file and it can be run as post-build event.
Resumo da semana natalino…
Resumo da semana natalino…
This is really a cool thing, I mean, having a new way of designing HTML pages but good only for the few developers that are building also the presentation side of web apps.
I don’t think could be a good replacement of the old HTML used by all the designers around the world.
Nicely done.
Which assemblies and namespaces are included in the compilation? The same ones as the webforms engine (i.e. defined in the web.config if needed) ?
I’m just trying to make sure we will have extension methods and any other custom code available in the templates.
[...] man z.B. die Routingfunktionalitäten oder auch die View-Engine ändern bzw. ersetzen kann. Mit NHaml ist eine weitere View Engine am [...]
New view engines in the MvcContrib project for asp.net mvc…
New view engines in the MvcContrib project for asp.net mvc…
@Sergio,
The references are:
mscorlib, System, System.Core, Mindscape.NHaml, Mindscape.NHaml.ViewEngine, System.Web.Extensions, System.Data.Linq, MVCToolkit
The namespaces are:
System, System.Text, Mindscape.NHaml, Mindscape.NHaml.Utilities, System.Web, System.Web.Mvc, Mindscape.NHaml.ViewEngine;
These are currently only configurable in code (NHamlViewFactory.cs) but feel free to submit a patch :-)
Cheers,
Andrew.
What is the reason to use spaces instead of tabs for indentations? I’m not against spaces but tabs are just more suitable IMO.
Andrew,
First of all, Great Work!
I may have found a bug. If there is a hyphen in the path to a view then that hyphen gets invlided in the generated class name for the view (which is invalid syntax).
I’ve created a failing test in:
[Test]
public void
Should_replace_hyphens_with_underscores_in_classnames_for_a_view()
{
string className = TemplateCompiler.MakeClassName(”C:\\test-path\\Views\\Test\\Test.haml”);
Assert.AreEqual(”C__test_path_Views_Test_Test_haml”,className);
}
(I needed to make MakeClassName public to facilitate testability)
I then made this test pass by changing the regex in _pathCleaner to [-/\\/\.:\s]
Greg
AndrewM,
2 spaces is the standard used by Rails and Haml and is also my preferred approach.
We can probably make this configurable.
Cheers,
Andrew.
Greg,
Good work. I’m in the process of moving the project to MVC Contrib so I’ll fix it there soon.
Cheers,
Andrew.
>> 2 spaces is the standard used by Rails and Haml and is also >> my preferred approach.
>> We can probably make this configurable.
That would be great! Thx.
I’ve found little problem in file CompiledView.cs:
private void CompileView(object viewData)
{
string viewDataType = “System.Web.Mvc.ViewData”;
if(!NHamlViewFactory.ViewDataIsDictionary(viewData))
{
_templateCompiler.AddReference(viewData.GetType().Assembly.Location);
………
This code adds reference to assembly, which contains type of value, passed in ViewData. But there is compilation error appears, if passed type has reference to another type, which is declared in other assembly - “The type ” is defined in an assembly that is not referenced.”
AndrewM,
Custom references can be added in code (NHamlViewFactory.cs static ctor). This will be configurable in web.config soon.
Cheers,
Andrew.
I get an error on your TestApp, it cannot compile the Index.haml, indicating there are invalid tokens.
Hi Mike,
This is probably the same error raised by Greg Banister above. The error has been fixed in the trunk here:
Cheers,
Andrew.
Is it possible to render partials that are in other Controller folders and/or Shared?
Is it possible to pass values to the partial? For instance, my partial does what was previously a postback and I would like to be able to process some stuff by the controller that it posts to and then redirect to the original controller/action.
Thanks.
Oops forgot something, THANK YOU VERY MUCH!!! I have missed HAML since I started ASP.NET :)
2008 第一帖:asp.net mvc相关开源项目推荐…
asp.net mvc ctp版本发布不到一个月时间,在社区出现了丛多的优秀开源项目,社区的活跃性非常高哦,前一段时间园子里也引发了MVC和WebForm的讨论,现在给各位推荐几个相关的优秀项目,这些…
Gabe,
NHaml is now part of MVC Contrib. Please feel free to create a feature request on CodePlex or better yet submit a patch :-)
Cheers,
Andrew.
Architecture Chat #22 This Thursday…
…
Sorry I really don’t see the point of this. I’d have to see some hard stats that this really does improve anything.
I love it.
[...] language and HAML… (Note to self, write HAML view factory for ASP.NET MVC. UPDATE: Crap! The brilliant Andrew Peters made NHAML this last month and added it to MVC Contrib. New Note to self, crush Andrew Peters for being too awesome.) [...]
NHaml for Sitecore?…
…
NHaml for Sitecore?…
“Haml is a markup language that‘s used to cleanly and simply describe the XHTML of any web document,…
Does it work with VB?
[...] Introducing NHaml - An ASP.NET MVC View Engine [...]
@Scott,
Thanks!
@John,
Not currently. It _should_ be possible however. We would need to make the compilation system pluggable. We’d love to see that patch! :-)
The script tag should not be automatically closed. Since that does is not supported by some browsers.
That is fixed in the trunk at:
Is this only for VS 2008? Im on 2005, and cant run any test application.
I’m gonna go ahead and second the request for SASS. I’ve been doing some work with haml and sass using PHP (yuck) for a while now, and since I’m pretty much a closet python freak, it’s a breath of fresh air to work with HAML and SASS. Hell, CSS constants and color math are worth it ALONE.
[...] will be used for persistence, Castle Windsor for dependency injection, NUnit and NMock for testing, NHaml for the views, and principles from agile, domain-driven design, and test-driven development will be [...]
[...] want to use NHaml instead af that annoying ASPX thing to render our views. If you are unfamiliar with NHaml, I can [...]
[...] three that I’ve looked at so far have been the standard ASP.NET WebForms, NVelocity and NHaml. I kinda like what I see in NVelocity and NHaml, but the documentation and support appears to be a [...]
I’m interested using haml in a .net 2.0 project (without asp).
I can’t really figure out how to just use the lib.
[...] NHAML [...]
Andrew,
Great work, thank you! Eager to see final release of ASP.NET MVC and Contrib package!
I’d rather repeat Jonas’ question: how could I use NHaml template engine outside MVC?
Igor,
I just posted about how to use NHaml standalone: https://andrewpeters.net/2008/04/19/standalone-nhaml/
Cheers,
Andrew.
There is a handler for Sass like files on CodePlex. I didn’t use it but it seems like it can handle very basic parsing functionality.
This is amazing!
What is the syntax for getting a localized resource from a resx file (in the global resources folder for example?)
For example, with the webform engine, I would say: Resources.Language.MyString (for example). With this view engine I get a “Resources cannot be found” exception.
Thank you!!
Pretty nice, Andrew!
I’m wondering though… in your layout file example, you have:
%link{href=”../../Content/Sites”, rel=”stylesheet”, type=”text/css”}
… which would only work intermittently, wouldn’t it?
It’d be fine for /Home/Index/, but wouldn’t /Home/ end up unstyled?
During development, my URL’s are like: /Project/Home/About, and in production, they’re just /Home/About … so I can’t use absolute URLs for these things…
Any ideas?
[...] NHamlStringTemplate NVelocity and here [...]
[...] Sergey has announced NHAML for Monorail. Andrew Peters brough NHAML to ASP.NET MVC last year, and now us Monorail users can enjoy using a very different kind of templating engine to [...]
Andrew I am having issues with rendering the nhaml website in iis. Its working in cassini perfectly ? any experience with iis
David,
Not personally. Try posting your question here:
Cheers,
Andrew.
It looks nice, haven’t tried it yet, but will very shortly! JD keeps prodding me to do it :P
Two comments: in the first example, you don’t generate the exact same HTML - you’re missing () around an section.
Secondly, I guess this is inherited from haml, but the use of the | for multiline strings is, IMO, a horrible convention.
I think using a double-indent, i.e. 4 spaces would do the trick, assuming you have a strict parser.
Jessica :)
[...] tried the NHaml view engine, a .NET implementation of the Rails Haml view engine. My NHaml default layout (master [...]
Can’t compile the ViewEngine. It keeps saying it can’t find IView, RequestContext and IViewFactory. I referenced everything, System.Web.Mvc, extensions, routing, abstractions, the mvctoolkit, and so on, without any good.
Anyone knows the reason?
Hi Matteo.
The version linked to in this post is old. The latest version is available here:
Cheers,
Andrew.
using NHaml.Web.Mvc;
and
ControllerBuilder.Current.SetControllerFactory(typeof(NHamlControllerFactory));
insted of:
ControllerBuilder.Current.SetDefaultControllerFactory(typeof(NHamlControllerFactory));
did it for me using:
Microsoft Visual Studio 2008
Version 9.0.30428.1 SP1Beta1
Microsoft .NET Framework
Version 3.5 SP1
Beside that very nice port, I always found it annoying that I had to end stuff when the indentation was clear. It’s a joy to write less :)
I’d really like to see the option to use tabs instead of spaces.
But even more importantly I’d like to see a vs.net template so you can start a new project and not have to configure it for nhaml.
And finally all this wrapped up in a msi (or the like) for the masses.
I’m new to .net so I didn’t understand much from looking at the source but thanks for releasing them.
Finally keep up the great work and thanks for doing it.
[...] As you probable guessed Haml has been built for Ruby (and hence for Rails and Merb) but it also functions indepently with PHP (2 flavors: here and here) and .NET [...]
[...] community as mainstream as Microsoft .NET developers starts porting libraries from your community (NHaml and Castle ActiveRecord) it says [...]
Brilliant!
I would love to use NHaml together with F# in the future.
One question though: I made a Layout with a Partial in it. Do I have to place the partial in every View folder? I didn’t manage to place a Partial in the Shared folder. Did I miss something obvious? It would have been great to be able to create “global” Partials.
Yes! I found the solution to my problem here, when you answered the same question:
[...] 2、 NHaml –ASP.NET MVC View Engine,这是一个Ruby的Haml的版本,对于熟悉Ruby开发的同学一定很熟悉,项目网站:http://haml.hamptoncatlin.com/。具体介绍可看这篇文章:https://andrewpeters.net/2007/12/19/introducing-nhaml-an-aspnet-mvc-view-engine [...]
Hi Andrew,
Thanks for the hard work!
NHaml simply rocks!!!
-Rajasekhar Bathula
I can’t get NHaml to work with ASP.NET MVC Beta. Anyone else having the same problem?
[...] Pomijając moją nieudolną próbę definicji tego pojęcia HAML to w praktyce poprostu jeden wielki skrót HTML’a. Z założenia autorzy napisali go by ulżyc programistom framework’a RoR, ale plotka głosi istnieją wersje, które spokojnie zadziałają również w php i ASP .NET. [...]
You’ve forgot to mention the the ^ evaluator :)
Parsa,
Yeah, that is a NHaml-specific extensions that I added later on.
We working on putting together proper documentation :-)
Cheers,
Andrew.
Same problem as Johan. Can’t get it to work in MVC Beta. Has there been any discussion with Microsoft on improving support for NHAML? It’s a great view engine and I just read MS is adding support for jQuery to MVC so why not NHAML also.
Peter, I actually got it to work again. Unfortunately I don’t remember what I did, but I think I just updated the source via SVN.
I’m getting a strange error with NHaml CSharp2TemplateCompiler in the latest version via svn
I’ve followed the convention where I have projects in a solution named Solution.Subset ie Nexus.Data and Nexus.DALC and Nexus.Services…
I’ve got NHAML causing the following error:
An error occurred when compiling the file: C:\nexus checkout\Nexus.Interface.MVC\Views\CorporateEntity\CorporateEntityIndex.haml
c:\Documents and Settings\Plizon\Local Settings\Temp\yubdtk_w.0.cs(10,161) : error CS0246: The type or namespace name ‘Nexus’ could not be found (are you missing a using directive or an assembly reference?)
0008: using NHaml.Web.Mvc;
0008: public class C__nexus_checkout_Nexus_Interface_MVC_Views_CorporateEntity_CorporateEntityIndex_haml : NHaml.Web.Mvc.NHamlMvcView<System.Collections.Generic.List> {
0010: protected override void CoreRender(TextWriter textWriter){
There’s no ‘Nexus’ namespace but there is a Nexus.something namespace. Is this the reason for the error? NHaml using reflection?
Peter,
NHaml templates are compiled. As such, any third party assembly needs to be referenced during compilation. You can add references through the NHaml config section or through code using TemplateEngine.AddReference.
Cheers,
Andrew.
Hi Andrew,
Could you point me to a piece of documentation or the right unit test to look at to see how this is accomplished?
As a brute force approach I referenced the third party assembly in the Nhaml.Web.Mvc project and then in the NHamlMvcViewEngine.cs file added the following
_templateEngine.AddReference(typeof(Nexus.Data.CorporateEntity).Assembly.Location);
The error I get now is
An error occurred when compiling the file: C:\nexus checkout\Nexus.Interface.MVC\Views\CorporateEntity\CorporateEntityIndex.haml
\Local Settings\Temp\ue35e7u3.0.cs(320,66) : error CS1026: ) expected
0318: textWriter.Write(@” “);
0318: textWriter.WriteLine(HttpUtility.HtmlEncode(Convert.ToString(nbsp;)));
0320: textWriter.WriteLine(@” “);
\Local Settings\Temp\ue35e7u3.0.cs(320,67) : error CS1525: Invalid expression term ‘)’
0318: textWriter.Write(@” “);
0318: textWriter.WriteLine(HttpUtility.HtmlEncode(Convert.ToString(nbsp;)));
0320: textWriter.WriteLine(@” “);
Seems unrelated so I guess I did something wrong referencing / configuring the viewEngine?
Hi Peter,
Looks like a syntax error in your markup:
textWriter.WriteLine(HttpUtility.HtmlEncode(Convert.ToString(nbsp;)));
From something like this:
=
Which is invalid because = expects a valid C# expression
oops, my nbsp; wasn’t rendered above
Nice work. I’m impressed!
Andrew, understood. Thanks got it working.
[...] wish ASP.NET MVC and NHaml existed a year ago when I started my last ASP.NET project. I am in love with the simplicity and [...]
[...] what is NHaml? NHaml is a .Net port of the excellent Ruby Haml which is a HTML/Xml DSL ported by Andrew Peters which also provides a ASP.Net ViewEngine. You could read more on his [...]
[...] options. One of those is NHaml which is a very different way to create HTML (can read about it here) and I thought that looked very interesting. Viewers should contain no logic, they should focus on [...]
[...] Now insert some NHaml markup. [...]
Hi…….
I am using Asp.Net MVC RC1…….
and m using NHaml in that one
m getting the error of
Kind Regards,
Saurabh
[...] to Vote[FriendFeed] Andrew Peters’ Blog » Blog Archive » Introducing NHaml - An ASP.NET MVC View Engine…Thursday, March 05, 2009 from [...]
[...] Luckily for me, Microsoft’s ASP.NET will soon have access to HAML via the MVC Contribs project. Alas, no native Sass support is on the [...]
ASP.NET MVC…
Bookmarks Downloads Microsoft ASP.NET 3.5 Extensions Preview…
.NET Open Space Süd 2009 in Ulm - Castle Monorail vs. Microsoft MVC…
Nach den gestrigen Scrum-Notizen hier gleich der Mitschrieb zur nächsten Session vom Ulmer Open Space. Leider gab es in der Session keinen wirklichen Vergleich zwischen den beiden MVC-Frameworks, da niemand der Anwesenden gleichzeitig beide so richtig…
Hey, congrats! Great job :)
but, i don’t see activity in the project… it was discontinued?
@Leandro,
The project is located here:
Cheers,
Andrew
Hello, I’ve made some tests with nhaml and its pretty nice.
Thanks for that.
Just one thing for now is that I think the script tag should be indented to one line when it’s empty(just for importing purposes).
It would really look nicier since haml is all about smart and beautiful code.