2009-10-04 6 views
3

Mon client wcf me renvoie l'erreur suivante lors du téléchargement d'un fichier depuis le service: "Une erreur s'est produite lors de la réception de la réponse HTTP à http://mypc-pc/xmlLoadService/Service.svc.Cela peut être dû au fait que la liaison du point de terminaison de service n'utilise pas le protocole HTTP Cela peut aussi être dû à l'abandon d'un contexte de requête HTTP par le serveur (probablement en raison de l'arrêt du service) Voir les journaux du serveur pour plus de détails. "Échec du service WCF en streaming

Le code en cours d'exécution est la suivante:

System.IO.FileStream fs; 
     try 
     { 
      fs = (System.IO.FileStream)client.Download(@"C:\UploadedFiles\Test.txt"); 
      byte[] arr = new byte[fs.Length]; 
      int read; 
      do 
      { 
       read = fs.Read(arr, 0, arr.Length); 

      } while (read != arr.Length); 

      Console.WriteLine(ASCIIEncoding.ASCII.GetString(arr)); 
      Console.ReadLine(); 
     } 

Voici ma config web.config:

<bindings> 
    <basicHttpBinding> 
     <binding name="basicHTTP" receiveTimeout="00:10:00" 
       sendTimeout="00:03:00" closeTimeout="00:10:00" 
       openTimeout="00:03:00" messageEncoding="Mtom" 
       maxBufferSize="100000" maxReceivedMessageSize="100000" 
       transferMode="Buffered"> 
     </binding> 
    </basicHttpBinding> 
</bindings> 
<services> 
    <service behaviorConfiguration="ServiceBehavior" name="Service"> 
     <endpoint address="" binding="wsHttpBinding" contract="IService"> 
      <identity> 
       <dns value="localhost" /> 
      </identity> 
     </endpoint> 
     <endpoint address="mex" binding="mexHttpBinding" 
       contract="IMetadataExchange" /> 
    </service> 
    <service behaviorConfiguration="mexBehavior" 
      name="LoadXMLService.XMLOperations"> 
     <endpoint address="" 
        binding="basicHttpBinding" 
        bindingConfiguration="basicHTTP" 
        behaviorConfiguration="" 
        contract="LoadXMLService.IxmlLoad" /> 
    </service> 
</services> 

Il échoue lorsque la fonction 'téléchargement' est appelé sur le serveur. MISE À JOUR: D'après ce que je comprends du journal de suivi, le fichier n'est pas ouvert à la fin du service.

C'est le code qui est censé ouvrir le fichier, et il ne jette aucune exception lorsque vous passez par étape par étape:

public Stream Download(string path) 
    { 
     try 
     { 
      using (FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read)) 
      { 

       return stream; 
      } 
     } 
     catch (Exception ex) 
     { 
      string error = ex.Message; 

      return null; 
     } 
    } 

Le fichier est un fichier texte avec une seule ligne à l'intérieur . Voici le journal de suivi:

<E2ETraceEvent xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent"> 
<System xmlns="http://schemas.microsoft.com/2004/06/windows/eventlog/system"> 
<EventID>524340</EventID> 
<Type>3</Type> 
<SubType Name="Error">0</SubType> 
<Level>2</Level> 
<TimeCreated SystemTime="2009-10-04T15:20:22.7770000Z" /> 
<Source Name="System.ServiceModel" /> 
<Correlation ActivityID="{cb13d023-8122-4199-896c-78684b2461db}" /> 
<Execution ProcessName="WebDev.WebServer" ProcessID="8104" ThreadID="8" /> 
<Channel /> 
<Computer>TONY-PC</Computer> 
</System> 
<ApplicationData> 
<TraceData> 
<DataItem> 
<TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Error"> 
<TraceIdentifier>http://msdn.microsoft.com/en-GB/library/System.ServiceModel.ServiceOperationExceptionOnReply.aspx</TraceIdentifier> 
<Description>Replying to an operation threw a exception.</Description> 
<AppDomain>b986c3da-11-128991431145070000</AppDomain> 
<Source>System.ServiceModel.Dispatcher.ImmutableDispatchRuntime/48562646</Source> 
<Exception> 
<ExceptionType>System.ObjectDisposedException, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType> 
<Message>Cannot access a closed file.</Message> 
<StackTrace> 
at System.IO.__Error.FileNotOpen() 
at System.IO.FileStream.Read(Byte[] array, Int32 offset, Int32 count) 
at System.Xml.XmlMtomWriter.WriteXOPBinaryParts() 
at System.Xml.XmlMtomWriter.WriteEndElement() 
at System.ServiceModel.Channels.Message.OnWriteMessage(XmlDictionaryWriter writer) 
at System.ServiceModel.Channels.Message.WriteMessage(XmlDictionaryWriter writer) 
at System.ServiceModel.Channels.MtomMessageEncoder.WriteMessage(Message message, Stream stream, String startInfo, String boundary, String startUri, Boolean writeMessageHeaders) 
at System.ServiceModel.Channels.MtomMessageEncoder.WriteMessage(Message message, Stream stream, String boundary) 
at System.ServiceModel.Channels.HttpOutput.WriteStreamedMessage(TimeSpan timeout) 
at System.ServiceModel.Channels.HttpOutput.Send(TimeSpan timeout) 
at System.ServiceModel.Channels.HttpRequestContext.OnReply(Message message, TimeSpan timeout) 
at System.ServiceModel.Activation.HostedHttpContext.OnReply(Message message, TimeSpan timeout) 
at System.ServiceModel.Channels.RequestContextBase.Reply(Message message, TimeSpan timeout) 
at System.ServiceModel.Channels.RequestContextBase.Reply(Message message) 
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.Reply(MessageRpc&amp; rpc) 
</StackTrace> 
<ExceptionString>System.ObjectDisposedException: Cannot access a closed file. 
    at System.IO.__Error.FileNotOpen() 
    at System.IO.FileStream.Read(Byte[] array, Int32 offset, Int32 count) 
    at System.Xml.XmlMtomWriter.WriteXOPBinaryParts() 
    at System.Xml.XmlMtomWriter.WriteEndElement() 
    at System.ServiceModel.Channels.Message.OnWriteMessage(XmlDictionaryWriter writer) 
    at System.ServiceModel.Channels.Message.WriteMessage(XmlDictionaryWriter writer) 
    at System.ServiceModel.Channels.MtomMessageEncoder.WriteMessage(Message message, Stream stream, String startInfo, String boundary, String startUri, Boolean writeMessageHeaders) 
    at System.ServiceModel.Channels.MtomMessageEncoder.WriteMessage(Message message, Stream stream, String boundary) 
    at System.ServiceModel.Channels.HttpOutput.WriteStreamedMessage(TimeSpan timeout) 
    at System.ServiceModel.Channels.HttpOutput.Send(TimeSpan timeout) 
    at System.ServiceModel.Channels.HttpRequestContext.OnReply(Message message, TimeSpan timeout) 
    at System.ServiceModel.Activation.HostedHttpContext.OnReply(Message message, TimeSpan timeout) 
    at System.ServiceModel.Channels.RequestContextBase.Reply(Message message, TimeSpan timeout) 
    at System.ServiceModel.Channels.RequestContextBase.Reply(Message message) 
    at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.Reply(MessageRpc&amp; rpc)</ExceptionString> 
</Exception> 
</TraceRecord> 
</DataItem> 
</TraceData> 
<System.Diagnostics xmlns="http://schemas.microsoft.com/2004/08/System.Diagnostics"> 
<LogicalOperationStack></LogicalOperationStack> 
<Timestamp>921505170062</Timestamp> 
<Callstack> 
at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo) 
at System.Environment.get_StackTrace() 
at System.Diagnostics.TraceEventCache.get_Callstack() 
at System.Diagnostics.XmlWriterTraceListener.WriteFooter(TraceEventCache eventCache) 
at System.Diagnostics.XmlWriterTraceListener.TraceData(TraceEventCache eventCache, String source, TraceEventType eventType, Int32 id, Object data) 
at System.Diagnostics.TraceSource.TraceData(TraceEventType eventType, Int32 id, Object data) 
at System.ServiceModel.Diagnostics.DiagnosticTrace.TraceEvent(TraceEventType type, TraceCode code, String description, TraceRecord trace, Exception exception, Object source) 
at System.ServiceModel.Diagnostics.TraceUtility.TraceEvent(TraceEventType severity, TraceCode traceCode, TraceRecord extendedData, Object source, Exception exception) 
at System.ServiceModel.Diagnostics.TraceUtility.TraceEvent(TraceEventType severity, TraceCode traceCode, Object source, Exception exception) 
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.Reply(MessageRpc& rpc) 
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessageCleanup(MessageRpc& rpc) 
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc) 
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc& rpc) 
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3(MessageRpc& rpc) 
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(MessageRpc& rpc) 
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1(MessageRpc& rpc) 
at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet) 
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.Dispatch(MessageRpc& rpc, Boolean isOperationContextSet) 
at System.ServiceModel.Dispatcher.ChannelHandler.DispatchAndReleasePump(RequestContext request, Boolean cleanThread, OperationContext currentOperationContext) 
at System.ServiceModel.Dispatcher.ChannelHandler.HandleRequest(RequestContext request, OperationContext currentOperationContext) 
at System.ServiceModel.Dispatcher.ChannelHandler.AsyncMessagePump(IAsyncResult result) 
at System.ServiceModel.Dispatcher.ChannelHandler.OnAsyncReceiveComplete(IAsyncResult result) 
at System.ServiceModel.Diagnostics.Utility.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result) 
at System.ServiceModel.AsyncResult.Complete(Boolean completedSynchronously) 
at System.ServiceModel.Channels.InputQueue`1.AsyncQueueReader.Set(Item item) 
at System.ServiceModel.Channels.InputQueue`1.EnqueueAndDispatch(Item item, Boolean canDispatchOnThisThread) 
at System.ServiceModel.Channels.InputQueue`1.EnqueueAndDispatch(T item, ItemDequeuedCallback dequeuedCallback, Boolean canDispatchOnThisThread) 
at System.ServiceModel.Channels.InputQueueChannel`1.EnqueueAndDispatch(TDisposable item, ItemDequeuedCallback dequeuedCallback, Boolean canDispatchOnThisThread) 
at System.ServiceModel.Channels.SingletonChannelAcceptor`3.Enqueue(QueueItemType item, ItemDequeuedCallback dequeuedCallback, Boolean canDispatchOnThisThread) 
at System.ServiceModel.Channels.HttpChannelListener.HttpContextReceived(HttpRequestContext context, ItemDequeuedCallback callback) 
at System.ServiceModel.Activation.HostedHttpTransportManager.HttpContextReceived(HostedHttpRequestAsyncResult result) 
at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.HandleRequest() 
at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.BeginRequest() 
at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.OnBeginRequest(Object state) 
at System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.WorkItem.Invoke2() 
at System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.WorkItem.Invoke() 
at System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.ProcessCallbacks() 
at System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.CompletionCallback(Object state) 
at System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.ScheduledOverlapped.IOCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped) 
at System.ServiceModel.Diagnostics.Utility.IOCompletionThunk.UnhandledExceptionFrame(UInt32 error, UInt32 bytesRead, NativeOverlapped* nativeOverlapped) 
at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP) 
</Callstack> 
</System.Diagnostics> 
</ApplicationData> 
</E2ETraceEvent> 
+0

@Tony: vous devez définir le 'transferMode = StreamedResponse' si vous voulez revenir un STREAM pour lire votre fichier sur le client –

+0

ah, oui, d'accord - vous ne pouvez pas mettre votre serveur codez dans un bloc 'using() {....}' - cela referme le flux à la fin du bloc! –

+0

Merci beaucoup! Ça marche maintenant ... Je pense que je ferais mieux d'étudier un peu plus le fonctionnement de la WCF. –

Répondre

4

Étant donné que vous semblez utiliser des réponses en streaming - à quoi ressemble votre configuration? Avez-vous quelque chose comme ça dans votre config client?

<system.serviceModel> 
    <bindings> 
     <basicHttpBinding> 
     <binding name="FileTransferBinding" 
        transferMode="StreamedResponse" /> 
     </basicHttpBinding> 
    </bindings> 
    <client> 
     <endpoint name="DefaultEndpoint" 
       address="....." 
       binding="basicHttpBinding" 
       bindingConfiguration="FileTransferBinding" 
       contract="IYourContract" /> 
    </client> 
    </system.serviceModel> 
  • un BindingConfiguration qui a une transferMode=Streamed ou transferMode=StreamResponse
  • un point de terminaison client qui a une binding=basicHttpBinding et un bindingConfiguration=FileTransferBinding (où le nom de la configuration de liaison est le même que ci-dessus dans la déclaration de la configuration de liaison)

C'est le strict minimum absolu vous devriez avoir - mais sans cette information cruciale fournie, il est juste devinettes .....

MISE À JOUR: Votre problème comme la plupart est le fait que vous n'avez pas transferMode="StreamResponse" dans votre configuration de liaison. Ce n'est que si vous avez ce réglage que vous pourrez lire un Stream comme réponse de l'appel de service!

MISE À JOUR 2: si vous continuez à avoir des problèmes, je vous suggère fortement configurer et activer le suivi WCF - ajouter cet extrait à votre configuration client:

<configuration> 
    <system.diagnostics> 
     <sources> 
      <source name="System.ServiceModel" 
        switchValue="Information, ActivityTracing" 
        propagateActivity="true"> 
      <listeners> 
       <add name="traceListener" 
        type="System.Diagnostics.XmlWriterTraceListener" 
        initializeData= "c:\log\Traces.svclog" /> 
      </listeners> 
     </source> 
     </sources> 
    </system.diagnostics> 
</configuration> 

Il rédigera des informations de trace le fichier C:\log\traces.svclog (assurez-vous que le répertoire existe), et vous pouvez inspecter les avec le service Viewer Trace (SvcTraceViewer.exe dans votre C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin\)

Vérifiez la MSDN docs sur la façon de configurer et de configuration WCF pour le suivi d'infor mation.

MISE À JOUR 3: puisque vous voulez revenir en fait le flux (et non fermer sur le serveur), vous devriez pas mettre votre code de flux dans un bloc using() {...}!

Essayez ceci:

public Stream Download(string path) 
{ 
    try 
    { 
     FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read); 
     return stream; 
    } 
    catch (Exception ex) 
    { 
     string error = ex.Message; 
     return null; 
    } 
} 

Vous devez ouvrir le flux sur le serveur, et le laisser ouvert et de le retourner. C'est le travail du client de s'assurer qu'il sera fermé après que le client l'ait lu.

La mise en place de ce code dans un bloc using() {....} est la meilleure pratique en général, mais ne fonctionne pas dans ce scénario «Le serveur ouvre le flux et le renvoie au client».

Marc

+0

J'ai posté ma config web.config pour vous. J'espère que cela pourra aider. –

+0

J'ai donc changé la configuration en StreamedResponse et maintenant je reçois cette erreur: "Une erreur (Impossible de lire les données de la connexion de transport: la connexion était fermée.) S'est produite lors de la transmission de données via le canal HTTP." Cela pourrait-il être quelque chose avec les timings sur la chaîne? –

+0

Vous devriez vérifier le traçage WCF et le laisser suivre les messages d'erreur dans un fichier et examiner cela! –