I am currently developing a GP Tool / WebTool for ArcGIS Enterprise. Main goal of the tool is to write what3word tags to point features.
Workflow is as follows:
- User selects a layer in the webmap
- Run the tool
- Tool checks if certain attributes are available in the layer (
w3w
,w3w_last_edited_date
andlast_edited_date
– editor tracking must be enabled) - If
w3w_last_edited_date
andlast_edited_date
do not match the w3w field gets updated using the w3w endpoint likehttps://api.what3words.com/v3/convert-to-3wa?coordinates={lat}%2C{lng}&key={key}
Running the tool from ArcGIS Pro is working fine. But when I publish it as a WebTool
on ArcGIS Enterprise I get a long error message – the important part is Exception: Unable to generate token. 'token' must be specified in the request, for server token.
As you can see in my code I am using the GetSigninToken
method from arcpy
. But it looks like this is not what I want. My question is – is it possible to access the token of the user who runs the GP Tool / WebTool so the tool can make all the requests / updates using the user token?
from arcpy import GetSigninToken, GetParameterAsText, AddMessage, AddError
from arcgis.features import FeatureLayer, FeatureCollection
from platform import node
from datetime import datetime
import requests
# Main Function
def ScriptTool(featureLayerUrl):
# W3W Key
W3WKEY = "********"
# Check for token
tokenDict = GetSigninToken()
if tokenDict is not None:
token = tokenDict["token"]
# Load Layer
layerUrl = f'{featureLayerUrl}/0?token={token}'
featureLayer = FeatureLayer(layerUrl)
# Check if mandatory fields exist
mandatoryFieldNames = ["w3w", "w3w_last_edited_date", "last_edited_date"]
existingFieldNames = [f["name"] for f in featureLayer.properties["fields"]]
for mandatoryFieldName in mandatoryFieldNames:
if mandatoryFieldName not in existingFieldNames:
AddError(f'Missing mandatory field: {mandatoryFieldName}!')
return
# Iterate over all items
# If w3w_last_edited_date and last_edited_date are different update w3w
fc = FeatureCollection.from_featureset(featureLayer.query(out_sr=4326))
updates = []
for feature in fc.query():
# Access properties
w3w_last_edited_date = feature.attributes["w3w_last_edited_date"]
last_edited_date = feature.attributes["last_edited_date"]
lat = feature.geometry["y"]
lng = feature.geometry["x"]
# Check if date changed
if w3w_last_edited_date != last_edited_date:
try:
res = requests.get(f'https://api.what3words.com/v3/convert-to-3wa?coordinates={lat}%2C{lng}&key={W3WKEY}')
w3w = res.json()["words"]
feature.attributes["w3w"] = w3w
feature.attributes["w3w_last_edited_date"] = last_edited_date
updates.append(feature)
AddMessage(f'Updated location at Lat: {lat}, Lng: {lng}')
except:
AddError("Error updating w3w")
update_result = featureLayer.edit_features(updates=updates)
AddMessage(update_result)
return
# This is used to execute code if the file was run but not imported
if __name__ == '__main__':
# Parameter 1 is the layer on which the w3w tag should be set
featureLayerUrl = GetParameterAsText(0)
ScriptTool(featureLayerUrl)
Best Answer
The key point here can be found in the help of the GetSignInToken tool
This tool is to be used from within ArcGIS Pro, where you have already signed in to the Portal. Your web tool is not signed in. The GetSigninToken tool is able to take advantage of the already established connection and grab the token for you. You would need to sign in when the tool is run. The session (and being signed in) does not persist from one web tool execution to another. I'd look into using the SignInToPortal tool to establish that connection. I'll caution: depending on the authentication requirements of your Portal, it's possible this may not work. The next caution is you'll need to hard code username and passwords into the tool. If you aren't comfortable doing this, you'll need to look into other ways to authenticate (such as the ArcGIS Python API, as this offers different ways to 'login')