Personalizzare le richieste HTTP di Windows Phone con schema fittizi

di Cristian Civera, in Windows Phone,

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

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Approfondimenti

I più letti di oggi