2009-08-27 13 views
20

Próbuję użyć strumieniowania WCF z kontraktami wiadomości, ponieważ potrzebuję dodatkowych parametrów obok samego strumienia.WCF: korzystanie z przesyłania strumieniowego za pomocą kontraktów wiadomości

Zasadniczo tworzę usługę przesyłania i pobierania plików, z dodatkową logiką na górze.

Niestety, gdy próbuję trafić usługę z przeglądarki, aby sprawdzić, czy wszystko jest w porządku, pojawia się następujący błąd:

Server Error in „/” Application. Operacja "UploadFile" w umowie "IFileTransferService" korzysta z MessageContract, który ma nagłówki SOAP. Nagłówki SOAP nie są obsługiwane przez opcję Brak komunikatu.

Niestety googlowanie nie przyniosło żadnych znaczących rezultatów, które mi pomogły. Czy możecie mi pomóc? Tutaj szczegóły usługi (usunąłem część pobierania ze względu na miejsce).

[ServiceContract(Namespace = "http://www.acme.org/2009/04")] 
public interface IFileTransferService 
{ 
    [OperationContract(Action = "UploadFile")] 
    void UploadFile(FileUploadMessage request); 
} 

[MessageContract] 
public class FileUploadMessage 
{ 
    [MessageHeader(MustUnderstand = true)] 
    public FileMetaData Metadata { get; set; } 

    [MessageBodyMember(Order = 1)] 
    public Stream FileByteStream { get; set; } 
} 

[DataContract(Namespace = "http://schemas.acme.org/2009/04")] 
public class FileMetaData 
{ 
    [DataMember(Name="FileType", Order=0, IsRequired=true)] 
    public FileTypeEnum fileType; 

    [DataMember(Name="localFilename", Order=1, IsRequired=false)] 
    public string localFileName; 

    [DataMember(Name = "remoteFilename", Order = 2, IsRequired = false)] 
    public string remoteFileName; 
} 

Próbowałem używać zarówno BasicHttpBinding i customhttp wiążącą z nie pozytywny efekt:

<customBinding> 
    <binding name="customHttpBindingStream"> 
     <textMessageEncoding messageVersion="Soap12" /> 
     <httpTransport transferMode="Streamed" maxReceivedMessageSize="2147483647"/> 
    </binding> 
</customBinding> 

UPDATE: czytanie dokumentacji online wydaje się, że strumieniowe z MessageContracts powinny być rzeczywiście możliwe. Patrz na przykład MSDN (Large Data and Streaming):

Programming Model for Streamed Transfers

The programming model for streaming is straightforward. For receiving streamed data, specify an operation contract that has a single Stream typed input parameter. For returning streamed data, return a Stream reference. [...] This rule similarly applies to message contracts. As shown in the following message contract, you can have only a single body member in your message contract that is a stream. If you want to communicate additional information with the stream, this information must be a carried in message headers. The message body is exclusively reserved for the stream content.

[MessageContract] 
public class UploadStreamMessage 
{ 
    [MessageHeader] 
    public string appRef; 
    [MessageBodyMember] 
    public Stream data; 
} 

widziałem też na blogu od ludzi, usług przesyłania plików realizujących i pobierz bardzo podobny do tego, co staram się połączyć (na przykład here).

UPDATE 2 Próbowałem utworzenie małej konsoli i własny hosting usługi z basicHttpBinding i nie działa jak czar. Zaczynam wierzyć, że problemem może być hosting na IIS. Dowolny pomysł?

UPDATE 3Zobacz moją odpowiedź.

+0

Wierzę, że 'Order = 1' jest zbędny w atrybucie' MessageBodyMember', ponieważ masz tylko jeden element body –

Odpowiedz

8

I w końcu okazało się, jaki był błąd: to nie miało nic wspólnego z wersjami mydło, strumieni, itp ... Ja po prostu błędnie nazwę własnego serwisu, używając FileTransfer zamiast (!) FileTransferService.

W końcu basicHttpBinding było idealnie w porządku, nie musiałem uciekać się do niestandardowego wiązania.

Original (złe) wersja:

<service 
    behaviorConfiguration="serviceBehavior" 
    name="Acme.Service.FileTransfer"> 
    <endpoint address="" 
     name="basicHttpStream" 
     binding="basicHttpBinding" 
     bindingConfiguration="httpLargeMessageStream" 
     contract="Acme.Service.IFileTransferService" /> 
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/> 
</service> 

Nowa wersja (stałe):

<service 
    behaviorConfiguration="serviceBehavior" 
    name="Acme.Service.FileTransferService"> 
    <endpoint address="" 
     name="basicHttpStream" 
     binding="basicHttpBinding" 
     bindingConfiguration="httpLargeMessageStream" 
     contract="Acme.Service.IFileTransferService" /> 
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/> 
</service> 

Wciąż nie mogę powiedzieć, że komunikat o błędzie był pomocny w żaden sposób zrozumieć, co się dzieje tutaj ....

Jeśli jesteś zainteresowany całą usługą, możesz znaleźć więcej informacji na moim blogu pod następującym linkiem: File Transfer with WCF

2

Czy potrzebujesz przesyłania strumieniowego (np. Transfer dużych kwot danych) zarówno na żądanie, jak i na odpowiedź? Lub po prostu odpowiedź (zazwyczaj: pobieranie pliku lub dużego zestawu danych)?

Jeśli potrzebujesz tylko od odpowiedzi, należy spróbować ustawić transferMode do „StreamedResponse”:

<customBinding> 
    <binding name="customHttpBindingStream"> 
     <textMessageEncoding messageVersion="Soap12" /> 
     <httpTransport transferMode="StreamedResponse" 
         maxReceivedMessageSize="2147483647"/> 
    </binding> 
</customBinding> 

W „strumieniowe” ustawienie będzie transmitować obie strony - zarówno wniosek dzieje się z serwerem, jak jak również odpowiedź z serwera, będą przesyłane strumieniowo. Częściej niż nie, to nie jest idealny scenariusz.

Marc

+0

Witaj Marc, jak wspomniałem w moim pytaniu, tworzę usługę plików, która pozwala zarówno na wysyłanie, jak i pobieranie plików . Dlatego muszę mieć możliwość przesyłania strumieniowego w obie strony. Czy uważasz, że ma to coś wspólnego z błędem, którego doświadczam? –

+0

Nie jestem pewien - nigdy wcześniej nie widziałem kombinacji przesyłania strumieniowego z kontraktami Message ..... i widziałem przypadki, w których pobieranie z serwera było duże (pobieranie plików) i ustawienie TransferMode na StreamedResponse pomogło –

+0

działa, jeśli korzystasz tylko z DataContract (bez części Message Contract) - wystarczy, aby zobaczyć, do testowania –

0

Wystąpił błąd po użyciu szablonu "Usługa danych WCF" do wygenerowania pliku svc zamiast szablonu "Usługa WCF". Poprawiono plik hosta usługi, którego problem został rozwiązany.

Powiązane problemy