New ASP.NET Bundling Features - How can i programmatically refresh a certain bundle?
Asked Answered
B

2

14

I'm mucking around with the new ASP.NET bundling features (using the System.Web.Optmization 1.0.0-beta pre-release) in my ASP.NET MVC 3 web application.

Works great.

However, we have certain dynamic CSS/JS which is stored in the database.

I want to get this added to a seperate bundle for my core bundle, say "DynamicBundle". I know how to do that, not a problem.

Now my question is, when this CSS/JS is changed in the database, that bundle needs to be "refreshed" so that the content of those files are re-read in to the bundle.

Essentially, i need ASP.NET to re-generate that magic guid/string that is appended to the bundle URL.

Ideally, i'd only like to refresh a specific bundle, not the entire bundle table.

Is there a way to do this?

EDIT:

Okay second problem, can't figure out how to add the dynamic CSS/JS to the bundle. bundle.AddFile takes a virtual path to a file, but it's not a physical file, it's a string. How am i going to do this? Surely i don't have to write out string to files first?

EDIT 2: So i've decided not to bundle my dynamic content. For 2 reasons:

  1. It's only 1 file, so i'm not gaining any "bundling" benefits
  2. Bundling is designed for static content, this is not

So what i've done is manually minified my dynamic css/js at runtime (once, then cached). That way i can easily refresh it, by simply clearing the cache.

That being said, this is still a relevant question (refreshing bundles) so i'll leave it open..

Blacksnake answered 28/3, 2012 at 23:35 Comment(1)
Seems like a custom handler that spits out the dynamic JS / CSS might be better for you. This is how some other engines that generate JS at runtime work (for example, Ajax.NET Pro does this: ajaxpro.codeplex.com). You could alternately use a simple .aspx page that returns the dynamic content, and sets the cache headers to not cache so that the client requests it every time.Partial
K
5

That "that magic guid/string" is a hash of the combined file contents.

You can test this with the following workflow which assumes that you have a mybundle.css. If you use Fiddler to watch the traffic, you will see it request something with a hash like

http://localhost:20206/mybundle.css?v=-6520265193368900210

Now, "touch" one of the files in the bundle as much as you want without actually changing the contents. The file is newer (LastModified / LastWrite is more recent), but the hash remains constant as it is being computed from the same combined contents. You could even add spaces to the file since those would be minified out.

http://localhost:20206/mybundle.css?v=-6520265193368900210

Next, actually make a change. Perhaps set a border to 2px instead of 1px. The hash will change now, since the contents feeding the hash have changed.

http://localhost:20206/mybundle.css?v=-4725541136976015445

Finally, set the border back to what it was (in the above example, back to 1px). The "magic string" is actually not random or magic at all. Instead, it returns to the matching one-way hash computed from the contents.

http://localhost:20206/mybundle.css?v=-6520265193368900210

Now you can rest easy that the hash will update only when it is needed, without manual intervention.

As for the other part of your question,

when this CSS/JS is changed in the database, that bundle needs to be "refreshed" so that the content of those files are re-read in to the bundle.

I think we just reverse the thinking. Instead of refreshing the bundle to trigger a re-read, we update the files to trigger the refresh. When ASP.NET sees the file(s) change, it will recombine the contents and update the hash.

Kokoschka answered 3/4, 2012 at 21:11 Comment(5)
I know how to do this, but i asked how to do it programatically. Are you suggesting i "touch" the file in the actual application code? E.g StreamWriter stuff?Blacksnake
The point of my answer is that you don't need to do what you think you need to do...the string is not "magic". Whatever is included in the bundle, if it changes, the "magic string" will update based on those contents.Kokoschka
A touch is not enough, since you actually need to change the contents. You could use a StreamWriter to save out the changed contents from the db into physical files, in which case the hash will take care of itself.Kokoschka
fair enough. But i was hoping there was a built-in method to refresh the bundle. I guess part of the problem here is that the bundle works on physical files, and this is not a physical file, it's a string in the DB. And as i said in my EDIT, i can't bundle this file anyway. So yeah, it's kind of a moot point.Blacksnake
Yeah, I think I got into a mixed mode of answering the original question (notify ASP.NET that the DB string has changed) and the remaining general case (how would one refresh a bundle comprised of physical files). Ultimately I wanted this to be here for people in the future who might be wondering about where the hash comes from and what triggers the update.Kokoschka
L
3

I have good news for you. Many people have been asking for virtual path provider support for scenarios similar to yours, where they have content that's not necessarily from disk, so we currently are planning on supporting VPP in the next release.

To take advantage of this support, you will have to implement a VPP for your dynamic js/css.

VPP also has cache dependency mechanisms built in, so we should be able to use those to automatically flush the correct bundle cache entry for you.

Lucent answered 23/8, 2012 at 17:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.