确保所有 *.cshtml 文件都设置为 "Content" 用于生成操作

Make sure all *.cshtml files are set to be "Content" for Build Action

有几次当我 copy-paste *.cshtml 文件时,Visual Studio 出于某种原因将这些文件的 Build Action 设置为 "None":

当您在本地工作时,这是不可能检测到的,因为文件存在。但是,当您通过 WebDeploy 进行部署时,不会打包在 Build Action 上标记为 "None" 的文件。结果我在服务器上得到 non-working 应用程序。

问题:有没有办法自动检测并防止此类事件的发生?

我建议实施自定义构建任务。在 msbuild/tfs 脚本中的预构建中调用它。 自定义构建任务应该只检查 .scproj 文件是否存在带有构建操作 none 的 cshtml 包含文件。所以只是退出返回一个非零的 int 值。

您可以使用一个小片段来扩展 .csproj,当 "None" 组中的项目具有扩展名 .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),您可以将它们添加到筛选项定义中。

如果您想要更高级的检测,您需要实际解析适合此 Xpath 的任何项目的项目文件 //ItemGroup/*[not(self::Content)]/@Include

<Target Name="EnsureContentOnViewsXML" BeforeTargets="BeforeBuild">
  <XmlPeek XmlInputPath="$(MSBuildProjectFile)" Namespaces="&lt;Namespace Prefix='msb' Uri='schemas.microsoft.com/developer/msbuild/2003'/&gt;"; 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 ...>

您需要手动将这些片段之一放入您的项目文件中:

嗯,@jessehouwing 确实对我有用!所以这个修复很好地保留在我的 .csproj 文件中 :)... 只是,我只是仔细检查了一下,看起来那个不错的片段在上个月的某个地方由于另一个开发人员的合并或其他原因而消失了。 .(真实故事)

NPM 替代方案

无论如何,我想提一下已安装的 NPM 模块 check-vs-includes I created for this. It is especially convenient for dev's that have Node(如果您没有安装,那么您可能应该:))。

我 运行 在每次部署之前手动检查,而不是在每次构建时检查。但由于合并,它不太可能从您的 .csproj 文件中消失(未被注意到)。

然而,使用此 NPM 包的主要优点是,除了检查生成操作 NONE 外,它还会检查根本不包含在您的项目中的文件。因为当您使用 Visual Studio 的 Web 部署时,这也会导致(微妙但令人讨厌的)错误。如果出现以下情况,实际上很可能会丢失包含: 1) 你的团队中有 1 名非 VS 开发人员,或者 2) 由于 .csproj 文件的合并(通常存在合并问题)。

查看 NPM 页面以获取说明。但下面是一个简单的例子,假设你使用 Node 和 Gulp:

简单的例子

  1. 安装节点模块

    npm i check-vs-includes

  2. 向您的gulpfile.js添加任务:

     var checkVSIncludes = require('check-vs-includes');

     ...

     gulp.task('checkVSIncludes', function() {
        checkVSIncludes(['/Views/**/*.cshtml', '/app/**/*.js']);
     });
  1. 运行 检查您的项目文件夹(例如,您的 .csproj 文件所在的位置)

    gulp checkVSIncludes

谢谢 jessehouwing 让我入门!我喜欢您的解决方案并投了赞成票。我遇到了一点麻烦,结果如下:

<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>

就在 csproj 文件中我的 </Project> 标记之前。