2014-05-12 15 views
7

Tôi có một dịch vụ WCF an toàn (webHttpBinding) tự lưu trữ. Hầu hết các phương thức đều trả về phiên bản xml hoặc json của các đối tượng cho máy khách.Làm cách nào để phát trực tuyến phản hồi từ WCF mà không bị giật?

Tôi có một vài phương thức GET kích hoạt các phương pháp chạy dài và tôi muốn gửi phản hồi nhật ký cho trình duyệt (hoặc ứng dụng) để người dùng biết điều gì đang xảy ra. Điều này sẽ đơn giản để thực hiện với HttpContext.Current.Response.OutputStream.Write. Thật không may, HttpContext.Current là luôn luôn null trong một dịch vụ WCF tự lưu trữ, ngay cả khi tôi bao gồm các cấu hình aspNetCompatibilityEnabled (IIS không phải là một lựa chọn không may).

Tôi đã thử AnonymousPipeServerStream: WCF and streaming requests and responses

cùng với khung cảnh đầu tiên:

OutgoingWebResponseContext context = WebOperationContext.Current.OutgoingResponse; 
context.ContentType = "text/plain"; 

để các phản ứng đi vào trình duyệt nó không tải dòng vào một tập tin để tiết kiệm.

Trong Chrome nó không hoạt động chút nào - nó sẽ lưu vào bộ đệm cho đến cuối. Trong IE hoặc wget nó xuất hiện để đệm cho khoảng 4k (hoặc một cái gì đó) tại một thời điểm. Điều này là không tốt cho việc đăng nhập như trừ khi tôi nhổ ra vô số thông điệp tường trình không cần thiết để buộc đầu ra, người dùng không thực sự biết những gì đang xảy ra. Tôi chỉ có thể giả định rằng điều này là bởi vì phản ứng thực sự là một phản ứng chunked và các khối là 4k (thay vì chỉ viết cho outputstream).

Việc sửa lỗi để đưa chrome ra đầu ra rõ ràng là ghi một số rác vào nội dung trước khi gửi phản hồi chunked: Chunked transfer encoding - browser behavior, tuy nhiên, tôi không nghĩ rằng điều này là có thể với WCF.

Vì vậy, giải pháp khả thi Tôi đang tìm:

  • Một cách để viết thư cho OutputStream trong WCF trong một dịch vụ lưu trữ tự (không có IIS). hoặc
  • Cách kiểm soát kích thước đoạn trong phản hồi luồng (& cách viết nội dung trước tiên để Chrome sẽ hiển thị các khối).

Một tùy chọn khác, tôi giả sử, là để bỏ WCF ủng hộ điều gì đó REST thân thiện hơn (tôi bắt đầu nghĩ WCF không phải là lựa chọn đúng). Tuy nhiên, đã viết rất nhiều trong WCF bây giờ, điều này có vẻ như một công việc tẻ nhạt. Trừ khi có điều gì đó tôi có thể chuyển sang đó sẽ là một sự chuyển đổi dễ dàng (ví dụ: nếu tôi có thể sử dụng lại cùng các lớp dịch vụ, có lẽ chỉ với các thuộc tính khác nhau). Nancy có thể?

Trả lời

2

Tôi đã làm điều gì đó giống như những gì bạn đang yêu cầu ở đây - cũng được lưu trữ trên máy chủ. Tôi đã viết một dịch vụ WCF (BasicHttpBinding) đã làm cả trực tuyến và đệm dữ liệu cho các thiết bị khách hàng tiêu thụ dịch vụ của tôi để đồng bộ hóa dữ liệu. Phát trực tuyến rất khó, như bạn có thể đã tìm ra và tôi không nghĩ có cách nào để "viết vào luồng".

Trong một ý nghĩa cơ bản, phát trực tuyến qua dịch vụ WCF làm việc cùng một cách mà File.IO hoạt động, như đã thấy trong đoạn code dưới đây

FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read); 
BinaryReader br = new BinaryReader(fs); 

Nếu tập tin trong câu hỏi là 1 GB, FileStream bạn sẽ bắt đầu trả về byte trước khi nó đọc đến cuối tập tin. Streaming qua WCF hoạt động theo cùng một cách (trên thực tế, nó thực hiện FileStream, theo kinh nghiệm của tôi), đó là lý do tại sao nó tốt cho khối dữ liệu khổng lồ. Nó đọc ... nó sẽ gửi; nó đọc ... nó sẽ gửi. Vì vậy, tôi không chắc chắn làm thế nào bạn muốn tiêm một số thông tin vào dòng đó cho đầu ra màn hình của bạn.

Có nói rằng, giao diện người dùng đồng bộ của chúng tôi hiển thị tổng số byte xuống, cộng với tỷ lệ phần trăm hoàn thành, để ngăn người dùng tắt máy hoặc hủy. Chúng tôi thực hiện việc này bằng cách có một chuỗi riêng biệt đọc kích thước của tệp tải xuống sau mỗi 10 giây và tính tỷ lệ phần trăm của toàn bộ (kích thước đầy đủ được gửi lại dưới dạng tham số trong phản hồi), sau đó ghi kết quả ra cửa sổ kết quả giao diện người dùng . Vì vậy, giải pháp thực sự khá đơn giản, trong trường hợp của chúng tôi.

+0

Vì vậy, theo ý kiến ​​của bạn, những gì tôi đang cố gắng làm chỉ là không thể? – David

+0

Tôi đoán nó phụ thuộc vào những gì bạn đang cố gắng phát trực tiếp. Có phải dữ liệu thô bạn đang di chuyển từ địa điểm này sang địa điểm khác không? Phát trực tuyến thường được sử dụng cho các tập dữ liệu khổng lồ (tức là chúng tôi phát nhạc và phim từ Amazon) và sau khi phát trực tuyến, máy khách và máy chủ đang ở chế độ khóa, gửi và nhận cho đến khi quá trình kết thúc. Tôi không chắc chắn làm thế nào hoặc tại sao bạn muốn tiêm một cái gì đó vào loại chảy. Nếu bạn lo lắng về việc người dùng của bạn đang làm điều gì đó kỳ lạ bởi vì anh ấy/cô ấy không thấy tiến bộ, có nhiều cách (như tôi mô tả) xung quanh vấn đề đó. – Brian

+0

Tôi đang cố gắng truyền thông tin ghi nhật ký (xem OP). Vì vậy, số lượng dữ liệu có thể thay đổi từ một vài dòng (nếu mọi thứ đang diễn ra tốt) đến 1000 dòng nếu mọi thứ đang diễn ra xấu. Đây là một cái gì đó tôi đã làm trong quá khứ không có vấn đề bằng cách viết cho dòng đầu ra (trong NET và các ngôn ngữ khác), nhưng vấn đề dường như là WCF không cho tôi sự linh hoạt tôi đang tìm kiếm. – David

0

tôi nộp trực tuyến như thế này:

Nhóm các phương pháp mà trả về dữ liệu mà cần phải được xem trực tiếp vào một thiết bị đầu cuối và sau đó thêm transferMode xem trực tiếp trên thiết bị đầu cuối đó.

Đây là cấu hình tôi sử dụng (đối với basicHttpBinding).

<services> 
    <service name="CustomersService"> 
    <endpoint address="FilesService.svc" binding="basicHttpBinding" bindingConfiguration="StreamedBinding" contract="Soap.Interfaces.IFilesService" /> 
    </service> 
</services> 

và xác định cấu hình ràng buộc:

<bindings> 
    <basicHttpBinding> 
     <binding name="IntersolveWebServicesStreamedBinding" allowCookies="true" transferMode="Streamed" maxReceivedMessageSize="67108864" /> 
    </basicHttpBinding> 
</bindings> 

Về cơ bản, bạn cần phải thiết lập các transferMode trong cấu hình ràng buộc.

Tôi chưa thử với webHttpBinding, vì vậy hãy cho tôi biết nếu nó hoạt động cho bạn.

+0

Có, tôi đã thử điều này (xem OP) – David

0

Chỉ cần đánh lừa trình duyệt vào suy nghĩ đó là một phản ứng HTML với Multipart Content-Type

http://www.w3.org/Protocols/rfc1341/7_2_Multipart.html

Tôi đã sử dụng này cho khá một vài điều trong đó có MJPEG nhưng bạn cũng có thể sử dụng nó cho COMET/WebSocket như phản ứng .

+0

Tôi đã thử điều này, nhưng WCF xuất hiện để kiểm soát lượng dữ liệu được đệm trong phản hồi chunked. Loại nội dung "văn bản/đơn giản" tôi đề cập trong OP có cùng tác động. – David

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