NetTfsClient 1.3.1

dotnet add package NetTfsClient --version 1.3.1
NuGet\Install-Package NetTfsClient -Version 1.3.1
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="NetTfsClient" Version="1.3.1" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add NetTfsClient --version 1.3.1
#r "nuget: NetTfsClient, 1.3.1"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install NetTfsClient as a Cake Addin
#addin nuget:?package=NetTfsClient&version=1.3.1

// Install NetTfsClient as a Cake Tool
#tool nuget:?package=NetTfsClient&version=1.3.1

TESTS

Run tests

NetTfsClient

Microsoft Team Foundation Server .Net Library is a client for Azure service. It can manage workitems, projects and team members.

Installing

TBD

Basic usage

  1. Install nettfsclient package
  2. Create client connection with ClientFactory
  • Authorize with PAT
var serverUrl = "https://tfs.server.my";
var projetName = "DefaultCollection/Myroject";
var userPat = "mypersonalaccounttoken";

// authorize with personal account token
var connection = ClientFactory.CreateClientConnection(serverUrl, projetName, userPat);
  • Authorize with NTLM
var serverUrl = "https://tfs.server.my";
var projetName = "DefaultCollection/Myroject";
var userName = "User";
var userPassword = "password";

// authorize with personal account token
var connection = ClientFactory.CreateClientConnection(userName, userPassword, serverUrl, projectName);
  1. Manage projects, teams and team members
/* Get IProjectClient with extension method GetProjectClient() on connection */
var projectClient = connection.GetProjectClient();

Console.WriteLine("### SECTION PROJECTS ###");

// Get projects with GetProjectsAsync()
var projects = await projectClient.GetProjectsAsync();

foreach (var project in projects)
{
    Console.WriteLine($"Project: {project.Id} {project.Name}");
}
Console.WriteLine();

// Get all teams with GetAllTeamsAsync()
var teams = await projectClient.GetAllTeamsAsync();

Console.WriteLine("TFS Teams:");
foreach (var team in teams)
{
    Console.WriteLine($"Team: {team.Id} {team.Name}");
}
Console.WriteLine();

// Project teams
if (projects.Any())
{
    var project = projects.First();

    // Get project teams with GetProjectTeamsAsync(project)
    var projectTeams = await projectClient.GetProjectTeamsAsync(project);

    if (projectTeams.Any())
    {
        Console.WriteLine($"Teams of project {project.Name}");
        foreach (var projectTeam in projectTeams)
        {
            Console.WriteLine($"Team: {projectTeam.Id} {projectTeam.Name}");
        }
        Console.WriteLine();

        var team = projectTeams.First();
        
        // Get team members with GetProjectTeamMembersAsync(project, team)
        var members = await projectClient.GetProjectTeamMembersAsync(project, team);

        if (members.Any())
        {
            Console.WriteLine($"Members of team {team.Name} of project {project.Name}");
            foreach(var member in members)
            {
                Console.WriteLine($"Member: {member.Id} {member.UniqueName} {member.DisplayName}");
            }

            Console.WriteLine();
        }
        else
        {
            Console.WriteLine($"You don't have any members of team {team.Name} of project {project.Name}");
        }
    }
    else
    {
        Console.WriteLine($"You don't have any teams for project {project.Name} :(");
        Console.WriteLine();
    }
}
else
{
    Console.WriteLine("You don't have any projects :(");
}
  1. Manage workitems
* Get IWorkitemClient with extension method GetProjectClient() on connection */
var workitemClient = connection.GetWorkitemClient();

var workitemId = 1;
// Get single workitem and properties with GetSingleWorkitemAsync()
var workitem = await workitemClient.GetSingleWorkitemAsync(workitemId);
if (workitem != null)
{
    Console.WriteLine($"--- {workitem.Id} {workitem.Title} {workitem.TypeName} ---");
    Console.WriteLine($"WI propery (System.Title): {workitem["System.Title"]}");
    Console.WriteLine($"Description: {workitem.Description} Revision: {workitem.Rev}");

    if (workitem.Relations.Any())
    {
        Console.WriteLine("Workitem relations:");
        foreach (var rel in workitem.Relations)
        {
            Console.WriteLine($"Relation: workitem {rel.WorkitemId} -> {rel.TypeName} ({rel.RelationType})");
        }
    }
    else
    {
        Console.WriteLine($"Workitem {workitem.Id} {workitem.Title} doen't have relation");
    }
}
else
{
    Console.WriteLine($"Can't get workitem with ID={workitemId}");
}
Console.WriteLine();

if (workitem != null)
{
    Console.WriteLine("Get workitem changes with GetWorkitemChangesAsync() on IWorkitem");

    var changes = await workitem.GetWorkitemChangesAsync();
    if (changes != null)
    {
        Console.WriteLine($"Workitem {workitem.Id} {workitem.Title} has {changes.Count()} changes");
        foreach (var change in changes)
        {
            Console.WriteLine($"Change {change.Id}: Rev: {change.Revision} Date: {change.RevisedDate} by {change.RevisedBy.DisplayName}");
            if (change.FieldsChanges.Any())
            {
                Console.WriteLine("Fields changes:");
                foreach (var fldChange in change.FieldsChanges)
                {
                    Console.WriteLine($"Field {fldChange.FieldName} change: Old value: {fldChange.OldValue} New value: {fldChange.NewValue}");
                }
            }
            else
            {
                Console.WriteLine("Change doesn't have any fields changes");
            }

            if (change.RelationsChanges.HasChanges)
            {
                var addedCount = change.RelationsChanges.Added.Count;
                var updatedCount = change.RelationsChanges.Updated.Count;
                var removedCount = change.RelationsChanges.Removed.Count;

                Console.WriteLine($"Relation changes: Added={addedCount} Updated={updatedCount} Removed={removedCount}");
            }
            else
            {
                Console.WriteLine("Change doesn't have any relation changes");
            }
        }
    }
    else
    {
        Console.WriteLine($"Can't get history changes of workitem {workitem.Id} {workitem.Title}");
    }
}
workitemId = 100;

var wi = await workitemClient.GetSingleWorkitemAsync(workitemId);
if (wi != null)
{
    // Set title and description
    wi.Title = "New Title";
    wi.Description = "Some description";

    // Custom field (eg. System.History)
    wi["System.History"] = "Hello there!";

    // Save changes
    var updateResult = await wi.SaveFieldsChangesAsync();
    if (updateResult == UpdateFieldsResult.UPDATE_SUCCESS)
    {
        Console.WriteLine($"Update success: {wi.Id} {wi.Title} {wi.Description}");
    }
}
else
{
    Console.WriteLine($"Can't get item with id={workitemId}");
}

Coding style

Google codestyle: https://google.github.io/styleguide/csharp-style.html

Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.3.1 87 2/7/2024
1.3.0 63 2/6/2024
1.2.0 110 9/19/2023
1.1.0 102 8/13/2023
1.0.0 135 4/23/2023