Кеширование ASP.NET MVC. (Обнаружение изменений файлов css) (внутреннее поведение)

Я много погружался в внутреннюю функциональность ASP.NET MVC (по разным причинам), но по-прежнему не могу охватить все поведение. Один из тех, что я не сделал, - subj.

Принцип работы:

если я связывает некоторые файлы (например, файлы css), фреймворк обнаруживает эти изменения и генерирует новый id для нового пакета ( чтобы браузеры могли обновлять изменения), например href= "/Content/css? v = qartPE4jGe-l1U0I7kNDZPZzVTdh0kT8VBZZA_uURjI1".

То, что я на самом деле пытаюсь понять:

  • Как именно структура (возможно, не MVC, но .NET) обнаруживает, что файлы изменены (поскольку активных наблюдателей нет (так как я могу изменить файл, даже если веб-сервер, если он отключен), чтобы увидеть изменения файла в реальном времени, а также система обнаруживает фактическое изменение содержимого файла (я пытался просто сохранить файлы без изменения их содержимого, а номер пакета также не изменился))? (Я считаю, что, очевидно, система не может сравнивать все содержимое файла, чтобы обнаружить его изменения в каждом запросе).

  • Где (и как) фреймворки хранят текущий идентификатор пакета и как он хранит предыдущие версии (поскольку предыдущие пакеты все еще доступны, когда идут на их URL-адреса)

Спасибо большое!

Ответы

Ответ 1

Рамка оптимизации ASP.NET кэширует ответ пакета в HttpContext.Cache и использует CacheDependency для мониторинга каждого файла в комплекте для изменений. Вот почему обновление файлов напрямую аннулирует кеш и регенерирует пакет.

Имя файла пакета является хешем содержимого пакета, который обеспечивает изменение URL-адреса при изменении любого из файлов пакета. Виртуальный путь связки используется как ключ кэш.

Соответствующий код из библиотеки (обратите внимание, что это немного устарело, но я считаю, что логика все та же):

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);
    }
}

Наконец, как и для старых URL-адресов пакетов, я думаю, вы обнаружите, что они либо возвращаются из кеша браузера, либо фактически возвращают последнюю версию пакета, поскольку путь пакета не изменяется, а только строка запроса версии.