2015-11-24 81 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编写的代码示例,它将流返回给客户端,服务器可以写入单独的数据块。你可以做一个示例项目/代码片段? –