T4 templates error: loading the include file ef.utility.cs.ttinclude returned a null or empty string

Mark_Gibson picture Mark_Gibson · Nov 10, 2011 · Viewed 13.6k times · Source

I have overridden the controller generation T4 templates (ControllerWithContext.tt) as described here.
I would like to take advantage of the code helper utilities found in EF.utility.CS.ttinclude as used in the POCO model generator T4 template. Therefore I copied the following lines from my Model.tt to my ControllerWithContext.tt.

<#@ include file="EF.Utility.CS.ttinclude"#>

However, when I try to add a controller I am getting the error message

Loading the include file 'EF.utility.CS.ttinclude' returned a null or empty string

According to the MSDN documentation, this error is because the included file is blank, which it clearly isn't because it works with Model.tt

The only difference I can see is that the overridden ControllerWithContext.tt does not have a Custom Tool defined, whereas the Model.tt has it set to TextTemplatingFileGenerator.

My workaround is to copy the functions I need from ef.utility.cs.ttinclude into my ControllerWithContext.tt, which in itself threw up more errors but which were easily solved.

How can I include T4 templates without a custom tool defined?

Answer

Mark_Gibson picture Mark_Gibson · Nov 21, 2011

Following @DustinDavis' advice, and using the invaluable information found on OlegSych's site, here's what I did:

  • Created a new project called CodeGenerationTools.
  • Added project references to

    • System.Data.Entity.Design
    • EnvDTE
    • System.Data.Entity
    • Microsoft.VisualStudio.TextTemplating.10.0

    For this last reference I had to install the correct version of the Visual Studio SDK

  • Copied the EF.Utility.CS.ttinclude file into the project.
  • Renamed it CodeGenerationTools.cs
  • Edited the file and convert all <#@ import namespace="<name>" #> to using <name>;
  • Deleted the opening and closing <#+ #>
  • Added the directive using Microsoft.VisualStudio.TextTemplating;
  • Extended the class:

    public class CodeGenerationTools : TextTransformation
    
  • Override the TransformText method

    public override string TransformText() {
        throw new NotImplementedException();
    }
    
  • Added empty constructor

    public CodeGenerationTools() {
        _textTransformation = DynamicTextTransformation.Create(this);
        _code = new CSharpCodeProvider();
        _ef = new MetadataTools(_textTransformation);
        FullyQualifySystemTypes = false;
        CamelCaseFields = true;
    }
    
  • Finally, build this project.

The next steps took place in the main project - Edited the T4 template file. - Changed template directive to

    <#@ template language="C#" HostSpecific="True" debug="false" inherits="CodeGenerationTools"#>

- Added the directives

    <#@ assembly name="C:\Visual Studio 2010\Projects\CodeGenerationTools\CodeGenerationTools\bin\Debug\CodeGenerationTools.dll" #>
    <#@ import namespace="CodeGenerationTools" #>

All of which now means I can use the helper methods found in EF.Utility.CS.ttinclude in my own T4 templates, and I have the means to add my own helper methods which will be available to all projects.