2015-11-24 126 views
6

我試圖遷移一個web api項目(經典web.config項目)那裏使用PushStreamContent到最新的asp.net 5 web應用程序(project.json)。在asp.net 5/mvc 6 PushStreamContent不工作

我的問題是,我不能讓PushStreamContent工作。

當我使用這個API控制器 - 結果將在一個JSON格式的結束,而不是作爲一個流:

[Route("api/[controller]")] 
public class EventsController : Controller 
{ 
    private static readonly ConcurrentQueue<StreamWriter> s_streamWriter = new ConcurrentQueue<StreamWriter>(); 

    [HttpGet] 
    public HttpResponseMessage Get(HttpRequestMessage request) 
    { 
     HttpResponseMessage response = request.CreateResponse(); 
     response.Content = new PushStreamContent(new Action<Stream, HttpContent, TransportContext>(WriteToStream), "text/event-stream"); 
     return response; 
    } 

    private void WriteToStream(Stream outputStream, HttpContent headers, TransportContext context) 
    { 
     var streamWriter = new StreamWriter(outputStream) {AutoFlush = true}; 
     s_streamWriter.Enqueue(streamWriter); 
    } 
} 

如果我改變控制器動作返回一個任務,並在一類MyPushStreamResult包裝PushStreamContent - 像這樣:

[HttpGet] 
public async Task<IActionResult> Get(HttpRequestMessage request) 
{ 
    var stream = new PushStreamContent(new Action<Stream, HttpContent, TransportContext>(WriteToStream), "text/event-stream"); 
    return new MyPushStreamResult(stream, "text/event-stream"); 
} 

public class MyPushStreamResult : ActionResult 
{ 
    public string ContentType { get; private set; } 
    public PushStreamContent Stream { get; private set; } 
    public MyPushStreamResult(PushStreamContent stream, string contentType) 
    { 
     Stream = stream; 
     ContentType = contentType; 
    } 
    public override async Task ExecuteResultAsync(ActionContext context) 
    { 
     var response = context.HttpContext.Response; 
     response.ContentType = ContentType; 
     await Stream.CopyToAsync(response.Body); 
    } 
} 

到我的控制器操作的請求,現在返回一個流,但該流不刷新它接近的服務器端或者包含大量數據的之前。當我將數據推送到PushStreamContent輸出流時,我在每次寫入文本後進行刷新,但我猜刷新不在response.Body流中。

我錯過了什麼?找不到任何具有asp.net 5結構的示例。

+1

'IHttpBufferingFeature'功能可以幫助我想,你是否嘗試禁用緩衝? –

+0

它看起來像'IHttpBufferingFeature'不支持Kestrel [文檔](http://docs.asp.net/en/latest/fundamentals/servers.html#supported-features-by-server) –

+0

在第一個例子中你從不寫信給流。 – usr

回答

4

HttpResponseMessage不在ASP.NET 5中專門處理,除非您使用的是Microsoft.AspNet.Mvc.WebApiCompatShim包。如果您可以使用ASP.NET 5功能來執行類似的工作,並且創建它以支持向後兼容性,則此包是而不是

如此以來HttpResponseMessage沒有被認爲是特殊的,它被呈現爲JSON由JsonOutuptFormatter就像任何其他.NET對象

相反的PushStreamContent,你現在有機會獲得響應流通過HttpContext.Response.Body財產直接,所以你可以直接寫入流。

更新
PushStreamContent在網頁API允許你直接寫入響應流。這種類型是由Web API團隊創建的,並且不存在作爲其他所有內容類型的庫的一部分,以便可以直接寫入流,例如,從控制器或過濾器等中寫入。替代PushStreamContent是StreamContent,它只允許你提供一個Stream對象,然後主機層從源流中'複製'數據(如'拉''數據)。另外PushStreamContent本身並沒有什麼特別之處。人們可以編寫自己的類型,其源自HttpContent

總而言之,PushStreamContent允許直接寫入響應流,因爲在ASP.NET 5中我們可以直接訪問流,因此您可以寫入它。

更新時間:
在非常基本的形式(右,你都可以轉換成的ActionResult可測性),下面應該工作。

[HttpGet] 
public Task Get() 
{ 
    HttpContext.Response.ContentType = "text/event-stream"; 
    var sourceStream = // get the source stream 
    return sourceStream.CopyToAsync(HttpContext.Response.Body); 
} 
+0

'PushStreamContent'用於多次寫入流 - 就像服務器可以將新數據推送到客戶端的聊天一樣。我看不到我可以多次寫入'HttpContext.Response.Body'。你能舉個例子嗎? –

+0

更新我的帖子,更多細節。 –

+0

我已閱讀您的更新並嘗試了不同的事情。但是我無法使它工作,並且無法找到任何用asp.net 5編寫的代碼示例,它將流返回給客戶端,服務器可以寫入單獨的數據塊。你可以做一個示例項目/代碼片段? –