title: What is the fastest method of retrieving TFS team projects using the TFS SDK API?
body: <p>I have some answers! Feel free to contribute your own findings.</p>
  
  <p>As far as I know, there are 3 main ways to retrieve a simple list of Team Projects from TFS:</p>
  
  <ul>
  <li>Using the new Catalog service (TFS 2010)</li>
  <li>Using the VersionControlServer (TFS 2008/2010)</li>
  <li>Using the ICommonStructureService (TFS 2008/2010)</li>
  </ul>
  
  <p>The simple tests I conducted compared the three methods when counting the total number of projects returned.</p>
  
  <p><strong>Method 1: Catalog Service (TFS 2010 Only)</strong></p>
  
  <pre><code>    public IEnumerable&lt;string&gt; GetTeamProjectNamesUsingCatalog()
      {
          ReadOnlyCollection&lt;CatalogNode&gt; projectNodes = new TfsTeamProjectCollection(collectionUri).CatalogNode.QueryChildren(
                      new[] { CatalogResourceTypes.TeamProject },
                      false, CatalogQueryOptions.None);
  
          foreach (var tp in projectNodes)
              yield return tp.Resource.DisplayName;
      }
  </code></pre>
  
  <p><strong>Method 2: VersionControlServer</strong></p>
  
  <pre><code>    public IEnumerable&lt;string&gt; GetTeamProjectNamesUsingVCS()
      {
          TfsTeamProjectCollection tp = new TfsTeamProjectCollection(collectionUri);
  
          foreach (var p in tp.GetService&lt;VersionControlServer&gt;().GetAllTeamProjects(false))
              yield return p.Name;
      }
  </code></pre>
  
  <p><strong>Method 3: ICommonStructureService</strong></p>
  
  <pre><code>    public IEnumerable&lt;string&gt; GetTeamProjectNamesUsingStructureService()
      {
          var structService = new TfsTeamProjectCollection(collectionUri).GetService&lt;ICommonStructureService&gt;();
  
          foreach (var p in structService.ListAllProjects())
              yield return p.Name;
      }
  </code></pre>
  
  <p>The unit tests I ran were super simple. I used the .Count() method to make sure we iterated all the team projects (.Any() is faster as it will stop after the first name is returned).</p>
  
  <p><strong>Results</strong></p>
  
  <p>For TFS 2010, running 3 tests 5 times in a row:</p>
  
  <p><img src="https://i.stack.imgur.com/ofLoy.png" alt="TFS 2010 Chart Average Duration"></p>
  
  <p><img src="https://i.stack.imgur.com/F8C89.png" alt="TFS 2010 Duration Results"></p>
  
  <p>For TFS 2008, running 2 tests (no Catalog service) 5 times in a row:</p>
  
  <p><img src="https://i.stack.imgur.com/kXJkS.png" alt="TFS 2008 Chart Average Duration"></p>
  
  <p><img src="https://i.stack.imgur.com/Lwjvo.png" alt="TFS 2008 Duration Results"></p>
  
  <p><strong>Biases</strong></p>
  
  <ul>
  <li>The TFS 2010 server this was running against was in development, so hardly anyone was using it.</li>
  <li>I didn't test this with any least-privilege user accounts; I am an Admin on the server.</li>
  <li>I am communicating with a TFS server within the corporate network.</li>
  <li>In TFS 2010, you can have multiple <code>TfsTeamProjectCollections</code>; you will need to iterate through those as well. In this test, I only used one collection.</li>
  <li>I used the constructor for creating the <code>TfsTeamProjectCollection</code>; I switched to using the <code>TfsTeamProjectCollectionFactory.GetTeamProjectCollection()</code> method and it was actually slower each test run. It might be faster if you make multiple calls per request.</li>
  <li>For TFS 2008, the server is a production server under load (i.e. real world).</li>
  </ul>
  
  <p><strong>Findings</strong></p>
  
  <p>As you can see, it seems like the <code>ICommonStructureService</code> is fairly fast at finding all the team projects <em>after the first execution</em>. <em>Note: I had done earlier tests using <code>ICommonStructureService3</code> (new in TFS 2010 API) and the same code was slower than the other two methods.</em></p>
  
  <p>If consistent performance is key, I think I'd recommend <code>VersionControlServer</code> to do it.</p>
  
  <p>Keep in mind what it is you want to do with the team projects, however. If simply listing them is all you need, the ICSS is probably the way to go. If you want to use the list for navigation, you'll also need the path (<code>$/TeamProject</code>) or Uri. In that case, VCS is probably the best way to go as you can use the <code>ServerItem</code> property, which holds the path to the item. You might also get away with simple string concatenation using ICSS (<code>"$/" + p.Name</code>).</p>
  
  <p>Hope this helps some other TFS API developers.</p>