microsoft / azure-devops-extension-sdk

Client SDK for developing Azure DevOps extensions
MIT License
125 stars 39 forks source link

Get host URL #28

Closed pelizza closed 2 years ago

pelizza commented 4 years ago

In the old VSS SDK it was possible to retrieve the host URL easily but I can't find a way to do that with this new SDK. I suppose it's something that could easily be added to the object returned by SDK.getHost()?

This is useful since extensions run in iframes and sometimes we need to refer to the host URL. For example, I'm currently struggling to render a user avatar. The identity API returns a relative URL for the avatar and we need to append the host to it in order to render the image correctly in the iFrame.

I appreciate any guidance or having my suggestion accepted and added to the SDK.

Thanks.

altinoren commented 4 years ago

The "How to get an organization's URL" section may help:

https://docs.microsoft.com/en-us/azure/devops/extend/develop/work-with-urls?view=azure-devops&tabs=http#how-to-get-an-organizations-url

pelizza commented 4 years ago

Thank you, I can definitely use that.

However, still, would be nice to add this to the initial handshake data, as I think this information should be present there given the old SDK used to have it. It would be very simple to use and it is such basic information.

Feel free to close this issue if you think that's not important or not doable. I don't think this is a blocker, but an improvement suggestion.

pelizza commented 4 years ago

@altinoren I have been trying to use your suggestion and I have figured out how to use this with azure-devops-extension-api. However, nothing that I try seems to work well.

This is what I am currently doing:

import { LocationsRestClient } from "azure-devops-extension-api/Locations";
import { CoreRestClient } from "azure-devops-extension-api/Core";

const resourceAreas = await getClient(
    LocationsRestClient
  ).getResourceAreaByHost(CoreRestClient.RESOURCE_AREA_ID, SDK.getHost().id);

This produces a request just like the one described on the link you sent to me:

GET https://dev.azure.com/appgami-dev/_apis/ResourceAreas/79134c72-4a58-4b42-976c-04e7115f32bf?hostId=840706e2-37c7-4c99-9d67-5cfe4ef29225

...but it responds with a 500 error and the message below:

TFS.WebApi.Exception: TF400367: The request could not be performed due to a host type mismatch. Please check any connection information and verify the information is correct. The request was executed against a ProjectCollection.

I'm trying this on AzureDevops Services.

Have you got any ideas of why this error happens?

Thank you.

EDIT:

This works well for retrieving the host base URL:

  const service = await SDK.getService(CommonServiceIds.LocationService);
  const hostBaseUrl = await service.getResourceAreaLocation(
    CoreRestClient.RESOURCE_AREA_ID
  );

Still, there seems to be a bug on the previous endpoint I mentioned above this EDIT.

FlexiGit commented 4 years ago

I'm using this:

import * as SDK from "azure-devops-extension-sdk";
import { getClient } from "azure-devops-extension-api/Common";
import { CoreRestClient } from "azure-devops-extension-api/Core";

const collId = SDK.getHost().id;
const coreClient = getClient(CoreRestClient);
const collection = await coreClient.getProjectCollection(collId);
return collection._links.web.href;

Unfortunately I only found this while inspecting the returned objects in browser debug console and it is using internal/private code. But since this repo seems not to be updated very frequently I guess you could call it stable.

pelizza commented 4 years ago

Thanks @FlexiGit, good to know that there are alternatives. I'm pasting here my edit above, just so it's better visible since it also works for retrieving the base URL:

import * as SDK from "azure-devops-extension-sdk";
import { CoreRestClient } from "azure-devops-extension-api/Core";
import { CommonServiceIds } from "azure-devops-extension-api";

const service = await SDK.getService(CommonServiceIds.LocationService);
const hostBaseUrl = await service.getResourceAreaLocation(
  CoreRestClient.RESOURCE_AREA_ID
);
tomsjansons commented 2 years ago

Even though this issue is closed, I thought I'd share what I've found. The full URL can be recreated by doing the following

const navigationService = await SDK.getService<API.IHostNavigationService>(CommonServiceIds.HostNavigationService)
const locationService = await SDK.getService<API.ILocationService>(CommonServiceIds.LocationService)
const route = await navigationService.getPageRoute()
const routeUrl = await locationService.routeUrl(route.id, route.routeValues)

In my case it adds a few query parameters to the original URL but it still seems to work reliably enough to be used for my purposes