asp.net 5/mvc 6中的PushStreamContent无法正常工作

ras*_*s-s 7 c# pushstreamcontent asp.net-core-mvc asp.net-core

我试图迁移一个web api项目(经典的web.config项目),使用PushStreamContent到最新的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);
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我更改控制器操作以返回任务并在类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);
    }
}
Run Code Online (Sandbox Code Playgroud)

对我的控制器操作的请求现在返回一个流,但是在服务器端关闭流或包含大量数据之前,流不会刷新.当我将数据推送到PushStreamContent输出流时,我在每次文本写入后刷新,但我想flush不在response.Body流上.

我错过了什么?使用asp.net 5结构找不到任何样本.

Kir*_*lla 6

HttpResponseMessage除非您使用的是Microsoft.AspNet.Mvc.WebApiCompatShim包,否则不会在ASP.NET 5中专门处理.如果您可以使用ASP.NET 5功能执行类似的操作并且创建它以支持向后兼容性,则不建议使用此程序包.

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

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

更新:
PushStreamContent在Web API中允许您直接写入响应流.此类型是由Web API团队创建的,并不作为System.Net.Http所有其他内容类型的库的一部分出现,因此可以直接写入流,例如,从控制器或过滤器等.PlusStreamContent的替代方法是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);
}
Run Code Online (Sandbox Code Playgroud)

  • 我曾经尝试过,但服务器只是在完成方法后立即关闭流,并且客户端将不会因请求结束而获取数据.我创建了一个[带有示例项目的github repo](https://github.com/rasmus-s/stackoverflow-PushStreamContent) - 感谢您的帮助. (3认同)