FeatureLayer with Tokens

415
8
Jump to solution
07-14-2021 10:53 AM
JeffBoyton
New Contributor II

I am connection to a Map Service that requires a token and this code works to get the list of layers (where url is something like http://myhost/arcgis/rest/services/MapServer?token=abcdefg😞

using (var client = new HttpClient())
{
    client.BaseAddress = new Uri(url + "&f=pjson");
    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    return client.GetAsync("").Result;
}

I then want to go through each layer and add it as a feature layer to a map (where layerUrl looks like  http://myhost/arcgis/rest/services/MapServer/5?token=abcdefg)

Uri serviceUri = new Uri(layerUrl);
FeatureLayer layer = new FeatureLayer(serviceUri);

await layer.LoadAsync();
Map.OperationalLayers.Add(layer);

This does not seem to be working.  I am getting no errors, but the layer is also showing no features.  Is it obvious what I am doing wrong?

0 Kudos
2 Solutions

Accepted Solutions
AdityaTogani
Esri Contributor

The recommended way to authenticate is to generate tokens using the AuthenticationManager as done above. But if you already have a token, you can add it to the outgoing request by doing something like this 

ArcGISHttpClientHandler.HttpRequestBegin += (a, b) =>
{
    if (b.RequestUri.OriginalString.Contains(mapserverUrl))
    {
        b.RequestUri = new Uri(b.RequestUri + "token=abcdefg");
    }

    //OR try adding the token as part of the header

    if (b.RequestUri.OriginalString.Contains(mapserverUrl))
    {
        b.Headers.Add("X-Esri-Authorization", "My Custom Header");
    }
};
ArcGISHttpClientHandler.HttpResponseEnd += (a, b) =>
{
    // Check for response codes here
};

 

View solution in original post

0 Kudos
AdityaTogani
Esri Contributor

If you use the authentication code mentioned in my previous reply then every time a request is made to the requestUri, the Clienthandler will kick in and add the token/authorization header to the outgoing request.

View solution in original post

0 Kudos
8 Replies
AdityaTogani
Esri Contributor

Hello,

Is this a custom token parameter that is specific to your environment?

0 Kudos
JeffBoyton
New Contributor II

No, this would be a security token created for a 'secure' map service.  I am actually simulating the existence of this token parameter (this is a customer environment I do not have access to) by putting '?blah=blah' at the end of the REST url.

0 Kudos
AdityaTogani
Esri Contributor

Do you have the credentials for the user's ArcGIS Server (username and password)?

If yes, then you can try using the following code to generate tokens

MyView1.Map = new Map(Basemap.CreateImagery());
Esri.ArcGISRuntime.Security.AuthenticationManager.Current.ChallengeHandler = new ChallengeHandler(
    async info => await Esri.ArcGISRuntime.Security.AuthenticationManager.Current.GenerateCredentialAsync
                                (info.ServiceUri,
                                    "username",
                                    "password", info.GenerateTokenOptions));
var featureURL = "http://myhost/arcgis/rest/services/MapServer/5";
var layer = new FeatureLayer(new Uri(wms));
await layer.LoadAsync();
MyView1.Map.OperationalLayers.Add(layer);
0 Kudos
JeffBoyton
New Contributor II

I do not have a username/password (which is why I am using a generated token).

0 Kudos
AdityaTogani
Esri Contributor

The recommended way to authenticate is to generate tokens using the AuthenticationManager as done above. But if you already have a token, you can add it to the outgoing request by doing something like this 

ArcGISHttpClientHandler.HttpRequestBegin += (a, b) =>
{
    if (b.RequestUri.OriginalString.Contains(mapserverUrl))
    {
        b.RequestUri = new Uri(b.RequestUri + "token=abcdefg");
    }

    //OR try adding the token as part of the header

    if (b.RequestUri.OriginalString.Contains(mapserverUrl))
    {
        b.Headers.Add("X-Esri-Authorization", "My Custom Header");
    }
};
ArcGISHttpClientHandler.HttpResponseEnd += (a, b) =>
{
    // Check for response codes here
};

 

View solution in original post

0 Kudos
AdityaTogani
Esri Contributor

Checking the layerViewState for errors is a good way to debug your code. The spatial reference of the features and that of the map should be the same for the features to be displayed on the map. Also, if you want to parse the MapServer to get the layer ids, you can try doing something like this (using ServiceGeoDatabase instead)

var sgdb = new ServiceGeodatabase(new Uri(mapserverUrl));
await sgdb.LoadAsync();
​
var map = new Map(Basemap.CreateTopographic());
​
MyMapView.LayerViewStateChanged += (a, b) =>
    {
        var error = b.LayerViewState.Error ?? b.Layer.LoadError;
        if (error != null)
            MessageBox.Show(error.Message, error.GetType().Name);
    };
​
MyMapView.Map = map;
​
foreach(var info in sgdb.ServiceInfo.LayerInfos)
{
    var layer = new FeatureLayer(new Uri($"{mapserverUrl}/{info.Id}"));
    await layer.LoadAsync();
    map.OperationalLayers.Add(layer);
}

 

0 Kudos
JeffBoyton
New Contributor II

In this code snippet, how are you giving the FeatureLayer the security token (line 17)?

0 Kudos
AdityaTogani
Esri Contributor

If you use the authentication code mentioned in my previous reply then every time a request is made to the requestUri, the Clienthandler will kick in and add the token/authorization header to the outgoing request.

View solution in original post

0 Kudos