2013-07-25 16 views
6

Quindi ho un progetto MVC. Questo progetto MVC contiene un controller, che ha bisogno di eseguire lo streaming del contenuto al client. Quando inizia lo streaming, non c'è modo di determinare la lunghezza del contenuto (viene calcolato al volo). Così apro HttpContext.Current.Response.OutputStream, e iniziare a scrivere e Flushing periodicamente (ho già disabilitato uscita tamponata, e attaccato le intestazioni HTTP appropriate):Controller MVC che restituisce la codifica del contenuto Chunked

while (some condition){ 

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

Se poi forzare il flusso di chiudere:

HttpContext.Current.Response.Close(); 

E non finisce correttamente il contenuto Chunked (che non aggiunge un pezzo 0 lunghezza, alla fine, per indicare EOF al cliente).

Se invece chiudere il flusso di uscita più grazia:

HttpContext.Current.Response.End(); 

O

HttpContext.Current.ApplicationInstance.CompleteRequest(); 

Si chiude correttamente il (blocco lunghezza zero aggiunto alla fine) flusso, ma ottengo un'eccezione lanciata da l'applicazione, che indica che non è possibile inserire intestazioni HTTP nel flusso di output, perché il flusso è stato già scritto!

In entrambi i casi, il controller continua a restituire null (o EmptyActionResult).

Suppongo che l'eccezione sia dovuta perché lo stack MVC richiede che ogni ActionResult imposti le intestazioni HTTP dopo che il controller ha terminato l'esecuzione. Se questo è il caso, come si implementa un flusso Chunked in MVC?

Grazie in anticipo!

EDIT: L'eccezione esatto essere gettato è:

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) 

risposta

2

ho trovato la soluzione.

I HTTP 1.1 specifica standard che Chunked codifica deve essere chiuso con un pezzo 0 lunghezza, solo quando la modalità richiesta è keep-alive

In modalità keep-alive, la connessione tra client/server è persistito per più richiesta/risposta. La codifica Chunked deve essere terminata con il blocco della lunghezza zero in questo contesto, perché non c'è altro modo che il client sappia quando termina la risposta precedente.

Se si specifica "Connessione: chiusa" come intestazione, diversamente da "Connessione: keep-alive", quindi la connessione non viene mantenuta tra una richiesta, il client può utilizzare la chiusura della connessione come un'indicazione di terminazione della risposta, e non richiede il chunk di lunghezza 0 che indica EOF.

ho appena deciso di chiudere manualmente la HttpResponse utilizzando:

HttpContext.Current.Response.Close(); 

Pur avendo specificato in precedenza nel codice per dire al cliente che la connessione si chiude su di EOF. Questo ha risolto il problema in cui il client non stava ricevendo il blocco della lunghezza 0, perché ora il client non lo richiede.