Ogni risorsa consumabile in Windows Phone e su qualsiasi piattaforma, viene in genere rappresentata da un URI, come ad esempio http://miosito/miarisorsa.txt, il quale si compone di varie parti:
- http: lo schema;
- la porta: 80 implicita per l'HTTP;
- miosito: il dominio;
- miarisorsa.txt: il path.
Facoltativamente si aggiungono poi la querystring e il fragment. Nel .NET Framework, e quindi anche in Windows Phone, quando si sfruttano le classi WebRequest o WebClient per scaricare una risorsa e proprio in virtù delle provenienza delle risorse, ogni schema determina il motore da utilizzare per ottenere una risposta: se HTTP occorre seguire un certo protocollo, se FTP un altro, se FILE invece occorre utilizzare le API di sistema, e così via.
E' possibile però registrare un proprio schema di propria invenzione, sia per implementare protocolli non supportati da Windows Phone, ma anche per aggiungere e centralizzare funzionalità aggiuntive da applicare ai protocolli già implementati. In questo script ad esempio si pone il semplice obiettivo di evitare, in modo centralizzato, di effettuare richieste HTTP in mancanza già a priori della rete internet, senza aspettare il timeout della richiesta.
In pratica, supponendo di inventare lo schema myhttp, quello che si vuole ottenere è poter scaricare la risorsa in questo modo:
WebClient client = new WebClient(); client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted); client.DownloadStringAsync(new Uri("myhttps://www.aspitalia.com"));
Per farlo occorre prima registrare il prefisso con il relativo oggetto responsabile della creazione delle richieste.
WebRequest.RegisterPrefix("myhttp", new AutoWebRequestCreator());
La classe AutoWebRequestCreator implementa l'interfaccia IWebRequestCreate e compie una semplice scelta: se internet è presente effettua la normale chiamata HTTP, mentre in caso contrario restituisce una fittizia implementazione di WebRequest che non esegue alcuna operazione.
public class AutoWebRequestCreator : IWebRequestCreate { public WebRequest Create(Uri uri) { // Internet è presente if (NetworkInterface.GetIsNetworkAvailable()) { // Restituisco una richiesta HTTP cambiando lo schema return WebRequest.CreateHttp(uri.ToString().Replace("myhttp://", "http://")); } else return new DummyWebRequest(); } }
La classe DummyWebRequest sovrascrive i metodi BeginGetResponse e EndGetResponse per restituire a loro volta un finto IAsyncResult, oggetto che rappresenta l'operazione asincrona.
public class DummyWebRequest : WebRequest { public override IAsyncResult BeginGetResponse(AsyncCallback callback, object state) { // Risultato fittizio DummyAsyncResult ar = new DummyAsyncResult(state); // Chiamo subito il callback callback(ar); return ar; } public override WebResponse EndGetResponse(IAsyncResult asyncResult) { // L'operazione è stata cancellata throw new WebException("Cancelled", WebExceptionStatus.RequestCanceled); } }
Il DummyAsyncResult è invece implementato in modo da restituire costanti che indicano che l'operazione è già terminata.
public class DummyAsyncResult : IAsyncResult { public DummyAsyncResult(object state) { this.AsyncState = state; } public object AsyncState { get; private set; } public System.Threading.WaitHandle AsyncWaitHandle { get { return null; } } public bool CompletedSynchronously { get { return true; } } public bool IsCompleted { get { return true; } } }
I vantaggi che si ottengono con questo approccio sono molteplici. Per prima cosa si centralizzano una logica che, seppur semplice in questo esempio, è brutto e scomodo da replicare. Inoltre rende tutto piuttosto trasparente per quanto riguarda l'accesso alle risorse e infine permette di implementare scenari più evoluti. Ad esempio è possibile implementare una coda in modo da sequenzializzare le chiamate, oppure effettuare una cache sulle risorse web ed evitare di andare fisicamente sulla rete, recuperando il risultato dalla memoria o dall'isolated storage.
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Sfruttare lo stream rendering per le pagine statiche di Blazor 8
Autenticarsi in modo sicuro su Azure tramite GitHub Actions
Ottimizzazione dei block template in Angular 17
Utilizzare HiLo per ottimizzare le insert in un database con Entity Framework
Ottimizzare il mapping di liste di tipi semplici con Entity Framework Core
Creare alias per tipi generici e tuple in C#
Effettuare delete massive con Entity Framework Core 7
Utilizzare domini personalizzati gestiti automaticamente con Azure Container Apps
Utilizzare la libreria Benchmark.NET per misurare le performance
Eseguire una query su SQL Azure tramite un workflow di GitHub
Copiare automaticamente le secret tra più repository di GitHub
Gestire errori funzionali tramite exception in ASP.NET Core Web API
I più letti di oggi
- Riordinare le righe di una GridView di ASP.NET con jQuery
- Creazione di un alarm con suono personalizzato con Windows Phone 7.1
- Utilizzare la session affinity con Azure Container Apps
- Blue-green deployment con Azure Web App e DevOps
- Ed infine anche il calendario :)
- Configurare la diagnostica di Azure attraverso Visual Studio
- Recuperare la data di creazione di un tag tramite una pipeline YAML di Azure DevOps
- Microsoft Security Bulletin MS05-002
- .NET Core e dispositivi IoT
- Eseguire attività pianificate con Azure Container Jobs