Перезапись 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 здесь. И для веб-сервера нецелесообразно обслуживать файлы, которые постоянно меняются. Веб-серверы хороши в обслуживании статических файлов.
Теперь, если ваши [файлы] настолько динамичны, возможно, вам нужно будет обрабатывать их через серверную программу.
Поскольку вы упомянули в комментарии, что ваши конечные пользователи меняют файлы, я бы предложил сделать следующее, чтобы исключить вероятность конфликта блокировок:
- Используйте метод действия для обслуживания содержимого пакета.
- По умолчанию читайте файлы с диска.
- Когда конечный пользователь загружает функцию редактирования приложения, загружает содержимое из файла (файлов) в кэш. Ваш метод действия, который обслуживает контент, должен сначала проверить этот кеш, обслуживая его, если он доступен, и обслуживать файлы с диска, если нет.
- Когда конечный пользователь сохраняет содержимое, компилирует содержимое, записывает его на диск, а затем делает кэш недействительным. Если пользователь не сохранит данные, то время ожидания кеша просто истечет, и конечные пользователи снова прочитают файлы с диска.
См. Как я могу добавить результат действия контроллера ASP.NET MVC в Bundle? для некоторых потенциальных решений о том, как обслуживать пакет из метода действия. Я бы, вероятно, использовал решение, подобное этому (хотя стратегия кэширования могла бы быть другой).
В качестве альтернативы, вы можете сделать перезагрузку кеша каждый раз, когда он пуст в пользовательском запросе, и обновить как файлы, так и кеш во время операции "сохранить", что, вероятно, было бы проще и уменьшило бы вероятность проблемы с блокировкой файла до нуля, но не Масштаб также.
Когда одна страница отображается в браузере, оптимизатор обрабатывает связанные css и jqueries в кешировании. Таким образом, когда однажды страница была очищена, одна страница повторно запросит браузер, сначала проверит содержимое страницы в кэше, если его нет, то только вызов службы. Есть только два решения для вашего вопроса меньше или sss типа использования CSS.
- отключить связывание
- Less,coffeescript,scss & sass bundling