WCF: использование потоковой передачи с контрактами сообщений - PullRequest
20 голосов
/ 27 августа 2009

Я пытаюсь использовать потоковую передачу WCF с Контрактами сообщений, потому что мне нужны дополнительные параметры помимо самого потока.

По сути, я создаю службу загрузки и выгрузки файлов с некоторой дополнительной логикой сверху.

К сожалению, когда я пытаюсь запустить сервис из браузера, чтобы проверить, что все в порядке, я получаю следующую ошибку:

Ошибка сервера в «/» приложении. Операция «UploadFile» в контракте «IFileTransferService» использует MessageContract с заголовками SOAP. Заголовки SOAP не поддерживаются None MessageVersion.

К сожалению, поиск в Google не дал какого-либо существенного результата, который помог мне. Ребята, вы можете мне помочь? Вот подробности службы (я удалил часть загрузки по причине нехватки места).

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

Я попытался использовать привязку basichttpbinding и привязку customhttp с не положительным эффектом:

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

ОБНОВЛЕНИЕ : при чтении документации онлайн кажется, что потоковая передача с MessageContracts действительно должна быть возможной. См., Например, MSDN ( Большие данные и потоковая передача ):

Модель программирования для потоковых передач

Модель программирования для потоковой передачи простой. Для получения потоковые данные, укажите операцию контракт, который имеет один поток типизированный входной параметр. Для возвращения потоковые данные, вернуть поток ссылка. [...] Это правило аналогично относится к сообщениям контрактов. Как показано в следующем сообщении вы может иметь только один член тела в ваше сообщение сообщение, которое является поток. Если вы хотите общаться дополнительная информация с поток, эта информация должна быть переносится в заголовках сообщений. тело сообщения исключительно зарезервировано для потокового контента.

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

Я также видел сообщения в блогах людей, выполняющих услуги загрузки и скачивания файлов, очень похожие на то, что я пытаюсь собрать (например, здесь ).

ОБНОВЛЕНИЕ 2 Я попытался создать небольшую консоль и самостоятельно разместить службу с помощью BasicHttpBinding, и там она работает как шарм. Я начинаю верить, что проблема может быть в хостинге на IIS. Есть идеи?

ОБНОВЛЕНИЕ 3 Смотрите мой собственный ответ.

Ответы [ 3 ]

8 голосов
/ 28 августа 2009

Я наконец выяснил, в чем была ошибка: это не имело никакого отношения к версиям Soap, потокам и т. Д. ... Я просто неправильно ввел имя своей собственной службы (!), Используя FileTransfer вместо FileTransferService.

В итоге basicHttpBinding был в порядке, мне не нужно было прибегать к пользовательской привязке.

Оригинальная (плохая) версия:

<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>

Новая (исправленная) версия:

<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>

Тем не менее я не могу сказать, что сообщение об ошибке каким-либо образом помогло понять, что здесь происходит ...

Если вас интересует весь сервис, вы можете найти более подробную информацию в моем блоге по следующей ссылке: Передача файлов с WCF

2 голосов
/ 27 августа 2009

Нужна ли вам потоковая передача (т. Е. Передача огромных объемов данных) как по запросу, так и по ответу? Или просто на ответ (обычно: загрузка файла или большой набор данных)?

Если вам нужен только ответ, попробуйте установить режим передачи в «StreamedResponse»:

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

Параметр «Потоковая передача» будет выполнять потоковую передачу в обоих направлениях - и запрос, отправляемый на сервер, и ответ от сервера будут передаваться в потоковом режиме. Чаще всего это не идеальный сценарий.

Марк

0 голосов
/ 06 июля 2012

Я получил ошибку после использования шаблона «Служба данных WCF» для создания файла svc вместо шаблона «Служба WCF». Исправление файла хоста службы. Проблема была решена.

...