ASP.NET 2.0 fornisce una serie di servizi basati su provider per leggere, scrivere e gestire lo stato tra le applicazioni e lo stesso run-time. Questo pattern non è stato introdotto solo per i servizi build-in del framework; ma permette, agli sviluppatori, di creare i propri servizi basati su provider rendendo così le proprie applicazioni indipendenti, per esempio, dalla fonte dati.
In questo articolo dimostreremo come sia possibile creare un Provider da utilizzare nelle nostre applicazioni per fornire un servizio non incluso nell’attuale versione di ASP.NET.
.gif)
In questa pagina
Servizi basati su Provider
Geographic Information System Provider
Un esempio di implementazione
Conclusioni
Riferimenti utili
Servizi basati su Provider
Un servizio basato su Provider richiede l’implementazione di alcune classi per garantire un corretto funzionamento durante il suo utilizzo. In particolare è necessario definire:
Il Microsoft Framework 2.0, mette a disposizione le necessarie classi base per semplificare lo sviluppo di un provider e della sua sezione di configurazione; mi riferisco alla classe System.Configuration.Provider.ProviderBase per il Provider e alla classe System.Configuration.ConfigurationSection per la configurazione. Se questo non fosse sufficiente, possiamo contare su un Provider Toolkit che ci fornisce un’implementazione di esempio da cui partire per creare il nostro custom provider.
Partendo da questo toolkit, possiamo quindi iniziare a costruire il nostro servizio guidati da una struttura base che ci aiuta a ridurre sensibilmente i tempi complessivi di realizzazione.
Provider Toolkit
Il modello contenuto del Provider Toolkit contiene cinque file che, grazie al file readme.txt contenuto nello zip, possiamo rapidamente modificare per impostare il nostro custom provider. I file contenuti nel file .zip sono:
| Nome file | Descrizione contenuto |
| EULA.rtf | Contiene l’accordo di licenza (End-User License Agreement) che si deve rispettate per utilizzare i file forniti come modello. |
| MyProvider.cs | Definizione base delle funzionalità di una classe Provider. |
| MyProviderCollection.cs | Definizione di una collezione fortemente tipizzata per poter essere utilizzata con il nostro custom provider. |
| MyProviderConfiguration.cs | Classe di configurazione di esempio che può essere utilizzata come rappresentazione fortemente tipizzata della configurazione necessaria alla nostra implementazione. La classe di esempio contiene le definizioni per un attributo "defaultProvider" dell’elemento radice della nostra configurazione come anche la definizione di un elemento <provider> quale sotto-elemento dell’elemento radice della nostra sezione di configurazione. |
| MyStaticProvider.cs | Esempio di un’implementazione concreta di provider per le funzionalità del nostro servizio. In particolare contiene il codice necessario a gestire la configurazione specifica per il nostro provider ed a verificare la presenza di eventuali elementi di configurazione non indispensabili. |
| ProviderManager.cs | Classe statica contenente l’implementazione base per gestire i necessari nodi di configurazione che permettono di velocizzare l’avvio delle istanze per ogni singolo provider indicato in configurazione. |
| readme.txt | Istruzioni per una rapida personalizzazione dell’esempio fornito. |
Geographic Information System Provider
Le nostre applicazioni web fanno sempre più spesso uso d’informazioni geografiche, ad esempio mappe, per fornire contenuti agli utenti finali. Oggi il mercato offre molte soluzioni gratuite di elevato contenuto grafico e tecnologico che possiamo facilmente inserire nelle soluzioni che realizziamo. Le più note sono sicuramente Microsoft Virtual Earth e Google Maps API, capaci di fornire anche i controlli necessari alla visualizzazione dei servizi geografici, sfruttando le ultime tecnologie Ajax Based per garantire un’esperienza molto piacevole all’utilizzatore finale. Allora perché pensare ad un Geographic Information System Provider (GIS Provider)? I motivi sono diversi e spesso legati ad un target di applicazioni che non si riesce a soddisfare pienamente con servizi come Virtual Earth o Google Maps in quanto soluzioni basate su mappe particolari finalizzate ad utilizzi specifici (geologici, ambientali, ecc). In questi casi normalmente s’impiegano soluzioni GIS più avanzate come quelle fornite dai produttori specializzati in applicazioni GIS quali, a puro titolo di esempio, ESRI.
Il codice descritto in questo articolo, per semplicità e per garantire la possibilità di testare la soluzione, utilizza MapPoint Web Services come GIS provider. In questo modo, chi fosse interessato, potrà richiedere un proprio account per far funzionare l’esempio.
Scopo del provider
Il GIS provider fornirà un supporto alla ricerca geografica di località fornendo, come risultato, delle semplici informazioni. Capito il funzionamento non sarà difficile inserire altre funzionalità per rendere il provider più potente e in grado di soddisfare scenari più articolati rispetto a quello presentato nell’articolo.
Un esempio di implementazione
Il primo passo per implementare il nostro provider è creare una classe per incapsulare un punto GIS che chiameremo GisPoint.
using System;
using System.Collections.Generic;
using System.Text;
namespace Knodev.Provider.Gis
{
/// <summary>
/// Implementazione della classe GisPoint
/// </summary>
public class GisPoint
{
/// <summary>
/// Campo privato latitude
/// </summary>
private decimal latitude;
/// <summary>
/// Imposta/ritorna il valore della proprietà Latitude
/// </summary>
public decimal Latitude
{
get { return latitude; }
set { latitude = value; }
}
/// <summary>
/// Campo privato longitude
/// </summary>
private decimal longitude;
/// <summary>
/// Imposta/ritorna il valore della proprietà Longitude
/// </summary>
public decimal Longitude
{
get { return longitude; }
set { longitude = value; }
}
/// <summary>
/// Campo privato city
/// </summary>
private string city;
/// <summary>
/// Imposta/ritorna il valore della proprietà City
/// </summary>
public string City
{
get { return city; }
set { city = value; }
}
/// <summary>
/// Campo privato mapUrl
/// </summary>
private string mapUrl;
/// <summary>
/// Imposta/ritorna il valore della proprietà MapUrl
/// </summary>
public string MapUrl
{
get { return mapUrl; }
set { mapUrl = value; }
}
/// <summary>
/// Campo privato address
/// </summary>
private string address;
/// <summary>
/// Imposta/ritorna il valore della proprietà Address
/// </summary>
public string Address
{
get { return address; }
set { address = value; }
}
/// <summary>
/// Campo privato state
/// </summary>
private string state;
/// <summary>
/// Imposta/ritorna il valore della proprietà State
/// </summary>
public string State
{
get { return state; }
set { state = value; }
}
/// <summary>
/// Campo privato zip
/// </summary>
private string zip;
/// <summary>
/// Imposta/ritorna il valore della proprietà Zip
/// </summary>
public string Zip
{
get { return zip; }
set { zip = value; }
}
/// <summary>
/// Campo privato country
/// </summary>
private string country;
/// <summary>
/// Imposta/ritorna il valore della proprietà Country
/// </summary>
public string Country
{
get { return country; }
set { country = value; }
}
/// <summary>
/// Campo privato message
/// </summary>
private string message;
/// <summary>
/// Imposta/ritorna il valore della proprietà Message
/// </summary>
public string Message
{
get { return message; }
set { message = value; }
}
}
}
Le proprietà di questa classe ci permetteranno di mantenere alcuni dati della località individuata e forniranno una base di supporto per la nostra interfaccia grafica qualora intendessimo utilizzare un ObjectDataSource per visualizzare i dati restituiti dal servizio.
Realizzato il nostro GisPoint, creiamo una classe astratta GisProvider, che derivi da ProviderBase, in modo da predisporre delle linee guida che i nostri provider concreti dovranno seguire.
using System;
using System.Configuration.Provider;
using System.Collections.Generic;
namespace Knodev.Provider.Gis
{
/// <summary>
/// Implementazione della classe GisProvider
/// </summary>
public abstract class GisProvider : ProviderBase
{
/// <summary>
/// Fornisce una lista GisPoint partendo da una stringa di ricerca
/// </summary>
/// <param name="location">Località da ricercare</param>
/// <returns>Collezione di GisPoint contenente i dati delle località che corrispondono alla
/// ricerca</returns>
public abstract List<GisPoint> GetPoints(string location);
/// <summary>
/// Fornisce l'url di un punto
/// </summary>
/// <param name="latitude">Latitudine del punto</param>
/// <param name="longitude">Longitudine del punto</param>
/// <returns>Url della mappa per il punto richiesto</returns>
public abstract string GetMap(decimal latitude, decimal longitude);
}
}
Dal codice è facile notare che sono presenti due metodi: GetPoints e GetMap. Il primo permette, data una stringa di ricerca, di recuperare un elenco di punti che rispondono ai criteri forniti. Il secondo metodo permette di ottenere un url che punta alla mappa di uno specifico punto avente delle precise coordinate geografiche passate come parametri del metodo.
Per gestire una collezione di provider, abbiano la necessità di creare una collezione tipizzata che soddisfi questa esigenza. Il codice che segue ne è un esempio:
using System;
using System.Configuration.Provider;
namespace Knodev.Provider.Gis
{
/// <summary>
/// Implementazione della classe GisProviderCollection
/// </summary>
public class GisProviderCollection : ProviderCollection
{
/// <summary>
/// Aggiunge un provider alla collezione
/// </summary>
/// <param name="provider">Provider da aggiungere</param>
public override void Add(ProviderBase provider)
{
if (provider == null)
throw new ArgumentNullException("Il parametro provider non può essere nullo.");
if (!(provider is GisProvider))
throw new ArgumentException("Il parametro provider deve essere del tipo GisProvider.");
base.Add(provider);
}
/// <summary>
/// Indexer nella collezione di provider
/// </summary>
/// <param name="name">Nome del provider</param>
/// <returns>Provider rispondente al nome indicato</returns>
new public GisProvider this[string name]
{
get { return (GisProvider)base[name]; }
}
/// <summary>
/// Copia i provider contenuti in un array di GisProvider nella collezione
/// partendo dall'indice indicato come parametro
/// </summary>
/// <param name="array">Array di GisProvider</param>
/// <param name="index">Indici iniziale di inserimento</param>
public void CopyTo(GisProvider[] array, int index)
{
base.CopyTo(array, index);
}
}
}
La collezione GisProviderCollection eredita da ProviderCollection, classe fornita dal framework proprio a questo scopo. Ora siamo in grado di predisporre un manager per gestire eventuali inizializzazioni della collezione dei nostri provider. Il codice necessario alla sua realizzazione è il seguente:
using System;
using System.Configuration;
using System.Configuration.Provider;
using System.Web.Configuration;
namespace Knodev.Provider.Gis
{
/// <summary>
/// Implementazione della classe GisManager per la gestione di un provider Gis
/// </summary>
public class GisManager
{
#region Inizializzazione
//Inizializzazione delle variabili e della logica
private static bool isInitialized = false;
private static Exception initializationException;
private static object initializationLock = new object();
static GisManager()
{
Initialize();
}
/// <summary>
/// Inizializzazione
/// </summary>
private static void Initialize()
{
try
{
//Recupero delle informazioni di configurazione
GisConfiguration gc =
(GisConfiguration)ConfigurationManager.GetSection("Gis");
if (gc.DefaultProvider == null || gc.Providers == null || gc.Providers.Count < 1)
throw new ProviderException("Specificare un valido GisProvider di Default.");
//Instanze dei provider
providerCollection = new GisProviderCollection();
ProvidersHelper.InstantiateProviders(gc.Providers,
providerCollection, typeof(GisProvider));
providerCollection.SetReadOnly();
defaultProvider = providerCollection[gc.DefaultProvider];
if (defaultProvider == null)
{
throw new ConfigurationErrorsException(
"Specificare un valido GisProvider di Default per questa funzionalità.",
gc.ElementInformation.Properties["defaultProvider"].Source,
gc.ElementInformation.Properties["defaultProvider"].LineNumber);
}
}
catch (Exception ex)
{
initializationException = ex;
isInitialized = true;
throw ex;
}
//Conferma dell'inizializzazione in assenza di errori
isInitialized = true;
}
#endregion
#region Funzionalità pubbliche
private static GisProvider defaultProvider;
private static GisProviderCollection providerCollection;
/// <summary>
/// Ritorna l'istanza del provider
/// </summary>
public static GisProvider Provider
{
get
{
return defaultProvider;
}
}
/// <summary>
/// Ritorna la collezione di provider
/// </summary>
public static GisProviderCollection Providers
{
get
{
return providerCollection;
}
}
#endregion
}
}
Il GisManager si preoccupa di verificare la configurazione e predisporre i nostri provider affinché eventuali istanze siano più velocemente eseguibili. La classe contiene, oltre al metodo di inizializzazione, due proprietà che permettono di recuperare il provider di default e la collezione dei provider presenti nel file di configurazione.
Come si è intuito, i nostri provider dipendono da alcuni parametri di configurazione. Parametri che saranno contenuti in una sezione personalizzata del web.config. La creazione di una classe, che derivi da ConfigurationSection ci permette di raggiungere questo risultato.
using System;
using System.Configuration;
namespace Knodev.Provider.Gis
{
/// <summary>
/// Implementazione della classe GisConfiguration per la configurazione di un provider GIS
/// </summary>
public class GisConfiguration : ConfigurationSection
{
/// <summary>
/// Ritorna la collezione di provider presenti in configurazione
/// </summary>
[ConfigurationProperty("providers")]
public ProviderSettingsCollection Providers
{
get
{
return (ProviderSettingsCollection)base["providers"];
}
}
/// <summary>
/// Imposta/Ritorna il default provider indicato in configurazione
/// </summary>
[ConfigurationProperty("defaultProvider", DefaultValue = "VirtualEarthGisProvider")]
[StringValidator(MinLength = 1)]
public string DefaultProvider
{
get
{
return (string)base["defaultProvider"];
}
set
{
base["defaultProvider"] = value;
}
}
}
}
La classe GisConfiguration ci permette di specificare come sarà composta la sezione di configurazione delle applicazioni che faranno uso di questo provider e che dovremo inserire nel web.config. Per il nostro esempio, la sezione utilizzata nel sito web di test è la seguente:
<configuration>
<configSections>
<section name="Gis"
type="Knodev.Provider.Gis.GisConfiguration, Knodev.Provider.Gis"
allowDefinition="MachineToApplication" />
</configSections>
<Gis defaultProvider="MapPoint">
<providers>
<add name="MapPoint"
type="Knodev.Provider.Gis.MappointGisProvider, Knodev.Provider.Gis"
serviceUrl="http://staging.mappoint.net/standard-30/mappoint.wsdl"
userID="utente" <!-- sostituire con quello fornito per il vostro account-->
password="password" <!-- sostituire con quella fornita per il vostro account-->
renderServiceUrl="http://renderv3.staging.mappoint.net/Render-30/RenderService.asmx"
findServiceUrl="http://findv3.staging.mappoint.net/Find-30/FindService.asmx"
routeServiceUrl="http://routev3.staging.mappoint.net/Route-30/RouteService.asmx"
commonServiceUrl="http://findv3.staging.mappoint.net/Find-30/Common.asmx"
dataSourceName="MapPoint.EU"
description="GIS Provider che utilizza MapPoint Web Services"/>
</providers>
</configuration>
Gli elementi di configurazione da inserire, sono composti dalla dichiarazione della configurazione, elemento <section> contenuto in <configSections> in cui si specifica la classe e l’assembly che contiene la nostra sezione di configurazione personalizzata; dal gruppo compreso nell’elemento <Gis> in cui si inseriranno tutti i provider, disponibili per il nostro servizio, che intendiamo utilizzare nell’applicazione web. Gli attributi definiti all’interno dell’elemento <add> contenuto in <providers> servono a caratterizzare le diverse implementazioni concrete del nostro provider cartografico. Ecco i parametri di configurazione che abbiamo deciso di inserire per questo specifico provider:
| Attributo | Descrizione |
| type | Indica il tipo del provider. Rappresenta il nome completo del nostro oggetto |
| serviceUrl | Indirizzo base del wsdl che descrive i servizi del nostro provider |
| userID | Utente attribuito al vostro account per la connessione. |
| Password | Password attribuita al vostro account per la connessione. |
| renderServiceUrl | Indirizzo per il web service di Rendering |
| findServiceUrl | Indirizzo per il web service di Ricerca |
| routeServiceUrl | Indirizzo per il web service di Route |
| commonServiceUrl | Indirizzo per il web service delle funzionalità core |
| dataSourceName | Nome della fonte dati di MapPoint da cui attingere le informazioni |
| description | Descrizione del provider |
Questo approccio ci permette di modificare gli attributi da provider a provider in modo da incontrare al meglio le esigenze di ogni singolo fornitore. Potremo quindi, per un altro provider Gis, inserire parte o addirittura nessuno degli attributi sopra indicati, sostituendoli con quelli specifici per la nuova implementazione. Per esempio:
| Attributo | Descrizione |
| type | Indica il tipo del provider. Rappresenta il nome completo del nostro oggetto |
| serviceUrl | Indirizzo base del servizio su cui si appoggia il nostro provider |
| applicationKey | Identificativo dell’applicazione fornito dal fornitore del servizio su cui si appoggia il provider. La politica di assegnazione varia da fornitore a fornitore; alcuni forniscono un identificativo univoco, altri invece per applicazione legandolo ad un Url ben preciso. |
| outputFormat | Formato con cui si desiderano ricevere le risposte dal fornitore. Anche per questo parametro i valori possono cambiare e dipendono dalle scelte fatte dal fornitore esterno. |
Terminata la predisposizione dell’infrastruttura del nostro servizio basato su provider, è venuto il momento di concretizzare il nostro lavoro creando il primo GisProvider: il MappointGisProvider. Questo provider erediterà dalla classe astratta, precedentemente creata, chiamata GisProvider. Il codice che otteniamo è questo:
using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI.WebControls;
using System.Net;
using System.Web;
using System.Configuration.Provider;
using System.Diagnostics;
using Knodev.Provider.Gis.MapPointService;
namespace Knodev.Provider.Gis
{
public class MappointGisProvider: GisProvider
{
private string serviceUrl;
private string userId;
private string password;
private string renderServiceUrl;
private string findServiceUrl;
private string routeServiceUrl;
private string commonServiceUrl;
private string dataSourceName;
/// <summary>
/// Inizializzazione del provider concreto
/// </summary>
/// <param name="name">Nome del provider</param>
/// <param name="config">Sezione della configurazione relativa al provider</param>
public override void Initialize
(string name, System.Collections.Specialized.NameValueCollection config)
{
if ((config == null) || (config.Count == 0))
throw new ArgumentNullException("Fornire una sezione di configurazione valida.");
if (string.IsNullOrEmpty(config["description"]))
{
config.Remove("description");
config.Add("description", "MapPoint Web Services Provider.");
}
//Esecuzione dell'inizializzazione della classe base
base.Initialize(name, config);
//Esecuzione delle inizializzazioni specifiche del provider
//Recupero del Url del servizio
serviceUrl = config["serviceUrl"];
if (String.IsNullOrEmpty(serviceUrl))
throw new ProviderException("Specificare un attributo serviceUrl.");
config.Remove("serviceUrl");
//Recupero dell'id utente
userId = config["userID"];
if (String.IsNullOrEmpty(userId))
throw new ProviderException("Specificare un attributo userId.");
config.Remove("userID");
//Recupero della password
password = config["password"];
if (String.IsNullOrEmpty(password))
throw new ProviderException("Specificare un attributo password.");
config.Remove("password");
//Recupero del renderServiceUrl
renderServiceUrl = config["renderServiceUrl"];
if (String.IsNullOrEmpty(renderServiceUrl))
throw new ProviderException("Specificare un attributo renderServiceUrl.");
config.Remove("renderServiceUrl");
//Recupero del findServiceUrl
findServiceUrl = config["findServiceUrl"];
if (String.IsNullOrEmpty(findServiceUrl))
throw new ProviderException("Specificare un attributo findServiceUrl.");
config.Remove("findServiceUrl");
//Recupero del routeServiceUrl
routeServiceUrl = config["routeServiceUrl"];
if (String.IsNullOrEmpty(routeServiceUrl))
throw new ProviderException("Specificare un attributo routeServiceUrl.");
config.Remove("routeServiceUrl");
//Recupero del commonServiceUrl
commonServiceUrl = config["commonServiceUrl"];
if (String.IsNullOrEmpty(commonServiceUrl))
throw new ProviderException("Specificare un attributo commonServiceUrl.");
config.Remove("commonServiceUrl");
//Recupero del dataSourceName
dataSourceName = config["dataSourceName"];
if (String.IsNullOrEmpty(dataSourceName))
throw new ProviderException("Specificare un attributo dataSourceName.");
config.Remove("dataSourceName");
//Verifica di attributi non attesi nel set di configurazione
if (config.Count > 0)
{
string extraAttribute = config.GetKey(0);
if (!String.IsNullOrEmpty(extraAttribute))
throw new ProviderException
(@"E' stato trovato il seguente attributo " + Name + "non riconosciuto nella configurazione: '" +
extraAttribute + "'");
else
throw new ProviderException
(@"E' stato trovato un attributo non riconosciuto nella configurazione.");
}
//Inizializza i servizi di MapPoint Web Services
this.InitializeMPNetConnection();
}
/// <summary>
/// Fornisce una lista GisPoint partendo da una stringa di ricerca
/// </summary>
/// <param name="location">Località da ricercare</param>
/// <returns>
Collezione di GisPoint contenente i dati delle località che corrispondono alla ricerca</returns>
public override List<GisPoint> GetPoint(string location)
{
if(string.IsNullOrEmpty(location))
return null;
List<GisPoint> points = new List<GisPoint>();
FindSpecification fs = new FindSpecification();
fs.DataSourceName = this.dataSourceName;
fs.InputPlace = location;
FindResults results = this.FindService.Find(fs);
foreach (FindResult result in results.Results)
{
GisPoint point = new GisPoint();
if (result.FoundLocation.Address != null)
{
point.Address = result.FoundLocation.Address.AddressLine as string;
point.City = result.FoundLocation.Address.PrimaryCity as string;
point.Country = result.FoundLocation.Address.CountryRegion as string;
point.State = result.FoundLocation.Address.Subdivision as string;
point.Zip = result.FoundLocation.Address.PostalCode as string;
}
else
{
point.City = result.FoundLocation.Entity.Name;
point.Address = result.FoundLocation.Entity.DisplayName;
}
point.Latitude = (decimal)result.FoundLocation.LatLong.Latitude;
point.Longitude = (decimal)result.FoundLocation.LatLong.Longitude;
point.Message = result.Score.ToString() as string;
points.Add(point);
}
return points;
}
/// <summary>
/// Fornisce l'url di un punto
/// </summary>
/// <param name="latitude">Latitudine del punto</param>
/// <param name="longitude">Longitudine del punto</param>
/// <returns>Url della mappa per il punto richiesto</returns>
public override string GetMap(decimal latitude, decimal longitude)
{
ViewByScale[] views = new ViewByScale[1];
ViewByScale view = new ViewByScale();
view.CenterPoint = new LatLong();
view.CenterPoint.Longitude = (double)longitude;
view.CenterPoint.Latitude = (double)latitude;
view.MapScale = 2500;
views[0] = view;
MapOptions options = new MapOptions();
options.ReturnType = MapReturnType.ReturnUrl;
options.Zoom = 1;
options.Format = new ImageFormat();
options.Format.Height = 500;
options.Format.Width = 620;
MapSpecification ms = new MapSpecification();
ms.Views = views;
ms.Options = options;
ms.DataSourceName = this.dataSourceName;
MapImage[] maps = this.RenderService.GetMap(ms);
return maps[0].Url;
}
#region MapPointNet
private MapPointService.RenderServiceSoap renderService;
private MapPointService.FindServiceSoap findService;
private MapPointService.RouteServiceSoap routeService;
private MapPointService.CommonServiceSoap commonService;
/// <summary>
/// Inizializza la connessione ai servizi di MapPoint .NET
/// </summary>
private void InitializeMPNetConnection()
{
try
{
NetworkCredential ourCredentials = new NetworkCredential(this.userId, this.password);
// Crea il servizio di rendering
renderService = new MapPointService.RenderServiceSoap();
renderService.Credentials = ourCredentials;
renderService.PreAuthenticate = true;
renderService.Url = this.renderServiceUrl;
// Crea il servizio di ricerca
findService = new MapPointService.FindServiceSoap();
findService.Credentials = ourCredentials;
findService.PreAuthenticate = true;
findService.Url = this.findServiceUrl;
// Crea il servizio di route
routeService = new MapPointService.RouteServiceSoap();
routeService.Credentials = ourCredentials;
routeService.PreAuthenticate = true;
routeService.Url = this.routeServiceUrl;
// Crea il servizio comune
commonService = new MapPointService.CommonServiceSoap();
commonService.Credentials = ourCredentials;
commonService.PreAuthenticate = true;
commonService.Url = this.commonServiceUrl;
}
catch (Exception ex)
{
Debug.Assert(false, "Exception attempting to connect to MapPoint .NET: " + ex.Message);
}
}
/// <summary>
/// Ritorna un'istanza al servizio Render
/// </summary>
public MapPointService.RenderServiceSoap RenderService
{
get
{
return renderService;
}
}
/// <summary>
/// Ritorna un'istanza al servizio Find
/// </summary>
public MapPointService.FindServiceSoap FindService
{
get
{
return findService;
}
}
/// <summary>
/// Ritorna un'istanza al servizio Route
/// </summary>
public MapPointService.RouteServiceSoap RouteService
{
get
{
return routeService;
}
}
/// <summary>
/// Ritorna un'istanza al servizio Common
/// </summary>
public MapPointService.CommonServiceSoap CommonService
{
get
{
return commonService;
}
}
#endregion
}
}
I punti salienti di questa implementazione sono tre: il metodo d’inizializzazione, il metodo di recupero dei punti geografici e il metodo per l’ottenimento dell’url della mappa.
Initialize
Questo metodo è deputato alla fase di inizializzazione del nostro provider concreto. In particolare, si assicura di leggere tutte le informazioni, dal file di configurazione, necessarie al provider; verifica che non siano presenti elementi non previsti e quindi conferma l’avvenuta inizializzazione.
GetPoints
Permette di ottenere alcune informazioni riepilogative sugli eventuali punti corrispondenti ai parametri di ricerca indicati dall’utilizzatore. L’unica variabile, fornibile a questo metodo, è una stringa che può anche rappresentare una serie di informazioni separate da una virgola “,”; eccone una possibile selezione:
-
city
-
city, state
-
city, state, zip
-
zip
I punti ottenuti da questo metodo, nascono da una conversione dei punti secondo la strutturazione dei MapPoint Web Services, e una più generica implementazione che prende il nome, nel nostro progetto, di GisPoint. Questo approccio permette di garantire, a chi consuma il provider, di ricevere sempre lo stesso tipo di dato indipendentemente dal fornitore esterno che si utilizza per produrlo.
Le classi create e un’applicazione di esempio che le sfrutta, sono disponibili, per il download, al link riportato nella sezione Riferimenti utili.
Conclusioni
Quando abbiamo l’esigenza di rendere le nostre applicazioni web astratte dal repository di persistenza o dalla fonte che alimenta il nostro sito con informazioni o altro, è consigliabile utilizzare il pattern suggerito dal framework 2.0 per la gestione di servizi basati su provider. L’articolo ha dimostrato come sia semplice la creazione di provider personalizzati per soddisfare particolari esigenze che, durante la nostra attività lavorativa ci possiamo trovare ad affrontare.
Riferimenti utili
A completamento delle informazioni fornite, suggerisco i seguenti link:
Per scaricare l’esempio utilizzato in quest’articolo, cliccate qui.