If a user is already logged into a Portal will my code override their currently active Portal?

1118
9
Jump to solution
02-12-2020 09:46 AM
Vidar
by
Occasional Contributor II

Basically I don't want to "hijack" and take over the user's active portal (i.e. the one setup by the user through the Pro UI) because it could be their company's own portal and it's useful to them in session.  I want my code to be able to login to a portal different from the user's active one (their company's portal) and do some things without affecting the user's portal that they currently think they are still connected to in that session. 

So if I did some code like this:

var someOtherCompanyUri = new Uri("http://someothercompany.com/portal/", UriKind.Absolute); 
var someOtherCompanyPortal = ArcGISPortalManager.Current.AddPortal(someOtherCompanyUri);
ArcGISPortalManager.Current.SetActivePortal(someOtherCompanyPortal);

Will this change the user's active portal that was setup up by them through the standard UI of ArcGIS Pro? Effectively kicking them off their company's portal say?

If it does, is there a way to get round this?

Tags (1)
0 Kudos
1 Solution

Accepted Solutions
Wolf
by Esri Regular Contributor
Esri Regular Contributor

Hi Simon,

 Charlie is out of town so i looked at your issue and found the following:

I you search on a portal, let's call this portal 'X', that is not the 'active' portal, let's call the active portal 'Y', the search on portal 'X' works as long as you are signed in on portal 'X'.  So far so good.  In my sample i am searching and finding  a 'Portal Feature Layer' on my portal 'X' (a local Enterprise portal), however, my active portal 'Y' is ArcGIS Online.  Below is a screen shot of the portal 'X' item i am trying to add to my map:

Your code snippet above is correct, as you have to first create an Item using 'ItemFactory.Instance.Create' by passing in the portal 'X' item's ID and eventually you call 'LayerFactory.Instance.CreateLayer' by passing in that item created by item factory.  However, it turns out that both methods:  ItemFactory.Instance.Create and LayerFactory.Instance.CreateLayer will not work if the portal 'X' is not the active portal.  You can actually observe the same behavior if you take the portal URL of your portal 'X' item and try to add it to your map manually through the 'Add Data from Path' dialog:

You will get this error if Portal 'X' is not the active portal.  

If you change Portal 'X' to be the active portal temporarily then 'Add Data from Path' works fine.  So this led me to the following workaround for this issue - by simply changing Portal 'X' to be the active portal until the layer has been created, then restoring the original active portal:

private async Task SignInAsync(ArcGISPortal nonActivePortal)
{
  var signInResult = await nonActivePortal.SignInAsync();
  var pqp = PortalQueryParameters.CreateForItemsOfType(PortalItemType.Layer, "title:fooLayerTitle");
  PortalQueryResultSet<PortalItem> results = await ArcGISPortalExtensions.SearchForContentAsync(nonActivePortal, pqp);

  //Get the first result
  var myPortalItem = results.Results?.OfType<PortalItem>().FirstOrDefault();
  FeatureLayer featureLayer = null;
  Item testLayer = ItemFactory.Instance.Create(myPortalItem.ID, ItemFactory.ItemType.PortalItem);
  // let's try to change the active portal
  var currentActivePortal = ArcGISPortalManager.Current.GetActivePortal();
  if (testLayer == null && nonActivePortal != currentActivePortal)
  {
    ArcGISPortalManager.Current.SetActivePortal(nonActivePortal);
    testLayer = ItemFactory.Instance.Create(myPortalItem.ID, ItemFactory.ItemType.PortalItem);
  }
  if (LayerFactory.Instance.CanCreateLayerFrom(testLayer))
  {
    await QueuedTask.Run(() =>
    {
      featureLayer = LayerFactory.Instance.CreateLayer(testLayer, MapView.Active.Map, 0) as FeatureLayer;
    });
  }
  // reset the original active portal
  if (nonActivePortal != currentActivePortal)
    ArcGISPortalManager.Current.SetActivePortal(currentActivePortal);
}

i will bring this issue to the attention of our development group. For the time being see if the workaround will suffice.

- Wolf

View solution in original post

9 Replies
CharlesMacleod
Esri Regular Contributor

Assuming you have a portal instance (eg via GetPortal from the ArcGISPortalManager), you could use its SignInAsync method to sign in. This will prompt for credentials with the sign-in window unless they have been previously cached (eg, via a preceding connection).

If you need a token for REST requests then call GetToken to get the token.

0 Kudos
Vidar
by
Occasional Contributor II

OK - I do have a portal instance with credentials that I want the user to use (let's say I've sent these details and credentials in an email) - if after they have signed in via the sign-in window, will this kick them off the Portal they were just using?

0 Kudos
CharlesMacleod
Esri Regular Contributor

No. The active portal will remain the active portal

0 Kudos
Vidar
by
Occasional Contributor II

The SignInAsync() doesn't allow me to add any content into Pro (i.e. a feature layer) from "someothercompany" portal - (for simplicity I have passed the unique id of the layer) see code below:

public static async Task AddAGOLTestLayer(string layerId)
{
  Item testLayer = ItemFactory.Instance.Create(layerId, ItemFactory.ItemType.PortalItem);
  await QueuedTask.Run(() =>
  {
    if (LayerFactory.Instance.CanCreateLayerFrom(testLayer))
    LayerFactory.Instance.CreateLayer
 (testLayer, MapView.Active.Map, 0) as FeatureLayer;
  });

}

The only way I can get the code to work above is by setting the Active Portal to "someothercompany" - but, as my original question outlines, I don't want to do that. I just thought I would try it to make sure that was the case

So what actual functionality do you have when using the SignInAsync() method?

Can I add data to Pro without setting the Active Portal? Or is it just searching for content or something?

To get the behaviour I want would I have to cache the object/details of the currently active portal - switch into "someothercompany" portal, make it active add content etc, then switch back to cached portal. Seems cluncky though.

Do I have to start calling rest endpoints to get content into Pro using EsriHttpClient instead of using code like above? This I suspect is more involved than just using out of the box api calls like above.

0 Kudos
CharlesMacleod
Esri Regular Contributor

Hi Simon, as I mentioned earlier, the active portal remains the active portal even if you programmatically connect to a different portal and there is only one portal active at any given time.

You could try to search and retrieve item content via portal methods from your non-active portal...and then use MapFactory.CreateMapFromItem or LayerFactory.CreateItem overloads that consume Item (depending on what the content is).

0 Kudos
Vidar
by
Occasional Contributor II

Hi Charles,

Yep, I've tried adding layers from my non-active portal (with the code I posted before - AddAGOLTestLayer()) - it just returns null when it tries to create the layer from the factory. But when active its ok, it returns a valid layer.

I will try and search for content after my SignInAsync() and then add Layer from there - but I can't see how that works - it makes no sense that you have to do a search in order to get the LayerFactory to work successfully.

UPDATE

So bascially I have tried searching for content under my non-active portal and results are brought back - yay!

When trying to add content to the map (still under my non-active portal) - using the LayerFactory method - it still returns null, so basically I can't add content.

Here is my code below:

private async Task SignInAsync(ArcGISPortal nonActivePortal)
{
  var signInResult = await nonActivePortal.SignInAsync();
  var pqp = PortalQueryParameters.CreateForItemsOfType(PortalItemType.Layer, "title:fooLayerTitle");
  PortalQueryResultSet <PortalItem> results = await ArcGISPortalExtensions.SearchForContentAsync(nonActivePortal, pqp);

  //Get the first result
  var myPortalItem = results.Results?.OfType<PortalItem>().FirstOrDefault();
  FeatureLayer featureLayer = null;
  Item testLayer = ItemFactory.Instance.Create(myPortalItem.ID, ItemFactory.ItemType.PortalItem);
  await QueuedTask.Run(() =>

  {
    if (LayerFactory.Instance.CanCreateLayerFrom(testLayer))

        featureLayer = LayerFactory.Instance.CreateLayer(testLayer, MapView.Active.Map, 0) as FeatureLayer;
  });

}

0 Kudos
RichardHowe
Occasional Contributor III

I'm confused.

Charles Macleod

What is the purpose of allowing a connection to a non-active portal if you can't use this method to add data? Unless I'm misunderstanding then surely the entire purpose of this functionality is to allow a user to add data from a non-active portal

Wolf
by Esri Regular Contributor
Esri Regular Contributor

Hi Simon,

 Charlie is out of town so i looked at your issue and found the following:

I you search on a portal, let's call this portal 'X', that is not the 'active' portal, let's call the active portal 'Y', the search on portal 'X' works as long as you are signed in on portal 'X'.  So far so good.  In my sample i am searching and finding  a 'Portal Feature Layer' on my portal 'X' (a local Enterprise portal), however, my active portal 'Y' is ArcGIS Online.  Below is a screen shot of the portal 'X' item i am trying to add to my map:

Your code snippet above is correct, as you have to first create an Item using 'ItemFactory.Instance.Create' by passing in the portal 'X' item's ID and eventually you call 'LayerFactory.Instance.CreateLayer' by passing in that item created by item factory.  However, it turns out that both methods:  ItemFactory.Instance.Create and LayerFactory.Instance.CreateLayer will not work if the portal 'X' is not the active portal.  You can actually observe the same behavior if you take the portal URL of your portal 'X' item and try to add it to your map manually through the 'Add Data from Path' dialog:

You will get this error if Portal 'X' is not the active portal.  

If you change Portal 'X' to be the active portal temporarily then 'Add Data from Path' works fine.  So this led me to the following workaround for this issue - by simply changing Portal 'X' to be the active portal until the layer has been created, then restoring the original active portal:

private async Task SignInAsync(ArcGISPortal nonActivePortal)
{
  var signInResult = await nonActivePortal.SignInAsync();
  var pqp = PortalQueryParameters.CreateForItemsOfType(PortalItemType.Layer, "title:fooLayerTitle");
  PortalQueryResultSet<PortalItem> results = await ArcGISPortalExtensions.SearchForContentAsync(nonActivePortal, pqp);

  //Get the first result
  var myPortalItem = results.Results?.OfType<PortalItem>().FirstOrDefault();
  FeatureLayer featureLayer = null;
  Item testLayer = ItemFactory.Instance.Create(myPortalItem.ID, ItemFactory.ItemType.PortalItem);
  // let's try to change the active portal
  var currentActivePortal = ArcGISPortalManager.Current.GetActivePortal();
  if (testLayer == null && nonActivePortal != currentActivePortal)
  {
    ArcGISPortalManager.Current.SetActivePortal(nonActivePortal);
    testLayer = ItemFactory.Instance.Create(myPortalItem.ID, ItemFactory.ItemType.PortalItem);
  }
  if (LayerFactory.Instance.CanCreateLayerFrom(testLayer))
  {
    await QueuedTask.Run(() =>
    {
      featureLayer = LayerFactory.Instance.CreateLayer(testLayer, MapView.Active.Map, 0) as FeatureLayer;
    });
  }
  // reset the original active portal
  if (nonActivePortal != currentActivePortal)
    ArcGISPortalManager.Current.SetActivePortal(currentActivePortal);
}

i will bring this issue to the attention of our development group. For the time being see if the workaround will suffice.

- Wolf

Vidar
by
Occasional Contributor II

Thanks Wolf

You have done exactly as I have done whilst waiting for a response - basically toggling between making the non-active portal active, adding the data then making it non-active again.

This workaround will suffice whilst I get on building the rest of my add-in, and it certainly confirms my findings which gives me confidence to continue the rest of my code. However I hope that with your input that you can influence the development team to prioritise a change in behaviour - so that you can add content from an non-active portal.

Thanks once again, and thanks to Charlie too for your help. I look forward to seeing develpments in this area

Simon.

0 Kudos