2013-07-25 29 views
6

所以我有一個MVC項目。這個MVC項目包含一個Controller,需要將內容傳輸回客戶端。流式傳輸開始時,無法確定內容長度(它是在即時計算的)。所以,我打開HttpContext.Current.Response.OutputStream,並定期開始寫和沖洗(我已經禁用緩衝輸出,並附相應的HTTP報頭):MVC控制器返回分塊內容編碼

while (some condition){ 

    HttpContext.Current.Response.OutputStream.Write(buffer, 0, buffer.Length); 
    HttpContext.Current.Response.Flush(); 
} 

如果我再逼流關閉:

HttpContext.Current.Response.Close(); 

它不正確結束的分塊內容(它不會在端追加一個0長度塊,以指示EOF到客戶端)。

如果我不是關閉更優雅的輸出流:

HttpContext.Current.Response.End(); 

OR

HttpContext.Current.ApplicationInstance.CompleteRequest(); 

它正確地關閉該流(追加到結束零長度塊),但我得到拋出的異常該應用程序指示它不能將HTTP頭插入輸出流,因爲該流已經寫入!

在這兩種情況下,Controller都會繼續返回null(或EmptyActionResult)。

我假設異常是由於MVC堆棧要求每個ActionResult在Controller完成執行後設置HTTP標頭而引起的。如果是這種情況,那麼在MVC中如何實現一個Chunked流?

在此先感謝!

編輯:確切異常被拋出是:

Uncaught Exception: System.Web.HttpException (0x80004005): Server cannot set status after HTTP headers have been sent. 
    at System.Web.Http.WebHost.HttpControllerHandler.EndProcessRequest(IAsyncResult result) 
    at System.Web.Http.WebHost.HttpControllerHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) 
    at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() 
    at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) 

回答

2

我找到了解決辦法。

的HTTP 1.1標準指定分塊編碼必須用0長度塊被關閉,只有當請求模式是保持活動

在保活模式,客戶端/服務器之間的連接被持續了多個請求/響應。分塊編碼需要在此上下文中以零長度塊結束,因爲沒有其他方式讓客戶端知道前一個響應何時結束。

如果指定「Connection:close」作爲頭,而不是「Connection:keep-alive」,那麼連接在請求之間不會持久,客戶端可以使用連接關閉作爲響應終止的指示,並且不需要指示EOF的0長度塊。

我剛剛決定用手動關閉的HttpResponse:

HttpContext.Current.Response.Close(); 

雖然之前曾在代碼中指定告訴客戶端連接將關閉在EOF。這解決了客戶端沒有收到0長度塊的問題,因爲現在客戶端不需要它。