SLaks.Blog

Making the world a better place, one line of code at a time

Creating Markup Actions in Razor

Posted on Monday, May 02, 2011, at 6:06:00 PM UTC

Razor’s inline helpers allow you to create lambda expression that return markup (as a HelperResult).  However, there is no simple way to create a lambda expression that writes HTML directly to the page (instead of returning it).

In ASPX pages, one can simply put the beginning and end of a lambda expression in expression blocks, then put markup in the middle.

For example, this code creates a delegate that writes a <b> tag to the page:

<%
    Action pageWriter = () => {%><b>I'm from a lambda!</b><%};
    pageWriter();
    pageWriter();
    pageWriter();
%>

Calling the pageWriter delegate will write directly to the HTTP response stream.

By contrast, Razor inline expressions return their markup.  To do this in a Razor page, one would write

@{
    Func<object, HelperResult> htmlMaker
         = @<b>I'm from a lambda!</b>;
    @htmlMaker(null)    //Note @ sign
    @htmlMaker(null)    //Note @ sign
    @htmlMaker(null)    //Note @ sign
}

Calling htmlMaker without an @ sign will return HTML, but won’t write anything to the page.

When working with libraries designed for ASPX pages, it can be necessary to create ASPX-style inline helpers that write to the page instead of returning a value.  You can do that by creating an inline helper lambda and passing it to the Write method:

@{
    Action pageWriter = () => Write(new Func<object, HelperResult>(
         @<b>I'm from a lambda!</b>
    )(null));

    pageWriter();
    pageWriter();
    pageWriter();
}

Like the ASPX version, pageWriter now writes directly to the page and does not return anything.

This code can be made simpler by wrapping it in a separate method:

Action MakeAction(Func<object, HelperResult> inlineHelper) {
    return () => Write(inlineHelper(null));
}

This method takes an inline helper and returns an Action that writes the helper’s output to the page.  Since it needs to call the page’s Write method (to use the page’s output stream), this method must be defined in the WebPageBase instance, either in an @functions block or in a common base class.

Any code in the inline helper will execute each time the resulting Action is called.

It can be called like this:

@{
    Action pageWriter2 = MakeAction(@<b>I'm from a lambda!</b>);

    pageWriter();
    pageWriter();
    pageWriter();
}

This code is equivalent to the previous sample, but it’s much simpler.

One can also write write a version that takes a parameter:

Action<T> MakeAction<T>(Func<T, HelperResult> inlineHelper) {
    return param => Write(inlineHelper(param));
}
Note that the type parameter must be specified explicitly; C# does not infer type parameters from the method’s return type.

Categories: Razor, ASP.Net, inline-helpers, .Net Tweet this post

comments powered by Disqus