I have a controller action that returns Javascript file. I can reference this file from my view and it works fine. I'd like to put it in a System.Web.Optimization.Bundle with the other JS files.
I'm trying to do this, essentially:
new Bundle().Include("~/DynamicScript/UrlDictionary");
The other files in my Bundle get rendered just fine, but this one is ignored. Seeing this behavior, my assumption is that bundling gets handled before the application is able to resolve URLs through the routing infrastructure, or maybe that the bundling component doesn't request files in a manner that would allow that resolution to happen.
If someone could confirm that for me and/or point me in a good direction here, it would be much appreciated.
The other way of passing the data from Controller to View can be by passing an object of the model class to the View. Erase the code of ViewData and pass the object of model class in return view. Import the binding object of model class at the top of Index View and access the properties by @Model.
ViewData, ViewBag, and TempData are used to pass data between controller, action, and views. To pass data from the controller to view, either ViewData or ViewBag can be used. To pass data from one controller to another controller, TempData can be used.
EnableOptimizations = true if you want to see bundles in the debug mode. Now, to include the above bs-jq-bundle in your webpage, use Scripts. Render() method in the layout view, as shown below. Now, when you run the application in the release mode, you will see the bundle is created and loaded in a single request.
I think this is quite doable - but before I get into my solution - Remember that the bundle is created on the first hit and is reused - this means that any 'dynamic' script still has to be global (ie it cannot be dependant on a specific user etc). This is why generally it only allows static js files. Saying that... I could imagine a situation where you might want to stick variables like version number or something like that in your js (though in that case I personally would just use Ajax/JSON to get it).
I think the way to go about it is to create an derived type from Bundle. In it you would overwrite the EnumerateFiles method. Initially you would enumerate over the base.EnumerateFiles and then include your own virtual file.
Something like (Note: not tested code):
public class VirtualMethodBundle : Bundle
{
private List<VirtualFile> _virtualContent = new List<VirtualFile>();
public override IEnumerable<VirtualFile> EnumerateFiles(BundleContext context)
{
foreach(var file in base.EnumerateFiles(context))
{
yield return file;
}
foreach(var virtual in _virtualContent)
{
yield return virtual;
}
}
public void AddCustomFile(VirtualFile file)
{
_virtualContent.Add(method);
}
}
Then you would have a special VirtualFile defined type that overrides the Open/Name method and returns your dynamic content there... Something like.
public class MethodBasedVirtualFile : VirtualFile
{
private readonly Func<string> _contentFactory;
private readonly string _path;
public MethodBasedVirtualFile(string path, Func<string> contentFactory)
{
_path = path;
_contentFactory = contentFactory;
}
public override string Name { get { return _path; } }
public override Stream Open()
{
MemoryStream stream = new MemoryStream();
StreamWriter writer = new StreamWriter(stream);
writer.Write(_contentFactory());
writer.Flush();
stream.Position = 0;
return stream;
}
}
So then to use it all you would have...
var bundle = new VirtualMethodBundle();
bundle.Include(... real files ...);
bundle.AddCustomFile(
new MethodBasedVirtualFile("~/DynamicScript/UrlDictionary",
... the method that creates the content of that script...)
);
If you were clever you could just make a UrlVirtualFile that takes the url path and uses MVC to automatically get the content when required.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With