martedì 2 settembre 2014

Creazione personalizzati HttpClient gestori

Accesso alle API Web può essere fatto facilmente utilizzando il gestore HTTPClient. Questa classe accelera il processo di sviluppo di accedere ai dati da un Web API, e consente di personalizzare i gestori cliente in caso di necessità.
HTTPClient è un oggetto utilizzato per l'accesso di richiesta e risposta dei messaggi da e verso API web. Come chiamate client-server tradizionali, la HTTPClient chiama il server utilizzando uno specifico URI, aspetta il risultato, quindi restituisce un oggetto risposta al chiamante.

Come per tutto il resto nello sviluppo di software, la necessità finirà per sorgere per lo sviluppo personalizzato. Per fortuna, la classe HttpClient consente per questo. Un gestore di messaggi singolo, o un numero di gestori, possono essere creati e aggiunti in un ordine specifico per lo stack di chiamate utilizzando il metodo HttpClientFactory.Create.

Uno o più gestori di messaggi personalizzati possono essere creati e organizzati in una catena di gestori che vengono automaticamente chiamato con ogni richiesta e la risposta. Una volta creata la classe del gestore messaggio, esso può essere utilizzato per eseguire operazioni personalizzate durante la sequenza di chiamata. Osservando lo schema di figura 1 , la sequenza inizia con la richiesta del cliente, poi continua attraverso la catena di gestori. Una volta che il messaggio raggiunge il server, la risposta viene inviata indietro propagazione attraverso la catena dei gestori in ordine inverso.


Figura 1. Flusso dei messaggi per la richiesta del cliente e risposta
Per dimostrare i gestori personalizzati sul cliente, sarà necessaria una API Web per inviare richieste e ricevere risposte da. In un precedente articolo , ho dimostrato come è possibile creare un Web API. Il codice utilizzato in tale articolo servirà come l'API Web per questo articolo, con una piccola modifica. Nel metodo Registro della App_Start \ WebApiConfig.cs di file, aggiungerò la dichiarazione config.Formatters.Add (nuovo JsonMediaTypeFormatter ()) ;. Ciò consentirà l'API Web per formattare i dati di output in formato JSON. Si può vedere il codice completo in Listato 1 .

Listato 1: Contenuto del WebApiConfig.cs (in API Web di progetto) dopo la modifica
Pubblicità


utilizzando System.Net.Http.Formatting;
utilizzando System.Web.Http;

namespace CarInventory21
{
  pubblico WebApiConfig classe statica
  {
    public void Registro static (HttpConfiguration config)
    {
      // Configurazione e servizi Web API

      // percorsi API Web
      config.MapHttpAttributeRoutes ();

      config.Routes.MapHttpRoute (
        Nome: "DefaultApi",
        routeTemplate: "api / {comando} / {id}",
        default: nuovo {id = RouteParameter.Optional}
      );
      
      config.Formatters.Clear (); // Rimuovere tutti gli altri formattatori
      config.Formatters.Add (nuovo BsonMediaTypeFormatter ()); // Abilita BSON nel servizio Web
      config.Formatters.Add (nuovo JsonMediaTypeFormatter ());
    }
  }
}
Ora l'API Web è pronto per essere utilizzato con il nuovo demo applicazione client. Per questo, creerò una nuova applicazione Windows Form, come si vede in figura 2 .

 
[Clicca sull'immagine per ingrandirla.] Figura 2. Creazione di un'applicazione Windows Form come un client API Web
L'interfaccia utente per l'applicazione è mantenuto semplice per scopi dimostrativi, come si vede in Figura 3 L'applicazione client demo è destinato a funzionare da C:. \ WebAPI21ClientDemo.

 
[Clicca sull'immagine per ingrandirla.] Figura 3. ui per Web Demo Client API
Dopo aver impostato l'interfaccia utente in figura 3 , io aggiungo la classe Car ai frmMain.cs. La classe Car è un modello dei dati ricevuti dalla chiamata API web. E 'lo stesso modello utilizzato nel progetto Web API. Assicurarsi di aggiungere questo dopo la frmMain classe nello spazio dei nomi CarInventory21Client del file frmMain.cs. In caso contrario, verrà visualizzato un errore quando si tenta di visualizzare il form designer. Ecco la classe Car:

public class Auto
{
  pubblica Int32 ID {get; set; }
  pubblica Int32 Anno {get; set; }
  stringa di rendere pubblico {get; set; }
  stringa Modello pubblico {get; set; }
  public string colore {get; set; }
}
Avanti, creerò un nuovo gestore classe personalizzata denominata CustomHandlerA, come si è visto in Listato 2 . Questa classe sarà anche nello spazio dei nomi CarInventory21Client del file frmMain.cs, ma al di sotto della classe frmMain. Vi spiegherò il motivo di questo più tardi.

Listing 2: La classe CustomHandlerA 
Classe CustomHandlerA: DelegatingHandler
{
  CustomHandlerA pubblico ()
  {
  }
     
  protected override async Task <HttpResponseMessage> SendAsync (HttpRequestMessage richiesta, 
    CancellationToken CancellationToken)
  {
    // Aggiungere funzionalità personalizzate qui, prima o dopo base.SendAsync ()
    WriteLog ("CustomHandlerA () - prima handler interno");
    HttpResponseMessage risposta = attendere base.SendAsync (richiesta, CancellationToken);
    WriteLog ("CustomHandlerA () - dopo handler interno; response.StatusCode =" + 
      response.StatusCode);

    ritorno di risposta;
  }

  WriteLog public void (string msg)
  {
    StreamWriter sw = new StreamWriter ("C: \\ WebAPI21ClientDemo \\ LogFile.txt", true);
    sw.WriteLine (DateTime.Now.ToString () + "" + Msg);
    sw.Close ();
  }
}
La funzionalità di questa classe è minimo e mantenuto semplice per scopi dimostrativi. Il gestore registra semplicemente un messaggio in un file di log prima e dopo la chiamata al metodo base.SendAsync. Questi messaggi vengono registrati in un file di testo utilizzando il metodo WriteLog.

Per dimostrare la sequenza di chiamate utilizzando più gestori personalizzati durante una chiamata API Web, sarò anche creare CustomHandlerB. Questa classe avrà la stessa funzionalità CustomHandlerA, ma verrà utilizzata per dimostrare la sequenza di chiamate da un gestore ad un altro.

Una volta completato, i frmMain.cs file conterrà quattro classi utilizzate in questo esempio:

frmMain: classe per Windows Forms funzionalità
Auto: modello di dati utilizzato per de-serializzare i dati ricevuti
CustomHandlerA: classe di handler HttpClient personalizzato
CustomHandlerB: classe per abitudine HttpClient gestore
Tutte le classi saranno nello spazio dei nomi CarInventory21Client. In genere, l'ordine degli oggetti all'interno di un file è irrilevante. Tuttavia, in un'applicazione Windows Form, l'errore in figura 4 viene rilevato se la classe Windows Form non è la prima classe della lista.

 
[Clicca sull'immagine per ingrandirla.] Figura 4. Errore Grazie al modulo di classe non essere primo nel file
L'errore si legge: "Il frmMain classe può essere progettato, ma non è la prima classe nel file di Visual Studio richiede che i progettisti utilizzano la prima classe nel file Spostare il codice della classe in modo che sia la prima classe nel file e provare.. caricare di nuovo il progettista. " Per risolvere questo errore, spostare semplicemente la classe del form alla parte superiore dello spazio dei nomi.

Guardando la classe CustomHandlerA più in dettaglio, prima che sarà ereditato da System.Net.Http.DelegatingHandler. La classe DelegatingHandler è un tipo di base per gestori HTTP, delegando l'elaborazione dei messaggi di risposta HTTP a un altro gestore, noto come il "gestore interiore." Per saperne di più su questa classe, vedere la pagina di MSDN Library, " DelegatingHandler classe . "

Una volta che la classe DelegatingHandler viene ereditata, il metodo SendAsync può essere ignorato. Questo sarà il metodo per eseguire codice personalizzato, prima o dopo la chiamata al gestore interno (base.SendAsync). Il base.SendAsync è il metodo che invia la richiesta al successivo gestore della catena.

Guardando il codice del gestore eventi per btnGet_Click nel Listato 3 , prima della firma del metodo è stato modificato per restituire in modo asincrono, utilizzando la parola chiave "async".

Listato 3: btnGetClick da frmMain.cs 
privato async vuoto btnGet_Click (object sender, EventArgs e)
{
  CustomHandlerA Cha = new CustomHandlerA ();
  CustomHandlerB CHB = new CustomHandlerB ();
  HttpClient client = HttpClientFactory.Create (CHA, CHB);

  client.BaseAddress = new Uri ("http: // localhost: 15324 /");
  client.DefaultRequestHeaders.Accept.Clear ();
  client.DefaultRequestHeaders.Accept.Add (
    nuovo MediaTypeWithQualityHeaderValue ("application / json"));
            
  HttpResponseMessage risposta = attendere client.GetAsync ("api / auto");
  se (response.IsSuccessStatusCode)
  {
    Auto [] = myCarArray attendono response.Content.ReadAsAsync <Auto []> ();
    foreach (myCar auto in myCarArray)
    {
      txtResults.AppendText (string.Format ("{0} \ t {1} \ t {2} \ n \ n", myCar.Id, myCar.Make, 
        myCar.Model));
    }                    
  }   
}
Successivamente, vengono istanziati istanze del CustomHandlerA e CustomHandlerB. Tali istanze vengono poi utilizzati durante la creazione di un oggetto HttpClient. Passando istanze dei gestori personalizzati per il metodo Create, Sono la creazione di un oggetto client con uno specifico ordine di delegare gestori. I prossimi tre istruzioni nel codice impostare URI e il tipo di formattazione JSON Media.

Dopo le proprietà richieste dell'oggetto client sono impostate, la chiamata client.GetAsync viene eseguito. Questo restituisce un oggetto HttpResponseMessage contenente i dati richiesti in formato JSON. I dati possono poi essere analizzati dall'oggetto response.Content. I risultati verranno visualizzati nella finestra dell'applicazione, come mostrato nella Figura 5 .

 
[Clicca sull'immagine per ingrandirla.] Figura 5. risultati visualizzati dopo aver chiamato il Web API
Guardando il contenuto del file di log (LogFile.txt), visto in qui, vedrete l'ordine di esecuzione:

2014/06/12 12:07:52 CustomHandlerA () - prima handler interno
2014/06/12 12:07:52 CustomHandlerB () - prima handler interno
2014/06/12 12:07:52 CustomHandlerB () - dopo handler interno; response.StatusCode = OK
2014/06/12 12:07:52 CustomHandlerA () - dopo handler interno; response.StatusCode = OK

Nessun commento:

Posta un commento