I am not sure if this is the same issue, or if it has been fixed in a later version of Runtime (we are still on 100.6). But I have seen a timing issue with credentials. It is discussed a bit here:
Offline Map Sync Error: Job error 6004...
I am not sure if this is related but was happening when I tried to sync soon after connecting the credentials had not been been applied to everything in my offline map. So I got credentials errors. Even though I set the credentials.
What I do to solve this is basically make a dummy hit against all layers before actually trying to do the real load of them.
Basically I load a layer, don't worry if it gives me an error and then load the layer again and the second time the token has been properly applied.
/// <summary>
/// This is used because of issue with the timing issues associated to
/// getting tokens in first sync
/// </summary>
/// <returns></returns>
private async Task InitialzeTokens(Map map)
{
if ( !_firstSync ) return;
foreach (var featureLayer in map.OperationalLayers.OfType<FeatureLayer>())
{
var pars = new QueryParameters {WhereClause = "1=0", MaxFeatures = 1};
if ( !(featureLayer.FeatureTable is GeodatabaseFeatureTable gdbFeatureTable) ) continue;
if ( gdbFeatureTable.Geodatabase?.Source == null ) continue;
var serviceFeatureTable = new ServiceFeatureTable(gdbFeatureTable.Geodatabase.Source);
try
{
await serviceFeatureTable.LoadAsync();
var _ = await serviceFeatureTable.QueryFeaturesAsync(pars);
}
catch (Exception)
{
//_log.Error(e, e.Message);
}
}
_firstSync = false;
}
Also along the lines of what @JenniferNery describes. Instead of doing
IdentityManager.Current.AddCredential(cred);
Use the ChallengeHandler and you can see when it requests credentials
//put in constructor
AuthenticationManager.Current.ChallengeHandler = new ChallengeHandler(CreateCredentialAsync);
private async Task<Credential> CreateCredentialAsync(CredentialRequestInfo info)
{
try
{
_log.Info($"CHALLENGE ********** : {info.ServiceUri} ***********");
if ( info.ServiceUri == null ) return null;
var credential = await AuthenticationManager.Current.GenerateCredentialAsync(info.ServiceUri, Settings.UserName, Settings.Password);
_log.Info($"RETURN credential *********: {info.ServiceUri} ********");
return credential;
}
catch (Exception e)
{
_log.Error(e, e.Message);
return null;
}
}
Good Luck
Thanks,
-Joe