POST
|
There is currently no way from SubtypeSublayer to get to its parent layer. But if you have a feature from an identify or query, this feature has reference to the table, and the table has reference to the layer it comes from. As for the SubtypeSublayer.Id, in the Native SDKs this is meant to match the Subtype.code property. If you are using search.layer | Web Map Specification | Esri Developer, I think there's an optional subLayer property that will match SubtypeSublayer.Id. The "id" on this search is a string so it will not match the sublayer. There is however, a SubtypeSublayer.unsupportedJSON property that is deprecated and will be removed in the next release that contains the "id" string. JSON on the left can be web/mobile map, watch window on the right is from map loaded in Native SDK for .NET.
... View more
3 weeks ago
|
1
|
0
|
369
|
POST
|
The query operations are on the FeatureLayer.featureTable property. ArcGISFeatureTable, you can use the Sublayer's subtype code as additional filter in your where clause or use SubtypeSubtable. Whether you're getting SubtypeFeatureLayer from web map or table that supports subtype, you can try the following code. Notice that for "Service Station" subtype (code: 21) on a Pipeline Device there's only 1 feature of this subtype out of 31411 features. var credential = await AccessTokenCredential.CreateAsync(new Uri("https://sampleserver7.arcgisonline.com/portal/sharing/rest"), "viewer01", "I68VGU^nMurF");
AuthenticationManager.Current.AddCredential(credential);
var geodatabase = new ServiceGeodatabase(new Uri("https://sampleserver7.arcgisonline.com/server/rest/services/UtilityNetwork/NapervilleGasV6/FeatureServer"));
await geodatabase.LoadAsync();
var table = geodatabase.GetTable(0);
var layer = new SubtypeFeatureLayer(table);
await layer.LoadAsync();
var sublayer = layer.SubtypeSublayers.LastOrDefault();
ArgumentNullException.ThrowIfNull(sublayer);
var query = new QueryParameters();
query.WhereClause = $"{table.SubtypeField} = {sublayer.Subtype.Code}";
ArgumentNullException.ThrowIfNull(layer.FeatureTable);
var features = await layer.FeatureTable.QueryFeaturesAsync(query);
var subtypeTable = new SubtypeSubtable(sublayer.Subtype);
table.SubtypeSubtables.Add(subtypeTable);
var subtypeFeatures = await subtypeTable.QueryFeaturesAsync(new QueryParameters() { WhereClause = "1=1" });
var count = await layer.FeatureTable.QueryFeatureCountAsync(new QueryParameters() { WhereClause = "1=1" }); Hm, there is no back-reference to the parent layer from SubtypeSublayer though. Can you describe your workflow, how you have access to the sublayer only but not have access to the layer?
... View more
3 weeks ago
|
0
|
1
|
408
|
POST
|
Just adding to William's suggestion. Should you need to get more information about the GenerateOfflineMapJob and its subjobs, before awaiting for the job's result, you can subscribe and print out messages for the job. It may tell you more where it's failing. job.MessageAdded += (s, e) =>
{
System.Diagnostics.Debug.WriteLine($"{e.Severity}{e.Message}");
}; When you get this value - you can inspect what the current UtilityNetworkSyncMode, SyncModel, ContinueOnError properties as well before changing it. var gdbParameters = paramsOverride.GenerateGeodatabaseParameters[overrideKey];
... View more
06-06-2025
10:14 AM
|
1
|
0
|
344
|
POST
|
Side note if you're on 11.1, there is a config file you can change to see this advanced option UI see step 4 here: Offline Utility Networks in ArcGIS Maps SDKs for Native Apps: Part 2 Offline Utility Networks in ArcGIS Native SDKs: Part 2 Update the config.js file to enable the utility network offline options on your ArcGIS Enterprise Portal. Find the Home App config.js file in your Portal installation directory. This can typically be found at the following location: C:\Program Files\ArcGIS\Portal\framework\webapps\arcgis#home\js\arcgisonline. Using a standard text editor, find the line that reads utilNetworkOfflineOptionsEnabledand change its value from false to true. Restart Portal for ArcGIS Enterprise.
... View more
04-02-2025
07:13 PM
|
0
|
0
|
656
|
POST
|
I'm glad to have met you finally. Thank you for being an MVP! You've helped fellow developers and given us feedback to improve our API. I can't remember all now but the definition expression affecting `GetFeaturesForElementsAsync` is from you. Good to know it's working for you now. Jennifer
... View more
04-02-2025
07:08 PM
|
0
|
0
|
656
|
POST
|
Hi Joe, It is possible for field crew without UN extensions to download edits from server by disabling editing capabilities on the feature service. You can check out the "Trace Offline (read-only)" in this part 4 of the blog series. The utility network sync mode for offline map is determined from this advanced offline setting of the portal item. This cannot be changed for ahead-of-time workflow with preplanned map area since the geodatabase is generated on the server and only downloaded on the client. But if you have 11.3 with the offline patch, there is a known limitation that it remains read-only despite the portal item advanced offline setting indicating "Trace and edit" for preplanned map area. If you are using on-demand workflow where you generate the offline map on the client by specifying an area of interest, you can still change this utility network sync mode using parameters override. This can also be found in our guide doc. var task = await OfflineMapTask.CreateAsync(map);
var parameters = await task.CreateDefaultGenerateOfflineMapParametersAsync(areaOfInterest);
var parametersOverride = await task.CreateGenerateOfflineMapParameterOverridesAsync(parameters);
var overrideKey = new OfflineMapParametersKey(map.UtilityNetworks[0]);
var geodatabaseParameters = parametersOverride.GenerateGeodatabaseParameters[overrideKey];
// simple features
geodatabaseParameters.UtilityNetworkSyncMode = UtilityNetworkSyncMode.None;
var job = task.GenerateOfflineMap(parameters, downloadDirectoryPath, parametersOverride);
var result = await job.GetResultAsync(); But I think if you want the ability to trace, this should be UtilityNetworkSyncMode.SyncSystemAndTopologyTables with a feature service that is read-only, which will allow you download-only sync. I hope this helps. Jennifer
... View more
04-02-2025
02:58 PM
|
0
|
0
|
681
|
POST
|
Hi Pierre, I have not seen sluggish query when zooming in/out but I've seen the expected lock errors when editing the same version simultaneously from different apps. How are you creating the ServiceGeodatabase? If you're opening from a web map, there is a load setting that you can set to persistent if you wish to lock the version for editing. It is transient by default. If you've created from URL, be sure all layers and tables of the map come from the same service geodatabase. Use the service geodatabase to apply the edits (instead of table apply edits). More information about session management here. When starting from web map var map = new Map(new Uri(WebmapItemUrl));
map.LoadSettings = new LoadSettings() { FeatureServiceSessionType = FeatureServiceSessionType.Persistent }; When starting from feature service URL var sgdb = await ServiceGeodatabase.CreateAsync(featureServiceUrl, FeatureServiceSessionType.Persistent); // specify session mode Be sure to call close at the end when done with working on the branch version to release the read/write locks. var parameters = new ServiceVersionParameters()
{
Name = $"VALID_VERSION_{digits}",
Description = versionDescription,
Access = VersionAccess.Private
};
var serviceVersionInfo = await sgdb.CreateVersionAsync(parameters); // create version
await sgdb.SwitchVersionAsync(serviceVersionInfo.Name); // switch
var layer = sgdb.GetTable(serviceLayerId); // all layers/tables
await sgdb.CloseAsync(); // when done Opening the same version in ArcGIS Pro or Map Viewer will attempt to acquire read and write locks as well. On the server, there's purge lock and delete version that will allow you to cleanup versions that should be released and deleted.
... View more
03-17-2025
09:47 AM
|
1
|
0
|
360
|
POST
|
Hi Joe,
The ExportDeltaAsync is based on the last sync time on the geodatabase. I just tested the following code, if there's a syncGeodatabase happened in between, no delta is created. Code snippet against sample server is shared below.
HasEdits only reset after edits are applied/sync'd or undone/rolled back. Edits in a mobile geodatabase can be wrapped in explicit transaction by gdb.Begin/Commit/RollbackTransaction().
If you're uploading client delta a different way, the API will not have information about the last acknowledged update to compare with the edit and gdb tracking fields. Geodatabase.hasLocalEdits(), ArcGISFeatureTable.hasLocalEdits() and ArcGISFeatureTable.getLocalEditsAsync() are all based on this time. There's a GeodatabaseFeatureTable.getHasLocalEditsSince() with DateTimeOffset parameter that you could use but it only returns boolean.
Is there something in the current sync workflow that can be improved to support your custom sync processes?
private const string FeatureServiceUrl = "https://sampleserver6.arcgisonline.com/arcgis/rest/services/Sync/SaveTheBaySync/FeatureServer";
private async Task TestExportDeltaAsync(bool syncBeforeExport = false)
{
try
{
var task = await GeodatabaseSyncTask.CreateAsync(new Uri(FeatureServiceUrl));
var areaOfInterest = task.ServiceInfo?.FullExtent;
ArgumentNullException.ThrowIfNull(areaOfInterest);
var parameters = await task.CreateDefaultGenerateGeodatabaseParametersAsync(areaOfInterest);
var pathToGeodatabase = $@"C:\dev\gdb\{Guid.NewGuid()}.geodatabase";
Debug.WriteLine(pathToGeodatabase);
var job = task.GenerateGeodatabase(parameters, pathToGeodatabase);
var gdb = await job.GetResultAsync();
// introduce an edit
areaOfInterest = gdb.GenerateGeodatabaseGeometry?.Extent;
ArgumentNullException.ThrowIfNull(areaOfInterest);
if (gdb.GetGeodatabaseFeatureTable(0) is GeodatabaseFeatureTable table)
{
await table.LoadAsync();
if (table.GeometryType == GeometryType.Point
&& table.FeatureTypes.Count > 0
&& !string.IsNullOrEmpty(table.LayerInfo?.DisplayFieldName))
{
var random = new Random();
var index = random.Next(0, table.FeatureTypes.Count - 1);
var featureType = table.FeatureTypes[index];
double x = areaOfInterest.XMin + random.NextDouble() * areaOfInterest.Width;
double y = areaOfInterest.YMin + random.NextDouble() * areaOfInterest.Height;
var point = new MapPoint(x, y, areaOfInterest.SpatialReference);
var feature = table.CreateFeature(featureType, point);
feature.SetAttributeValue(table.LayerInfo.DisplayFieldName, $"Added on {DateTimeOffset.UtcNow}");
await table.AddFeatureAsync(feature);
}
}
if (syncBeforeExport)
{
var syncParameters = await task.CreateDefaultSyncGeodatabaseParametersAsync(gdb);
var syncJob = task.SyncGeodatabase(syncParameters, gdb);
await syncJob.GetResultAsync();
}
var deltaPath = $@"{gdb.Path.Replace(".geodatabase", "")}-delta.geodatabase";
var hasDeltaExported = await GeodatabaseSyncTask.ExportDeltaAsync(gdb, deltaPath);
Debug.WriteLine($"Exported? {hasDeltaExported}");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
private async void OnExportDelta(object sender, RoutedEventArgs e)
{
await TestExportDeltaAsync(true);
await TestExportDeltaAsync(false);
}
Thanks.
Jennifer
... View more
09-25-2024
11:21 AM
|
0
|
0
|
404
|
POST
|
No problem. The NumberOfFeatures would be a cumulative value of the features retrieved in the table so far. So if you have this table rendered as a layer on a map, a query with view extent would have already run to fetch features. Or if you had previous queries made with different fips value. There is a QueryFeatureCountAsync method if you only want the count for features from a specific query. But if you will be working on the features returned from QueryFeaturesAsync then you can use features.Count() instead where features is the return value of the awaited query task.
... View more
07-24-2024
07:32 AM
|
1
|
0
|
829
|
POST
|
I don't see anything wrong with how you formed the query. String equality looks correct provided the field exists with the correct name and type. If you want query to return just one, you can set MaxFeatures = 1; but if you say this value is unique then you should expect a single feature returned without MaxFeatures. var attributeValue = "270530265081";
var table = BlockGroupGeoPackage.GeoPackageFeatureTables[0];
var tableField = table.GetField("fips");
var query = new QueryParameters()
{
WhereClause = $"{tableField.Name} = '{attributeValue}'",
MaxFeatures = 1
};
I would await the result of query though and may be inspect the features that come back. Output window should have the attribute value for each feature. var features = await table.QueryFeaturesAsync(query);
foreach(var feature in features)
{
// Consider printing other attributes to identify the feature (i.e. OBJECTID)
System.Diagnostics.Debug.WriteLine($"{tableField.Name}: feature.Attribute[tableField.Name]")
}
... View more
07-23-2024
06:26 PM
|
0
|
2
|
897
|
POST
|
I do not see anything wrong with your code that could've led to this error. Just a suggestion (but likely not relevant to the error you're seeing) since you are awaiting the result of syncJob.GetResultAsync() already in a try-catch. There is no need to call syncJob.Start() or handle success/fail in JobChanged. Based on the API name, I think you are using an older version of ArcGIS Maps SDK for .NET. One thing I would like to suggest (if you're able) is try the same request with latest 200.4. The equivalent event for JobChanged is StatusChanged. There is also a MessageAdded that could provide some insight at what stage this error happens (if it still happens). There could be a number of things that could result to this generic server error. Are you able to inspect ArcGISWebException.Details property? According to this doc, one possibility is the replica GUID no longer exists on server. If you have access to the ArcGIS Server Logs, it may give more information on the GP Server error. You can also see if you are hitting these support issues: https://support.esri.com/en-us/knowledge-base/error-code-400-description-unable-to-complete-operation-000020342 https://support.esri.com/en-us/knowledge-base/problem-unable-to-sync-services-in-arcgis-server-000027501 Another case that I've seen in my sync testing, it's possible for sync to fail to acquire the necessary lock to apply delta changes or have synchronization conflicts that need to be resolved.
... View more
06-04-2024
09:17 AM
|
0
|
0
|
569
|
POST
|
Thanks for following-up and sharing with us the root of the problem. I am curious to know how the table was created and why ServiceGeodatabase do not see this edit. If you loaded the feature service from a webmap or called ServiceGeodatabase.getTable() to create the ServiceFeatureTable, the ServiceFeatureTable will have a ServiceGeodatabase property. You'd see ServiceGeodatabase.connectedTables include this table. Your feature should have access to the same ServiceGeodatabase. If however, you used a ServiceFeatureTable constructor, then the table will not have a ServiceGeodatabase. You can add a check to ServiceGeodatabase.hasLocalEdits() or ServiceFeatureTable.hasLocalEdits(), before calling the appropriate applyEdits. If this returns false, there are no edits to send to server. It is best to use ServiceGeodatabase, for these reasons: https://developers.arcgis.com/net/edit-features/apply-edits/ if (feature.FeatureTable is ServiceFeatureTable sft && sft.ServiceGeodatabase is ServiceGeodatabase sgdb)
{
if (sgdb.HasLocalEdits())
{
await sgdb.ApplyEditsAsync();
}
}
... View more
04-08-2024
09:13 AM
|
0
|
0
|
1176
|
POST
|
Could your ApplyEdits be wrapped in a try-catch? Can you see if exception has message/details? Could the new feature be rejected by server because of geometry (has or lack of m/z-value, spatial reference, outside layer extent) or attributes (any unspecified required fields, data type mismatch, domain errors, or perhaps constraint rule violation)? Few other things you can try: After addFeatureAsyc, check getAddedFeaturesCountAsync to ensure new feature was added. Before applyEdits subscribe to ArcGISHttpClientHandler events: HttpBeginRequest and HttpResponseEnd. You can check request URI on Begin to ensure an /applyEdits request was made. And read content as string on End to ensure an appropriate server response in JSON was received. This should provide objectid or globalid when successful or an error code/message. If the message is the generic unable to complete, you can check server logs for verbose message if you have access to the server.
... View more
04-05-2024
06:37 AM
|
1
|
1
|
1223
|
POST
|
I used your code to generate geodatabase from a feature service portal item but I only see 1 replica created. We also have branch versioning enabled on this feature service. What ArcGIS Enterprise version are you using? I tried ArcGIS Enterprise 11.0, utility network version 6. ArcGIS Runtime WPF build 200.2.
... View more
11-14-2023
01:20 PM
|
0
|
0
|
1462
|
POST
|
You can try the following simplified sample that contains the MapView with GraphicsOverlay for displaying the new geometry and some buttons that Start/Stop/DeleteVertex on GeometryEditor. Using the PropertyChanged event of the GeometryEditor, you can check its Geometry and update its VertexTool properties. The PolylineBuilder's IsSketchValid currently checks the minimum required number of points for a polyline so having two unique points is considered valid. Per Shelly's recommendation, if you want to continue to edit the geometry, you can use the Tools' InteractionConfiguration to enable/disable which vertex editing is allowed. For example, disable new vertex creation. <esri:MapView x:Name="MyMapView" />
<StackPanel VerticalAlignment="Top"
HorizontalAlignment="Right">
<Button Content="Line Segment"
Click="OnDrawLine" />
<Button Content="Delete Vertex"
Click="OnDeleteVertex" />
<Button Content="Complete Line Segment"
Click="OnCompleteDraw" />
</StackPanel> public MainWindow()
{
InitializeComponent();
MyMapView.Map = new Map(SpatialReferences.WebMercator);
MyMapView.GraphicsOverlays.Add(new GraphicsOverlay()
{
Renderer = new SimpleRenderer(new SimpleLineSymbol() { Color = Color.Blue, Style = SimpleLineSymbolStyle.Solid, Width = 2 })
});
MyMapView.GeometryEditor.PropertyChanged += OnGeometryPropertyChanged;
}
private bool EnsureTwoPoints => MyMapView.GeometryEditor?.Geometry is Polyline polyline &&
new PolylineBuilder(polyline).IsSketchValid;
private void OnGeometryPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(GeometryEditor.Geometry))
{
if (MyMapView.GeometryEditor.Tool is VertexTool vertexTool)
{
vertexTool.Configuration.AllowVertexCreation = !EnsureTwoPoints;
}
}
}
private void OnDrawLine(object sender, RoutedEventArgs e)
{
if (MyMapView.GeometryEditor.IsStarted)
{
return;
}
MyMapView.GeometryEditor.Start(GeometryType.Polyline);
}
private void OnDeleteVertex(object sender, RoutedEventArgs e)
{
if (!MyMapView.GeometryEditor.IsStarted)
return;
if (MyMapView.GeometryEditor.SelectedElement is GeometryEditorVertex)
MyMapView.GeometryEditor.DeleteSelectedElement();
}
private void OnCompleteDraw(object sender, RoutedEventArgs e)
{
if (!MyMapView.GeometryEditor.IsStarted || !EnsureTwoPoints)
return;
var geometry = MyMapView.GeometryEditor.Stop();
if (MyMapView.GraphicsOverlays.FirstOrDefault() is GraphicsOverlay overlay)
{
overlay.Graphics.Add(new Graphic(geometry));
}
} Click Line Segment button to start drawing Click Delete Vertex button to remove selected vertex Click Complete Line Segment button to stop drawing. Notice in this small sample code, vertex creation is only allowed when you have not met the minimum 2 points.
... View more
11-13-2023
09:05 AM
|
1
|
0
|
1376
|
Title | Kudos | Posted |
---|---|---|
1 | 3 weeks ago | |
1 | 06-06-2025 10:14 AM | |
1 | 03-17-2025 09:47 AM | |
1 | 07-24-2024 07:32 AM | |
1 | 04-05-2024 06:37 AM |
Online Status |
Offline
|
Date Last Visited |
3 weeks ago
|