เหตุใด HttpClient BaseAddress จึงไม่ทำงาน


299

พิจารณาโค้ดต่อไปนี้โดยที่BaseAddressกำหนดพา ธ URI บางส่วน

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");
}

ผมคาดหวังนี้จะดำเนินการร้องขอไปยังGET http://something.com/api/resource/7แต่มันก็ไม่ได้

หลังจากบางค้นหาฉันคิดว่าคำถามนี้และคำตอบ: HttpClient กับ BaseAddress ข้อเสนอแนะคือการสถานที่ในตอนท้ายของ/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");
}

มันยังไม่ทำงาน นี่คือเอกสารประกอบ: HttpClient.BaseAddressเกิดอะไรขึ้นที่นี่?


สำเนาซ้ำที่เป็นไปได้ของHttpClient ด้วย BaseAddress
George Lanetz

@ ГеоргийЛанецมีการเสนอซ้ำที่ซ้ำกันแล้ว ฉันเขียนคำถามนี้โดยเฉพาะเพราะคำถามอื่นไม่ได้เขียนในลักษณะที่คนค้นพบปัญหาเดียวกันมากและฉันเขียนคำตอบที่นี่เพราะคำตอบที่เหลืออยู่เป็นประเด็นสำคัญ
Timothy Shields

แต่คำถามนี้ถูกถามในภายหลัง
George Lanetz

2
@ ГеоргийЛанецนั่นไม่ใช่วิธีการทำงาน โดยทั่วไปคำถาม "บัญญัติ" ส่วนใหญ่จะเป็นคำถามที่ทำให้ซ้ำซ้อน คำถามอื่นนั้นเกี่ยวกับปัญหาเดียวที่ผู้ใช้มีแทนที่จะอ่านเหมือนคำถามที่พบบ่อย
Timothy Shields

2
@ ГеоргийЛанецสังเกตว่าฉันอ้างถึงคำถามอื่นในคำถามนี้และฉันอธิบายว่าทำไมคำถามและคำตอบอื่น ๆ ไม่เพียงพอสำหรับการแก้ปัญหา
Timothy Shields

คำตอบ:


719

แต่กลับกลายเป็นว่าออกจากสี่พีชคณิตเป็นไปได้ของรวมหรือไม่รวมต่อท้ายหรือนำทับบนBaseAddressและญาติ URI ส่งผ่านไปยังGetAsyncวิธีการ - หรือแล้วแต่วิธีการอื่น ๆ ของHttpClient- เพียงหนึ่งการเปลี่ยนแปลงงาน คุณต้องวางสแลชในตอนท้ายBaseAddressและคุณต้องไม่วางสแลชที่จุดเริ่มต้นของ URI ที่เกี่ยวข้องของคุณดังตัวอย่างต่อไปนี้

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");
}

แม้ว่าฉันจะตอบคำถามของฉันเองฉันคิดว่าฉันจะมีส่วนร่วมในการแก้ปัญหาที่นี่ตั้งแต่อีกครั้งพฤติกรรมที่ไม่เป็นมิตรนี้จะไม่มีเอกสาร เพื่อนร่วมงานของฉันและฉันใช้เวลาส่วนใหญ่พยายามแก้ปัญหาที่เกิดจากความผิดปกติHttpClientนี้


4
ขอบคุณ. ที่แก้ไขปัญหาที่ฉันได้รับการดิ้นรนกับส่วนใหญ่ของสองวันตอนนี้ระหว่างสลับไปยัง Azure กลับไปที่ IIS และกลับไปที่ IIS Express ซึ่งส่วนใหญ่หยาบคายละเว้นเครื่องหมายทับหรือใส่ผิดไปข้างหน้า เมื่อตั้งค่าในชั้นฐานของฉันRestClientมันเกือบจะมองไม่เห็นและไม่ได้รับความสนใจเลยและฉันไม่เคยเห็น URL แบบเต็มในที่เบรกพอยต์ของฉัน ฯลฯ
ProfK

43
ฉันสามารถยืนยันได้ว่าสิ่งผิดปกตินี้ (และการแก้ไขนี้) ยังคงเกี่ยวข้องใน. NET Core ขอบคุณที่ลดติโมเธียนผม
Nate Barbettini

8
นี่เป็นเพราะไม่มีสแลชต่อท้ายเมื่อมันสร้างคำขอมันจะลดลงส่วนสุดท้าย ดังนั้นมันจึงเป็นสิ่งที่ . com/resource/ 7 หากคุณตั้งค่าที่อยู่พื้นฐานเป็นอย่าง / com (ไม่สำคัญว่าจะมีหรือไม่มีเครื่องหมายทับ) ก็ไม่สำคัญว่าคุณจะใส่เครื่องหมายทับที่จุดเริ่มต้นของ api / resource / 7 ส่วนสุดท้ายของที่อยู่ฐานจะถือว่าเป็นไฟล์และหลุดเมื่อไม่มีการร้องขอ
Piotr Perak

12
นี่ไม่ใช่การตอบคำถามเดิมโดยตรง แต่เกี่ยวข้องกัน สำหรับ Mircosoft ควรกำหนดอินสแตนซ์ของ HttpClient () ให้กับตัวแปรแบบสแตติกและนำมาใช้ซ้ำ ( docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/… - Creating a new HttpClient instance per request can exhaust the available sockets) ดังนั้นคุณควรพิจารณาลบการใช้ ()
sanmcp

6
เพียงการใช้งานที่น่ากลัว ทำไมพวกเขาถึงไม่แก้ไขสิ่งนี้?
timmkrause

55

มติตามที่อธิบายโดยRFC 3986 Uniform Resource Identifier (URI): ทั่วไปไวยากรณ์ และนั่นคือวิธีที่มันควรจะทำงาน เพื่อรักษาพา ธ URI พื้นฐานคุณต้องเพิ่มเครื่องหมายสแลชที่ส่วนท้ายของ URI ฐานและลบเครื่องหมายสแลชที่จุดเริ่มต้นของ URI ที่เกี่ยวข้อง

ถ้า URI ฐานมีเส้นทางที่ไม่ว่างให้รวมโพรซีเดอร์ทิ้งว่าเป็นส่วนสุดท้าย (หลังจากครั้งสุดท้าย/) ส่วนที่เกี่ยวข้อง:

5.2.3 รวมเส้นทาง

รหัสเทียมข้างต้นอ้างถึงชุดคำสั่ง "ผสาน" สำหรับการรวมการอ้างอิงแบบสัมพันธ์กับเส้นทางของเส้นทางของ URI ฐาน นี่คือความสำเร็จดังนี้:

  • หาก URI ฐานมีองค์ประกอบอำนาจที่กำหนดไว้และเส้นทางที่ว่างเปล่าแล้วส่งกลับสตริงที่ประกอบด้วย "/" ตัดแบ่งกับเส้นทางของการอ้างอิง; มิฉะนั้น

  • ส่งคืนสตริงที่ประกอบด้วยองค์ประกอบเส้นทางของการอ้างอิงผนวกเข้ากับทุกส่วนยกเว้นส่วนสุดท้ายของเส้นทางของ URI ฐาน (กล่าวคือไม่รวมอักขระใด ๆ หลังจาก "/" ขวาสุดในเส้นทาง URI ฐานหรือไม่รวมเส้นทาง URI ฐานทั้งหมดถ้ามัน ไม่มีอักขระ "/")

หาก URI ที่สัมพันธ์กันเริ่มต้นด้วยเครื่องหมายสแลชจะเรียกว่า URI สัมพัทธ์ของเส้นทางแบบสัมบูรณ์ ในกรณีนี้ขั้นตอนการผสานจะละเว้นเส้นทาง URI ฐานทั้งหมด สำหรับข้อมูลเพิ่มเติมตรวจสอบ5.2.2 แปลงส่วนการอ้างอิง


3
ไม่เป็นไร แต่ไคลเอนต์ไลบรารีเช่น HttpClient ควรจะปกป้องเราจากรายละเอียดการใช้งานที่ลึกลับเช่นนี้
Jamie Ide

-1

พบปัญหากับ HTTPClient แม้จะมีข้อเสนอแนะก็ยังไม่สามารถพิสูจน์ตัวตนได้ ปรากฎว่าฉันต้องการส่วนท้าย '/' ในเส้นทางญาติของฉัน

กล่าวคือ

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

อีกทางเลือกหนึ่ง - ไม่ใช้BaseAddressเลย ใส่ URL ทั้งหมดในGetAsync()


33
ไม่ตอบคำถามใด ๆ
Archibald

7
BaseAddress ลดเสียงรบกวน ต่อสายตาของฉันอยู่ดี :)
MetalMikester

2
ฉันจะไม่เห็นด้วยกับความคิดเห็นเชิงลบ ฉันใช้เวลา 2 วันในการพยายามหาสาเหตุที่การโทร HttpClient ของฉันทำงานบน Dev PC ของฉัน แต่ใช้เซิร์ฟเวอร์ไม่ได้ Powershell ผิดปกติทำงานได้ แต่. net ไม่ได้ ฉันใช้. SendAsyc จากนั้นฉันก็ค้นพบว่า. GetAsyc ทำงานได้ นี่นำฉันไปสู่ถนนสายอื่นและในที่สุดก็มาถึงที่นี่ การเพิ่มหรือลบ / ระหว่างที่อยู่ฐานและ URL สัมพัทธ์ไม่ได้ทำอะไรเลย ยังคงมีข้อผิดพลาด 404 .... แต่เมื่อฉันไม่ได้ตั้งค่าที่อยู่ฐานและใส่เส้นทางทั้งหมดในญาติ .. มันใช้งานได้! อีกครั้งนี่คือ. SendAsync แต่มี 2 วันฉันจะไม่กลับมา!
da_jokker
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.