An unhandled exception of type 'System.Net.WebException' occurred in system.web.services.dll
Additional information: The request failed with the error message:
--
發生了什么呢?原來HTTP請求收到的不是“200 OK”響應。如果你熟悉HTTP協議,你或許可以從響應中的HTML代碼中發現這是一個“302 Found”響應,這意味著該請求被重定向到超鏈接中指定的地址。返回HTML代碼是很明智的,這樣如果一個瀏覽器因為某些原因不支持重定向的話,它可以把代碼顯示出來,或者在重定向過程中顯示這些代碼直到重定向完成。注意到超鏈接中包含了一個有趣的字符串“(l2z3psnhh2cf1oahmai44p21)”,顯然,我們可以推斷這就是ASP.net的會話ID,它被嵌入了我們要重定向到的位置的URL中。在客戶端代理中,我們需要做的僅僅是重新發送請求到這個新的URL。
無須再在Win32 WinInet API編程中跋涉,我們可以直接找到proxy類的一個屬性允許自動重定向。用外行人的說法,就是如果我們接收到一個“302 Found”響應,就直接將請求重新發送到相應中HTTP位置頭所指示的URL。當Visual Studio.net的智能提示顯示proxy類的AllowAutoRedirect屬性時,我感到這東西真是機靈得可愛。我馬上就在代碼中加上如下一行:
proxy.AllowAutoRedirect = True
我認為這仍然比創建一個CookieContainer類并關聯到proxy類要容易得多,于是我又一次運行程序。很不幸,我遭遇了如下異常(為了簡潔起見有所刪節):
An unhandled exception of type 'System.InvalidOperationException' occurred
in system.web.services.dll
Additional information: Client found response content type of 'text/html; charset=utf-8',
but expected 'text/xml'.
The request failed with the error message: …
如果你看到錯誤消息的內容,你會發現你所看到的HTML頁面跟你瀏覽.ASMX文件的頁面一樣。問題是,為什么當我傳送XML(以SOAP封裝了的形式)到Web Service服務器時它返回的卻是HTML代碼?結果證實,你并沒有在SOAP封裝中發送HTTP POST請求,而僅僅發送了一個簡單的沒有內容的HTTP GET請求,因此你的Web Service服務端理所當然地假設這個請求來自瀏覽器,于是它返回普通的HTML響應。為什么會這樣呢?
如果你了解HTTP協議,你會發現一個HTTP客戶端在收到“302 Found”響應時發送HTTP GET請求到響應中指定的地址是合情合理的,即使初始請求是HTTP POST。這種方式下瀏覽器工作得很好,因為開始幾乎所有的請求都是HTTP GET類型的,只有當你試圖傳遞數據到一個URL時,才會出現上述失敗的結果。
理由是在傳送的數據中可能包含潛在的敏感數據,因此你需要確認是否用戶真的想向新的資源傳送數據。顯然如果你轉向基于重定向設置的新地址,你就沒能確認用戶是否真的允許將他們的數據發送到新的地址。因此數據并沒有被發送,而代之以簡單的HTTP GET請求。
新聞熱點
疑難解答