سؤال

عندما أحاول النشر إلى عنوان 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.

باستخدام an. HttpWebRequest/HttpWebResponse الزوج أو HttpClient لا تحدث فرقا.

ما الذي يسبب هذا الاستثناء؟

هل كانت مفيدة؟

المحلول

system.net.net.httpwebrequest يضيف رأس "HTTP رأس" يتوقع: 100 - متابعة "" إلى كل طلب ما لم تسأل عن طريق الإعداد بشكل صريح هذه الملكية الثابتة إلى خطأ:

System.Net.ServicePointManager.Expect100Continue = false;

بعض الخوادم تخنق هذا الرأس وإرسال خطأ 417 الذي تراه.

أعط أن الطلقة.

نصائح أخرى

طريق اخر -

أضف هذه الأسطر إلى قسم تكوين ملف تكوين التطبيق الخاص بك:

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

يمكن أن تنشأ نفس الحالة والخطأ هذا أيضا مع إنشاء معالج افتراضي وكيل خدمة Web Soap (وليس 100٪ إذا كان هذا هو الحال أيضا على WCF System.ServiceModel مكدس) عند وقت التشغيل:

  • تم تكوين جهاز المستخدم النهائي (في إعدادات الإنترنت) لاستخدام وكيل لا يفهم HTTP 1.1
  • ينتهي العميل بإرسال شيء لا يفهم وكيل HTTP 1.0 (عادة Expect رأس كجزء من HTTP POST أو PUT طلب بسبب اتفاقية بروتوكول قياسية لإرسال الطلب في جزأين كما مغطاة في هذه التصريحات هنا)

... العائد 417.

كما مغطاة في الإجابات الأخرى، إذا كانت المشكلة المحددة التي تديرها هي أن Expect يسبب الرأس المشكلة، ثم هذه المشكلة المحددة يمكن توجيهها عن طريق إجراء تبديل عالمي نسبيا من ناقل الحركة / Post 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 هو الوكيل إضافة معالج مرجعي ويب فيك.)


تحديث: إليك ما أستخدمه في الإنتاج:

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

هل يحتوي النموذج الذي تحاول محاكاة حقلين أو اسم مستخدم وكلمة مرور؟

إذا كان الأمر كذلك، هذا الخط:

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

غير صحيح.

ستحتاج سطرين مثل:

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

يحرر:

حسنا، نظرا لأن هذه ليست المشكلة، طريقة واحدة لمعالجة هذا هو استخدام شيء مثل Fiddler أو Wireshark لمشاهدة ما يتم إرساله إلى خادم الويب من المتصفح بنجاح، ثم قارن ذلك مع ما يتم إرساله من التعليمات البرمجية. إذا كنت ذاهبا إلى منفذ عادي 80 من .NET، فلن تظل FIDLLER التقاط هذه الحركة.

ربما يكون هناك بعض حقل مخفي آخر في النموذج الذي يتوقعه خادم الويب أنك لا ترسل.

حل من الجانب الوكيل، واجهت بعض المشاكل في عملية مصافحة 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 دون الحاجة إلى تغيير أي شيء في جانب العميل، نأمل أن يساعد هذا.

ل Powershell هو

[System.Net.ServicePointManager]::Expect100Continue = $false

إذا كنت تستخدم "httpclient"، ولا تريد استخدام التكوين العالمي للتأثير على كل البرنامج الذي يمكنك استخدامه:

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

أنا تستخدم "العميل على شبكة الإنترنت"أعتقد أنه يمكنك محاولة إزالة هذا الرأس عن طريق الاتصال:

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

في وضعي، يبدو أن هذا الخطأ يحدث فقط إذا كان لدى كمبيوتر عميلي سياسة جدار حماية صارم، مما يمنع برنامجي من التواصل مع خدمة الويب.

لذلك الحل الوحيد الذي يمكن أن أجده هو التقاط الخطأ وإبلاغ المستخدم بتغيير إعدادات جدار الحماية يدويا.

يعمل نهج Web.config لإجراء مكالمات خدمات InfoPath Form إلى القواعد الممكنة لخدمة الويب Intapp.

  <system.net>
    <defaultProxy />
    <settings> <!-- 20130323 bchauvin -->
        <servicePointManager expect100Continue="false" />
    </settings>
  </system.net>
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top