TFS2018 path to api - tfs

I have a TFS2018 setup on a server and I am trying to figure out what is the path to the api. Should the path look look like this? Do I have to enable the API on the server?
https://myserver/tfs/DefaultCollection/MyProject/_apis
If I run this in code like this
var cred = new VssCredentials(
new WindowsCredential(new NetworkCredential("username", "Pass")));
var buildClient = new BuildHttpClient(new Uri("https://myserver/tfs/DefaultCollection/MyProject/_apis", UriKind.Absolute), cred);
await buildClient.CreateDefinitionAsync(buildDef);
I get the following error
Web method running:
[https://myserver/tfs/DefaultCollection/MyProject/_apis]
(OPTIONS)_apis[]

It depends on how the server was setup. If it's a fresh install, the /tfs/ is no longer used. If it's an upgrade the /tfs/ is retained to not break existing clients. And I suspect you can leave off the /_api/ part as well, as that should be automatically added.
The best way to get to the BuildCLient is to use the TFS Server or Collection object and request the server:
var collection = new TfsTeamProjectCollection(tfsCollectionUri, credential);
var buildClient = collection.GetClient<BuildHttpClient>();

Related

How do I get TFS wiki page attachment over API

I need to download TFS wiki page attachment via the TFS API.
From MS Docs, it looks like the API alows to create it but I can't seem to find a way to get it.
Calling GET on /_apis/wiki/wikis/{wikiIdentifier}/pages/{pageId}/attachments/{attachmentId} returns Method not allowed
Then I tried to use the WIT attachments API /_apis/wit/attachments/{id} but that one does not find the attachment and returns 404. (I suspect it can access only work items attachments.)
use GitHttpClient.GetItemContentAsync({project}, {repositoryId}, path:{path})
where
path is "/.attachments/my attached file-89553727-xxx-yyy-zzz-829fbe167411.docx" as found in the wiki page content (note the leading /)
Found this completely by accident once I moved to experimenting with GitHttpClient and listed all items in my repo. One of the items was an attachment and it had this path populated which I then plugged into the GetItemContentAsync method and voila.
My piece of code:
var uri = new Uri(_tfsBaseUri);
var credentials = GetCredentials();
using (var tpc = new TfsTeamProjectCollection(uri, credentials))
{
var wikiClient = tpc.GetClient<WikiHttpClient>();
var gitClient = tpc.GetClient<GitHttpClient>();
var mypage = wikiClient.GetPageAsync(_tfsProject, _tfsWiki, "My page name", includeContent: true).GetAwaiter().GetResult();
var pageContent = mypage.Page.Content;
if (pageContent.Contains("(.attachments"))
{
var path = "";// parse out the attachment path
var attachmentContent = gitClient.GetItemContentAsync(_tfsProject, new Guid("_tfsWiki repo ID"), path: path).GetAwaiter().GetResult();
}
}
private static VssCredentials GetCredentials()
{
return new VssCredentials(new Microsoft.VisualStudio.Services.Common.WindowsCredential(CredentialCache.DefaultCredentials));
}
Actually the TFS/Azure DevOps Server Wiki are just Git repos, so if you want you can clone them and get all the content by using
Git clone "https://{instance}/{collection}/{project}/_git/{projectName}"
If it's the default project wiki. If you want to get a wiki based on a git repo, then you just clone the repo in question and get the content.
Update:
Your attachments will be in the .attachments folder.

How to send a masstransit command using SQS?

I am able to send messages with rabbitmq by using this
private void SendRabbitMqCommand(string queueName, object message)
{
var hostname = ConfigurationManager.AppSettings["ExportQueueHostname"];
var uri = new Uri(string.Concat(hostname, "/", queueName));
var sendEndpoint = this._bus.GetSendEndpoint(uri).Result;
sendEndpoint.Send(message);
}
But now I need to switch to SQS. I have been trying to figure out how to build the "uri" for the GetSendEndpoint method and cannot seem to find an example in the documentation.
BTW, I am using the latest MassTransit production build 5.5.6 and my company does not like using development builds. I read that in version 6 it will be possible to do following below:
var uri = new Uri("queue:" + queueName)
But I cannot use version 6 as it is not yet released as a production build.

TfsTeamProjectCollection does not ask for credential

Dears
Please help me with VS add-in Tfs connection question.
I've wrote VS 2017 plugin that uses TfsTeamProjectCollection class to connect to the tfs server. Tfs server is hosted in the https://dev.azure.com
However on certain computers it fails to connect to the Tfs server.
For example, I've tried to reproduce this and cleared all caches like described here. After clearing/connecting several cycles I've got the following:
VS Team Explorer is connected to the Tfs. I can checkout/checkin files, load history etc.
My add-in fails to connect with 401 non authorized error.
unity test started by VS is able to connect to the same Tfs using the same code
I've created sample console application that uses exactly the same class and method from add-in to connect and it works too.
Here is the source code I'm using to connect:
public override TfsTeamProjectCollection CreateCollection(WorkspaceInfo wi)
{
var s = (overrideConfig ?? Config);
var u = wi.ServerUri;
var vssCred = new VssClientCredentials(); // GetCredentials(s.Vsts);
Logger.Debug("getting collection for url:{0}", u);
TfsTeamProjectCollection tpc = null;
try
{
tpc = new TfsTeamProjectCollection(u, vssCred);
Logger.Debug("authenticating");
tpc.Authenticate(); // 401 non authorized exception here
}
I've tried to add vssCred.Storage = new VssClientCredentialStorage(); before Autheticate() but no luck
Then I've checked network packets using Fiddler application.
It shows the same request packet is sent using unit test, console application and add-in.
But console application and unit test produces initial request
POST
https://dev.azure.com/quipu-cwnet/Services/v3.0/LocationService.asmx
HTTP/1.1
and response is
HTTP/1.1 401 Unauthorized
X-TFS-FedAuthRedirect:
https://app.vssps.visualstudio.com/_signin?realm=dev.azure.com&reply_to=https%3A%2F%2Fdev.azure.com%2F...
Then console and unit test sends packet to the redirect url and asks for user credentials.
When add-in tries to connect to the Tfs server fiddler shows only first POST request and 401 response (with the same X-TFS-FedAuthRedirect header. But there is no redirection. From user side it looks like application freezes for some period after 401 response is obtained and then fails with 401 error.
Both Unit test and add-in assemblies has the same references to the 15.0.0 assemblies like Microsoft.TeamFoundation.VersionControl.Client and related.
I've tried VssConnection but the same
VssConnection connection = new VssConnection(u, vssCred);
connection.ConnectAsync().SyncResult();
var prj = connection.GetClient<ProjectHttpClient>();
var prjCollection = prj.GetProjects().Result; // 401 error here when is executed as VS add-in
foreach (var pc in prjCollection)
Logger.Debug("\tVssConnection project {0} {1}", pc.Id, pc.Name);
I'm using the same user to start VS (and add-in) and console. No elevated permissions.
Is there anything I can do with TfsConnection when used as VS add-in ?
the answer is to execute Authenticate() in the separate thread (non GUI) :crazy
var authTask = Task.Run(() => tpc.Authenticate());
authTask.Wait();
Please note that I'm using VS 2017 15.9.11 and Microsoft.TeamFoundationServer.ExtendedClient.15.112.1
upd1: I've upgraded Microsoft.TeamFoundationServer.ExtendedClient to 15.113.1
it works on my machine but still fails on my colleague machine.
Tfs credentials are working like a charm on both machines:
var tfsClientCredentials = TfsClientCredentials.LoadCachedCredentials(wi.ServerUri, false, false);
var res = new TfsTeamProjectCollection(wi.ServerUri, tfsClientCredentials);
res.EnsureAuthenticated();
despite the fact it is marked as obsolete.

Get the URL of the WebAccess for a TFS Team Project programmatically

I want to get the URL of the web access Page for a specific TeamProject.
I found some samples using a TswaClientHyperlinkService object calling GetHomeUrl(new Uri("MyprojectName")), but I was not able to provide a correct Uri value for that. Maybe I did not understand how to format the parameter..
I know how to get the base url for the webaccess, but I want to get to the page for a specific Team Project within a specifc Team Project Collection.
It turns out that the GetHomeUrl method expects a vsts:// url, not the url to the project collection you'd normally use. The following code can be used to get the Uri:
var server = TfsConfigurationServerFactory.GetConfigurationServer(new Uri("http://localhost:8080/tfs" /* your tfs uri here */));
server.Authenticate();
var service = server.GetService<TswaClientHyperlinkService>();
var projectCollection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri("http://localhost:8080/tfs/DefaultCollection"));
var cssService = projectCollection.GetService<ICommonStructureService3>();
var project = cssService.GetProjectFromName(/*YourProjectNameHere*/);
var home = service.GetHomeUrl(new Uri(project.Uri));

TfsTeamProjectCollectionFactory.GetTeamProjectCollection failing despite available TFS server

So, I have a TFS server at http://mytfsserver:8080. I'm connected to it fine from visual studio doing all the usual TFSy things without any issue at all.
I'm trying to connect from code though - I do the following:
tfs = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri("http://mytfsserver:8080"));
tfs.EnsureAuthenticated();
But I get a TeamFoundationServiceUnavailableException.
I'm not connecting to my server in any funny ways, so what is different about what I'm doing to what VS does when it connects?
You just need to add the collection name at the end of the Uri
var tfs = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(
new Uri("http://TFS:8080/TFS/DefaultCollection"));
Try adding /tfs to your server URI.
var tfsServerUri = new Uri("http://mytfsserver:8080/tfs");
var tfs = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(tfsServerUri);
tfs.EnsureAuthenticated();

Resources