Убедитесь, что для всех файлов *.cshtml установлено значение "Содержимое" для действия сборки
Несколько раз, когда я копировал файлы *.cshtml
, Visual Studio по какой-то причине устанавливает Build Action
в эти файлы как "Нет":
![Comments.cshtml is set to be "None" on Build Action]()
Это невозможно обнаружить, когда вы работаете локально, потому что файлы присутствуют. Но при развертывании через WebDeploy файлы, помеченные как "Нет" в действии сборки, не упаковываются. В результате я получаю нерабочее приложение на сервере.
Вопрос: существует ли способ автоматического обнаружения таких случаев и предотвращения?
Ответы
Ответ 1
Вы можете расширить .csproj
небольшим фрагментом, который будет генерировать предупреждение, если элемент в группе "Нет" имеет расширение .cshtml
. Этот фрагмент будет выглядеть следующим образом:
<Target Name="EnsureContentOnViews" BeforeTargets="BeforeBuild">
<ItemGroup>
<Filtered Include="@(None)" Condition="'%(Extension)' == '.cshtml'" />
</ItemGroup>
<Warning
Condition="'@(Filtered)'!=''"
Code="CSHTML"
File="$(MSBuildProjectDirectory)\%(Filtered.Identity)"
Text="View is not set to [BuildAction:Content]"
/>
</Target>
Если вы видите другие действия сборки (например, EmbeddedResource
), вы можете добавить их в определение Filtered item.
Если вам требуется более продвинутое обнаружение, вам необходимо проанализировать файлы проекта для любого элемента, который подходит для этого Xpath //ItemGroup/*[not(self::Content)]/@Include
<Target Name="EnsureContentOnViewsXML" BeforeTargets="BeforeBuild">
<XmlPeek XmlInputPath="$(MSBuildProjectFile)" Namespaces="<Namespace Prefix='msb' Uri='schemas.microsoft.com/developer/msbuild/2003'/>"; Query="/msb:Project/msb:ItemGroup/*[not(self::msb:EmbeddedResource)]/@Include">
<Output TaskParameter="Result" ItemName="AllItems" />
</XmlPeek>
<!-- MsBuild uses XPath 1.0 which doesn't have the 'ends-with' or 'matches' function. -->
<ItemGroup>
<Filtered Include="@(AllItems)" Condition="'%(Extension)' == '.cshtml'" />
</ItemGroup>
<Warning
Code="CSHTML"
File="$(MSBuildProjectDirectory)\%(Filtered.Identity)"
Text="View is not set to [BuildAction:Content]"
Condition="'@(Filtered)'!=''"
/>
</Target>
Вместо <Warning ...>
вы также можете использовать <Error ...>
Вам нужно вручную поместить один из этих фрагментов в файл проекта:
![enter image description here]()
Ответ 2
Хорошо, @jessehouwing, безусловно, сработал у меня! Итак, это исправление прекрасно сохранилось в моем файле .csproj
:).... Только, я просто дважды проверял и выглядит так, как будто этот красивый снипп исчез где-то за последний месяц из-за слияния другого разработчика или чего-то еще.. ( истинная история)
Альтернатива NPM
В любом случае, я хотел бы упомянуть модуль NPM check-vs-includes, который я создал для этого. Особенно удобно для разработчиков, у которых Node установлен (и если вы этого не сделаете, то вам, вероятно, нужно:)).
Я запускаю проверку вручную перед каждым развертыванием, а не на каждой сборке. Но он вряд ли исчезнет (незаметно) из вашего .csproj файла из-за слияния.
Основным преимуществом использования этого пакета NPM является то, что помимо проверки для Build Action NONE он также проверяет файлы, которые НЕ включены в ваш проект. Потому что это может привести к (тонким, но противным) ошибкам при использовании Visual Studio Web Deploy. И отсутствие включений на самом деле довольно вероятно, если:
1) у вас есть 1 разработчик не VS в вашей команде, или
2) из-за слияния файла .csproj(который часто имеет проблемы слияния).
Обратитесь к странице NPM для получения инструкций. Но ниже простого примера, предполагающего, что вы используете Node и Gulp:
Простой пример
var checkVSIncludes = require('check-vs-includes');
...
gulp.task('checkVSIncludes', function() {
checkVSIncludes(['/Views/**/*.cshtml', '/app/**/*.js']);
});
- Запустите проверку в папке проекта (например, где находится ваш файл
.csproj
)
gulp checkVSIncludes
Ответ 3
Спасибо, что заработает! Мне понравилось ваше решение и проголосовали за него. У меня были небольшие проблемы с этим и в итоге было следующее:
<Target Name="EnsureContentOnViews" BeforeTargets="BeforeBuild">
<ItemGroup>
<Filtered Include="@(None)" Condition="'%(Extension)' == '.cshtml'" />
</ItemGroup>
<Error Condition="'@(Filtered)'!=''" Code="CSHTML" File="%(Filtered.Filename)" Text="Not set to [BuildAction:Content]: Identity: %(Filtered.Identity)" />
</Target>
Прямо перед тегом </Project>
в файле csproj.
Ответ 4
Я предлагаю выполнить задачу пользовательской сборки. Назовите его в prebuild в вашем msbuild/tfs script.
Задача пользовательской сборки должна просто проверять файл .scproj, если есть файл include cshtml с действием сборки none. Из этого просто выходим, возвращая ненулевое значение int.