Проблема потоковой передачи WCF с ASP.NET - PullRequest
4 голосов
/ 06 июля 2011

У меня есть служба WCF, размещенная в приложении ASP.NET, и я пытаюсь загрузить файл из другого клиентского приложения ASP.NET, используя режим потоковой передачи.Я получаю следующую ошибку:

Удаленный сервер возвратил неожиданный ответ: (400) Плохой запрос.

Я просмотрел сеть, чтобы получить помощь, но безрезультатно.

Конфигурация хоста:

    <bindings>
      <basicHttpBinding>
        <binding name="FileTransferServicesBinding"
          transferMode="Streamed"
          messageEncoding="Mtom"
          sendTimeout="01:05:00"
          maxReceivedMessageSize="10067108864">
        </binding>
      </basicHttpBinding>
    </bindings>
    <services>
      <service behaviorConfiguration="FileTransferServiceBehavior" name="WebServiceHost.TransferService">
        <clear />
        <endpoint address="" binding="basicHttpBinding"
          bindingConfiguration="FileTransferServicesBinding" contract="WebServiceHost.ITransferService">
          <identity>
            <dns value="localhost"/>
            <certificateReference storeName="My" storeLocation="LocalMachine"
                x509FindType="FindBySubjectDistinguishedName" />
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange">
        </endpoint>
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:11291/TransferService.svc" />
          </baseAddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="FileTransferServiceBehavior">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

Код контракта:

[ServiceContract]
public interface ITransferService
{
    [OperationContract]
    RemoteFileInfo DownloadFile(DownloadRequest request);

    [OperationContract]
    void UploadFile(RemoteFileInfo request);

    [OperationContract]
    string TestMethod();
}

[MessageContract]
public class DownloadRequest
{
    [MessageBodyMember]
    public string FileName;
}

[MessageContract]
public class RemoteFileInfo : IDisposable
{
    [MessageHeader(MustUnderstand = true)]
    public string FileName;

    [MessageHeader(MustUnderstand = true)]
    public long Length;

    [MessageBodyMember(Order = 1)]
    public System.IO.Stream FileByteStream;

    public void Dispose()
    {
        if (FileByteStream != null)
        {
            FileByteStream.Close();
            FileByteStream = null;
        }
    }
}

Конфигурация клиента:

<bindings>
  <basicHttpBinding>
    <binding name="FileTransferServicesBinding" sendTimeout="01:05:00"
        maxReceivedMessageSize="10067108864" messageEncoding="Mtom"
        transferMode="Streamed" />
  </basicHttpBinding>
</bindings>
<client>
  <endpoint address="http://localhost:11291/TransferService.svc/"
      binding="basicHttpBinding" bindingConfiguration="FileTransferServicesBinding"
      contract="TransferServiceReference.ITransferService" name="FileTransferService"
      kind="">
    <identity>
      <dns value="localhost" />
      <certificateReference storeName="My" storeLocation="LocalMachine"
          x509FindType="FindBySubjectDistinguishedName" />
    </identity>
  </endpoint>
</client>
<behaviors>
  <serviceBehaviors>
    <behavior>
      <serviceMetadata httpGetEnabled="true" />
      <serviceDebug includeExceptionDetailInFaults="true" />
    </behavior>
  </serviceBehaviors>
</behaviors>

Код клиента:

ITransferService clientUpload = new TransferServiceClient();

string datetime = clientUpload.TestMethod();

var uploadRequestInfo = new RemoteFileInfo();

uploadRequestInfo.FileName = FileUpload1.FileName;
uploadRequestInfo.Length = FileUpload1.PostedFile.ContentLength;
uploadRequestInfo.FileByteStream = FileUpload1.PostedFile.InputStream;
clientUpload.UploadFile(uploadRequestInfo);

Вызов не выполняется как для clientUpload.TestMethod (), так и clientUpload.UploadFile (uploadRequestInfo).В буферизованном режиме вызывается clientUpload.TestMethod (), поэтому проблема заключается в конфигурации в потоковом режиме.

Я был бы признателен за любую помощь по этому вопросу.Спасибо.

Ответы [ 2 ]

2 голосов
/ 31 октября 2012

У меня те же проблемы, и я нашел, что эта статья объясняет, как решить вашу ошибку. http://www.c -sharpcorner.com / uploadfile / BruceZhang / поток-операция-в-ФОС / .

Надеюсь, это поможет!

2 голосов
/ 06 июля 2011

Проблема в вашем контракте на данные - public System.IO.Stream FileByteStream;. Удалите этого участника из контракта на данные и используйте stream в контракте на операции - например:

[OperationContract(OneWay=true)]
void UploadFile(RemoteFileInfo request, System.IO.Stream fileData);

Цитируется из Большие данные и потоковая передача (MSDN):

Вы не должны использовать Производные типы System.IO.Stream внутри данных контрактов. Потоковые данные должны общаться с использованием потоковой передачи модель, объясненная в следующем Раздел «Потоковые данные».

В разделе «Потоковые данные» по той же ссылке это подробно объясняется.

Проблема в вашем договоре на передачу данных - public System.IO.Stream FileByteStream;. Удалите этого участника из контракта на данные и используйте stream в контракте на операции - например:

[OperationContract(OneWay=true)]
void UploadFile(RemoteFileInfo request, System.IO.Stream fileData);

Цитируется из Большие данные и потоковая передача (MSDN):

Вы не должны использовать Производные типы System.IO.Stream внутри данных контрактов. Потоковые данные должны общаться с использованием потоковой передачи модель, объясненная в следующем Раздел «Потоковые данные».

В разделе «Потоковые данные» по той же ссылке это подробно объясняется.

EDIT: Извинения - я пропустил ограничения. У вас есть два способа решения проблемы - используйте MessageContract или используйте несколько операций для одной транзакции. Пример использования нескольких операций будет

[OperationContract]
Token UploadFile(System.IO.Stream fileData);

[OperationContract]
void ProvideFileInfo(Token token,  RemoteFileInfo request);

Сначала загрузите данные на сервер, и сервер выдаст токен (например, guid), используйте токен для обновления другой информации.

Более предпочтительным способом будет использование MessageContract, которое вы уже пробовали. Несколько предложений по устранению неполадок:

  1. Если ваш хостинг это в IIS, проверьте maxRequestLength в web.config. Попробуйте загрузить небольшие файлы.
  2. Вместо того, чтобы использовать поток ОпубликованоFile напрямую, сохраните его на диск и используйте поток поверх него. Причиной того, что поток HTTP-запросов может быть очищен во время загрузки.
  3. Используйте инструмент, такой как fiddler, и просмотрите сообщение, передающееся по сервису через проволоку, которое может дать подсказку.
...