4 Errors when trying to use T4 template (View) - visual-studio-2010

I am taking a look into T4 and scaffolding and I decided to give it a try. So I got the MvcScaffolding package on NuGet in order to customize a "Create" template in a test project.
After I have done very small changes (added css styles and translated the button texts) I decided to test my template by generating a View with my own "Create" scaffolding template.
Then I got the error bellow. I have checked the references on my project and everything seems there. Any ideas on how to fix this?
EDIT: I have just realized that some of my VS2010 AddOns were generating this error. Once disabled, it worked but my template wasn't used...

I was facing the same error and was able to solve it by directly pointing to the referenced libaries in my View template:
<## assembly name="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.ComponentModel.DataAnnotations.dll" #>
<## assembly name="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Core.dll" #>
<## assembly name="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Data.Entity.dll" #>
<## assembly name="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Data.Linq.dll" #>
The source of this issue was an extension installed -> tangible T4 Editor. After deinstalling my T4 templates started to work without complete paths.

Related

T4 can't reference own project's assembly

In T4, I simply want to reference my own project's assembly. As per instructions online I tried the following:
<## assembly name="$(TargetDir)" #>
followed by:
<## import namespace="LazyDeploy" #>
For your reference, here is my solution structure:
Other than the HTMLFactory namespace, everything is scoped to the LazyDeploy namespace. I also tried taking the template into the root of the solution to no avail. The error is as follows:
An exception was thrown while trying to compile the transformation code. The following Exception was thrown:
System.IO.FileNotFoundException: Could not find a part of the path 'c:\users\kmalton\documents\visual studio 2017\Projects\LazyDeploy\LazyDeploy\bin\Debug\'.
File name: 'c:\users\kmalton\documents\visual studio 2017\Projects\LazyDeploy\LazyDeploy\bin\Debug\' ---> System.IO.DirectoryNotFoundException: Could not find a part of the path 'c:\users\kmalton\documents\visual studio 2017\Projects\LazyDeploy\LazyDeploy\bin\Debug\'.
I am not sure why this is the case as the directory exists, i.e. I can cut and paste directly from the stack trace into explorer and navigate there.
The solution was to be reference the dll directly as part of the assembly declaration:
<## assembly name="$(TargetDir)LazyDeploy.dll" #>

Cannot debug T4 template in VS2017

In VS2017 Community, I cannot debug T4 Templates, which works in 2015.
I have a very basic template, such as this...
<## template debug="true" hostspecific="false" language="C#" #>
<## output extension=".txt" #>
<#
var a = "Hello";
var b = "World";
#>
<#=($"{a} {b}!")#>
Run Custom Tool and Transform All T4 Templates both options work, and text file contains expected output
Hello World!
If I put breakpoint somewhere and use Debug T4 Template from the context menu of .tt, it throws this error
Unable to start transformation run creation process.
However it works fine in VS 2015, and I'm able to debug there.
What I could be missing? how to debug T4 Templates in VS 2017? Note that I don't have any Tool/ Extension installed in VS2015 to debug T4
I have had the same issue, I don't know why it doesn't work this way but I have a work around.
Set debug to true, and add the diagnostic namespace
<## template language="C#" debug="true" #>
<## import namespace="System.Diagnostics" #>
In your T4 template write
Debugger.Launch();
Then run your template (easiest way it just to save it) and it will ask if you would like to debug in a new instance of visual studio.
The easiest solution is to just add these two lines to the top of your T4 template.
<## template debug="true" hostspecific="false" language="C#" #>
<# System.Diagnostics.Debugger.Launch(); #>
Then just run the template by saving the file and visual studio will prompt you to debug in a new instance.
If you use Host in your template and you get the error The name 'Host' does not exist in the current context then set `hostspecific="true"'.

How do I fix missing type/namespace errors in my Entity Framework 4.1 model template?

I have a T4 template to generate C# classes for the entities backing my .edmx model. The template starts with this header:
<## template language="C#" debug="false" hostspecific="true"#>
<## include file="EF.Utility.CS.ttinclude"#>
<## output extension=".cs"#>
Attempting to build the project results in these errors
error CS0234: The type or namespace name 'Design' does not exist in the namespace 'System.Data.Entity'...
error CS0246: The type or namespace name 'EnvDTE' could not be found (are you missing a using directive...
error CS0234: The type or namespace name 'VisualStudio' does not exist in the namespace 'Microsoft'...
How can I fix this?
It turns out than, based on a VS Extensibility thread, the reason for the problem was
the Clarius Visual T4 extension. It reset this node in the .csproj
file to
<Compile Include="SomeModel.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>SomeModel.cs</LastGenOutput>
</Compile>
from
<None Include="SomeModel.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>SomeModel.cs</LastGenOutput>
</None>
The solution is to manually change the node to None in the .csproj file. Changing it
back via the Visual Studio properties editor for the .tt file does not work.
Finally, disabling the extension prevents this from happening again.
Just simply add needed assemblies at the beginning of your .tt file; like this:
<## template language="C#" debug="false" hostspecific="true"#>
<## assembly name="System.Data.Entity" #>
<## assembly name="System.Data.Entity.Design" #>
...

How to open a file on relative path using T4?

I'm trying to run a T4 template that opens a XML file and uses it contents to generate a code artifact. However, I'm getting the an error message when I try to run a T4 template similar to the one below
<## template debug="false" hostspecific="false" language="C#" #>
<## assembly name="System.Xml.dll" #>
<## assembly name="System.Xml.Linq.dll" #>
<## import namespace="System.IO" #>
<## import namespace="System.Xml" #>
<## import namespace="System.Xml.Linq" #>
<## output extension=".cs" #>
namespace ConsoleApplication1
{
<# XElement fragment = XElement.Load("data.xml"); #>
...
Visual Studio 2010 error list is showing the following message
Running transformation: System.IO.FileNotFoundException: Could not find file 'C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\data.xml'.
It is trying to open the file on the path where the TextTemplateFileGenerator custom tool runs. I'd like it to open the file relative to my project path, because other developers on my team use different folder structures. Does anyone know if it is something possible to accomplish?
Change hostspecific option in template directive to "true" and call Host.ResolvePath("data.xml").
I had a similar problem but Host.ResolvePath didn't work for me because my relative path contained "..\.." in it. I worked around it by doing this:
string ttpath = this.Host.TemplateFile;
string resolvedPath = Path.GetFullPath(Path.GetDirectoryName(ttpath) + #"..\..\<Path To File>");

Get Project or Relative Directory with T4

How can I get a reference to the directory of the visual studio project or solution or the directory of the t4 template from within a t4 template?
I have a template that concatenates a number of files together which are located relative to the template. I need to get a reference to there absolute location through a relative means. Hard coding an absolute path is not acceptable because the visual studio project will not always be in the same location and this would break the code generation. Reading the current working directory from the environment doesn't work either because that returns the location of where the T4 engine lives not the template. I'm just getting in to t4 so any help would be appreciated.
See The Host Specific Parameter section HERE.
This snippet shows how to get the full path of src relative to the template.
<## template hostspecific="true" #>
// The location of the src folder relative to the t4 template:
// <#= Host.ResolvePath("src") #>
You can grab the path like this aswell
<## template hostspecific="true" #>
<#= Path.GetDirectoryName(this.Host.TemplateFile) #>

Resources