Taming your .csproj File

If you work with Visual Studio, you’ve probably cursed your .csproj file at some point, especially if more than one person on your team is using the same .csproj file. I certainly have, but I’ve finally come to terms with this unruly beast, and today I’m going to share some of the things I’ve learned.

The .csproj file provides a partially synchronized view of your directory structure, rooted in the same directory as the .csproj file itself. I say partially synchronized because if you delete a file from the directory that’s referenced in the .csproj file, that reference does not go away (however, it will cause problems). Likewise, if you create a file somewhere, it will not automatically show up in your .csproj file. If you’re doing most of your content editing in Visual Studio, this usually does not present an obstacle: you add & delete your files from Visual Studio, and everything’s synchronized. Where this causes a problem is when you’re managing assets that are needed in your project outside of visual studio. A great example of this is image assets for a website: you’re probably not editing your images with Visual Studio (unless you’re a masochist). This rapidly became a problem with our team because the images folder in a website we were working on was very volatile, with the graphic designers creating, deleting, moving, and renaming image assets fairly frequently. Every time they pushed their work to the depot, an engineer would have to manually add each asset to the .csproj file through Visual Studio before they would be correctly deployed (similarly, deleted/moved/renamed assets would have to be removed). Fortunately, there is a way around this problem: you can do a wildcard include of assets in your project file. (I learned about this technique here.) For example, if you open your .csproj file, you’ll see something like this:

<ItemGroup>
    <Content Include="Content\Images\Picture-01.jpg" />
</ItemGroup>
<ItemGroup>
    <Content Include="Content\Images\Picture-02.jpg" />
</ItemGroup>
<!-- etc -->

Let’s say you always want to include all files in the Content\Images directory except for .gitignore files. All you have to do is replace all of those individual ItemGroup elements with one single one using a wildcard:

<Content Include="Content\Images\**\*.*" Exclude="Content\media\**\.gitignore" />

You might be wondering about the curious “**\*.*” wildcard. “**\” is a Microsoft wildcard convention that means “any subdirectory”. So, for example, *.* will match Image-01.jpg and Image-02.jpg, but not cats\Cat-01.jpg whereas **\*.* will.
You no longer have to worry about managing any images in that subdirectory in Visual Studio. As a matter of fact you must refrain from doing so. If you attempt to add, delete, include, or exclude any asset in this subdirectory through Visual Studio, it will remove your wildcard include and replace it with individual Content elements for each file. It’s not a total disaster, of course: you just have to re-edit the .csproj file, but it may be a while before you even notice this has happened.

It would be great if future versions of Visual Studio provided support for this.  For example, if you could mark folder in your project as “wildcard folders” that would be safe from the problems mentioned above, I think that would be a significant improvement.

Some of you are probably thinking that this sounds like a hassle, and why do things like image assets even need to be referenced in the .csproj.  The only snag with that argument is that it breaks Visual Studio’s new web deployment functionality, which will be the subject of an upcoming blog post.


No Comments on Taming your .csproj File

Comments on this entry are closed.