2015-12-10 7 views
5

Ho usato HttpClient nel codice per un po 'di tempo e ho sempre sentito che il suo uso di Uris ha comportato un po' di fragilità nella mia implementazione. La maggior parte degli indirizzi di base degli endpoint del servizio si trovano in app./web.config. Di conseguenza, possono essere facilmente modificati.Utilizzo di stringhe Uri che potrebbero avere o meno il sottotitolo

Ho scoperto che quando si utilizzano queste stringhe di endpoint per generare un Uri, se non terminano in un /, ottengo un comportamento davvero instabile. Quando si chiama GetAsync() con un non / -terminated BaseAddress, l'URL risultante concatenati che viene inviato la richiesta GET scende spesso la stringa dopo la finale / nel BaseAddress, o lascerà cadere la stringa che precede la prima / nel getUri.

Ad esempio:

BaseAddress: http://test/serviceEndpoint

GetUri: api/customer

Quando HttpClient.GetAsync() viene chiamato con quel GetUri, tenterà di ottenere da http://test/api/customer. Se copolo BaseAddress con un /, tutto funziona come previsto.

Il mio problema è cheBaseAddress è config-driven, e mettendo in un commento nel file .config dicendo "Assicuratevi di terminare tutti gli URL di servizio con un /!" è una soluzione davvero fragile.

Così ho preso l'abitudine di utilizzare il seguente codice in tutta la mia HttpClient costruzione:

 var service = settings.GetValue("ServiceBaseUrl"); 
     var serviceUri = !service.EndsWith("/") 
      ? new Uri(service + "/") 
      : new Uri(service); 

     _client = new HttpClient 
     { 
      BaseAddress = serviceUri 
     };` 

Anche se questo non è fragile, si sente ripetitivo di avere in ogni HttpClient costruttore. C'è qualcosa in HttpClient o Uri che posso usare per evitare questo codice boilerplate?

+0

Si può cercare di avvolgere la logica in un metodo di estensione per ridurre la quantità di ripetizione. E dovresti usare var serviceUri = service.GetBaseURL() attraverso la tua app. https://msdn.microsoft.com/en-us/library/bb383977.aspx – Paul

+0

Solo un caso limite ha pensato: 'serviceUri = servizio.TrimEnd ('/') + "/" 'catturerebbe situazioni in cui il' ServiceBaseUrl' termina con più di un '/' e situazioni in cui non finisce con un '/'. – test

risposta

2

Non c'è niente in HttpClient o Uri per risolvere questo problema, motivo per cui l'ho affrontato in un paio di modi in Flurl. I metodi di Flurl AppendPathSegment e AppendPathSegments garantiranno uno e un solo "/" separatore tra i segmenti. Ad esempio, questi producono risultati identici:

"http://mysite/".AppendPathSegment("/endpoint") 
"http://mysite".AppendPathSegment("endpoint") 

Il Url.Combine metodo statico ha anche questo comportamento, agisce come una sorta di Path.Combine per gli URL.

Queste ed altre utile bit URL-building sono disponibili nel pacchetto di base Flurl, ma il vero divertimento è in Flurl.Http, che unisce la creazione URL fluente con un involucro leggero in cima HttpClient e Json.NET che ti permette di andare da stringa a URL richiesta HTTP al risultato deserializzati senza sollevare la penna dalla carta, per così dire:

var result = await settings.GetValue("ServiceBaseUrl") 
    .AppendPathSegment("endpoint") 
    .GetJsonAsync<T>(); 
+0

Questo è bello, grazie per il suggerimento! –

Problemi correlati