Innanzitutto creiamo il servizio lato server che verrà chiamato lato client. In questo esempio che vi illustro usiamo il template WCF Rest per il Framework 4.0 (CS) , ci connettiamo ad un servizio Geodata e ci facciamo restituire i dati richiesti.
using System; using System.Collections.Generic; using System.Configuration; using System.Linq; using System.ServiceModel; using System.ServiceModel.Activation; using System.ServiceModel.Web; using ESRI.ArcGIS.ADF; using ESRI.ArcGIS.ADF.Connection.AGS; using ESRI.ArcGIS.Geodatabase; using ESRI.ArcGIS.GeoDatabaseDistributed; using ESRI.ArcGIS.Server; [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)] public class GeoData : IGeoData { #region IGeoDataService Members [WebGet(UriTemplate = "/Comune?q={filter}&limite={limit}", ResponseFormat = WebMessageFormat.Json)] public ListaComuni GetListaComuni(string filter, int limit) { List<Comune> items = new List<Comune>(); if (string.IsNullOrEmpty(filter)) return new ListaComuni() { Items = items }; filter = filter.Substring(0, filter.Length - 1); if (filter.Length <= limit) return new ListaComuni() { Items = items }; IServerContext serverContext = null; try { // Connessione ad ArcGIS Server Identity identity = new Identity(); identity.UserName = ConfigurationManager.AppSettings.Get("utenteAGS"); identity.Password = ConfigurationManager.AppSettings.Get("passwordAGS"); string domain = ConfigurationManager.AppSettings.Get("domainAGS"); if (!string.IsNullOrEmpty(domain)) identity.Domain = domain; using (AGSServerConnection agsServerConnection = new AGSServerConnection(ConfigurationManager.AppSettings.Get("hostnameAGS"), identity)) { try { agsServerConnection.Connect(); } catch { throw; } // get a server context IServerObjectManager som = agsServerConnection.ServerObjectManager; serverContext = som.CreateServerContext(ConfigurationManager.AppSettings.Get("serviceGeoData"), "GeodataServer"); // get the workspace from the GeodataServer IGeoDataServer gds = serverContext.ServerObject as IGeoDataServer; IGeoDataServerObjects geoDataServerObjects = gds as IGeoDataServerObjects; IWorkspace workspace = geoDataServerObjects.DefaultWorkingWorkspace; IFeatureWorkspace featureWorkspace = workspace as IFeatureWorkspace; IFeatureClass featureClass = featureWorkspace.OpenFeatureClass("Comuni"); string nomeCampo = "COMUNE"; int idxField = featureClass.FindField(nomeCampo); IQueryFilter queryFilter = serverContext.CreateObject("esriGeodatabase.QueryFilter") as IQueryFilter; queryFilter.SubFields = nomeCampo; if (!string.IsNullOrEmpty(filter)) { ISQLSyntax sqlSyntax = workspace as ISQLSyntax; string wildcardMany = sqlSyntax.GetSpecialCharacter(esriSQLSpecialCharacters.esriSQL_WildcardManyMatch); string prefixDI = sqlSyntax.GetSpecialCharacter(esriSQLSpecialCharacters.esriSQL_DelimitedIdentifierPrefix); string suffixDI = sqlSyntax.GetSpecialCharacter(esriSQLSpecialCharacters.esriSQL_DelimitedIdentifierSuffix); string where = string.Format("{0}{1}{2} LIKE '{3}{4}'", prefixDI, nomeCampo, suffixDI, filter.ToUpper(), wildcardMany); queryFilter.WhereClause = where; } using (ComReleaser comReleaser = new ComReleaser()) { IFeatureCursor featureCursor = featureClass.Search(queryFilter, true); comReleaser.ManageLifetime(featureCursor); IFeature feature = null; string item = null; while ((feature = featureCursor.NextFeature()) != null) { item = Convert.ToString(feature.get_Value(idxField)); items.Add(new Comune() { Name = item }); } } items = items.OrderBy(x => x.Name).ToList(); //if (limit > 0) // items = items.Take(limit).ToList(); } return new ListaComuni() { Items = items }; } catch { return new ListaComuni() { Items = new List<Comune>() }; } finally { if (serverContext != null) serverContext.ReleaseContext(); } } #endregion }
using System.Collections.Generic; using System.Runtime.Serialization; using System.ServiceModel; [ServiceContract] public interface IGeoData { [OperationContract] ListaComuni GetListaComuni(string filter,int limit); } [DataContract] public class ListaComuni { [DataMember(Name = "items")] public List<Comune> Items { get; set; } } [DataContract] public class Comune { [DataMember(Name = "name")] public string Name { get; set; } }
Dalla nostra pagina che esegue codice lato client utilizziamo il QueryReadStore e richiamiamo il nostro servizio REST.
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <meta http-equiv="X-UA-Compatible" content="IE=7" /> <!--The viewport meta tag is used to improve the presentation and behavior of the samples on iOS devices--> <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no"/> <link rel="stylesheet" type="text/css" href="http://serverapi.arcgisonline.com/jsapi/arcgis/2.1/js/dojo/dijit/themes/claro/claro.css"> <script type="text/javascript"> var djConfig = { parseOnLoad: true, isDebug: true, baseUrl: './', modulePaths: { 'custom': 'custom' } }; </script> <script type="text/javascript" src="http://serverapi.arcgisonline.com/jsapi/arcgis/?v=2.1"></script> <script type="text/javascript"> dojo.require("dijit.dijit"); // optimize: load dijit layer dojo.require("dijit.layout.BorderContainer"); dojo.require("dijit.layout.ContentPane"); dojo.require("dijit.layout.TabContainer"); dojo.require("dijit.Tooltip"); dojo.require("dijit.TitlePane"); dojo.require("esri.map"); dojo.require("dojox.data.QueryReadStore"); dojo.require("dijit.form.ComboBox"); dojo.require("custom.ComboBoxReadStore"); var map; function Init() { dojo.style(dojo.byId("map"), { width: dojo.contentBox("map").w + "px", height: (esri.documentBox.h - dojo.contentBox("navTable").h - 40) + "px" }); var initExtent = new esri.geometry.Extent({ "xmin": 6.55059928850006, "ymin": 45.0006208151578, "xmax": 8.22229873550003, "ymax": 45.6702338525465, "spatialReference": { "wkid": 4326 } }); map = new esri.Map("map", { extent: initExtent }); var layer = new esri.layers.ArcGISDynamicMapServiceLayer("http://localhost/ArcGIS/rest/services/LimitiComuni/MapServer", { "opacity": 0.5 }); var layerBaseMap = new esri.layers.ArcGISTiledMapServiceLayer("http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer"); map.addLayer(layerBaseMap); map.addLayer(layer); var resizeTimer; dojo.connect(map, 'onLoad', function (theMap) { dojo.connect(dijit.byId('map'), 'resize', function () { clearTimeout(resizeTimer); resizeTimer = setTimeout(function () { map.resize(); map.reposition(); }, 500); }); }); } dojo.addOnLoad(Init); </script> </head> <body class="tundra"> <table style="width:100%"> <tr> <td> <table id="navTable" width="100%"> <tbody> <tr valign="top"> <td id="breadcrumbs"> ArcGIS JavaScript API: LimitiComuni </td> <td align="right" id="help"> <div dojoType="custom.ComboBoxReadStore" jsId="theStore" url="http://localhost:1385/GeoData/Comune?" requestMethod="get"> </div> <input dojoType="dijit.form.ComboBox" searchAttr="name" name="theSelect" id="theSelect" store="theStore" placeHolder="Cerca comune" hasDownArrow="false"> </td> </tr> </tbody> </table> </td> </tr> </table> <div id="map" style="margin:auto;width:97%;border:1px solid #000;"></div> </body> </html>
In custom/ComboBoxReadStore.js subclassiamo dojox.data.QueryReadStore per poter modificare eventualmente il passaggio dei parametri dal client al server:
dojo.provide("custom.ComboBoxReadStore"); dojo.require("dojox.data.QueryReadStore"); dojo.declare("custom.ComboBoxReadStore", dojox.data.QueryReadStore, { fetch:function(request) { request.serverQuery = {q:request.query.name, limite:2}; // Call superclasses' fetch return this.inherited("fetch", arguments); } });