Last Updated: September 09, 2019
·
7.028K
· spoike

Nesting Razor Helper Methods

The Razor view option called helper is something that's been available for developers since ASP.NET MVC3. Helpers work like any other methods exposed to Razor but it is composed of view code and the output is a HelperResult.

But did you know you can nest helpers in Razor? You can use the output from one helper and pass it in a containing helper that has a HelperResult as a parameter. Here is a quick example:

@helper Container(HelperResult stuff)
{
    <div class="stuff-container">
        @stuff
    </div>
}
@helper Stuff(string s)
{
    <p>
        Will the real @s, 
        please stand up?
    </p>
}

Calling it in your Razor view is sort of what you expect when you compose them together like this:

@Container(Stuff("Slim Shady"))

The code above will output the following HTML where the code from the second helper is put inside the code in the containing helper:

<div class="stuff-container>
    <p>
        Will the real Slim Shady, 
        please stand up?
    </p>
</div>

The great thing with using HelperResult is that is quite dynamic, in such terms that you can use any other helper:

@* Another helper *@
@helper Sweet(string candy) {
    <p>I like @candy</p>
}

@* Invocation with the new helper *@
@Container(Sweet("lollipop"))

<!-- Outputs: -->
<div class="stuff-container>
    <p>I like lollipop</p>
</div>    

But why?

Nesting the helpers will be useful for container of elements where you need to switch out the parts that are different inside that container. For example here is some helper code where the container can take the look of a "header" from another helper:

@helper ItemsContainer(string containerCssClass, HelperResult headerInfo, List<Item> items) {
    <article class="@containerCssClass">
        @headerInfo
        @foreach(var item in items) {
            <dl>
                <dt>
                    @Url.ActionLink(item.Title, ...)
                </dt>
                <dd>@item.Description</dt>
            </dl>
        }
    </article>
}

The header can be anything, such as html-snippet with header tag and an icon (common icon font usage):

@helper Header(string text, string iconClass = null) {
    <h1>
        @if (!String.IsNullOrEmpty(iconClass) {
            <i class="@iconClass"></i>
        }
        @text
    </h1>
}

The usage would be something like this, where the code needs to output several different kind of items:

@ItemsContainer(
            "news-article", 
            Header("News", "icon-news"), 
            Model.NewsItems)

@ItemsContainer(
            "blog-article", 
            Header("The Blog", "icon-blogpost"), 
            Model.BlogItems)

Using helpers this way will cut down some of the errors of consistency in your HTML design that easily happens when you cut and paste similar snippets of code.

1 Response
Add your response

Can you make an example of how to do the same thing using extension methods?

over 1 year ago ·