WCF: использование потоковой передачи с контрактами сообщений
Я пытаюсь использовать потоковую передачу WCF с Контрактами сообщений, потому что мне нужны дополнительные параметры помимо самого потока.
По сути, я создаю сервис загрузки и выгрузки файлов с некоторой дополнительной логикой сверху.
К сожалению, когда я пытаюсь запустить сервис из браузера, чтобы убедиться, что все в порядке, я получаю следующую ошибку:
Ошибка сервера в приложении '/' Операция "UploadFile" в контракте "IFileTransferService" использует Message Contract с заголовками 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>
ОБНОВЛЕНИЕ: читая документацию онлайн, кажется, что потоковая передача с Message Contracts действительно должна быть возможной. Обратитесь, например, к MSDN ( Большие данные и потоковая передача):
Модель программирования для потоковых передач
Модель программирования для потоковой передачи проста. Для получения потоковых данных укажите контракт операции, который имеет один типизированный входной параметр Stream. Для возврата потоковых данных верните ссылку на поток. [...] Это правило аналогично применяется к контрактам сообщений. Как показано в следующем контракте сообщений, в контракте сообщений может быть только один элемент тела, который является потоком. Если вы хотите передать дополнительную информацию потоку, эта информация должна быть перенесена в заголовки сообщения. Тело сообщения исключительно зарезервировано для содержимого потока.
[MessageContract]
public class UploadStreamMessage
{
[MessageHeader]
public string appRef;
[MessageBodyMember]
public Stream data;
}
Я также видел сообщения в блоге людей, выполняющих услуги по загрузке и скачиванию файлов, очень похожие на то, что я пытаюсь собрать (например, здесь).
ОБНОВЛЕНИЕ 2 Я попытался создать небольшую консоль и самостоятельно разместить службу с базовым HTTBBinding, и там она работает как шарм. Я начинаю верить, что проблема может быть в хостинге на IIS. Любая идея?
ОБНОВЛЕНИЕ 3 См мой собственный ответ.
3 ответа
Я, наконец, выяснил, в чем была ошибка: это не имело ничего общего с версиями 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
Вам нужна потоковая передача (т. Е. Передача огромных объемов данных) как по запросу, так и по ответу? Или просто на ответ (как правило: загрузка файла или большой набор данных)?
Если вам нужен только ответ, попробуйте установить режим передачи в "StreamedResponse":
<customBinding>
<binding name="customHttpBindingStream">
<textMessageEncoding messageVersion="Soap12" />
<httpTransport transferMode="StreamedResponse"
maxReceivedMessageSize="2147483647"/>
</binding>
</customBinding>
Параметр "Потоковая передача" будет выполнять потоковую передачу в обоих направлениях - и запрос, отправляемый на сервер, и ответ от сервера будут передаваться в потоковом режиме. Чаще всего это не идеальный сценарий.
Марк
Я получил ошибку после использования шаблона "Служба данных WCF" для создания файла SVC вместо шаблона "Служба WCF". Исправление файла хоста службы проблема была решена.