Подтвердить что ты не робот

WCF: использование потоковой передачи с сообщениями

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

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

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

Ошибка сервера в приложении "/". Операция "UploadFile" в контракте "IFileTransferService" использует MessageContract с заголовками SOAP. Заголовки SOAP не поддерживаются ни одним 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 (Large Data and Streaming):

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

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

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

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

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

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

4b9b3361

Ответ 1

Наконец-то я узнал, в чем была ошибка: это не имело ничего общего с версиями 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

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

Если вам нужен только ответ, вы должны попытаться установить передаточный режим в "StreamedResponse":

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

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

Марк

Ответ 3

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