Web.Optimizations - any way to get all includes from a Style/Script Bundle? Web.Optimizations - any way to get all includes from a Style/Script Bundle? asp.net asp.net

Web.Optimizations - any way to get all includes from a Style/Script Bundle?


The Bundle class uses an internal items list that is not exposed to the application, and isn't necessarily accessible via reflection (I tried and couldn't get any contents). You can fetch some information about this using the BundleResolver class like so:

var cssBundle = new StyleBundle("~/bundle/css");cssBundle.Include(config.Source);// if your bundle is already in BundleTable.Bundles list, use that.  Otherwise...var collection = new BundleCollection();collection.Add(cssBundle)// get bundle contentsvar resolver = new BundleResolver(collection);List<string> cont = resolver.GetBundleContents("~/bundle/css").ToList();

If you just need a count then:

int count = resolver.GetBundleContents("~/bundle/css").Count();

Edit: using reflection

Apparently I did something wrong with my reflection test before.

This actually works:

using System.Reflection;using System.Web.Optimization;...int count = ((ItemRegistry)typeof(Bundle).GetProperty("Items", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(cssBundle, null)).Count;

You should probably add some safety checks there of course, and like a lot of reflection examples this violates the intended safety of the Items property, but it does work.


You can use the following extension methods for Bundle:

public static class BundleHelper{    private static Dictionary<Bundle, List<string>> bundleIncludes = new Dictionary<Bundle, List<string>>();    private static Dictionary<Bundle, List<string>> bundleFiles = new Dictionary<Bundle, List<string>>();    private static void EnumerateFiles(Bundle bundle, string virtualPath)    {        if (bundleIncludes.ContainsKey(bundle))            bundleIncludes[bundle].Add(virtualPath);        else            bundleIncludes.Add(bundle, new List<string> { virtualPath });        int i = virtualPath.LastIndexOf('/');        string path = HostingEnvironment.MapPath(virtualPath.Substring(0, i));        if (Directory.Exists(path))        {            string fileName = virtualPath.Substring(i + 1);            IEnumerable<string> fileList;            if (fileName.Contains("{version}"))            {                var re = new Regex(fileName.Replace(".", @"\.").Replace("{version}", @"(\d+(?:\.\d+){1,3})"));                fileName = fileName.Replace("{version}", "*");                fileList = Directory.EnumerateFiles(path, fileName).Where(file => re.IsMatch(file));            }            else // fileName may contain '*'                fileList = Directory.EnumerateFiles(path, fileName);            if (bundleFiles.ContainsKey(bundle))                bundleFiles[bundle].AddRange(fileList);            else                bundleFiles.Add(bundle, fileList.ToList());        }    }    public static Bundle Add(this Bundle bundle, params string[] virtualPaths)    {        foreach (string virtualPath in virtualPaths)            EnumerateFiles(bundle, virtualPath);        return bundle.Include(virtualPaths);    }    public static Bundle Add(this Bundle bundle, string virtualPath, params IItemTransform[] transforms)    {        EnumerateFiles(bundle, virtualPath);        return bundle.Include(virtualPath, transforms);    }    public static IEnumerable<string> EnumerateIncludes(this Bundle bundle)    {        return bundleIncludes[bundle];    }    public static IEnumerable<string> EnumerateFiles(this Bundle bundle)    {        return bundleFiles[bundle];    }}

Then simply replace your Include() calls with Add():

var bundle = new ScriptBundle("~/test")    .Add("~/Scripts/jquery/jquery-{version}.js")    .Add("~/Scripts/lib*")    .Add("~/Scripts/model.js")    );var includes = bundle.EnumerateIncludes();var files = bundle.EnumerateFiles();

If you are also using IncludeDirectory(), just complete the example by adding a respective AddDirectory() extension method.