2015-11-24 6 views
6

Im пытается перенести проект web api (классический проект web.config), используя PushStreamContent до последнего веб-приложения asp.net 5 (project.json).PushStreamContent в asp.net 5/mvc 6 не работает

Моя проблема в том, что я не могу заставить PushStreamContent работать.

Когда я использую этот апи контроллер - результат будет в конечном итоге в формате 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); 
    } 
} 

запрос на мой контроллер действий теперь возвращается поток, но поток не топить, прежде чем его закрыть на ServerSide или содержит большое количество данных. Когда я выталкиваю данные в выходной поток PushStreamContent, я стираю после каждого текстового ввода, но я думаю, что флеш не включен в поток response.Body.

Что мне не хватает? Невозможно найти образцы с структурой asp.net 5.

+1

Функция 'IHttpBufferingFeature' может помочь, я думаю, вы пытались отключить буферизацию? –

+0

похоже, что «IHttpBufferingFeature» не поддерживается в Kestrel [docs] (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 в Web API позволил вам напрямую писать в поток ответа. Этот тип был создан (командой веб-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); 
} 
+0

'PushStreamContent' используется для записи несколько раз в поток - например, в чате, где сервер может передавать новые данные клиенту. Я не вижу, как я могу писать несколько раз в HttpContext.Response.Body'. Можете привести пример? –

+0

Обновлено мое сообщение с более подробной информацией. –

+0

Я прочитал ваше обновление и попробовал разные вещи. Но я не могу заставить его работать и не в состоянии найти какой-либо пример кода, написанный на asp.net 5, возвращает поток клиенту, сервер может писать отдельные куски данных. Можете ли вы сделать образец проекта/фрагмента кода? –

 Смежные вопросы

  • Нет связанных вопросов^_^