How to Run T4MVC on Build

T4MVC is a very nifty little T4 template that generates some strongly typed helpers, to avoid fiddling with strings when referring to controllers, actions and views.

Its build using EnvDTE these days, so you don’t have to build your solution before running the template, which is nice.

There is however one slight little thing, that would make the experience complete: If it would run before build, so its always updated and we thereby avoid build errors due to errors in generated code.

Out of the box, this is nearly working due to the setting AlwaysKeepTemplateDirty, that sets the saved boolean to false, forcing the template to run. But this only works if the template has run once.

So when you open Visual Studio and change a MVC controller, you have the problem.

The only way i could figure out how to do this, was to use EnvDTE and add an eventhandler to the BuildEvents.OnBuildBegin event.

You push ALT+F11 to get to the Macro IDE, click EnvironmenEvents and add the eventhandler in the below code snippet . Make sure that its added outside the autogenerated code section.

Public Sub OnBuildBegin(ByVal Scope As EnvDTE.vsBuildScope, _
                        ByVal Action As EnvDTE.vsBuildAction) _
                        Handles BuildEvents.OnBuildBegin
 
    If Scope = vsBuildScope.vsBuildScopeSolution _
        Or Scope = vsBuildScope.vsBuildScopeProject Then
 
        Dim projectItem As ProjectItem _
            = DTE.Solution.FindProjectItem("T4MVC.tt")
 
        If Not projectItem Is Nothing Then
            If Not projectItem.IsOpen Then
                projectItem.Open()
            End If
            projectItem.Save()
        End If
 
    End If
End Sub

***UPDATE***: Encouraged by the comment by David Ebbo, I have modified the code a little so that it runs the custom tool directly instead of opening and saving the file. This is cleaner, but you have to reference the VSLangProj.dll, to use the VSProjectItem.

Public Sub OnBuildBegin(ByVal Scope As EnvDTE.vsBuildScope, _
                ByVal Action As EnvDTE.vsBuildAction) _
                Handles BuildEvents.OnBuildBegin
 
    If Scope = vsBuildScope.vsBuildScopeSolution _
        Or Scope = vsBuildScope.vsBuildScopeProject Then
 
        Dim projectItem As VSProjectItem _
            = DTE.Solution.FindProjectItem("T4MVC.tt").Object
 
        If Not projectItem Is Nothing Then
            projectItem.RunCustomTool()
        End If
 
    End If
End Sub

This obviously isn’t the perfect solution, as it is run for all solutions or projects that you build – not just MVC ones. But if you keep it while you primarily work on MVC projects with T4MVC, and then comment it out when not, you’ll be fine.

This could also be wrapped up in an Addin, so that you could turn it on and off via the Addin menu.

Remember to change the filename if you are using Rory Beckers VB version T4MVCVB.tt

Resources:

Posted March 11, 2010 by Joachim Lykke Andersen
In

Comments [8]