HtmlTemplateBase<> For the RazorEngine on CodePlex

The RazorEngine project on CodePlex is a powerful Templating library that utilizes the Razor Syntax. If you are trying to use this library and wondering where is the HtmlTemplateBase<> as it is shown on the project's page, it does not really exist! That code snippet on RazorEngine's home page is an example of what you could possibly do with that library.

There is a thread on the project's discussion board where this is being discussed. Apparently no one had time to put it together.

So I wrote a version of my own HtmlTemplateBase<> that supports the Html Helper and ViewBag. You should be able to add Ajax Helper if you need it. I won't go into much details, as the code should be self explanatory. I am not saying this is the best way to do it, but it works.

Some people commented that it does not work in Winform. This is not intended for Winform context. I do not need it in Winform at the moment and haven't looked into an implementation that would work outside of HttpContext/WebPageContext. Sorry!

HtmlTemplateBase<>

/*** HtmlTemplateBase<> ***/
/*** Author: Abu Haider 
/*** September, 2011
/*** To be used as the Template base with the RazorEngine on CodePlex
/*** http://razorengine.codeplex.com
/*** Copyright 2011, Abu Haider, www.haiders.net
/*** Use at your own risk
/***/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using RazorEngine;
using RazorEngine.Templating;
using System.Web.Mvc;
using System.Web.WebPages;

namespace System.Web.Mvc
{
    [RequireNamespaces("System.Web.Mvc.Html")]
    public class HtmlTemplateBase:TemplateBase, IViewDataContainer
    {
        private HtmlHelper helper = null;
        private ViewDataDictionary viewdata = null;
        private System.Dynamic.DynamicObject viewbag = null;
        
        public dynamic ViewBag
        {
            get
            {
                return (WebPageContext.Current.Page as WebViewPage).ViewBag;
            }
        }

        public HtmlHelper Html
        {
            get
            {
                if (helper == null) 
                {
                    var p = WebPageContext.Current;
                    var wvp = p.Page as WebViewPage;
                    var context = wvp != null ? wvp.ViewContext : null;
    
                    helper = new HtmlHelper(context, this);
                }
                return helper;
            }
        }

        public ViewDataDictionary ViewData
        {
            get
            {
                if (viewbag == null)
                {
                    var p = WebPageContext.Current;
                    var viewcontainer = p.Page as IViewDataContainer;
                    viewdata = new ViewDataDictionary(viewcontainer.ViewData);

                    if (this.Model != null)
                    {
                        viewdata.Model = Model;
                    }

                }

                return viewdata;
            }
            set
            {
                viewdata = value;
            }
        }
    }

}

Using the HtmlTemplateBase<>

Make sure this class is part of your Web/MVC Project. It will work in the context of a WebPages (MVC) only, unless you tweak it a little to work on WebForms. It's fairly simple to use this as the Template base class. Before parsing any Template, use this single line of code:

    RazorEngine.Razor.SetTemplateBase(typeof(HtmlTemplateBase<>));

Notes

  1. This will not work in Winform context, because it uses the current WebPageContext for some of the functionality.
  2. This will add support for Html.EditorFor<>(), Html.EditorForModel<>() etc. within your Template.
  3. The Html Helper in your template will use the Model and Model Type that you use for the Template, not the Model Type of the Webpage it is being parsed in. Of course they can be the same. Much like the Html.Partial() helper method.
  4. The ViewBag will have all items added at the Page level prior to parsing the Template. You can set ViewBag items within your Template and they will be available at the Page level once you parse/execute the Template. However, if you set an item using ViewData["..."] = Value within your Template, it will not be available with ViewBag.ItemKey, within your Template, or outside the Template.

Hopefully this code will be enough to get you started on this.

Posted on September 29, 2011 03:33 by Haider

Comments

December 11. 2011 05:03

Maloric

Great work with the template.  I'm so tantalisingly close to getting it working but am getting an exception because WebPageContext.Current is null.  I have tried a few different methods to get around this but have come across other problems in doing so.  Have you had the above solution working on the final release of MVC3?  I noticed some of the classes have changed since the beta.

Maloric