2014-05-12 15 views
7

Mam restful (webHttpBinding) self-hosted usługi WCF. Większość metod zwraca klientowi wersję xml lub json.Jak mogę przesłać odpowiedź z WCF bez buforowania?

Mam kilka metod GET, które wyzwalają długotrwałe metody i chciałbym strumień odpowiedzi dziennika do przeglądarki (lub aplikacji), aby użytkownik wiedział, co się dzieje. Byłoby to łatwe do osiągnięcia dzięki HttpContext.Current.Response.OutputStream.Write. Niestety, HttpContext.Current jest zawsze pusta w samohostowanej usłudze WCF, nawet jeśli dołączę konfigurację aspNetCompatibilityEnabled (IIS niestety nie jest opcją).

Próbowałem AnonymousPipeServerStream: WCF and streaming requests and responses

wraz z pierwszym ustawieniu:

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

tak, że odpowiedź przychodzi w przeglądarce nie pobrać strumienia do pliku, aby zapisać.

W Chrome to w ogóle nie działa - buforuje do końca. W IE lub wget wydaje się buforować około 4k (lub coś w tym samym czasie). Nie jest to dobre dla logowania, chyba że wypluję mnóstwo niepotrzebnych komunikatów, aby wymusić wyjście, a użytkownik nie wie, co się dzieje. Mogę tylko założyć, że tak jest, ponieważ odpowiedź jest właściwie odpowiedzią kawałków, a kawałki to 4k (a nie tylko pisanie do strumienia wyjściowego).

Poprawkę na chrome na wyjście najwyraźniej napisać trochę śmieci do treści przed wysłaniem chunked odpowiedź: Chunked transfer encoding - browser behavior, jednak nie sądzę, jest to możliwe w WCF.

więc możliwe rozwiązania Szukam:

  • sposób zapisu OutputStream w WCF w self hostowane usługi (bez IIS). lub
  • Sposób kontrolowania wielkości porcji w odpowiedzi na strumień (& sposób na napisanie najpierw niektórych treści, aby Chrome renderował porcje).

Inna opcja, jak sądzę, to porzucić WCF na rzecz czegoś bardziej przyjaznego REST (zaczynam myśleć, że WCF nie był właściwym wyborem). Jednak po napisaniu tak wiele w WCF teraz, wydaje się to nużącym zadaniem. O ile nie byłoby czegoś, do czego mógłbym się przełączyć, byłaby to łatwa migracja (np. Gdybym mógł ponownie użyć tych samych klas usług, być może mając tylko inne atrybuty). Może Nancy?

Odpowiedz

2

Zrobiłem coś takiego, o co tu pytasz - samo hostowane. Napisałem usługę WCF (BasicHttpBinding), która wykonała zarówno strumieniowanie, jak i buforowanie danych do urządzeń klienckich pobierających moją usługę w celu synchronizacji danych. Strumieniowanie jest trudne, jak się pewnie domyślacie, i nie sądzę, że istnieje sposób na "zapisanie w strumieniu".

W podstawowym sensie Streaming nad usług WCF działa w ten sam sposób, w jaki działa File.IO, jak widać w kodzie poniżej

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

Jeśli dany plik jest 1 GB, rozpocznie swoją FileStream zwracanie bajtów przed odczytaniem do końca pliku. Przesyłanie strumieniowe przez WCF działa w ten sam sposób (w rzeczywistości implementuje FileStream, z mojego doświadczenia), dlatego jest dobre dla ogromnych porcji danych. Czyta ... wysyła; czyta ... wysyła. Nie jestem więc pewien, w jaki sposób wprowadziłbyś pewne informacje do tego strumienia, aby wyprowadzić je na ekran.

Po tym, nasz interfejs użytkownika synchronizacji wyświetla liczbę zmniejszających się bajtów oraz procentowy udział, aby uniemożliwić użytkownikom wyłączenie urządzenia lub anulowanie. Robimy to poprzez oddzielny wątek, który odczytuje rozmiar pobieranego pliku co 10 sekund i oblicza procent całości (pełny rozmiar jest wysyłany jako parametr w odpowiedzi), a następnie zapisuje wyniki w oknie wyników interfejsu użytkownika . Dlatego w naszym przypadku rozwiązanie jest całkiem proste.

+0

Czy Twoim zdaniem to, co próbuję zrobić, nie jest możliwe? – David

+0

Myślę, że to zależy od tego, co próbujesz przesyłać strumieniowo. Czy to surowe dane, które przenosisz z jednego miejsca do drugiego? Strumieniowanie jest zwykle używane w przypadku ogromnych zbiorów danych (tj. Przesyłamy muzykę i filmy z Amazon), a po rozpoczęciu przesyłania strumieniowego klient i host są w stanie blokady, wysyłania i odbierania do czasu zakończenia procesu. Nie jestem pewien, jak lub dlaczego chcesz wstrzyknąć coś w ten rodzaj przepływu. Jeśli martwisz się, że Twój użytkownik robi coś dziwnego, ponieważ nie widzi postępu, istnieją sposoby (jak opisuję) wokół tego problemu. – Brian

+0

Próbuję przesyłać strumieniowo informacje dotyczące rejestrowania (patrz OP). Tak więc ilość danych może różnić się od kilku linii (jeśli wszystko idzie dobrze) do 1000 linii, jeśli coś idzie źle. To jest coś, co zrobiłem w przeszłości bez problemu, pisząc do strumienia wyjściowego (w .NET i innych językach), ale problem wydaje się, że WCF nie daje mi elastyczności, której szukam. – David

0

Mam plik strumieniowy tak:

Grupa metody, która zwraca dane, które musi być przesyłane do punktu końcowego, a następnie dodać transmisjami transferMode tego punktu końcowego.

Oto konfiguracja, której używam (dla basicHttpBinding).

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

i definiowania konfiguracji wiązania:

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

Zasadniczo trzeba ustawić transferMode w konfiguracji wiążący.

Nie próbowałem go z webHttpBinding, więc proszę dać mi znać, czy to działa dla Ciebie.

+0

Tak, próbowałem tego (zobacz OP) – David

0

Wystarczy nakłonić przeglądarkę do myślenia, tam jest odpowiedź HTML z Multipart Content-Type

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

Użyłem tego już od kilku rzeczy, w tym MJPEG, ale można też użyć go do COMET/websocket jak odpowiedziach .

+0

Próbowałem tego, ale WCF wydaje się przejąć kontrolę nad tym, ile danych jest buforowanych w odpowiedzi kawałku. Typ treści "tekst/zwykły", o którym wspomniałem w PO, ma taki sam wpływ. – David

Powiązane problemy