Targets that should be in you ASP.Net MVC *.csproj file

As far as I know next version of ASP.Net is going to abandon MSBuild and build projects differently. Can’t wait for this to happen!

But for now we are still stuck with horribleness of XML and MSBuild (did I tell you I hate MSBUILD with passion?).

When I start a new MVC project, I add extra bits of MSBuild script into *.csproj file.

Missing Content files

First element is to fail a build if some of *.js or *.css files are missing from the project folder. This happened before – somebody in a team forgets to check-in a new file site.css – build server is silent for this matter. Only until somebody gets latest version of the project, builds, looks on it in a web-browser and notices that styles are not right, then the digging starts happening.

So here is the snippet to add to your project:

<Target Name="ValidateContentFiles">
    <Error Condition="!Exists(%(Content.FullPath))" Text="Missing Content file [%(Content.FullPath)]" />

Simples – issue error if some of the “Content” files not on the hard-drive.

*.cshtml files marked as “None” for Build Action

This happened to me a few times now: to create a new view you copy-paste existing file, rename the file and change the internals. This is much faster than having to ask Visual Studio to create a new View file for you. The problem starts that sometimes files created this way are marked as “None” in Build Action (Right click on the file, Properties -> Build Action). This is very subtle change and not discoverable on development stage. But when you deploy the application to a server, files marked as None are not packed into the package. And your server now missing these view files. And only when somebody navigates to that missing page – that’s when you get a nasty exception in your face (hopefully your face, not your customer’s).

To avoid this Stackoverflow actually provided me very good answer (for a change).
So to fail a build on *.cshtml file being marked as None, add this snippet to your .csproj file

<Target Name="EnsureContentOnViews" BeforeTargets="BeforeBuild">
        <Filtered Include="@(None)" Condition="'%(Extension)' == '.cshtml'" />
    <Error Condition="'@(Filtered)'!=''" Code="CSHTML" File="$(MSBuildProjectDirectory)\%(Filtered.Identity)" Text="View is not set to [BuildAction:Content]" />

I wish these were the default settings in the project template.

Can’t find the valid AspnetCompilerPath

A note to myself, next time I try to do view compilation in msbulid and see exception

Can’t find the valid AspnetCompilerPath

I should either install VS2013 on my build server. Or choose a different version of msbuild.exe:
C:\Program Files (x86)\MSBuild\12.0\Bin\msbuild.exe.

The problem is caused by version mis-match. New msbuild is part of Visual Studio 2013 and not part of .Net framework itself. And by default your PATH variable points to .Net folders where older msbuild is found. So you in your scripts you need to explicitly specify what msbuild you need to use.