Here’s an ASP.NET MVC HTML Helper that helps in the following scenario. Let’s say you have a partial that can be included a number of times in a view but has a bit of common code that need only be included once. Typically that bit of common code would be some script.
In ASP.NET such a scenario is addressed by RegisterClientScriptBlock. In the Spark View Engine it’s taken care of by the once attribute.
So, inspired by Phil Haack’s Templated Razor Delegates post from earlier this year I knew you could write helper functions for Razor that could take arbitrary markup. The key to it is taking a Func argument that returns a HelperResult.
To use it you invoke it like so:
@Html.Once("some unique key", @<div>arbitrary markup that gets rendered just once</div>)
More typically, for including script, e.g.:
@Html.Once("TABLE_SORTER_INIT_SCRIPT", @<script type="text/javascript">
$(function() {
$('table.sortable th').each(function(){
// . . .
});
});
</script>)
Here’s the implementation that adds the Once extension method to HtmlHelper:
using System;
using System.Web.Mvc;
using System.Web.WebPages;
namespace Foo
{
public static class HtmlUtils
{
public static HelperResult Once(this HtmlHelper html, string key, Func<object, HelperResult> template)
{
var httpContextItems = html.ViewContext.HttpContext.Items;
var contextKey = "HtmlUtils.Once." + key;
if (!httpContextItems.Contains(contextKey))
{
// Render and record the fact in HttpContext.Items
httpContextItems.Add(contextKey, null);
return template(null);
}
else
{
// Do nothing, already rendered something with that key
return new HelperResult(writer => { /*no-op*/ });
}
}
}
}
Hope that helps!
