Skip to content

Instantly share code, notes, and snippets.

@vendettamit
Forked from jbogard/HtmlHelperExtensions.cs
Created December 22, 2015 15:28
Show Gist options
  • Save vendettamit/b9b0a8661e4169e3f567 to your computer and use it in GitHub Desktop.
Save vendettamit/b9b0a8661e4169e3f567 to your computer and use it in GitHub Desktop.
public static class HtmlHelperExtensions
{
private static readonly char Separator = '/';
private static readonly string TemplateFolder = HttpContext.Current.Server.MapPath("~/App/templates");
private static readonly IViewEngine ViewEngine = new HandlebarsRazorViewEngine();
public static MvcHtmlString RenderEmber(this HtmlHelper helper, string path = "", bool noTemplateName = false)
{
if (HttpRuntime.Cache[path] == null)
{
var builder = new StringBuilder();
string absolutePath;
string templateName = "";
if (string.IsNullOrEmpty(path))
{
absolutePath = TemplateFolder;
}
else
{
templateName = path.Replace("\\", Separator.ToString());
absolutePath = Path.Combine(TemplateFolder, path);
}
if (File.Exists(absolutePath))
{
int fileExtensionPosition = templateName.LastIndexOf('.');
if (fileExtensionPosition > 0)
{
templateName = templateName.Substring(0, fileExtensionPosition);
}
AppendFileTemplate(builder, helper, templateName, null, null, new FileInfo(absolutePath), noTemplateName);
HttpRuntime.Cache.Insert(path, new MvcHtmlString(builder.ToString()), new CacheDependency(absolutePath));
}
else
{
if (Directory.Exists(absolutePath))
{
if (templateName.Length > 0 && templateName[templateName.Length - 1] != Separator)
{
templateName += Separator;
}
List<string> dependencyList = new List<string>();
AppendDirectoryTemplates(builder, helper, templateName, "", new DirectoryInfo(absolutePath), dependencyList);
var result = new MvcHtmlString(builder.ToString());
HttpRuntime.Cache.Insert(path, result, new CacheDependency(dependencyList.ToArray()));
}
else
{
return new MvcHtmlString(""); //nothing is found, return empty string and do not cache
}
}
}
return HttpRuntime.Cache[path] as MvcHtmlString;
}
private static void AppendDirectoryTemplates(StringBuilder builder, HtmlHelper helper, string templateName, string relativeDirName, DirectoryInfo rootDirectory, List<string> dependencyList)
{
dependencyList.Add(rootDirectory.FullName);
var newSubRelativeDirName = relativeDirName;
if (!string.IsNullOrEmpty(newSubRelativeDirName))
{
newSubRelativeDirName = newSubRelativeDirName + Separator;
}
foreach (DirectoryInfo subDir in rootDirectory.GetDirectories())
{
AppendDirectoryTemplates(builder, helper, templateName, newSubRelativeDirName + subDir.Name, subDir, dependencyList);
}
foreach (FileInfo templateFile in rootDirectory.GetFiles("*.hbs"))
{
string subtemplateName = templateFile.Name;
int fileExtensionPosition = subtemplateName.LastIndexOf('.');
if (fileExtensionPosition > 0)
{
subtemplateName = subtemplateName.Substring(0, fileExtensionPosition);
}
if (relativeDirName.Length > 0 && relativeDirName[relativeDirName.Length - 1] != Separator)
{
relativeDirName += Separator;
}
AppendFileTemplate(builder, helper, templateName, relativeDirName, subtemplateName, templateFile);
}
}
private static void AppendFileTemplate(StringBuilder builder, HtmlHelper helper, string templateName, string relativeDirName, string subtemplateName, FileInfo templateFile, bool noTemplateName = false)
{
if (templateFile.Extension.ToLowerInvariant().StartsWith(".htm"))
{
//for .html/.htm* files, we'll simply append the content
var content = File.ReadAllText(Path.Combine(Path.Combine(templateName, relativeDirName), subtemplateName));
builder.Append(content);
return;
}
var fullTemplateName = templateName + relativeDirName + subtemplateName;
//for other template files, we treate them as x-handlebars script type
if (noTemplateName)
{
builder.AppendLine("<script type=\"text/x-handlebars\">");
}
else
{
builder.AppendLine("<script type=\"text/x-handlebars\" data-template-name=\"" + fullTemplateName + "\">");
}
var controllerContext = new ControllerContext(helper.ViewContext.HttpContext, new RouteData(), helper.ViewContext.Controller);
controllerContext.RouteData.Values["controller"] = string.IsNullOrEmpty(relativeDirName) ? "Home" : Path.GetDirectoryName(relativeDirName);
var result = ViewEngine.FindView(controllerContext, subtemplateName, null, false);
var stringWriter = new StringWriter(builder);
var viewContext = new ViewContext(controllerContext, result.View, new ViewDataDictionary(), new TempDataDictionary(), stringWriter);
result.View.Render(viewContext, stringWriter);
builder.AppendLine("</script>");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment