Category: .tt

.TT – add more informations(.NET version , build ) – part 6 of 7

As you can see from the previous chapter, we have added to the AssemblyDescription more informations – like .NET version, build configuration , and more

You can see those with an explorer add-on http://www.codeproject.com/Articles/118909/Windows-7-File-properties-Version-Tab-Shell-Extens

Video : http://youtu.be/A_qSdVV93qk

Demo project here : https://traceabilitydemo.codeplex.com/releases/view/132231

Source code here : https://traceabilitydemo.codeplex.com/SourceControl/changeset/view/110446

Traceability in .NET–.tt files–add changeset – part 5 of 7

We wish to add , from the .tt file , the id of the last TFS checkin. For this purpose we will connect to TFS and we will investigate in the current project the latest change.

We will use the facility of .tt file to connect to the host and ask for various features ( such as TFS )

The .tt file code is:

  

<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ assembly name="Microsoft.VisualStudio.Shell.Interop.8.0" #>
<#@ assembly name="EnvDTE" #>
<#@ assembly name="EnvDTE80" #>


<#@ assembly name="Microsoft.VisualStudio.TeamFoundation.VersionControl" #>
<#@ assembly name="Microsoft.TeamFoundation.Client"#>
<#@ assembly name="Microsoft.TeamFoundation.Common"#>
<#@ assembly name="Microsoft.TeamFoundation"#>
<#@ assembly name="Microsoft.TeamFoundation.WorkItemTracking.Client"#>
<#@ assembly name="Microsoft.TeamFoundation.VersionControl.Client"#>
<#@ assembly name="Microsoft.TeamFoundation.ProjectManagement"#>


<#@ import namespace="Microsoft.TeamFoundation.Client"#>
<#@ import namespace="Microsoft.TeamFoundation.VersionControl.Client"#>


<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Text.RegularExpressions" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="EnvDTE" #>
<#@ import namespace="EnvDTE80" #>
<#@ output extension=".cs" #>
<#
DTE dte=null;
var serviceProvider = Host as IServiceProvider;
    if (serviceProvider != null) {
        dte = serviceProvider.GetService(typeof(DTE)) as DTE;
    }
	if (dte == null) {
        throw new Exception("generate build number can only execute through the Visual Studio IDE");
		}
ProjectItem projectItem = dte.Solution.FindProjectItem(Host.TemplateFile);
int netVersion=0;

var proj=projectItem.ContainingProject;
var configmgr = proj.ConfigurationManager;
var config = configmgr.ActiveConfiguration;
string regex=@"^.+?Version=v(?<version>\-?\d+\.\d+).*?$";
var options = RegexOptions.Multiline;
string input= proj.Properties.Item("TargetFrameworkMoniker").Value.ToString();
	
MatchCollection matches = Regex.Matches(input,regex,options);
foreach (Match match in matches)
{
		
    netVersion = (int)(double.Parse(match.Groups["version"].Value)*100);
		
}


string filePath = proj.FullName;
string dirPath = System.IO.Path.GetDirectoryName(filePath);
var wsInfo = Microsoft.TeamFoundation.VersionControl.Client.Workstation.Current.GetLocalWorkspaceInfo(filePath );
 
 // Get the TeamProjectCollection and VersionControl server associated with the
 // WorkspaceInfo
 var tpc = new TfsTeamProjectCollection(wsInfo.ServerUri);
 var vcServer = tpc.GetService<VersionControlServer>();
 
 // Now get the actual Workspace OM object
 var ws = vcServer.GetWorkspace(wsInfo);
 
 // We are interested in the current version of the workspace
 var versionSpec = VersionSpec.Latest;
 
 var historyParams = new QueryHistoryParameters(dirPath, RecursionType.Full);
 historyParams.ItemVersion = versionSpec;
 historyParams.VersionEnd = versionSpec;
 historyParams.MaxResults = 1;
 
 var changeset = vcServer.QueryHistory(historyParams).FirstOrDefault();


 var dt = DateTime.Now;
var userName = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
userName = userName.Split('\\').Last();

 #>
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following 
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("BuildTraceabilityDemo")]
//http://www.codeproject.com/Articles/118909/Windows-7-File-properties-Version-Tab-Shell-Extens
[assembly: AssemblyDescription("BuildDate,<#=dt.ToString("yyyyMMdd_HHmmss")#>\r\n<#=proj.Properties.Item("TargetFrameworkMoniker").Value.ToString()#>\r\nBuild by,<#=userName#>\r\nConfig,<#=config.ConfigurationName#>,\r\nChangeset,<#=changeset.ChangesetId#>")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("BuildTraceabilityDemo")]
[assembly: AssemblyCopyright("Copyright ©  <#= dt.Year#>")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Setting ComVisible to false makes the types in this assembly not visible 
// to COM components.  If you need to access a type in this assembly from 
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("75ff7863-cb83-4d9b-80de-4a0de2781918")]

// Version information for an assembly consists of the following four values:
//
//      Major Version
//      Minor Version 
//      Build Number
//      Revision
//
// You can specify all the values or you can default the Build and Revision Numbers 
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.<#=dt.Year#>.<#=dt.Month#>.<#=dt.Day#>")]


   

Video : http://youtu.be/A_qSdVV93qk

Demo project here : https://traceabilitydemo.codeplex.com/releases/view/132231

Source code here : https://traceabilitydemo.codeplex.com/SourceControl/changeset/view/110446

Traceability in .NET–.tt files–add build date– part 4 of 7

Firstly we propose that build can automatically put the data in AssemblyVersion. For this you will need somehow to generate the current date.

We can do this in several ways – for example, a post build event. We will use a .tt file that will automatically generate this date. We will use for other things – for example, last checkin of TFS.

Running .tt files can be done either via command Build => Transform all T4 templates or in a before build event solution here . The solution is taken from http://stackoverflow.com/questions/1646580/get-visual-studio-to-run-a-t4-template-on-every-build – run in pre-build event the .tt file.

You can download demo project from here: https://traceabilitydemo.codeplex.com/releases/view/132229

Source code: https://traceabilitydemo.codeplex.com/SourceControl/changeset/view/110438

Video : https://www.youtube.com/watch?v=lZJ1NCIDejU

Next time we will add the TFS checkin id

.tt files to maintain assembly version in sync

Let’s suppose you have a medium-big application and you have several dll-assemblies-component that the main application references( DAL, BLL). You have several deployments of the application at clients and , when a client , you must find each version of each assembly deployed.

I have developed a simple .tt file to  ensure that every component that you compile have the same version – you can run on the server on the automatic build(http://www.olegsych.com/2010/04/understanding-t4-msbuild-integration/) or by hand.

More, with this .tt file you can

    1. Have the date /time ( with minute) of the compile of the dll embedded into version information
    2. Read a text file and add same copyright to all projects( left as an exercise to the user) .

 

You can see the demo at http://youtu.be/PudBWl16308 .

You can download the project at https://github.com/ignatandrei/AssemblyInfoTT

MVC Help View Razor

My passion for .tt files is great . T4MVC is the best example of what you can achieve with .tt files in MVC . 

Now, the problem: For each project you have a help file must be created. I mostly work with ASP.NET MVC projects – so I frequently have this problem.

I have then created a .tt file that generates summary help .cshtml Razor files for each View that you have in an ASP.NET MVC project.  This .t t file generates for you the folder structure (including Areas ) for having a view help file for each view that you have in the project.
More, if the help file already exists in the project, it will be not overwritten.

The template can be customized:
-the folder name:
//change here the location folder where the help files will be generated
static string HelperFolderName="Help";
-the content of the file
//change here the default content of the file
string TextFile = "<html><body>This is the help file for the view {0}</body></html>";

(For improvements please create an issue on github)
See demo at http://youtu.be/ZGsNHyFA9yw
You can download from https://github.com/ignatandrei/RazorHelpFile/ 

Use the help file with

<a href=’@Url.Content("~/Help/Views/Home/Index.cshtml")’ target="_blank">Index Help</a>

Enjoy!

.TT files and property names

This is the second post of http://msprogrammer.serviciipeweb.ro/2012/07/09/tt-files/

Now I will show how .tt files helps you for sorting .

In many WebInterfaces you do present to the user an array of items – a list – and the user can sort after various fields. Let’s make an example:

You have an EmployeeViewModel class that have FirstName, LastName and DepartmentName ( take note that is an EmployeeViewModel that must show to the user the Department name too – and is not the Employee class that have a reference to the table Employee).

Usually, for loading easily the EmployeeViewModel you do create a view in database with the same columns as the names of the properties (FirstName, LastName and DepartmentName)

Now, how you sort after FirstName, LastName and DepartmentName  WITHOUT hardcoding the strings ?( Why hardcoding is not good: the modification are not catch at compile time, but at runtime – and can be hidden)

.TT files to the rescue:

Starting of this class

 

public partial class EmployeeViewModel
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string DepartmentName { get; set; }
        
    }

I generate , with classFieldNames.tt , this:

 

public partial class EmployeeViewModel
						{
        public static FieldNames fieldNames= new FieldNames();
        public class FieldNames{
								
                public  string FirstName ="FirstName";
                public  string LastName ="LastName";
                public  string DepartmentName ="DepartmentName";
		}													
        }

And now in the code is that:

 

 var field = EmployeeViewModel.fieldNames.DepartmentName;
            Console.WriteLine(field);

this is the code for TT_FieldNames. Enjoy!

.TT files and logging

This post is a continuation of http://msprogrammer.serviciipeweb.ro/2012/07/09/tt-files/

In this post I will present a simple method to have logging methods that are called – and, if you want , you can log the values of parameters too!

Let’s say you have this code in the GUI project

ViewModelEmployeeCreate.SaveNew(emp);

and you want to log the SaveNew method – maybe to see in how much time it is executed, or to see how many times is called or simply log the method.

I will use Convention over Configuration. I will log every method that begins with _On . So I will transform the

public static void SaveNew (Employee emp)

into

public static void _OnSaveNew(Employee emp)

Then the classLogging.tt file will intercept the _On method and add this

public static void SaveNew (Employee emp)
								{
									System.Console.WriteLine(" before void _OnSaveNew (Employee emp)") ;
									try
									{
										TT_Repository.ViewModelEmployeeCreate._OnSaveNew(emp);
									}
									catch(System.Exception ex)
									{
										System.Console.WriteLine(" exception in void _OnSaveNew (Employee emp) " + ex.Message); 
										throw;
									}
									finally
									{
										System.Console.WriteLine(" after void _OnSaveNew (Employee emp)  " ); 
										
									}
								}

( you can add anything you like it – since the code is in .tt file )

So the output will be:

image

The code can be downloaded from here
and the interesting part is classLogging.tt from TT_Repository project.

Enjoy the .tt!

.TT files

I want to make a blog series about what you can do with .tt files. I do not mean now what cen be generated from edmx( I have blogged about that at

http://msprogrammer.serviciipeweb.ro/2010/09/27/generating-history-trigger-with-ef-edmx-and-tt-files/

and

http://msprogrammer.serviciipeweb.ro/2010/06/28/ef-automatic-history-of-table-and-t4-files-tt-files/

)

I will start from a .tt template that will be analyzing a class( the ViewModel in MVC terms ) and then, starting from this template, I will generate:

  1. Loading the class from config file( web / app)
  2. Generating resx files for translating
  3. Generating help / tooltip
  4. Generating logging for all methods ( with an _On convention)
  5. Generating shallow copy for the class, saving the properties and an Interface ( usually  good for DI / Ioc)
  6. Generating

I expect your suggestions too. What do you have iteratively do in your development( MVC Winking smile ) more than one time for each ViewModel ( Model) class ?

( this is the .tt file)

Generating history trigger with EF , edmx and TT files

I have wrote in an older post ( http://msprogrammer.serviciipeweb.ro/2010/06/28/ef-automatic-history-of-table-and-t4-files-tt-files/ ) how to generate history code for tables . The easy solution was to create a tt file that track for the ObjectContext the SaveChanges for each table that has a “history” in name. the limitation is that , when you raise an sql command such as “update table ” you must load from database a lot of rows for this….

Now I want to show the same thing, but generating triggers in database for that ! I start also from edmx file and with a template stealed from http://forums.asp.net/p/1599616/4083198.aspx ( to have type of fields in the database ) and another stealed and modified from StackOverflow(to generate trigger for after insert , update, delete) I manage to have a solution to generate sql tables and trigger code.

When is that good ?At the beginning stages of a project when the table structure changes by adding a new parameter.

Sample code generated for table Notes(ID, TextNote, PersonID)

print 'Create table Notes_History ';
Create Table Notes_History(
		ID_Notes_History BIGINT IDENTITY NOT NULL
		,History_Action varchar(50)
		,History_From varchar(100) default HOST_NAME()
		,History_User varchar(50) default SYSTEM_USER
		,History_Date varchar(50) default  getdate()
	   ,Id  int   NOT NULL
	   ,Textnote  nvarchar (255)  NULL
	   ,PersonId  int   NULL
	)
print 'end Create table Notes_History ';
GO
print 'create trigger for Notes'
GO
CREATE TRIGGER dbo.TR_IUP_Notes
   ON  Notes
   AFTER INSERT, UPDATE, DELETE
AS
BEGIN
    SET NOCOUNT ON;
	DECLARE @Ins int

DECLARE @Del int

SELECT @Ins = Count(*) FROM inserted

SELECT @Del = Count(*) FROM deleted
if(@Ins  + @Del = 0)
	return;

declare @operation varchar(50)
	set @operation ='update';
	if(@ins < @del)
		set @operation ='delete';
	if(@ins > @del)
		set @operation ='insert';

	if(@ins <= @del)
	begin
		INSERT INTO Notes_History(History_Action ,Id,Textnote,PersonId)
			select @operation ,Id,Textnote,PersonId from deleted
	end
    else
	begin
    INSERT INTO Notes_History(History_Action ,Id,Textnote,PersonId)
			select @operation ,Id,Textnote,PersonId from inserted
	end
END

The drawback of the code : the user that executes is not always the logged sql server user…
Anyway, what you have to do to use this automatically generated history/audit for tables ?

download historysql and modify

string inputFile = @”Model1.edmx”;

from historysql.tt to your edmx name. Then take the generated code and execute in sql server.

TT files – generate enum from database

Many times you will program against a table that contains something like an enum , like Status( open=1 , close=2, sent=3, approved=4 )  .

It is peculiar to wrote those status as text in the other tables – and you do not like also to have update their codes in the C# (VB.NET) code source each time you will add another one.

Rather , it is convenient to auto-generate from database at once.

But how to do it in Visual Studio ? The answer is .tt files – the files that generates also POCO

So here it is my own template for such enum from database .

To use ,unzip, add to your project that contains the edmx and do what is says below- and you will see as many  .cs file as tables want to put.

<#
//*********************************************************
//
//    NO Copyright .Use at your own risk.
//    Please modify :
//    1) the names of tables to generate enums : string nameforenum
//    2) the connection to the database : string connectionstring
//    3) the name of the model : string inputFile
//    Then save the file and you will have an enum …
//*********************************************************
#>

GenerateEnum