This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
authentication failed while connecting to tfs using tfs api
I am facing a strange issue.I want to connect tfs server using tfs api programmitcally.
Even after giving proper authentcaion crediatials it is failing.But if I do it manually by typing tfs server name in browser its got connected.
code:
TeamFoundationServer tfs =
new TeamFoundationServer(new Uri("http://xx.xx.xx.xx:8080/tfs"),
new NetworkCredential(#"user", "pass", "domain"));
tfs.EnsureAuthenticated()
Please suggest.
You may want to use this alternative:
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Framework.Client;
using Microsoft.TeamFoundation.Framework.Common;
using System;
using System.Collections.ObjectModel;
class Program
{
static void Main()
{
var tfsUri = new Uri("http://xx.xx.xx.xx:8080/tfs");
TfsConfigurationServer configurationServer =
TfsConfigurationServerFactory.GetConfigurationServer(tfsUri);
// Get the catalog of team project collections
ReadOnlyCollection<CatalogNode> collectionNodes = configurationServer.CatalogNode.QueryChildren(
new[] { CatalogResourceTypes.ProjectCollection },
false, CatalogQueryOptions.None);
// List the team project collections
foreach (CatalogNode collectionNode in collectionNodes)
{
// Use the InstanceId property to get the team project collection
Guid collectionId = new Guid(collectionNode.Resource.Properties["InstanceId"]);
TfsTeamProjectCollection teamProjectCollection = configurationServer.GetTeamProjectCollection(collectionId);
// Print the name of the team project collection
Console.WriteLine("Collection: " + teamProjectCollection.Name);
// Get a catalog of team projects for the collection
ReadOnlyCollection<CatalogNode> projectNodes = collectionNode.QueryChildren(
new[] { CatalogResourceTypes.TeamProject },
false, CatalogQueryOptions.None);
// List the team projects in the collection
foreach (CatalogNode projectNode in projectNodes)
{
Console.WriteLine(" Team Project: " + projectNode.Resource.DisplayName);
}
}
}
}
You can do it a simpler way (assuming you have pass through auth):
var tfsCollection = new TfsTeamProjectCollection(new Uri("http://yourtfs:8080/tfs/"));
tfsCollection.Authenticate();
var workItemStore = new WorkItemStore(TfsCollection);
Related
I am trying to automate some processes to make life a bit easier. We have multiple requests from the team to create a folder in TFS 2017 (they do not have permissions) and then set up the associated builds for that source control folder.
The build creation part I think I have a way to do, but querying our on premise TFS 2017 server to get a list of folders under a certain path is proving tricky. So far I am having trouble even connecting to the server in the first place with this :
var collectionUri = "http://tfs-server:8080/tfs/DefaultCollection/";
var teamProjectName = "MYPROJECT";
Uri uri = new Uri(collectionUri);
var clientCredentials = new VssCredentials(new WindowsCredential(new NetworkCredential("USERNAME", "PASSWORD", "COLLECTIONNAME")));
var connection = new VssConnection(uri, clientCredentials);
var sourceControlServer = connection.GetClient<TfvcHttpClient>();
That throws an exception : Error converting value "System.Security.Principal.WindowsIdentity;" to type 'Microsoft.VisualStudio.Services.Identity.IdentityDescriptor'
Can someone help me to get connected to the server first please! Documentation on this is very hard to find, and I dont see any examples that actually work.
What I was going to look at next was creating the folder if it doesn't exist. No idea how to do that yet, maybe using
sourceControlServer.GetBranchAsync(teamProjectName + FolderName);
Thanks!
EDIT:
Ok I got it to not error creating the connection by doing this instead :
Uri uri = new Uri("http://tfs-server:8080/tfs/DefaultCollection/");
var clientCredentials = new VssCredentials(new WindowsCredential(new NetworkCredential("USERNAME", "PASSWORD", "DOMAIN")));
var buildServer = new BuildHttpClient(uri, clientCredentials);
var sourceControlServer = new TfvcHttpClient(uri, clientCredentials);
So now to just figure out how to list and create folders from TFS and to create builds!
EDIT:
So I have got the querying working, so I can check if a folder exists under a path like this :
var teamProjectName = "USA";
Uri uri = new Uri("http://tfs-server:8080/tfs/DefaultCollection/");
var clientCredentials = new VssCredentials(new WindowsCredential(new NetworkCredential("USERNAME", "PASSWORD", "DOMAIN")));
TfvcHttpClient sourceControlServer = new TfvcHttpClient(uri, clientCredentials);
List<TfvcItem> branchItems;
using (sourceControlServer) {
branchItems = sourceControlServer.GetItemsAsync("$/USA/Development/NewFolder", VersionControlRecursionType.OneLevel).Result;
}
return branchItems.Count > 0;
That will find all the items under that folder. So if there isnt a folder, it will return 0, so I can go ahead and create that folder.
So next problem, is how to create the folder. Using CreateChangesetAsync.
Update:
To use Client API and CreateChangesetAsync method to create files in TFVC, you could refer below sample console app:
using Microsoft.TeamFoundation.SourceControl.WebApi;
using Microsoft.VisualStudio.Services.Common;
using Microsoft.VisualStudio.Services.WebApi;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp1
{
internal class Program
{
internal static async Task Main(string[] args)
{
var orgUrl = new Uri(args[0]);
string serverPath = args[1];
string localPath = args[2];
string contentType = args[3];
string pat = args[4];
var changes = new List<TfvcChange>()
{
new TfvcChange()
{
ChangeType = VersionControlChangeType.Add,
Item = new TfvcItem()
{
Path = serverPath,
ContentMetadata = new FileContentMetadata()
{
Encoding = Encoding.UTF8.WindowsCodePage,
ContentType = contentType,
}
},
NewContent = new ItemContent()
{
Content = Convert.ToBase64String(File.ReadAllBytes(localPath)),
ContentType = ItemContentType.Base64Encoded
}
}
};
var changeset = new TfvcChangeset()
{
Changes = changes,
Comment = $"Added {serverPath} from {localPath}"
};
var connection = new VssConnection(orgUrl, new VssBasicCredential(string.Empty, pat));
var tfvcClient = connection.GetClient<TfvcHttpClient>();
await tfvcClient.CreateChangesetAsync(changeset);
}
}
}
Besides, instead of using tf command line, please kindly check solution here:
C# TFS API: show project structure with folders and files, including their ChangeType (checked out, deleted,renamed) like in visual studio
I'm creating an integration from our testing framework (Selenium) to Team Foundation Server (TFS) 2018 using C# (our tests are already written in it) - the integration will generate work items in TFS based on test results. I'd like to create the work item from a template, and I can't seem to find any documentation on doing so. I'm using the TFS client library from Microsoft found here.
I can pull a template from TFS:
var client = new HttpClient()
// Client auth stuff removed
var method = new HttpMethod("GET");
var httpRequestMessage = new HttpRequestMessage(method, "http://server:port/tfs/collection/team/project/_api/wit/templates/12345abc");
var httpResponseMessage = client.SendAsync(httpRequestMessage).Result;
WorkItemTemplate tfs_template = httpResponseMessage.Content.ReadAsAsync<WorkItemTemplate>().Result;
The API for creating new work items here looks fairly straightforward, but I can't find any way to connect the two actions, or a way to apply a template using this call. Is it possible to create a work item via API with a template, and if so, is there any documentation for it?
You can not create work item from work item template. You can use work item templates to see which fields contains some default values. This example for new work item from template with rest api:
using Microsoft.TeamFoundation.Core.WebApi;
using Microsoft.TeamFoundation.Core.WebApi.Types;
using Microsoft.TeamFoundation.WorkItemTracking.WebApi;
using Microsoft.VisualStudio.Services.Common;
using Microsoft.VisualStudio.Services.WebApi;
using Microsoft.VisualStudio.Services.WebApi.Patch;
using Microsoft.VisualStudio.Services.WebApi.Patch.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static string ServiceURL = "https://your_name.visualstudio.com";
static string PAT = "your pat";
static void Main(string[] args)
{
string projectName = "your project";
string templateName = "Critical bug";
/*connect to service. I use VSTS. In your case:
VssConnection connection = new VssConnection(new Uri(ServiceURL), new VssCredential());
https://learn.microsoft.com/ru-ru/azure/devops/integrate/get-started/client-libraries/samples?view=vsts
*/
VssConnection connection = new VssConnection(new Uri(ServiceURL), new VssBasicCredential(string.Empty, PAT));
//get clients
var WitClient = connection.GetClient<WorkItemTrackingHttpClient>();
var ProjectClient = connection.GetClient<ProjectHttpClient>();
var project = ProjectClient.GetProject(projectName).Result;
//get context for default project team
TeamContext tmcntx = new TeamContext(project.Id, project.DefaultTeam.Id);
//get all template for team
var templates = WitClient.GetTemplatesAsync(tmcntx).Result;
//get tempate through its name
var id = (from tm in templates where tm.Name == templateName select tm.Id).FirstOrDefault();
if (id != null)
{
var template = WitClient.GetTemplateAsync(tmcntx, id).Result;
JsonPatchDocument patchDocument = new JsonPatchDocument();
foreach (var key in template.Fields.Keys) //set default fields from template
patchDocument.Add(new JsonPatchOperation()
{
Operation = Operation.Add,
Path = "/fields/" + key,
Value = template.Fields[key]
});
//add any additional fields
patchDocument.Add(new JsonPatchOperation()
{
Operation = Operation.Add,
Path = "/fields/System.Title",
Value = "My critical bug"
});
var newWorkItem = WitClient.CreateWorkItemAsync(patchDocument, projectName, template.WorkItemTypeName).Result;
}
}
}
}
My template:
I have a SharePoint Online where I can connect through my console application successfully:
private static ClientContext GetUserContext()
{
var o365SecurePassword = new SecureString();
foreach (char c in o365Password)
{
o365SecurePassword.AppendChar(c);
}
var o365Credentials = new SharePointOnlineCredentials(o365Username, o365SecurePassword);
var o365Context = new ClientContext(o365SiteUrl);
o365Context.Credentials = o365Credentials;
return o365Context;
}
But what I need now to do is to go into my SharePoint Document Library named "doc_archive" and check if there exists a folder with name "K20170409-01".
If not create a new one.
Failed Attempt
ClientContext context = GetUserContext();
Web web = context.Web;
Web webroot = context.Site.RootWeb;
context.Load(web);
context.Load(webroot);
List list = webroot.GetList("doc_archive");
context.Load(list);
FolderCollection folders = list.RootFolder.Folders;
context.Load(folders);
IEnumerable<Folder> existingFolders = context.LoadQuery(
folders.Include(
folder => folder.Name)
);
context.ExecuteQuery();
What is the fastest ways to check and create a folder within a document library in SharePoint Online via CSOM (commandline application)?
If you are happy with using external libraries then the OfficeDevPnP.Core has some great CSOM extensions for SharePoint and SharePoint Online. It's readily available as a NuGet package to add to your projects.
For your requirment there is the EnsureFolderPath extension. This function will check if a folder exists, create it if needed and return the Microsoft.SharePoint.Client.Folder object.
Very easy to use:
var webRelativeUrlToFolder = "/doc_archive/K20170409-01"
var folder = cc.Web.EnsureFolderPath(webRelativeUrlToFolder);
cc.Load(folder);
cc.ExecuteQuery();
I can't vouch for how fast this would be, but it works in the end on 0365. Note that it throws a ServerException if the target already exists.
using (var ctx = new ClientContext(siteUrl))
{
ctx.Credentials = new SharePointOnlineCredentials(username, securePwd);
var list = new ListCreationInformation()
{
Title = title
Description = "User Created Document Library",
TemplateType = asDocumentLibrary ? 101 : 100 // 100 is a custom list.
};
ctx.Web.Lists.Add(list);
ctx.ExecuteQuery();
success = true;
}
Most CSOM examples are found in Powershell. The process in C# CSOM is actually the same, so next time find a Powershell example when a C# one is not available.
Here is how I'm trying to list amazon (aws) security groups of VPC using AWSSDK in c#:
var ec2Client = new AmazonEC2Client(accessKey, secretKey, RegionEndpoint.USEast1);
var dsgRequest = new DescribeSecurityGroupsRequest();
var dsgResponse = ec2Client.DescribeSecurityGroups(dsgRequest);
List<SecurityGroup> mySGs = dsgResponse.SecurityGroups;
foreach (SecurityGroup item in mySGs)
{
Console.WriteLine("Existing security group: " + item.GroupId);
}
It only displays the default amazon security group while when I login to amazon via browser, I see lots of company security groups.
Any idea why this does not list them all?
I think it's because you didn't set a RegionEndpoint.
I modified your code slightly, and was able to enumerate my security groups:
var config = new AmazonEC2Config { RegionEndpoint = Amazon.RegionEndpoint.APSoutheast2};
var credentials = new BasicAWSCredentials(accessKey, secretKey);
using (var client = Amazon.AWSClientFactory.CreateAmazonEC2Client(credentials, config))
{
var dsgRequest = new DescribeSecurityGroupsRequest();
var dsgResponse = client.DescribeSecurityGroups(dsgRequest);
List<SecurityGroup> mySGs = dsgResponse.SecurityGroups;
foreach (SecurityGroup item in mySGs)
{
Console.WriteLine("Existing security group: " + item.GroupId);
}
}
Thanks for the help. I had actually set the end point properly. I ran the same code that I had a few days later and it worked. It must have been amazon services gone down or something like that.
Hello can someone please help me with getting all the teams in a given team project.
Current code gets all Team Projects (from http://msdn.microsoft.com/en-us/library/bb286958.aspx)
public void getTeamProjects()
{
TfsConfigurationServer configServer = TfsConfigurationServerFactory.GetConfigurationServer(_uri);
ReadOnlyCollection<CatalogNode> collectionNodes = configServer.CatalogNode.QueryChildren(
new[] { CatalogResourceTypes.ProjectCollection },
false, CatalogQueryOptions.None);
foreach (CatalogNode collectionNode in collectionNodes)
{
Guid collectionId = new Guid(collectionNode.Resource.Properties["InstanceId"]);
TfsTeamProjectCollection teamProjectCollection = configServer.GetTeamProjectCollection(collectionId);
Console.WriteLine("Collection: " + teamProjectCollection.Name);
ReadOnlyCollection<CatalogNode> projectNodes = collectionNode.QueryChildren(
new[] { CatalogResourceTypes.TeamProject },
false, CatalogQueryOptions.None);
foreach (CatalogNode projectNode in projectNodes)
{
Console.WriteLine("Team Project: " + projectNode.Resource.DisplayName);
// How do I access the Team names of each projectNode.
}
}
Console.WriteLine("Finished");
Console.ReadKey();
}
Currently on the console it is printing out all of the Team Projects correctly. I want the ability to access the team names in each team project.
Check the source code for the TFS Team Tools from the ALM Rangers over on codeplex. The ListTeams method does exactly what you're after.
this.teamService = this.teamProjectCollection.GetService<TfsTeamService>();
public List<string> ListTeams()
{
var teams = this.teamService.QueryTeams(this.projectInfo.Uri);
return (from t in teams select t.Name).ToList();
}