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.