Перезапись ASP.NET MVC активного пакета стилей

У меня есть таблица стилей в моем приложении ~/Content/theme/style.css, На него ссылаются в моем приложении, используя стандартную комплектацию как таковую:

bundles.Add(new StyleBundle("~/Content/css").Include(
 "~/Content/font-awesome/font-awesome.css",
 "~/Content/theme/style.css"));

Теперь я использовал компилятор Sass (Libsass), чтобы позволить мне изменить вывод style.css файл в пользовательский файл вывода пользователя по мере необходимости.

Так что в основном я делаю что-то вроде этого.

CompilationResult compileResult = SassCompiler.CompileFile(Server.MapPath(Path.Combine(WebConfigSettings.RootSassPath, "style.scss"), options: new CompilationOptions {
    SourceMap = true,
    SourceMapFileUrls = true
});

и затем я сохраняю, как это.

string outputPath = Server.MapPath(WebConfigSettings.ThemeOutputPath);
if (System.IO.File.Exists(outputPath))
    System.IO.File.Copy(outputPath, string.Format("{0}.bak", outputPath), true);

System.IO.File.WriteAllText(Server.MapPath(WebConfigSettings.ThemeOutputPath), compileResult.CompiledContent);

Однако периодически я получаю следующую страшную ошибку доступа: "Процесс не может получить доступ к файлу C:....\style.css", потому что он используется другим процессом. " (Примечание: это происходит на File.WriteAllText линия)

Это не имеет смысла, потому что я не открываю потоки для файла и выполняю то, что я предполагаю, чтобы быть единственной атомарной операцией, используя File.WriteAllText,

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

Я предполагаю, что происходит одна из двух вещей.

Или:

а. Пакетный упаковщик каким-то образом блокирует файл, потому что он был изменен, в то время как он обновляет пакеты и не снимает блокировку или

б. Поскольку два разных соединения обращаются к файлу, каким-то образом между ними сохраняется блокировка.

Так кто-нибудь сталкивался с чем-нибудь подобным? Любые предложения о том, как я мог бы решить эту проблему?

PS: я пытался использовать HttpRuntime.UnloadAppDomain(); как хакерский способ попытаться снять любые блокировки на файле, но это, кажется, не помогает.

2 ответа

Решение

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

Опция 1

Записать на диск в цикле повтора и игнорировать это исключение. Файлы могут быть доступны для записи в течение очень короткого промежутка времени.

Вариант 2

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

Из этого ответа:

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

Теперь, если ваши [файлы] настолько динамичны, возможно, вам нужно будет обрабатывать их через серверную программу.

Поскольку вы упомянули в комментарии, что ваши конечные пользователи меняют файлы, я бы предложил сделать следующее, чтобы исключить вероятность конфликта блокировок:

  1. Используйте метод действия для обслуживания содержимого пакета.
  2. По умолчанию читайте файлы с диска.
  3. Когда конечный пользователь загружает функцию редактирования приложения, загружает содержимое из файла (файлов) в кэш. Ваш метод действия, который обслуживает контент, должен сначала проверить этот кеш, обслуживая его, если он доступен, и обслуживать файлы с диска, если нет.
  4. Когда конечный пользователь сохраняет содержимое, компилирует содержимое, записывает его на диск, а затем делает кэш недействительным. Если пользователь не сохранит данные, то время ожидания кеша просто истечет, и конечные пользователи снова прочитают файлы с диска.

См. Как я могу добавить результат действия контроллера ASP.NET MVC в Bundle? для некоторых потенциальных решений о том, как обслуживать пакет из метода действия. Я бы, вероятно, использовал решение, подобное этому (хотя стратегия кэширования могла бы быть другой).

В качестве альтернативы, вы можете сделать перезагрузку кеша каждый раз, когда он пуст в пользовательском запросе, и обновить как файлы, так и кеш во время операции "сохранить", что, вероятно, было бы проще и уменьшило бы вероятность проблемы с блокировкой файла до нуля, но не Масштаб также.

Когда одна страница отображается в браузере, оптимизатор обрабатывает связанные css и jqueries в кешировании. Таким образом, когда однажды страница была очищена, одна страница повторно запросит браузер, сначала проверит содержимое страницы в кэше, если его нет, то только вызов службы. Есть только два решения для вашего вопроса меньше или sss типа использования CSS.

  1. отключить связывание
  2. Less,coffeescript,scss & sass bundling
Другие вопросы по тегам