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

后端 未结 4 1644
谎友^
谎友^ 2021-02-01 15:28

A few times when I copy-paste *.cshtml files, Visual Studio for some reason sets Build Action on these files to be \"None\":

相关标签:
4条回答
  • 2021-02-01 15:30

    I suggest to implement a custom build task. Call it on prebuild in your msbuild/tfs script. Custom build task should just check .scproj file if there is an include file of cshtml with build action none. Of so just exit returning a non zero int value.

    0 讨论(0)
  • 2021-02-01 15:35

    Well, @jessehouwing 's certainly worked for me! So that fix stays nicely in my .csproj file :).... Only, I just double-checked and it looks as if that nice snippet disappeared somewhere in the last month due to a merge of another developer or something.. (true story)

    NPM alternative

    Anyway, I would like to mention the NPM module check-vs-includes I created for this. It is especially convenient for dev's that have Node installed (and if you don't then you probably should :) ).

    I run the check manually before each deploy, instead of on every build. But it is less likely to disappear (unnoticed) from your .csproj file due to a merge.

    The main advantage however of using this NPM package, is that besides checking for Build Action NONE it also checks for files that are NOT included in your project at all. Because that can also lead to (subtle but nasty) bugs when you use Visual Studio's Web Deploy. And missing includes are actually pretty likely if: 1) you have 1 non VS developers in your team, or 2) due to merges of the .csproj file (which often has merge issues).

    Check the NPM page for instructions. But below a simple example, which assumes you use Node and Gulp:

    Simple example

    1. Install the Node module

      npm i check-vs-includes

    2. Add a task to your gulpfile.js:

         var checkVSIncludes = require('check-vs-includes');
    
         ...
    
         gulp.task('checkVSIncludes', function() {
            checkVSIncludes(['/Views/**/*.cshtml', '/app/**/*.js']);
         });
    
    1. Run the check in your project folder (e.g. where your .csproj file is)

      gulp checkVSIncludes

    0 讨论(0)
  • 2021-02-01 15:44

    Thank you jessehouwing for geting me started! I liked your solution and voted for it. I had a little trouble with it and ended up with the following:

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

    Right before my </Project> tag in the csproj file.

    0 讨论(0)
  • 2021-02-01 15:55

    You could extend the .csproj with a small snippet that will generate a warning when an item in the "None" group has the extension .cshtml. The snippet would be:

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

    If you see other build actions (like EmbeddedResource), you can add them to the Filtered item definition.

    If you want more advanced detection you need to actually parse the project files for any item that fits this 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>
    

    Instead of <Warning ...> you can also use <Error ...>

    You'll need to manually put one of these snippets in your project file:

    enter image description here

    0 讨论(0)
提交回复
热议问题