Thursday, January 27, 2011

Adding MVC view file extension exclusion to T4MVC

Yesterday I wrote about creating razor view engine code behind files. I've been playing with the T4MVC T4 template for ASP.NET MVC that I learned about by watching this video.

Today I discovered that the view code behind files I created are showing up in the MVC.<controller>.Views list because the files (*.cs) are in the views folders next to the actual views (*.cshtml). Due to the naming convention I used, the *.cs file comes first in the directory listing. While the T4 template code gracefully deals with files with the same name portion of the full filename, the consequence of my names resulted in the generation of the following two properties:
MVC.Shared.Views.PlantListPager
MVC.Shared.Views.PlantListPager_cshtml

The first is the result of the code-behind file (PlantListPager.cs) while the second comes from the actual view (PlantListPager.cshtml). Again, the template gracefully deals with a potential name conflict. However, access to the code-behind path is not needed and the resulting extra property looks messy.

I looked through the T4MVC.settings.t4 file and found the ExcludedStaticFileExtensions array of extensions that excludes the specified file extensions from property generation for the files found in the static folders (as specified by the StaticFilesFolders array just above it in the settings). Unfortunately, I didn't find a similar array specifying exclusions for view folder(s)'s files. Presumably, this is because the view folders would typically not have anything other than actual view files. So I added the following block to the settings:
// View file extensions to exclude from the generated links   
readonly string[] ExcludedViewFileExtensions = new string[] {
".cs"
};

In the T4MVC.tt template file, I found the code that excludes the static files in the "ProcessStaticFilesRecursive" method after which I modeled the following block that I added to the "AddViewsRecursive" method:
if (ExcludedViewFileExtensions.Any(extension =>
item.Name.EndsWith(extension, StringComparison.OrdinalIgnoreCase)))
continue; // ignore defined extensions

This checks for extension exclusions when the list of views to create as properties is first built up.

Now I realize that I should probably just contribute this change back into the MvcContrib project. However, I'm going to cop out for the following reasons:

  • I don't have the infrastructure tools and knowledge required (Mercurial & NUnit)

  • I thought it would be valuable to illustrate how relatively simple it is to make a change to an existing T4 template without totally messing it up.


If there's a T4MVC contributor out there reading this who'd like to include this change, by all means, please do.

1 comment:

David Ebbo said...

Yes, I'll try to get this in the main template when I get some cycles.