Pass HTML to extension method

Lately I’ve been working in MVC a lot and playing around with refactoring page generation approaches to make it more flexible and easier to customize. One method I wanted to pass along was how to pass HTML to a helper (extension) method.

I got the following from (once again) a post over on StackOverflow by Darin Dimitrov and thought I’d post a synopsis here for reference. Let’s say you want to register JavaScript code on your master page/root layout from a DisplayTemplate or EditorTemplate (my purpose was to attach the jQuery tokenInput library to a form in an EditorTemplate). Normally you’d need to bring the code to the top layout and implement it on all pages, but make it only activate when necessary. But below you can take advantage of passing html to a helper (and use the HttpContext to cache the registrations) then output anything registered from any other view. I’ll show you the code:

  1. public static MvcHtmlString RegisterScript(this HtmlHelper htmlHelper, Func<Object, HelperResult> script)
  2. {
  3.   String scriptKey = String.Format("_JavaScript_{0}", Guid.NewGuid());
  4.   htmlHelper.ViewContext.HttpContext.Items.Add(scriptKey, script);
  5.   return MvcHtmlString.Empty;
  6. }
  7. public static MvcHtmlString RenderScripts(this HtmlHelper)
  8. {
  9.   foreach (var key in htmlHelper.ViewContext.HttpContext.Items.Keys)
  10.   {
  11.     if (key.ToString().StartsWith("_JavaScript_"))
  12.     {
  13.       Func<Object, HelperResult> helper = htmlHelper.ViewContext.HttpContext.Items[key] as Func<Object, HelperResult>;
  14.       if (helper != null)
  15.       {
  16.         htmlHelper.ViewContext.Writer.Write(helper(null));
  17.       }
  18.     }
  19.   }
  20. }

And then in a view you’d use something like:

  1. @Html.RegisterScript(
  2.   @<script type="text/javascript">
  3.     $(function(){
  4.       $('#someControl').somePlugin()
  5.     });
  6.   </script>
  7. )

And then back in your _Layout file:

  1. @Html.RenderScripts()

Flattr this!