How to create an adapter for the TFS Integration Platform - Part I: Introduction
Note: This post is part of a series and you can find the rest of the parts in the series index.
Since September 2009 I have been engaged in a ALM Rangers project, namely the TFS Integration Platform. Which is:
The TFS Integration Platform is a project developed by the Team Foundation Server (TFS) product group and the Visual Studio ALM Rangers to facilitate the development of tools that integrate TFS with other systems. Currently, the scope of this project is to enable TFS to integrate with other version control and work-item/bug tracking systems, but the eventual goal of this project is to enable integration with a broader range of tools/systems (i.e. build). This platform enables the development of two major classifications of tools: tools that move data unidirectionally into TFS, and tools that synchronize data bidirectionally.
So in short it is a integration system, like BizTalk or SSIS but specially built for version control and work items. I have not said TFS there because, it can work to migrate between other source control and work item systems provided adapters exist. Adapters are the logic which allows the TFS platform to connect to a variety of technologies, and my goal has been to build two of them – one for SharePoint lists and one for SharePoint document libraries.
You may have noticed that SharePoint isn’t a version control or work item system, so why integrate? Well lots of companies do use it for ALM related items, such as the lists being used for tracking work items and the document libraries are used to store content which should be in a source control system. This is the first post in a series which will give you an idea of what is involved in building adapters, show you what to avoid and hopefully give you a few laughs at my expense.
Now I want to be clear this series will not covering usage of the platform or any of the core concepts in it. For those please see the links below in particular Willy-Peter’s blog. You do need to understand a bit about how the platform works before you attempt to build your own adapter.
As all my work was done for the ALM Rangers the source code for my adapters is included in the code which can be obtained from the CodePlex site.
To help you on your way let’s list a few links which are key for this:
- MSDN home page: http://msdn.microsoft.com/en-us/vstudio/bb840033.aspx
- CodePlex Project home page: http://tfsintegration.codeplex.com
- Willy-Peter Schaub’s blog: http://blogs.msdn.com/willy-peter_schaub/
- MSDN Forums for the Platform: http://social.msdn.microsoft.com/Forums/en-US/tfsintegration
How to create an adapter for the TFS Integration Platform – Series Index
This page provides an index of all the parts in the series. Parts which are not linked yet, indicate that they are still coming and you should subscribe to my RSS feed to get notified as soon as they are published.
- Part I: Introduction
- Part II: Setup of the environment
- Part III: Overview of adapters
- Part IV: IProvider
- Part V: Items (IMigrationItem & IMigrationItemSerializer)
- Part VI: IAnalysisProvider
- Part VII: WIT Conflict Handling
- Part VIII: IMigrationProvider
- Part IX: IServerPathTranslationService
- Part X: Reflection on SharePoint
- Appendix 1: Power Tips
- Appendix 2: SimpleDictionary
.NET 4 Baby Steps: Part XIII - Tiny steps
Note: This post is part of a series and you can find the rest of the parts in the series index.
There is a bunch of tiny additions in .NET 4 which I have not covered yet, this post provides a quick hit list of some of the new and improved features:
New
- StringBuilder.Clear: Quick method to clear a string builder.
- StopWatch.Reset: Quick method to reset a stop watch timer.
- IntPtr & UIntPtr: Both have had two new methods added, one for addition and one for subtraction.
- Thread.Yield: Allows you to yield execution to another thread that is ready to run on the current processor.
- System.Guid: Has got two new methods, TryParse and TryParseExact to allow for testing of the parsing.
- Microsoft.Win32.RegistryView: This allows you to request 64bit or 32bit views of the registry.
- Environment: Now contains two properties to identify 64bit scenarios:
- Is64BitOperatingSystem: To identify if the OS is 64bit.
- Is64BitProcess: To identify if the process is 64bit.
- System.Net.Mail.SmtpClient: Support for SSL
Improved
- Path.Combine: A new method overload to allow you to combine file paths.
- Compression.DeflateStream & Compression.GZipSteam: They have been improved so that they so no try to compress already compressed data.
- Compression.DeflateStream & Compression.GZipSteam: The 4Gb size limit has been removed.
- Monitor.Enter: A new overload has been added which allows you to pass in a reference boolean which returns true of the monitor was successfully entered.
- Microsoft.Win32.RegistryOptions: Now includes an option to specify a volatile key which is removed when the system restarts.
- Registry keys are no longer limited to 255 characters.
- System.Net.Mail.MaiMessage: Support for new headers
- HeadersEncoding: Sets the type of text encoding used in the mail header.
- ReplyToList: Sets the list of addresses to use when replying to a mail. This replaces ReplyTo which only supported one email address.
- System.Net.NetworkCredential: To improve security passwords can now be stored in a SecureString.
- ASP.NET Hashing: The default value has been changed from SHA1 to SHA256.
- ASP.NET Output caching: Previously setting the output cache to ServerAndClient also required calling SetOmitVaryStar to ensure it would be cached on the client. From .NET 4, calling of SetOmitVaryStar is no longer needed.
- TimeZoneInfo.Local & DateTime.Now: Both of these follow the OS daylight savings settings rather than using the .NET Framework settings.
- When running on Windows 7, locale info will be retrieved from the OS rather than being stored in the framework.
- Support for all 1400 characters of Unicode 5.1.
- ServiceInstaller.DelayedAutoStart: If you on a more modern OS (Vista, Win 7 etc…) then you can services can start as Automatic Delayed. This means they start, but after system boot so that the user gets in quickly. This is now possible for your .NET apps using the DelayedAutoStart property.
.NET 4 Baby Steps: Part XII - Numbers
Note: This post is part of a series and you can find the rest of the parts in the series index.
A new namespace has arrived in .NET 4 for those who spend a lot of time with numbers, System.Numerics which has two classes: BigInteger and Complex – and they are exactly what they say they are. BigInteger is for big integers and Complex is complicated ;)
BigInteger
BigInteger is a class, not a type (like float), which allows you to have an integer with no theoretical upper and lower limits! Why is that cool? think about Int64 which can do up to: 9,223,372,036,854,775,807. If you have an Int64 which has that massive value, and you add one to it, the Int64 it overflows and becomes -9,223,372,036,854,775,806. That is not possible with BigInt since it has no upper limit!
Being a class means it has methods and properties you can use too, for example some of the properties
- IsZero: Tells you if it equals zero.
- IsEven: Tells you if it is an even number.
An example of using it:
BigInteger firstBigInt = new BigInteger(Int64.MaxValue); BigInteger secondBigInt = new BigInteger(Int64.MaxValue); Console.WriteLine("First BigInt is even? {0}", firstBigInt.IsEven); Console.WriteLine("First BigInt = 1? {0}", firstBigInt.IsOne); Console.WriteLine("First BigInt is power of twp? {0}", firstBigInt.IsPowerOfTwo); Console.WriteLine("First BigInt = 0? {0}", firstBigInt.IsZero); Console.WriteLine("First BigInt is positive (1), zero (0), or negative (-1)? {0}", firstBigInt.Sign); Console.WriteLine("{0} multipled by {0} is {1}", Int64.MaxValue, BigInteger.Multiply(firstBigInt, secondBigInt));
You can also use the standard operators (-, +, * etc…) with it.
This gives the following output (look at the size of the number from the multiplication!):
BigRational
What if you want to work with rational numbers with no limits, rather than integers? Then you can use the BigRational class the BCL team has made available at http://bcl.codeplex.com/
Complex
A complex number is a number that comprises a real number part and an imaginary number part. A complex number z is usually written in the form z = x + yi, where x and y are real numbers, and i is the imaginary unit that has the property i2 = -1.
That snippet is the first line from the documentation on System.Numeric.Complex and unfortunately I am not smart enough to know what they are talking about. So who should understand this?
- Electrical engineers: Using Complex they can do the following: Resistance(R) and Reactance(X) to calculate the impedance Z.
- Mathematicians: Vector Calculus as well as Graphs.
- People using positional (mapping) info: X, Y coordinates on a map or 2d plane.
For an example I will just wimp out and show you what the MSDN documentation has:
// Create a complex number by calling its class constructor. Complex c1 = new Complex(12, 6); Console.WriteLine(c1); // Assign a Double to a complex number. Complex c2 = 3.14; Console.WriteLine(c2); // Cast a Decimal to a complex number. Complex c3 = (Complex)12.3m; Console.WriteLine(c3); // Assign the return value of a method to a Complex variable. Complex c4 = Complex.Pow(Complex.One, -1); Console.WriteLine(c4); // Assign the value returned by an operator to a Complex variable. Complex c5 = Complex.One + Complex.One; Console.WriteLine(c5); // Instantiate a complex number from its polar coordinates. Complex c6 = Complex.FromPolarCoordinates(10, .524); Console.WriteLine(c6);
That produces:
Some info on complex is from: http://www.dotnetspider.com/resources/36681-Examples-On-Complex-Class-C-New-Feature.aspx
.NET 4 Baby Steps - Part XI: Special folders
Note: This post is part of a series and you can find the rest of the parts in the series index.
Environment.SpecialFolder
If you are building an application which takes advantage of special folders in Windows (special folders are folders like My Documents), you will be happy to know that .NET 4 has expanded the number of special folders it support, by adding 25 new options to the Environment.SpecialFolder enum.
The new options are:
- AdminTools
- CDBurning
- CommonAdminTools
- CommonDesktopDirectory
- CommonDocuments
- CommonMusic
- CommonOemLinks
- CommonPictures
- CommonProgramFilesX86
- CommonPrograms
- CommonStartMenu
- CommonStartup
- CommonTemplates
- CommonVideos
- Fonts
- LocalizedResources
- MyVideos
- NetworkShortcuts
- PrinterShortcuts
- ProgramFilesX86
- Resources
- SystemX86
- Templates
- UserProfile
- Windows
Usage is:
Console.WriteLine(Environment.GetFolderPath(Environment.SpecialFolder.MyVideos));
GetFolderPath
The GetFolderPath method has also gotten an update with a new overload which takes a second enum, SpecialFolderOption. This has three values
- None: Returns the path, but does not verify whether the path exists. If the folder is located on a network, specifying this option can reduce lag time.
- Create: Verifies the folder path. If the folder does not exist, an empty string is returned. This is the default behavior.
- DoNotVerify: Forces the folder to be created if it does not already exist.
Super fast network option:
Console.WriteLine(Environment.GetFolderPath(Environment.SpecialFolder.MyVideos, Environment.SpecialFolderOption.None));
Visual Studio ALM Ranger Champions for 2010!
I am a proud contributor to the Microsoft Visual Studio ALM Rangers (see this post for who they are) and each year, the Rangers have a vote for who they believe are helping the Rangers initiatives the most. The top four from the votes are honoured with the title of Champion! I was honoured in 2009 to be included in the list of the four champions and even more honoured that I have again been listed in the top 4!
Congrats to the other three champions and especially to Mathias Olausson, who was also re-awarded!
For more details on the latest Rangers champions see: http://blogs.msdn.com/willy-peter_schaub/archive/2010/05/12/external-visual-studio-alm-rangers-the-votes-have-been-tallied-and-the-2010-champions-are-have-been-known.aspx
DevDays Durban Slides and Bits
I had a great time in Durban this week presenting at the DevDays event. I was a bit nervous for my first keynote but calmed down once I was up there. I was much less nervous for the sessions and they turned out to be great fun.
Knowing is half the battle
As part of my prep I did fully script the demos and those scripts are included in hidden slides in the slide shows – so if you are looking to recreate the demos please download the slides and have a look.
For both my sessions I made use of the excellent (but I’m biased) Rule 18 tool. So if you looking for the actual code, which I referred to in my scripts with Rule 18 key presses, you should really download that too.
All the demos were done using Visual Studio 2010.
What’s new in ASP.NET 4?
- Demo Bits
- Rule 18 Snippets
- Websites and tools mentioned in the talk:
- jQuery
- ASP.NET Chart Controls for Visual Studio 2008 and .NET 3.5
- Windows Server AppFabric (previous called Velocity), which is the distributed caching solution.
- Web Platform Installer
- Used to install web application to IIS, like Drupal or Joomla
- Used to install MVC 1
What’s new in .NET 4?
- Demo Bits
- To save size in the bits I have not included the IMDB data dump, which you will want to download and include to get the IMDB provider to work.
- Rule 18 Snippets
- Websites and tools mentioned in the talk:
.NET 4 Baby Steps - Part X: Location, Location, Location
Note: This post is part of a series and you can find the rest of the parts in the series index.
This is seriously some of the coolest stuff in .NET 4: System.Device.Location which gives you access to the Windows 7 sensor platform to build location aware applications. The two important classes to know are:
- GeoCoordinateWatcher: Think of this as your GPS device. It gives you time and latitude and longitude.
- CivicAddressResolver: This translates latitudes and longitude into addresses!
Usage
Usage of it is very easy. First we create a resolver and gps and then we tell the GPS to start. We assign an event to alert us when the position has changed and when we done we tell the GPS to stop.
static System.Device.Location.CivicAddressResolver resolver = new System.Device.Location.CivicAddressResolver(); static System.Device.Location.GeoCoordinateWatcher gps; static void Main(string[] args) { Console.Clear(); Console.WriteLine("Press any key to quit"); using (gps = new System.Device.Location.GeoCoordinateWatcher()) { gps.PositionChanged += new EventHandler<System.Device.Location.GeoPositionChangedEventArgs<System.Device.Location.GeoCoordinate>>(gps_PositionChanged); gps.Start(); Console.ReadKey(); gps.Stop(); } }
When the GPS position changes we write it to the screen as follows:
static void gps_PositionChanged(object sender, System.Device.Location.GeoPositionChangedEventArgs<System.Device.Location.GeoCoordinate> e) { Console.Clear(); Console.WriteLine("Last updated at: {0}", DateTime.Now); Console.WriteLine("Your location: {0}", e.Position.Location); Console.WriteLine("I think that is: {0}", NiceAddress(e.Position.Location)); Console.WriteLine("Press any key to quit"); }
How do we get our address and display it nicely?
private static object NiceAddress(System.Device.Location.GeoCoordinate geoCoordinate) { System.Device.Location.CivicAddress address = resolver.ResolveAddress(geoCoordinate); if (address.IsUnknown) { return "Unknown"; } return string.Join("\n", address.FloorLevel, address.Building, address.AddressLine1, address.AddressLine2, address.City, address.StateProvince, address.CountryRegion, address.PostalCode); }
And all this code produces the following:
Distances?
The GeoCoordinate class has a brilliant method called GetDistanceTo which returns the distance, in meters (Metric system FTW) between it and another GeoCoordinate. So for me to find the distance to the Lions Rugby Team home stadium I just do:
static void gps_PositionChanged(object sender, System.Device.Location.GeoPositionChangedEventArgs<System.Device.Location.GeoCoordinate> e) { Console.Clear(); Console.WriteLine("Last updated at: {0}", DateTime.Now); System.Device.Location.GeoCoordinate ellisPark = new System.Device.Location.GeoCoordinate(-26.1978417421848, 28.060884475708 ); Console.WriteLine("It is {0}km to Ellis Park", e.Position.Location.GetDistanceTo(ellisPark) / 1000); Console.WriteLine("Press any key to quit"); }
Which gives:
Accuracy?
The accuracy can be controlled in settings, but a lot of it is up to your GPS receiver device. Unfortunately I do not have a proper hardware based GPS device, so I have used the excellent free software based Geosense for Windows, which you can see is accurate enough for most scenarios.
No sensor?
If you are on a version of Windows prior to 7, then the status of the GPS sensor will be set to Disabled.
If you are on Windows 7 without a GPS sensor then when you run it, you will be prompted for your default location information which Windows can try and use to find you.
Mobile?
As a bonus to using this, it is similar as the geolocation system in the new Windows Phone 7 platform! You can find out about geolocation in Windows Mobile 7 in Rudi’s blog post.
.NET 4 Baby Steps: Part IX - Stream
Note: This post is part of a series and you can find the rest of the parts in the series index.
Streams are something I try to avoid, it feels to me like I am getting down and dirty when I use them – but maybe that is just flash backs to working in Delphi :) They are very useful, but they can be clunky especially when you need to get the content into another stream.
The key example of coping a steam is when you write your own file copy method (and which programmer hasn’t):
using (FileStream sourceFile = new FileStream("test.xml", FileMode.Open)) { using (FileStream destinationFile = new FileStream("target.xml", FileMode.Create)) { byte[] buffer = new byte[4096]; int read; while ((read = sourceFile.Read(buffer, 0, buffer.Length)) != 0) { destinationFile.Write(buffer, 0, read); } } }
The whole buffer/read/write pattern is just ugly.
Now with .NET 4, we can use the new CopyTo method to fix this up:
using (FileStream sourceFile = new FileStream("test.xml", FileMode.Open)) { using (FileStream destinationFile = new FileStream("target.xml", FileMode.Create)) { sourceFile.CopyTo(destinationFile); } }
Ah, much better!
.NET 4 Baby Steps: Part VIII - Enumerate Directories and Files
Note: This post is part of a series and you can find the rest of the parts in the series index.
.NET 4 has seven (!!) new methods for enumeration of directories, files and contents of files. What makes these stand apart from what we have had before, is these return IEnumerable<T> rather than arrays.
Why is it better to get IEnumerable<T> over an array? Rather than getting all the data into one structure first, the array, and returning a massive lump of data. With IEnumerable<T> it returns it one item at a time, as it enumerates that item. If this doesn’t make sense, see the example below.
Example
Old way
So in this example I use the old method:
DirectoryInfo root = new DirectoryInfo(@"c:\"); var collection = from f in root.GetFiles("*", SearchOption.AllDirectories) select f; foreach (var item in collection) { Console.WriteLine(item); }
However due to some permissions it will fail with an exception. Note where the exception is, it is where we are asking for the files and the the console output at this point is empty because it hasn’t finished loading all the data into the array.
New Way
Now we change it to the new method:
DirectoryInfo root = new DirectoryInfo(@"c:\"); var collection = from f in root.EnumerateFiles("*", SearchOption.AllDirectories) select f; foreach (var item in collection) { Console.WriteLine(item); }This time see how the exception occurred during the iteration of the items and note how the output contains some files now, because it has processed those already.
This is a major advantage of the new IEnumerable<T> versions, because now we do not need to wait for all items to be found first and that means it is easier to do high performance code and threading.
What are the new methods?
The seven methods are:
- Directory.EnumerateDirectories
- This returns IEnumerable<string> of the folder names.
- DirectoryInfo.EnumerateDirectories
- This returns IEnumerable<DirectoryInfo>.
- Directory.EnumerateFiles
- This returns IEnumerable<string> of the files fullname.
- DirectoryInfo.EnumerateFiles
- This returns IEnumerable<FileInfo>.
- Directory.EnumerateFileSystemEntries
- This returns IEnumerable<string> of the file system entries.
- DirectoryInfo.EnumerateFileSystemEntries
- This returns IEnumerable<FileSystemInfo>.
- File.ReadLines
- This returns IEnumerable<string> where each string is a line from text file.