HttpClient BaseAddress neden çalışmıyor?


299

BaseAddressKısmi bir URI yolunu tanımlayan aşağıdaki kodu göz önünde bulundurun .

using (var handler = new HttpClientHandler())
using (var client = new HttpClient(handler))
{
    client.BaseAddress = new Uri("http://something.com/api");
    var response = await client.GetAsync("/resource/7");
}

Bunun bir GETistekte bulunmasını bekliyorum http://something.com/api/resource/7. Ama öyle değil.

Biraz arama yaptıktan sonra bu soruyu ve cevabını buldum : BaseAddress ile HttpClient . Öneri, /sonuna yerleştirmektir BaseAddress.

using (var handler = new HttpClientHandler())
using (var client = new HttpClient(handler))
{
    client.BaseAddress = new Uri("http://something.com/api/");
    var response = await client.GetAsync("/resource/7");
}

Hala çalışmıyor. İşte belgeler: HttpClient.BaseAddress Burada neler oluyor?



@ ГеоргийЛанец Ters kopya zaten önerildi. Bu soruyu özellikle yazdım çünkü diğer soru aynı problemi olan insanlar tarafından çok keşfedilebilir bir şekilde yazılmamıştı ve yanıtı burada yazdım çünkü oradaki cevap önemli bir noktayı bıraktı.
Timothy Shields

ancak bu soru daha sonra sorulur
George Lanetz

2
@ ГеоргийЛанец Bu şekilde çalışmaz. Genellikle en "kanonik" soru, kopyaları işaret eden sorudur. Bu diğer soru, kullanıcının SSS gibi okumak yerine tek bir sorunla ilgiliydi.
Timothy Shields

2
@ ГеоргийЛанец Ayrıca bu sorudaki diğer soruya atıfta bulunduğumu fark ettim ve diğer soru ve cevabın sorunu çözmek için neden yetersiz olduğunu açıklıyorum.
Timothy Shields

Yanıtlar:


720

Sondaki dört olası permütasyondan, izleyen veya öne eğik çizgileri dahil etme veya hariç tutma yöntemine BaseAddressve göreli URI'nin GetAsyncyönteme - veya başka bir yöntemden HttpClient- yalnızca bir permütasyonun işe yaradığı ortaya çıktı. Sen gerekir sonunda bir eğik çizgi koyun BaseAddressve olmamalıdır aşağıdaki örnekte olduğu gibi, sizin göreceli URI başında eğik çizgi koyun.

using (var handler = new HttpClientHandler())
using (var client = new HttpClient(handler))
{
    client.BaseAddress = new Uri("http://something.com/api/");
    var response = await client.GetAsync("resource/7");
}

Her ne kadar kendi sorumu yanıtlasam da, yine bu düşmanca davranışın belgelenmediği için buradaki çözüme katkıda bulunacağımı düşündüm. Meslektaşım ve ben günün çoğunu bu tuhaflıktan kaynaklanan bir sorunu çözmeye çalışarak geçirdik HttpClient.


4
Teşekkür ederim. Bu, Azure'a geçiş yapmak, IIS'ye geri dönmek ve yanlış yerleştirilmiş veya fazladan eğik çizgileri en kaba şekilde görmezden gelen IIS Express'e geri dönmek arasında iki günden fazla uğraştığım bir sorunu çözdü. Bir zamanlar temel sınıfımda belirlendi RestClient, neredeyse görünmezdi ve hiç dikkat çekmedi ve kesme noktalarında vb. Tam url'yi hiç görmedim
ProfK

43
Bu tuhaflık (ve bu düzeltme) hala .NET Core ile ilgili olduğunu onaylayabilirsiniz. Saç çeken Timothy'mi azalttığın için teşekkürler.
Nate Barbettini

8
Bunun nedeni, istekleri oluştururken sondaki eğik çizgi olmadan son parçayı düşürmesidir. Bu yüzden bir şeye çarpıyor.com/ resource/7 . Temel adresi bir şey / com olarak ayarlarsanız (eğik çizgi ile veya eğik çizgi olmadan farketmez) api / resource / 7'nin başına eğik çizgi koymanızın da önemi yoktur. Sondaki eğik çizgi olmadan, temel adresin son kısmı bir dosya gibi ele alınır ve bina talebi sırasında bırakılır.
Piotr Perak

12
Bu doğrudan asıl soruyu değil, bununla ilgilidir. Mircosoft'a göre, bir HttpClient () örneği statik bir değişkene atanmalı ve yeniden kullanılmalıdır ( docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/… - Creating a new HttpClient instance per request can exhaust the available sockets). Bu yüzden Using () öğesini kaldırmayı düşünmelisiniz.
sanmcp

6
Sadece korkunç bir uygulama. Neden bunu düzeltmiyorlar?
timmkrause

56

Referans Çözünürlüğü, RFC 3986 Tekdüzen Kaynak Tanımlayıcısı (URI): Genel Sözdizimi tarafından tanımlanmıştır . Ve tam da böyle çalışması gerekiyordu. Temel URI yolunu korumak için, temel URI'nin sonuna eğik çizgi eklemeniz ve bağıl URI'nin başındaki eğik çizgiyi kaldırmanız gerekir.

Temel URI boş olmayan bir yol içeriyorsa, birleştirme işlemi son parçasını (sondan sonra /) atar . İlgili bölüm :

5.2.3. Yolları Birleştir

Yukarıdaki sözde kod, göreli yol referansını temel URI'nin yolu ile birleştirmek için bir "birleştirme" rutini anlamına gelir. Bu, aşağıdaki gibi gerçekleştirilir:

  • Temel URI'nin tanımlanmış bir yetki bileşeni ve boş bir yolu varsa, başvurunun yoluyla birleştirilmiş "/" dizesini döndürür; aksi takdirde

  • taban URI'sının yolunun son segmenti hariç hepsine eklenmiş referansın yol bileşeninden oluşan bir dize döndürün (yani, temel URI yolunda en sağdaki "/" karakterinden sonra veya herhangi bir karakter varsa, temel URI yolunun hariç tutulması durumunda) "/" karakteri içermiyorsa).

Göreli URI eğik çizgi ile başlarsa buna mutlak yollu göreli URI denir. Bu durumda birleştirme yordamı tüm temel URI yolunu yoksay. Daha fazla bilgi için 5.2.2'yi kontrol edin . Referansları Dönüştür bölümü.


4
İyi ama HttpClient gibi istemci kütüphanelerinin bizi böyle ezoterik uygulama detaylarından koruyacağı düşünülüyor.
Jamie Ide

Yanıtlar, NEDEN bir şey bu şekilde çalışır, ilgili bağlantılar ve alıntılarla nedenleri kapsar. Bu sorudan doğrudan soruna yardımcı olmasa bile, çok yardımcı olur.
Rast

-1

HTTPClient ile ilgili bir sorunla karşılaştı, hatta öneriler hala kimlik doğrulamasını alamadı. Göreceli yolumda bir '/' izine ihtiyacım olduğu ortaya çıktı.

yani

var result = await _client.GetStringAsync(_awxUrl + "api/v2/inventories/?name=" + inventoryName);
var result = await _client.PostAsJsonAsync(_awxUrl + "api/v2/job_templates/" + templateId+"/launch/" , new {
                inventory = inventoryId
            });

-6

Alternatif olarak - hiç kullanmayın BaseAddress. URL'nin tamamını GetAsync() içine koy


33
Soruya hiçbir şekilde cevap vermiyor.
Archibald

7
BaseAddress gürültüyü azaltır. Zaten gözlerime. :)
MetalMikester

2
Olumsuz yorumlara katılmam gerekecek. HttpClient çağrılarımın Dev PC'imde neden çalıştığını anlamaya çalışırken 2 gün geçirdim ama sunucuyu kırdım. Garip Powershell çalışıyor ama .net çalışmıyor. .SendAsyc kullanıyordum. Sonra .GetAsyc'in çalıştığını keşfettim. Bu beni farklı bir yoldan geçirdi ve sonunda burada. Temel Adres ile Göreli URL arasına / işareti eklemek veya kaldırmak hiçbir şey yapmadı. Hala 404 hataları var .... Ancak ne zaman temel adresi ve göreli içine tüm yol koymak vermedi .. işe yaradı! Yine, bu .SendAsync ile ama asla geri alamayacağım 2 gün oldu!
da_jokker
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.