2010-11-25 66 views
8

我有一個Silverlight(v3)應用程序,它使用WebRequest向與Silverlight應用程序相同網站上的網頁發出HTTP POST請求。此HTTP請求取回302(重定向)到同一網站上的另一個頁面,HttpWebRequest自動應該遵循(according to the documentation)。HttpWebRequest僅在Internet Explorer中爲302返回404s

沒有什麼特別之處發出請求的代碼(它使用瀏覽器的HTTP堆棧,它沒有配置爲使用備用內置的Silverlight HTTP堆棧):

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(String.Format("{0}?name={1}&size={2}", _UploadUrl, Uri.EscapeUriString(Name), TotalBytes)); 
request.Method = "POST"; 

所有這一切工作正常,在Firefox和Chrome; Silverlight發出POST HTTP請求,接收302響應並自動執行指定重定向URL的GET HTTP請求,並將其返回給我(我知道這是因爲我使用Fiddler觀看HTTP請求)。 但是,在Internet Explorer(v8)中,Silverlight執行POST HTTP請求,然後拋出帶有404錯誤代碼的WebException!

使用Fiddler,我可以看到Silverlight/Internet Explorer成功返回了請求的302狀態碼,並且我假設我在Silverlight中獲得的404狀態碼(和相關的WebException)是因爲就我而言知道通過瀏覽器堆棧完成的HTTP請求由於限制只能返回200或404。真正的問題是爲什麼Internet Explorer不像其他瀏覽器那樣遵循重定向?

在此先感謝您的幫助!

編輯:我寧願不使用Silverlight客戶端HTTP堆棧,因爲就由其發行我所知請求不包括作爲瀏覽器會話的一部分餅乾,看房包括ASP.NET驗證cookie,我需要附加到由Silverlight控件進行的HTTP請求。

編輯2:我發現當您執行POST請求時,Internet Explorer僅顯示此行爲。 GET請求成功重定向。考慮到現在有多少網站在Post-Redirect-Get樣式中執行操作,這似乎是非常糟糕的行爲。

我已經創建了一個簡單的demo VS2008 solution,如果它有幫助,它會表現出這種奇怪的行爲。它包含一個基本的ASP.NET MVC 1項目和一個Silverlight 3項目。導航到網站上的SilverlightControlTestPage.html頁面以查看問題的實際情況。

+0

重定向的URL也指向在同一臺服務器的資源所張貼的,而且從XAP來的? – AnthonyWJones 2010-11-26 13:32:02

+0

據我所知,Chrome和Firefox可能會以不同方式處理憑​​據。有關於證書的事嗎?請求的URL是否接受匿名或經過身份驗證的請求?您是否檢查HTTP代碼的服務器訪問日誌? – JoeBilly 2010-11-26 14:18:09

+0

您可以使用客戶端HTTP處理設施嗎?這樣你就可以訪問所有的狀態碼。請參閱http://msdn.microsoft.com/en-us/library/cc838250(v=VS.95).aspx – feroze 2010-11-26 18:35:17

回答

3

IE更接近本說明書中,在響應於一個302用於POST用戶代理應該發送POST(雖然它不應無需用戶確認這樣做)。

另一方面,FF和Chrome故意錯誤地複製了用戶代理程序在很久以前經常出錯的問題(問題始於HTTP早期)。

由於這個原因,在HTTP/1.1中引入了307以更清楚地表明應該使用相同的HTTP方法(即,在這種情況下,它應該是一個POST),而303一直意味着應該使用GET。

因此,而不是做Response.Redirect這會導致302 - 不同的用戶代理將以不同的方式處理,請發送303.下面的代碼是這樣做的(並且包括一個有效的實體主體只是在規格)。有過載,因此您可與URI或一個字符串調用它:

private void SeeOther(Uri uri) 
{ 
    if(!uri.IsAbsoluteUri) 
    uri = new Uri(Request.Url, uri); 
    Response.StatusCode = 303; 
    Response.AddHeader("Location", uri.AbsoluteUri); 
    Response.ContentType = "text/uri-list"; 
    Response.Write(uri.AbsoluteUri); 
    Context.ApplicationInstance.CompleteRequest(); 
} 
private void SeeOther(string relUri) 
{ 
    SeeOther(new Uri(Request.Url, relUri)); 
}