TFS 2012 Fails To Create New Team Project

Today, I went to add a new team project to TFS.  I did the usual steps by giving it a name and choosing the template type (not really relevant to me since I’m a solo programmer).  Visual Studio worked for a bit, then failed with the following error in the log file:

Event Description: TF30162: Task "LinkTypes" from Group "WorkItemTracking" failed
Exception Type: Microsoft.TeamFoundation.Client.PcwException
Exception Message: Page not found.

The Internet had plenty of advice to resolve TF30162 errors, but nothing useful for the specific LinkTypes error.  The only suggestion was to reload the project templates.  I was not able to do that because in TFS 2012, those templates are locked and unable to be uploaded and overwritten.

So I attempted a Repair install of TFS 2012.  That had no effect

I then made sure I was on the latest version of TFS, so I installed Update 4.  My scrum project template went from 2.0 to 2.2, but I still got the exact same error.

I then tried to create a new Project Collection and create a team project in that.  Still, no change.

Then I did a repair install on Visual Studio 2015.  This took a very long time and required two restarts.  And after that, no improvement.

So far, I’ve eliminated the TFS binaries, the TFS database, and the VS binaries.  There’s only one element left – IIS.  And that one seems to have potential because of the PageNotFound error.

Poking around the IIS log files, there’s entries in there like this:

2017-01-09 14:27:23 ::1 GET /tfs/_apis/connectionData connectOptions=IncludeServices&lastChangeId=-1&lastChangeId64=-1 8080 MicrosoftAccount\myaccount@domain.com ::1 VSServices/14.98.25331.0+(devenv.exe+,Pro,+SKU:31) – 404 0 0 1719

Looking at IIS log files prior to when my problem happened,  this 404 error has happened before, too.  but there was also other calls to the service like:

2016-03-25 12:43:46 ::1 OPTIONS /tfs/defaultcollection/_apis/ – 8080 MicrosoftAccount\myaccount@domain.com ::1 Team+Foundation+(devenv.exe,+14.0.24712.0,+Pro,+SKU:31)+VSServices/14.0.24712.0+(devenv.exe+,Pro,+SKU:31) – 404 0 0 8

Two suspects come up in Internet searches: Git and IIS plugins.  Disabling some of the plugins in C:\Program Files\Microsoft Team Foundation Server 11.0\Application Tier\Web Services\bin\Plugins made no difference.

At this point, I suspect an incompatibility between VS2015 and TFS 2012, so I upgrade my TFS install to 2015.  What else could it be?  A call is being made to a REST service that doesn’t exist, or is different enough that the inbound parameters don’t match up.  This TFS upgrade requires SQLExpress to be upgraded as well.  The rabbit hole keeps going deeper and deeper.

After that entire install and restart, I was finally able to create a new Team Project.  The new default project template is “Agile”, not that I care much.

So, the short solution for my error: Upgrade TFS from 2012 to 2015.  It must’ve become incompatible after a VS update somewhere along the way.

Staying On The Correct Path

In a current task where I had to consolidate the structure of a website and organize the files better, I ran across this interesting quirk.  When developing, we work in a virtual directory on our local machine, while on a real server, it runs in the root directory.  This poses problems whenever we want to use relative paths to images, style sheets, etc.

The key to fixing this is the VirtualPathUtility, which has the logic in it to determine the root of the web application and return a proper path.  I thought it would be easy to just use this object right in the markup like:

<head runat="server">
    <title></title>
    <link id="cssLinkOutside" href='<%=System.Web.VirtualPathUtility.ToAbsolute("~/StyleSheet.css")%>' rel="stylesheet" type="text/css" />
</head>

That didn’t work.  The rendered HTML turned out to be:

<link id="cssLinkOutside" href="&lt;%=System.Web.VirtualPathUtility.ToAbsolute(&quot;~/StyleSheet.css&quot;)%>" rel="stylesheet" type="text/css" />

Pretty literal.  The cause of this odd behavior is that the HEAD tag is set to runat=”server”.  If that piece is taken out, the embedded code works well.  So if you need the HEAD to be a server control – like when using themes – then what?  You can add code in the code-behind to do an attributes.add() on the LINK tag.  But having to add code in two places for such a simple need is just too much, especially when I was looking at updating a couple dozen pages.

The workaround is kind of surprising: Wrap the tag that contains dynamic code in a placeholder.

<head runat="server">
    <title></title>
    <asp:PlaceHolder runat="server" id="holder">
        <link id="cssLinkInside" href='<%=System.Web.VirtualPathUtility.ToAbsolute("~/StyleSheet.css")%>' rel="stylesheet" type="text/css" />
    </asp:PlaceHolder>
</head>

This renders the tag properly:

<link id="cssLinkInside" href='/WebTestbed/StyleSheet.css' rel="stylesheet" type="text/css" />