Search code examples
asp.netasp.net-mvcrazorrazor-declarative-helpers

How to pass HTML fragment (as a delegate?) to a declarative Razor Helper?


I've been writing some declarative Razor Helpers (using the @helper syntax) for use with the Umbraco 4.7 which now supports the Razor view engine (though I would imagine this applies equally to WebMatrix or ASP.NET MVC). They all work fine. However, I would like to make them a bit more flexible so that I can pass into them an HTML fragment that can be 'wrapped' around the output (but only when there is output). For instance, I have a helper (much simplified here) that can generate an HTML link from some parameters:

@helper HtmlLink(string url, string text = null, string title = null, 
string cssClass = null, bool newWindow = false)
{
    if (!String.IsNullOrEmpty(url))
    {
        System.Web.Mvc.TagBuilder linkTag = new System.Web.Mvc.TagBuilder("a");

        linkTag.Attributes.Add("href", url);
        linkTag.SetInnerText(text ?? url);

        if (!String.IsNullOrEmpty(title))
        {
            linkTag.Attributes.Add("title", title);
        }

        if (!String.IsNullOrEmpty(cssClass))
        {
            linkTag.Attributes.Add("class", cssClass);
        }

        if (newWindow)
        {
            linkTag.Attributes.Add("rel", "external");
        }

        @Html.Raw(linkTag.ToString())
    }
}

Calling @LinkHelper.HtmlLink("http://www.google.com/", "Google") would generate the HTML output <a href="http://www.google.com/">Google</a>.

What would be nice, though, is if I could optionally pass in an HTML fragment that would be wrapped around the generated hyperlink HTML so long as the URL has a value. I'd basically like to be able to do something like this:

@LinkHelper.HtmlLink("http://www.google.com/", "Google", @<li>@link</li>)

and get output

<li><a href="http://www.google.com/">Google</a></li>

or @LinkHelper.HtmlLink("", "", @<li>@link</li>)

and get no output at all.

I read in Phil Haacked's blog about Templated Razor Delegates but cannot get the hang of how they can be used in this context - if, indeed, it is possible. I get the feeling I'm missing something or barking up the wrong tree.


Solution

  • I think the problem is with @link. Templated razor delegates take the data using a 'magic' parameter @item. Try replacing @link with @item in your template.

    Also, post the code that executes the template - your HtmlLink method that takes Func<dynamic, object>.