2015-11-24 32 views
6

Tôi đang cố di chuyển một dự án web api (dự án web.config cổ điển) ở đó sử dụng PushStreamContent cho ứng dụng web asp.net 5 mới nhất (project.json).PushStreamContent trong asp.net 5/mvc 6 không hoạt động

Vấn đề của tôi là tôi không thể tải PushStreamContent để hoạt động.

Khi tôi sử dụng bộ điều khiển api này - kết quả là sẽ kết thúc trong một định dạng json và không phải là một dòng:

[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); 
    } 
} 

Nếu tôi thay đổi hành động điều khiển để trả về một nhiệm vụ và quấn PushStreamContent trong một MyPushStreamResult lớp - Như thế này:

[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); 
    } 
} 

Yêu cầu hành động điều khiển của tôi hiện đang trả về luồng, BẮT luồng không được xả trước khi đóng trên máy chủ hoặc chứa nhiều dữ liệu. Khi tôi đẩy dữ liệu vào dòng đầu ra PushStreamContent tôi xả sau mỗi lần soạn văn bản, nhưng tôi đoán rằng lệnh xóa không nằm trên luồng response.Body.

Tôi bỏ lỡ điều gì? Không thể tìm thấy bất kỳ mẫu nào có cấu trúc asp.net 5.

+1

tính năng 'IHttpBufferingFeature' có thể giúp tôi nghĩ, bạn có cố vô hiệu hóa bộ đệm không? –

+0

có vẻ như 'IHttpBufferingFeature' không được hỗ trợ trong Kestrel [docs] (http://docs.asp.net/en/latest/fundamentals/servers.html#supported-features-by-server) –

+0

Trong ví dụ đầu tiên bạn không bao giờ viết thư cho luồng. – usr

Trả lời

4

HttpResponseMessage không được xử lý đặc biệt trong ASP.NET 5 trừ khi bạn đang sử dụng gói Microsoft.AspNet.Mvc.WebApiCompatShim. Gói này là không phải được đề xuất nếu bạn có thể sử dụng tính năng ASP.NET 5 để thực hiện các công cụ tương tự và được tạo để hỗ trợ tính tương thích ngược.

Vì vậy, kể từ HttpResponseMessage chưa được xem xét đặc biệt, nó được trả lại như json bởi JsonOutuptFormatter giống như bất kỳ đối tượng .NET khác

Thay vì PushStreamContent, bạn đang có quyền truy cập vào dòng phản ứng trực tiếp qua HttpContext.Response.Body bất động sản, vì vậy bạn chỉ có thể ghi trực tiếp vào luồng.

Cập nhật:
PushStreamContent trong Web API cho phép bạn để viết trực tiếp vào dòng phản ứng. Loại này đã được tạo (bởi nhóm Web API và không có mặt trong thư viện System.Net.Http nơi tất cả các loại nội dung khác) để người dùng có thể viết trực tiếp vào luồng, ví dụ: từ bộ điều khiển hoặc bộ lọc, v.v ... thay thế cho PushStreamContent là StreamContent chỉ cho phép bạn cung cấp đối tượng Luồng và sau đó các lớp lưu trữ 'sao chép' dữ liệu từ luồng nguồn (như dữ liệu 'kéo'). Ngoài ra PushStreamContent cũng không có gì đặc biệt. Người ta có thể viết loại riêng của họ có nguồn gốc từ HttpContent.

Để tóm tắt, PushStreamContent cho phép ghi vào luồng phản hồi trực tiếp, như trong ASP.NET 5, chúng tôi có quyền truy cập trực tiếp vào luồng và do đó bạn có thể ghi vào luồng đó.

Cập nhật:
Tại hình thức rất cơ bản (bên phải, bạn có thể chuyển đổi sang ActionResult cho testability), sau đây nên làm việc.

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

'PushStreamContent' được sử dụng để ghi nhiều lần vào luồng - như một cuộc trò chuyện nơi máy chủ có thể đẩy dữ liệu mới đến máy khách. Tôi không thể thấy làm thế nào tôi có thể viết nhiều lần vào 'HttpContext.Response.Body'. Bạn có thể đưa ra một ví dụ? –

+0

Đã cập nhật bài đăng của tôi với nhiều chi tiết hơn. –

+0

Tôi đã đọc bản cập nhật của bạn và đã thử những thứ khác nhau. Nhưng tôi không thể có được nó để làm việc, và không thể tìm thấy bất kỳ ví dụ mã bằng văn bản trong asp.net 5 có trở lại một dòng cho khách hàng, máy chủ có thể viết khối dữ liệu cá nhân. Bạn có thể tạo một dự án mẫu/đoạn mã không? –

Các vấn đề liên quan