I'm looking to use the Feature Service Query API, and query multiple layers at once.
So, building off the example on the query API page, I want the query to look something like this:
http://<featureservice-url>/query?layerDefs=[{"layerId":<layerDef1>},{"layerId":<layerDef2>}]&geometry=<geometry>&f=json
And I can't seem to be able to figure out how to get that through the .NET runtime SDK (without resorting to using an ArcGISHttpClient). Any suggestions?
Hi,
The QueryTask class works against a single layer in a service, whereas the IdentifyTask and FindTask work against multiple layers in a service. It sounds like you might be able to use the IdentifyTask in your case, to provide a geometry filter which will return all features in layers from the service which intersect the geometry?
- Samples for the query task classes (Find / Identify / Query): arcgis-runtime-samples-dotnet/src/Desktop/ArcGISRuntimeSDKDotNet_DesktopSamples/Samples/QueryTasks a...
- API ref for the Tasks.Query namespace (Esri.ArcGISRuntime.Tasks.Query Namespace).
Depending on your exact workflow, you might also like to look at the ServiceFeatureTable Query method: ArcGISFeatureTable.QueryAsync Method (QueryFilter)
Cheers
Mike
Thanks Michael!
With the IdentifyTask, can I return certain fields along with the feature (like the outFields query parameter)? I'm looking to pull in a bunch of data from a feature service as quickly as possible. So, I'd rather not query every layer individually. Plus, I need certain fields on the features returned.
I did write a quick wrapper around the feature service query:
public class QueryEntry { private readonly int _layerId; private readonly string _whereClause; private readonly string _outFields; public QueryEntry(int layerId, string whereClause, string outFields) { _layerId = layerId; _whereClause = whereClause; _outFields = outFields; } [JsonProperty("layerId")] public int LayerId { get { return _layerId; } } [JsonProperty("where")] public string WhereClause { get { return _whereClause; } } [JsonProperty("outFields")] public string OutFields { get { return _outFields; } } }
public class QueryOperation { private readonly IEnumerable<QueryEntry> _queries; private readonly Esri.ArcGISRuntime.Geometry.Geometry _geometry; private readonly SpatialReference _inSpatialReference; private readonly SpatialReference _outSpatialReference; public QueryOperation(IEnumerable<QueryEntry> queries, Esri.ArcGISRuntime.Geometry.Geometry geometry = null, SpatialReference inSpatialReference = null, SpatialReference outSpatialReference = null) { _queries = queries; _geometry = geometry; _inSpatialReference = inSpatialReference; _outSpatialReference = outSpatialReference; } public override string ToString() { var edits = JsonConvert.SerializeObject(_queries); var options = new StringBuilder(); if (_geometry != null) { options.Append(String.Format("&geometry={0}&geometryType=esriGeometry{1}", _geometry.ToJson(), _geometry.GeometryType)); } if (_inSpatialReference != null) { options.Append(String.Format("&inSR={0}", _inSpatialReference.ToJson())); } if (_outSpatialReference != null) { options.Append(String.Format("&outSR={0}", _outSpatialReference.ToJson())); } return String.Format("layerDefs={0}{1}&f=pjson", edits, options); } }
And then it can be used like this:
var client = new ArcGISHttpClient(); var queryEntries = new List<QueryEntry>(); // Generate QueryEntries var queryOp = new QueryOperation(queryEntries, geometry); var content = new StringContent(queryOp.ToString()); content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded"); var result = await client.PostAsync(service.Uri + "/query", content); var json = await result.Content.ReadAsStringAsync();
That seems to give me what I want, but it feels like I'm rewriting something that already exists in the .NET runtime SDK.