Skip to content

Instantly share code, notes, and snippets.

@ismaelhamed
Created July 11, 2014 11:20
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ismaelhamed/307a9fc1025082f19574 to your computer and use it in GitHub Desktop.
Save ismaelhamed/307a9fc1025082f19574 to your computer and use it in GitHub Desktop.
Bundling AngularJS Templates with ASP.NET MVC
using System.Web.Optimization;
namespace NgTemplateBundling
{
using NgTemplateBundling.Bundling;
public class BundleConfig
{
public static void RegisterBundles(BundleCollection bundles)
{
// other bundles omitted
var ngTemplateBundle = new NgTemplateBundle("~/js/ng-templates");
ngTemplateBundle.IncludeDirectory("~/templates", "*.tpl.html", true);
ngTemplateBundle.Module = "myApp.Templates";
bundles.Add(ngTemplateBundle);
}
}
}
using System.Web.Optimization;
namespace NgTemplateBundling.Bundling
{
/// <summary>
/// Represents a bundle that does AngularJS Template minification.
/// </summary>
public class NgTemplateBundle : Bundle
{
/// <summary>
/// Name of the angular.module to register the templates with. Default is 'myApp'.
/// </summary>
public string Module { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="T:System.Web.Optimization.Bundle" /> class that takes a virtual path for the bundle.
/// </summary>
/// <param name="virtualPath">The virtual path for the bundle.</param>
public NgTemplateBundle(string virtualPath)
: this(virtualPath, null)
{ }
/// <summary>
/// Initializes a new instance of the <see cref="T:System.Web.Optimization.Bundle" /> class that takes virtual path and cdnPath for the bundle.
/// </summary>
/// <param name="virtualPath">The virtual path for the bundle.</param>
/// <param name="cdnPath">The path of a Content Delivery Network (CDN).</param>
public NgTemplateBundle(string virtualPath, string cdnPath)
: base(virtualPath, cdnPath, new IBundleTransform[] { new NgTemplateTransform() })
{
Module = "myApp";
}
}
}
using System.IO;
using System.Linq;
using System.Text;
using System.Web.Optimization;
namespace NgTemplateBundling.Bundling
{
/// <summary>
/// Represents a <see cref="T:System.Web.Optimization.IBundleTransform" /> that automatically combines your AngularJS templates.
/// </summary>
public class NgTemplateTransform : IBundleTransform
{
internal static string ContentType;
internal readonly static NgTemplateTransform Instance;
static NgTemplateTransform()
{
NgTemplateTransform.ContentType = "text/javascript";
NgTemplateTransform.Instance = new NgTemplateTransform();
}
/// <summary>
/// Transforms the content in the <see cref="T:System.Web.Optimization.BundleResponse"/> object.
/// </summary>
/// <param name="context">The bundle context.</param>
/// <param name="response">The bundle response.</param>
public void Process(BundleContext context, BundleResponse response)
{
var bundle = context.BundleCollection.FirstOrDefault(b => b.Path == context.BundleVirtualPath) as NgTemplateBundle;
if (bundle == null)
return;
var builder = new StringBuilder();
builder.AppendFormat("angular.module('{0}')", bundle.Module);
builder.AppendLine(".run(['$templateCache', function($templateCache) {");
foreach (var file in response.Files.Select(bundleFile => bundleFile.VirtualFile).Where(file => !file.IsDirectory))
{
using (var reader = new StreamReader(file.Open()))
{
var ngTemplate = string.Format("$templateCache.put('{0}', '{1}');", file.VirtualPath, reader.ReadToEnd().Trim());
builder.AppendLine(ngTemplate);
}
}
builder.AppendLine("}]);");
response.Content = builder.ToString();
response.ContentType = NgTemplateTransform.ContentType;
}
}
}
@bjornhol
Copy link

Hi,

Do you have an example using this?

Thanks

Bjørn Harald

@azurelogic
Copy link

Really useful. I fused this with some ideas from here: http://blog.scottlogic.com/2014/08/18/asp-angular-optimisation.html. Specifically, he passes the module name in as a parameter, escapes all of the single quotes, and removes newlines.

    public class AngularTemplateBundleTransform : IBundleTransform
    {
        private readonly string _moduleName;

        public AngularTemplateBundleTransform(string moduleName)
        {
            _moduleName = moduleName;
        }

        public void Process(BundleContext context, BundleResponse response)
        {
            var builder = new StringBuilder();
            builder.AppendFormat("angular.module('{0}')", _moduleName);
            builder.AppendLine(".run(['$templateCache', function($templateCache) {");

            foreach (var file in response.Files.Select(bundleFile => bundleFile.VirtualFile).Where(file => !file.IsDirectory))
            {
                using (var reader = new StreamReader(file.Open()))
                {
                    var ngTemplate = string.Format("$templateCache.put('{0}', '{1}');", file.VirtualPath, reader.ReadToEnd().Trim().Replace("'", "\\'"));
                    builder.AppendLine(ngTemplate);
                }
            }

            builder.AppendLine("}]);");

            response.Content = builder.ToString();
            response.ContentType = "text/javascript";
        }
    }

@praneeth4victory
Copy link

@azurelogic Do you have any working example for this,

I have implemented the same but i am getting "unexpected Token <" for every html file in my solution.

Thanks In Advance

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment