流式WCF服务失败

问题描述:

当尝试从服务中下载文件时,我的wcf客户端给我出现以下错误: “接收到对http://mypc-pc/xmlLoadService/Service.svc的HTTP响应时发生错误,这可能是由于服务端点绑定未使用HTTP协议,这也可能是由于HTTP请求上下文被服务器中止(可能是由于服务关闭),请参阅服务器日志以获取更多详细信息。流式WCF服务失败

正在执行的代码是这样的:

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(); 
     } 

这是我的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> 

它未能在 '下载' 功能被称为服务器上。

更新:从我所知道的跟踪日志中,文件没有在服务端打开。

这是应该打开该文件中的代码,并打算通过它一步一步当它不抛出任何异常:

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

该文件与里面只有一行文本文件。以下是跟踪日志:

<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:你需要设置'transferMode = StreamedResponse'如果你想回到一个流中读取客户 – 2009-10-04 14:44:57

+0

啊,对了,还好在你的文件 - 你不能把你的服务器编码到一个'using(){....}'块中 - 这将在块的末尾再次关闭流! – 2009-10-04 15:42:15

+0

非常感谢!它现在可以工作......我想我更好地研究一下WCF的工作。 – 2009-10-04 16:01:59

由于您似乎在使用流式响应 - 您的配置看起来如何?你的客户端配置中是否有这样的内容?

<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> 
  • 一个BindingConfiguration其具有具有binding=basicHttpBindingbindingConfiguration=FileTransferBinding(其中结合配置的名称是与上述相同的在声明一个transferMode=StreamedtransferMode=StreamResponse
  • 一个客户端端点的绑定配置)

这是绝对的最小值你应该有 - 但没有提供的重要信息,这只是猜测.....

UPDATE:您的问题最想的是,你不必transferMode="StreamResponse"在您绑定的配置。只有具备此设置,您才能够读取Stream作为服务电话的响应!

更新2:,如果你仍然有问题,我强烈建议您配置并启用WCF跟踪 - 这个片段添加到您的客户端配置:

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

将写入跟踪信息文件C:\log\traces.svclog(确保目录存在),您可以检查那些与服务跟踪查看器(SvcTraceViewer.exeC:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin\

退房有关如何配置和安装WCF跟踪更多的Infor的MSDN docs mation。

更新3:因为你想实际返回流(而不是关闭它在服务器上),你应该把你的流代码为using() {...}块!

试试这个:

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

您需要打开服务器上的数据流,并保持它的开放和返回。客户的工作是确保客户完成阅读后关闭它。

将该代码置于using() {....}块中通常是最佳做法,但在此“服务器打开流并将其返回给客户端”方案中不起作用。

马克

+0

我为你发布了我的web.config配置。希望有所帮助。 – 2009-10-04 14:40:30

+0

因此,我将配置更改为StreamedResponse,现在出现此错误: “通过HTTP通道传输数据时发生错误(无法从传输连接读取数据:连接已关闭。”)。 这可能是通道上的时钟吗? – 2009-10-04 14:58:58

+0

你应该签出WCF跟踪,并让它跟踪错误消息到一个文件并检查! – 2009-10-04 15:09:47