A few times when I copy-paste *.cshtml
files, Visual Studio for some reason sets Build Action
on these files to be "None":
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?
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.
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="<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>
Instead of <Warning ...>
you can also use <Error ...>
You'll need to manually put one of these snippets in your project file:
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With