Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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

This is impossible to detect when you work locally, because the files are present. But when you deploy through WebDeploy, files marked as "None" on Build Action are not packaged. As a result I get non-working application on the server.

Question: is there a way to automatically detect such occurrences and prevent?

like image 673
trailmax Avatar asked Jan 14 '15 23:01

trailmax


People also ask

What are Cshtml files used for?

What is a CSHTML file? A file with . cshtml extension is a C# HTML file that is used at server side by Razor Markup engine to render the webpage files to user's browser.


2 Answers

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

like image 136
jessehouwing Avatar answered Sep 29 '22 08:09

jessehouwing


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.

like image 34
Jacob Brewer Avatar answered Sep 29 '22 08:09

Jacob Brewer