16

I've been diving into ASP.NET MVC internal functionality much (different reasons), but still can not cover all the behaviour. One of those which I did not is subj.

The way it works is the following:

if I bundle some files (css files for instance), the framework detects those changes and generates new id for the new bundle (to make it easy for browsers to refresh the changes) like href="/Content/css?v=qartPE4jGe-l1U0I7kNDZPZzVTdh0kT8VBZZA_uURjI1".

What I am actually trying to understand:

  1. How exactly the framework (that's possibly not MVC but .NET stuff) detects that the files are changed (as there are no directory watchers active (as I can change the file even when web-server if off-line) to see the file changes live, and also the system detects actually the file content changes (I tried just to re-save files without changing their contents and the bundle number did not change as well))? (I consider that obviously the system can not compare every file content to detect its changings on every request came).

  2. Where (and how) the frameworks stores current bundle id and how it stores previous versions (as previous bundles are still available when go to their urls)?

Thanks a lot!

1
  • 1
    This site provides some insight into the bundle mechanism: dotnetexpertguide.com/2012/10/… As for your second question, it appears, by default, that a server cache is used. The bundle ID is a hash of the file contents, thus changes when you change contents. Old versions are not stored on the server and are no longer available. The URL would most likely still work (as it is just a query string used to make the browser realize it needs to download something new) but you would get the new content, not the old content. Commented Jan 23, 2014 at 17:37

1 Answer 1

14

The ASP.NET Optimization framework caches the bundle response in HttpContext.Cache and uses a CacheDependency to monitor each file in the bundle for changes. This is why updating the files directly invalidates the cache and regenerates the bundle.

The bundle file name is a hash of the bundle contents which ensures the URL changes when any of the bundle files are modified. The bundle's virtual path is used as the cache key.

The relevant code from the library (note this is slightly out of date but I believe the logic is still the same):

internal BundleResponse GetBundleResponse(BundleContext context)
{
    // check to see if the bundle response is in the cache
    BundleResponse bundleResponse = Bundle.CacheLookup(context);
    if (bundleResponse == null || context.EnableInstrumentation)
    {
        // if not, generate the bundle response and cache it
        bundleResponse = this.GenerateBundleResponse(context);
        if (context.UseServerCache)
        {
            this.UpdateCache(context, bundleResponse);
        }
    }
    return bundleResponse;
}

private void UpdateCache(BundleContext context, BundleResponse response)
{
    if (context.UseServerCache)
    {
        // create a list of all the file paths in the bundle
            List<string> list = new List<string>();
        list.AddRange(
            from f in response.Files
            select f.FullName);
        list.AddRange(context.CacheDependencyDirectories);
        string cacheKey = Bundle.GetCacheKey(context.BundleVirtualPath);
        // insert the response into the cache with a cache dependency that monitors
        // the bundle files for changes
        context.HttpContext.Cache.Insert(cacheKey, response, new CacheDependency(list.ToArray()));
        context.HttpContext.Response.AddCacheItemDependency(cacheKey);
        this._cacheKeys.Add(cacheKey);
    }
}

Finally as for old bundle URLs working, I think you will find they are either returned from your browser cache or actually return the latest version of the bundle since the bundle path doesn't change, only the version query string.

Sign up to request clarification or add additional context in comments.

8 Comments

Thank you for the answer. However, I am not sure I see exact answer to any of two parts of the question. 1. How exactly the does it detects related files changes? 2. Where (or how) the cache actually stores the values? (in case of several bundles (old and new ones) existence).
I've updated my answer but in short, the CacheDependency object monitors the files for changes and the bundle response is cached using the bundle virtual path as a key (only one entry for each bundle is stored so updating the bundle files removes the existing entry).
Yes, but the core question is how exactly does it monitor the files for changes? Is there any system watcher exists (I am doubting that, as what's about situation when the app is not running and the files changed)? Otherwise, how does it check the files modification? On every request?
Well, thank you for the answer, but it still sounds for me like: "It just uses caching". Well, I am sure it uses caching (this is how web (and many other) technologies work), but the point of my question was practical (not just some theoretical, which classes or modules the bundling ueses): it was to understand if the page rendering does checking for the files changes (from bundle ones) for every web-request? or not? and if not, then (curiously/theoretically) which exact way it monitors such changes?
I've provided answers to exactly what you have asked. If you want to understand the internals of CacheDependency and exactly how it monitors files then I suggest you post a different question. I suggest you read my answer through properly before drawing the conclusion of "it just uses caching".
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.