Category: Visual Studio

.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)

Attach macro

A visual studio macro to attach to a program to your choice:

Public Sub AttachPRogram()
        Try
            Dim dbg2 As EnvDTE80.Debugger2 = DTE.Debugger
            Dim trans As EnvDTE80.Transport = dbg2.Transports.Item("Default")
            Dim compName As String = System.Net.Dns.GetHostName()
            Dim procAll = dbg2.GetProcesses(trans, compName)
            For Each proc2 As Process2 In procAll
                If (proc2.Name.ToLower().Contains("your program name here")) Then

                    proc2.Attach()

                End If
            Next proc2

        Catch ex As System.Exception
            MsgBox(ex.Message)
        End Try
    End Sub