HTTP POST ส่งคืนข้อผิดพลาด: 417“ ความคาดหวังล้มเหลว”


212

เมื่อฉันพยายาม POST ไปยัง URL ผลลัพธ์จะมีข้อยกเว้นดังต่อไปนี้:

รีโมตเซิร์ฟเวอร์ส่งคืนข้อผิดพลาด: (417) การคาดหวังล้มเหลว

นี่คือตัวอย่างรหัส:

var client = new WebClient();

var postData = new NameValueCollection();
postData.Add("postParamName", "postParamValue");

byte[] responseBytes = client.UploadValues("http://...", postData);
string response = Encoding.UTF8.GetString(responseBytes); // (417) Expectation Failed.

การใช้HttpWebRequest/HttpWebResponseคู่หรือสิ่งHttpClientใดสร้างความแตกต่าง

อะไรทำให้เกิดข้อยกเว้นนี้


2
ดูเหมือนว่าปัญหาจะเกิดขึ้นเมื่อแอปพลิเคชันของคุณสื่อสารผ่านพร็อกซีเซิร์ฟเวอร์ แอปพลิเคชั่น. NET ที่ฉันเขียนทำงานเมื่อเชื่อมต่อกับอินเทอร์เน็ตโดยตรง แต่ไม่ใช่เมื่ออยู่หลังพร็อกซีเซิร์ฟเวอร์
Salman

2
ปฏิบัติตามเงื่อนไขนี้เมื่อไคลเอ็นต์กำลังทำงานผ่านพร็อกซีเซิร์ฟเวอร์ HTTP 1.0 (เท่านั้น) ไคลเอนต์ (asmx proxy ที่ไม่มีการกำหนดค่าใด ๆ ) กำลังส่งการร้องขอ HTTP 1.1 และพร็อกซี (ก่อนที่เซิร์ฟเวอร์จะเข้ามาเกี่ยวข้อง) จากนั้นปฏิเสธสิ่งที่พร็อกซีส่ง ควรผู้ใช้ปลายมีปัญหานี้โดยใช้วิธีการแก้ปัญหาการตั้งค่าดังต่อไปนี้เป็นวิธีแก้ปัญหาที่เหมาะสมตามที่มันจะก่อให้เกิดการร้องขอจะถูกสร้างขึ้นโดยไม่ต้องพึ่งพิงพร็อกซี่ความเข้าใจที่Expectส่วนหัวซึ่งเริ่มต้นโดยได้รับเพิ่มเป็นExpect100Continueเป็นtrueตามค่าเริ่มต้น
Ruben Bartelink

คำตอบ:


478

System.Net.HttpWebRequest เพิ่มส่วนหัว 'ส่วนหัว HTTP "คาดหวัง: 100- ดำเนินการต่อ" "ทุกคำขอเว้นแต่คุณจะขออย่างชัดเจนไม่ให้โดยการตั้งค่าคุณสมบัติคงที่นี้เป็นเท็จ:

System.Net.ServicePointManager.Expect100Continue = false;

เซิร์ฟเวอร์บางตัวสำลักในส่วนหัวนั้นและส่งกลับข้อผิดพลาด 417 ที่คุณเห็น

ลองยิงดูสิ


5
ฉันมีรหัสที่พูดกับ Twitter ว่าจู่ ๆ ก็หยุดทำงานหลังจากวันคริสต์มาส พวกเขาทำการเปลี่ยนแปลงอัปเกรดหรือกำหนดค่าที่ทำให้เซิร์ฟเวอร์เริ่มสำลักในส่วนหัวนั้น มันเป็นความเจ็บปวดในการค้นหาวิธีแก้ไข
xcud

8
ฉันคิดว่าฉันได้รับเพิ่ม 10 คะแนนเพื่อรับคำตอบที่ได้รับจากกระทู้ที่ Jon Skeet โพสต์วิธีแก้ปัญหา
xcud

1
ขอบคุณ! สิ่งนี้ควรถูกบันทึกไว้ที่ไหนสักแห่งในตัวอย่างmsdn
Eugene

25
คุณยังสามารถระบุคุณสมบัตินั้นใน app.config ของคุณ: <system.net> <settings> <servicePointManager expect100Continue = "false" /> nahidulkibria.blogspot.com/2009/06/…
Andre Luus

2
หมายเหตุ: การตั้งค่านี้ใช้กับ ServiceReferences ด้วยและฉันถือว่า WebReferences
Myster

114

วิธีอื่น -

เพิ่มบรรทัดเหล่านี้ในส่วนการกำหนดค่าไฟล์แอปพลิเคชันของคุณ:

<system.net>
    <settings>
        <servicePointManager expect100Continue="false" />
    </settings>
</system.net>

6
ทำงานได้ดีมากเมื่อคุณต้องทำการเปลี่ยนแปลงการปฏิบัติงานและไม่พร้อมสำหรับการเปลี่ยนรหัส
dawebber

1
บรรทัดการกำหนดค่านั้นทำอะไร
J86

31

สถานการณ์และข้อผิดพลาดเดียวกันนี้ยังสามารถเกิดขึ้นได้ด้วยตัวช่วยสร้างเริ่มต้นที่สร้างพร็อกซี SOAP Web Service (ไม่ใช่ 100% หากเป็นกรณีนี้ในSystem.ServiceModelสแต็กWCF ) เมื่อรันไทม์:

  • มีการกำหนดค่าเครื่องผู้ใช้ปลายทาง (ในการตั้งค่าอินเทอร์เน็ต) เพื่อใช้พรอกซีที่ไม่เข้าใจ HTTP 1.1
  • ไคลเอ็นต์สิ้นสุดการส่งสิ่งที่พร็อกซี HTTP 1.0 ไม่เข้าใจ (โดยทั่วไปExpectส่วนหัวเป็นส่วนหนึ่งของ HTTP POSTหรือการPUTร้องขอเนื่องจากการประชุมโปรโตคอลมาตรฐานในการส่งคำขอเป็นสองส่วนตามที่กล่าวไว้ในหมายเหตุที่นี่ )

... ยอมแพ้ 417

ในฐานะที่เป็นที่กล่าวถึงในคำตอบอื่น ๆ ถ้าปัญหาเฉพาะที่คุณใช้เป็นก็คือExpectส่วนหัวที่เป็นสาเหตุของปัญหาแล้วว่าปัญหาที่เฉพาะเจาะจงสามารถส่งไปรอบ ๆ ด้วยการทำสวิตชิ่งค่อนข้างทั่วโลกออกจาก PUT สองส่วน / System.Net.ServicePointManager.Expect100Continueโพสต์ส่งผ่าน

อย่างไรก็ตามสิ่งนี้ไม่ได้แก้ไขปัญหาพื้นฐานที่สมบูรณ์ - สแต็กอาจยังใช้สิ่งที่เจาะจง HTTP 1.1 เช่น KeepAlives เป็นต้น (แม้ว่าในหลายกรณีคำตอบอื่น ๆ จะครอบคลุมกรณีหลัก)

ปัญหาที่แท้จริงคืออย่างไรก็ตามรหัสที่สร้างอัตโนมัติจะถือว่าตกลงที่จะไปสุ่มสี่สุ่มห้าโดยใช้สิ่งอำนวยความสะดวก HTTP 1.1 เนื่องจากทุกคนเข้าใจสิ่งนี้ หากต้องการหยุดการสันนิษฐานนี้สำหรับพร็อกซีบริการเว็บที่ระบุคุณสามารถเปลี่ยนการแทนที่ค่าเริ่มต้นที่อ้างอิงHttpWebRequest.ProtocolVersionจากค่าเริ่มต้นที่1.1โดยการสร้างคลาสพร็อกซีที่ได้รับซึ่งจะแทนที่ดังที่แสดงในโพสต์นี้ : -protected override WebRequest GetWebRequest(Uri uri)

public class MyNotAssumingHttp11ProxiesAndServersProxy : MyWS
{
    protected override WebRequest GetWebRequest(Uri uri)
    {
      HttpWebRequest request = (HttpWebRequest)base.GetWebRequest(uri);
      request.ProtocolVersion = HttpVersion.Version10;
      return request;
    }
}

( MyWSพร็อกซีตัวช่วยสร้างเพิ่มการอ้างอิงเว็บอยู่ที่คุณ)


UPDATE: นี่คือนัยที่ฉันใช้ในการผลิต:

class ProxyFriendlyXXXWs : BasicHttpBinding_IXXX
{
    public ProxyFriendlyXXXWs( Uri destination )
    {
        Url = destination.ToString();
        this.IfProxiedUrlAddProxyOverriddenWithDefaultCredentials();
    }

    // Make it squirm through proxies that don't understand (or are misconfigured) to only understand HTTP 1.0 without yielding HTTP 417s
    protected override WebRequest GetWebRequest( Uri uri )
    {
        var request = (HttpWebRequest)base.GetWebRequest( uri );
        request.ProtocolVersion = HttpVersion.Version10;
        return request;
    }
}

static class SoapHttpClientProtocolRealWorldProxyTraversalExtensions
{
    // OOTB, .NET 1-4 do not submit credentials to proxies.
    // This avoids having to document how to 'just override a setting on your default proxy in your app.config' (or machine.config!)
    public static void IfProxiedUrlAddProxyOverriddenWithDefaultCredentials( this SoapHttpClientProtocol that )
    {
        Uri destination = new Uri( that.Url );
        Uri proxiedAddress = WebRequest.DefaultWebProxy.GetProxy( destination );
        if ( !destination.Equals( proxiedAddress ) )
            that.Proxy = new WebProxy( proxiedAddress ) { UseDefaultCredentials = true };
    }
}

2
ฉันรู้ว่าคุณโพสต์เรื่องนี้เมื่อไม่นานมานี้ แต่ Ruben คุณเป็นผู้ช่วยชีวิต ปัญหานี้ทำให้ฉันคลั่งไคล้จนฉันพบวิธีแก้ปัญหาของคุณและทำงานได้อย่างสมบูรณ์ ไชโย!
Christopher McAtackney

1
@ChrisMcAtackney ไม่เป็นไร แน่นอนว่ามันคุ้มค่ากับความพยายามในการจัดทำเอกสารที่พวกเขาเวลา ... ปัญหาทั่วไปที่เกิดขึ้นรอบ ๆ ขอบของการเป็นปัญหาที่สำคัญที่สุดและเพิ่งรบกวนฉันจนกว่าฉันจะตรวจสอบอย่างถูกต้อง - แต่ดูเหมือนจะไม่มีน้ำ google สำหรับ ด้านนั้นของปัญหา และมันเป็นหนึ่งในโพสต์ของ Attwood จากทางด้านหลังที่ผลักดันให้ฉันทำ (โหวตขึ้นพร้อมกับความคิดเห็นเช่นนี้เป็นที่น่าอัศจรรย์ BTW)
Ruben Bartelink

1
นอกจากนี้ที่ยอดเยี่ยมและเป็นตัวอย่าง ขอบคุณ!
Fadi Chamieh

5

แบบฟอร์มที่คุณพยายามจำลองมีสองฟิลด์ชื่อผู้ใช้และรหัสผ่านหรือไม่

ถ้าเป็นเช่นนั้นสายนี้:

 postData.Add("username", "password");

ไม่ถูกต้อง.

คุณต้องการสองบรรทัดเช่น:

 postData.Add("username", "Moose");
postData.Add("password", "NotMoosespasswordreally");

แก้ไข:

โอเคเนื่องจากไม่ใช่ปัญหาวิธีหนึ่งในการแก้ไขปัญหานี้คือการใช้สิ่งที่ชอบ Fiddler หรือ Wireshark เพื่อดูสิ่งที่ถูกส่งไปยังเว็บเซิร์ฟเวอร์จากเบราว์เซอร์เรียบร้อยแล้วเปรียบเทียบกับสิ่งที่ส่งจากรหัสของคุณ หากคุณกำลังจะไปที่พอร์ตปกติ 80 จาก. Net, Fiddler จะยังคงจับภาพการจราจรนี้

อาจมีฟิลด์ที่ซ่อนอยู่บางส่วนในแบบฟอร์มที่เว็บเซิร์ฟเวอร์คาดว่าคุณไม่ได้ส่ง


3

โซลูชันจากฝั่งพร็อกซีฉันประสบปัญหาบางอย่างในกระบวนการจับมือ SSL และฉันต้องบังคับพร็อกซีเซิร์ฟเวอร์ของฉันให้ส่งคำขอโดยใช้ HTTP / 1.0 เพื่อแก้ปัญหาด้วยการตั้งค่าอาร์กิวเมนต์นี้ใน httpd.conf SetEnv force-proxy-request-1.0 1 SetEnv proxy-nokeepalive 1หลังจากนั้นฉันพบข้อผิดพลาด 417 แอปพลิเคชันลูกค้าของฉันใช้ HTTP / 1.1 และพร็อกซีถูกบังคับให้ใช้ HTTP / 1.0 ปัญหาได้รับการแก้ไขโดยการตั้งค่าพารามิเตอร์นี้ใน httpd.conf ที่ด้านพร็อกซีRequestHeader unset Expect earlyโดยไม่จำเป็นต้องเปลี่ยนแปลงอะไรในฝั่งไคลเอ็นต์หวังว่าสิ่งนี้จะช่วย .



1

หากคุณกำลังใช้ " HttpClient " และคุณไม่ต้องการใช้การกำหนดค่าส่วนกลางเพื่อส่งผลกระทบต่อโปรแกรมทั้งหมดที่คุณสามารถใช้:

 HttpClientHandler httpClientHandler = new HttpClientHandler();
 httpClient.DefaultRequestHeaders.ExpectContinue = false;

ฉันใช้ " WebClient " ฉันคิดว่าคุณสามารถลบหัวข้อนี้ได้ด้วยการโทร:

 var client = new WebClient();
 client.Headers.Remove(HttpRequestHeader.Expect);

0

ในสถานการณ์ของฉันดูเหมือนว่าข้อผิดพลาดนี้จะเกิดขึ้นก็ต่อเมื่อคอมพิวเตอร์ของลูกค้าของฉันมีนโยบายไฟร์วอลล์ที่เข้มงวดซึ่งป้องกันไม่ให้โปรแกรมของฉันสื่อสารกับบริการเว็บ

ทางออกเดียวที่ฉันเจอคือจับข้อผิดพลาดและแจ้งผู้ใช้เกี่ยวกับการเปลี่ยนการตั้งค่าไฟร์วอลล์ด้วยตนเอง


-1

วิธีการ web.config ใช้สำหรับการเรียกใช้บริการฟอร์ม InfoPath จากกฎการเปิดใช้งานบริการบนเว็บของ IntApp

  <system.net>
    <defaultProxy />
    <settings> <!-- 20130323 bchauvin -->
        <servicePointManager expect100Continue="false" />
    </settings>
  </system.net>

2
dup of stackoverflow.com/a/7358457/11635โปรดแสดงความคิดเห็นที่นั่นหากคุณต้องการเพิ่มจุด
Ruben Bartelink
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.