【问题标题】:PushStreamContent in asp.net 5 / mvc 6 is not workingasp.net 5 / mvc 6 中的 PushStreamContent 不起作用
【发布时间】:2015-11-24 11:26:34
【问题描述】:

我正在尝试将使用 PushStreamContent 的 web api 项目(经典 web.config 项目)迁移到最新的 asp.net 5 web 应用程序(project.json)。

我的问题是我无法让 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);
    }
}

如果我更改控制器操作以返回任务并将 PushStreamContent 包装在 MyPushStreamResult 类中 - 像这样:

[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 结构的示例。

【问题讨论】:

  • IHttpBufferingFeature 功能可以帮助我想,您是否尝试禁用缓冲?
  • 看起来 Kestrel 不支持 IHttpBufferingFeature docs
  • 在第一个示例中,您永远不会写入流。
  • 它只是一个sn-p。我有一个方法可以遍历streamWriters的队列并写入它们。很抱歉没有说清楚。

标签: c# asp.net-core asp.net-core-mvc pushstreamcontent


【解决方案1】:

HttpResponseMessage 在 ASP.NET 5 中没有被特殊处理,除非您使用 Microsoft.AspNet.Mvc.WebApiCompatShim 包。如果您可以使用 ASP.NET 5 功能来做类似的事情并且创建该包以支持向后兼容性,则推荐使用此包。

因此,由于 HttpResponseMessage 不被认为是特殊的,它被 JsonOutuptFormatter 呈现为 json,就像任何其他 .NET 对象一样

您目前可以通过HttpContext.Response.Body 属性直接访问响应流,而不是PushStreamContent,因此您可以直接写入流。

更新
Web API 中的PushStreamContent 允许您直接写入响应流。这种类型是创建的(由 Web API 团队创建,不作为 System.Net.Http 库的一部分存在,所有其他内容类型都存在),因此可以直接写入流,例如,从控制器或过滤器等。 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);
}

【讨论】:

  • PushStreamContent 用于多次写入流 - 就像服务器可以将新数据推送到客户端的聊天一样。我看不出我怎么能多次写信给HttpContext.Response.Body。能举个例子吗?
  • 更新了我的帖子,提供了更多细节。
  • 我已阅读您的更新并尝试了不同的方法。但我无法让它工作,也找不到任何用 asp.net 5 编写的代码示例,那里将流返回给客户端,服务器可以将单独的数据块写入。你能做一个示例项目/代码sn-p吗?
  • 我粘贴了最基本的示例代码应该可以工作......否则请告诉我
  • 我已经尝试过了,但是服务器在完成方法后立即关闭流,由于请求已经结束,客户端将无法获取数据。我创建了一个github repo with a sample project - 感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-08
  • 1970-01-01
  • 2016-08-09
  • 2014-01-26
  • 2023-03-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多