Tag Archives: WorkItemTracking

TFS API Exception thrown: ‘System.MissingMethodException’ in MyApp.exe

The following error:

Exception thrown: ‘System.MissingMethodException’ in CreateTestCase.exe

Additional information: Method not found: ‘Void Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItemStore..ctor(Microsoft.TeamFoundation.Client.TfsTeamProjectCollection)’.

Occurred for me while trying to execute the following code:

public static IEnumerable<string> GetAllDistinctWorkItemTags(string uri, string projectName)
{
    TfsTeamProjectCollection tfs;

    tfs = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri(uri)); // https://mytfs.visualstudio.com/DefaultCollection
    tfs.Authenticate();

    var wis = new WorkItemStore(tfs);

    WorkItemCollection workItemCollection = wis.Query(
                 " SELECT [System.Tags]" +
                 " FROM WorkItems " +
                 $" WHERE [System.TeamProject] = '{projectName}' ");

Bizarrely, I was following my own blog post to create a test case, reading tags from the system.

This threw me for some time. I had a good idea it was caused by the wrong version of the Work Item Tracking extension library.

After a bit of searching, I came to the conclusion that MS don’t really support this method of integrating with TFS anymore; at least not for later versions. Consequently, I went to Nuget:

https://www.nuget.org/packages/Microsoft.TeamFoundationServer.ExtendedClient/

Installing this magically sorted the issue for me.

Programmatically create a bug in TFS

If you’re creating a TFS API program from scratch, the first thing that you’ll need is to reference the TFS API libraries. They are in extensions:

tfsbug1

Don’t worry too much about which one’s you’ll need just yet, when you start to write some code, this will be more obvious. The next stage is to create a function that creates your bug; it might look like this:

private static ActionResult CreateNewBug(Project teamProject, string title, string description, 
    string area, string iteration, string assignee, string reproductionSteps)
{
    WorkItemType workItemType = teamProject.WorkItemTypes["Bug"];
 
    // Create the work item. 
    WorkItem newBug = new WorkItem(workItemType);
    newBug.Title = title;
    newBug.Description = description;
    newBug.AreaPath = area;
    newBug.IterationPath = iteration;
    newBug.Fields["Assigned To"].Value = assignee;
 
    newBug.Fields["Repro Steps"].Value = reproductionSteps;
 
    var validationResult = newBug.Validate();
 
    if (validationResult.Count == 0)
    {
        // Save the new work item.
        newBug.Save();
 
        return new ActionResult()
        {
            Success = true
        };
    }
    else
    {
        // Establish why it can't be saved
        var result = new ActionResult()
        {
            Success = false,
            ErrorCodes = new List<string>()                
        };
 
        foreach (var res in validationResult)
        {
            Microsoft.TeamFoundation.WorkItemTracking.Client.Field field = res as Microsoft.TeamFoundation.WorkItemTracking.Client.Field;
            if (field == null)
            {
                result.ErrorCodes.Add(res.ToString());
            }
            else
            {
                result.ErrorCodes.Add($"Error with: {field.Name}");
            }
        }
 
        return result;
    }
}

Obviously, we’re not writing a new front end for TFS here, but the basics are there. The first part of the function gets the relevant fields; once the .Validate() has been called, then we have a look at the result. If there are no errors then just save; otherwise, we try and work out what they were.

In the example above, I’m returning a class of the following type:

public class ActionResult
{
    public bool Success { get; set; }
    public List<string> ErrorCodes { get; set; }
}

But that’s only because this is in its own library. The method above also accepts a Project; assuming that you know what the project is called, you could use something like this to return the correct object:


public static Project GetTeamProject(string uri, string name)
{
    TfsTeamProjectCollection tfs;
 
    tfs = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri(uri)); // https://mytfs.visualstudio.com/DefaultCollection
    tfs.Authenticate();
 
    var workItemStore = new WorkItemStore(tfs);
    
    var project = (from Project pr in workItemStore.Projects
                       where pr.Name == name
                       select pr).FirstOrDefault();
    if (project == null)
        throw new Exception($"Unable to find {name} in {uri}");
 
    return project;
}

And that’s it; here’s my calling code:

var result = TFSUtilLibrary.WorkItemHelper.CreateNewBug(TFSUri, "TFSSandbox",
    "Test new bug", "New bug description", @"TFSSandbox\Team 12", @"TFSSandbox\Iteration 1", "Paul Michaels",
    "Click the screen");

Here’s the bug to prove it works:

tfsbug2

tfsbug3