tags:

views:

2080

answers:

4

I have a simple web service to allow applications to query my CMDB. The function I am having trouble with works with a small resultset but fails with a larger one, indicating that it is something in the WCF service config that is preventing it succeeding.

I have a simple WinForms test app with a Service Reference to the web service and a single function that calls the function in question.

The smaller result set returns ~120KB of xml, the failing larger resultset is ~2MB. I have tried increasing the size of the maxReceivedMessageSize and maxStringContentLength without success.

Is there some config I have missed? I would be expecting a more detailed error message if that was the problem.

Thanks in advance,

Nick


The error the is returned is:

System.ServiceModel.CommunicationException: The underlying connection was closed: The connection was closed unexpectedly. --->
System.Net.WebException: The underlying connection was closed: The connection was closed unexpectedly.
   at System.Net.HttpWebRequest.GetResponse()
   at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
   --- End of inner exception stack trace ---

Server stack trace: 
   at System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException(WebException webException, HttpWebRequest request, HttpAbortReason abortReason)
   at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
   at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
   at System.ServiceModel.Channels.ClientReliableChannelBinder`1.RequestClientReliableChannelBinder`1.OnRequest(TRequestChannel channel, Message message, TimeSpan timeout, MaskingMode maskingMode)
   at System.ServiceModel.Channels.ClientReliableChannelBinder`1.Request(Message message, TimeSpan timeout, MaskingMode maskingMode)
   at System.ServiceModel.Channels.ClientReliableChannelBinder`1.Request(Message message, TimeSpan timeout)
   at System.ServiceModel.Security.SecuritySessionClientSettings`1.SecurityRequestSessionChannel.Request(Message message, TimeSpan timeout)
   at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs)
   at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
   at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

Exception rethrown at [0]: 
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
   at TestRig.CmdbDataService.ICmdbDataService.GetMonitors(String client)
   at TestRig.CmdbDataService.CmdbDataServiceClient.GetMonitors(String client) in C:\Documents and Settings\nfoster\My Documents\Visual Studio Projects\Virtual Operations Manuals\Trunk\src\TestRig\Service References\CmdbDataService\Reference.vb:line 1480
   at TestRig.Form1.btnGetServers_Click(Object sender, EventArgs e) in C:\Apps\Virtual Operations Manuals\Trunk\src\TestRig\Form1.vb:line 8

The calling function in the application is:

Private Sub btnGetMonitors_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnGetMonitors.Click
  txtResults.Text = String.Empty
  Dim proxy As CmdbDataService.CmdbDataServiceClient = Nothing
  Try
    proxy = New CmdbDataService.CmdbDataServiceClient("WSHttpBinding_ICmdbDataService")
    Dim monitors As TestRig.CmdbDataService.ConfigurationItems = proxy.GetMonitors(txtClientName.Text)
    proxy.Close()
    For Each monitor In monitors
      txtResults.Text &= monitor.Name & " (" & monitor.TypeName & ")" & vbCrLf
    Next
    txtResults.Text &= monitors.Count & " monitors returned"
  Catch ex As Exception
    If Not IsNothing(proxy) AndAlso proxy.State <> ServiceModel.CommunicationState.Closed Then proxy.Abort()
    txtResults.Text = ex.ToString
  Finally
    proxy = Nothing
  End Try
End Sub

On the test rig side the app.config contains the following serviceModel:

  <system.serviceModel>
    <diagnostics>
      <messageLogging logMalformedMessages="true" logMessagesAtServiceLevel="true"
        logMessagesAtTransportLevel="true" />
    </diagnostics>
    <behaviors />
    <bindings>
      <wsHttpBinding>
        <binding name="WSHttpBinding_Default" closeTimeout="00:05:00"
          openTimeout="00:05:00" receiveTimeout="00:10:00" sendTimeout="00:05:00"
          maxBufferPoolSize="104857600" maxReceivedMessageSize="104857600">
          <readerQuotas maxDepth="104857600" maxStringContentLength="104857600"
            maxArrayLength="104857600" maxBytesPerRead="104857600" maxNameTableCharCount="104857600" />
        </binding>
      </wsHttpBinding>
    </bindings>
    <client>
      <endpoint address="http://localhost/CmdbServices/DataService.svc/soap12"
        binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_Default"
        contract="CmdbDataService.ICmdbDataService" name="WSHttpBinding_ICmdbDataService">
        <identity>
          <userPrincipalName value="MyMachine\ASPNET" />
        </identity>
      </endpoint>
    </client>
  </system.serviceModel>

and on the service side the web.config is:

  <system.serviceModel>
    <diagnostics performanceCounters="Default">
      <messageLogging logMalformedMessages="true" logMessagesAtServiceLevel="true"
       logMessagesAtTransportLevel="true" />
    </diagnostics>
    <services>
      <service behaviorConfiguration="ServiceBehavior" name="MyCorp.Cmdb.Services.DataService.CmdbDataService">
        <endpoint address="soap12" binding="wsHttpBinding" contract="MyCorp.Cmdb.Services.DataService.ICmdbDataService" />
        <endpoint address="soap11" binding="basicHttpBinding" contract="MyCorp.Cmdb.Services.DataService.ICmdbDataService" />
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="ServiceBehavior">
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
A: 

UPDATED: OK, I see that you already have tracing turned on. Have you looked at the WCF traces?

Igor Brejc
I had a look through the traces but I find them really hard to decode, WCF is not my primary area. The exception is listed in there but the details are exactly as in the original exception :(
Nick
A: 

I would try increasing the timeout values.

Mr. Flibble
A: 

All this tells you is that the connection was closed when WCF didn't expect it to be closed. You should follow Igor's advice above.

One small issue, is that you should remove the Abort from the Catch block and Try block, and instead put proxy.Close in the Finally block.

John Saunders
if the proxy returns in a faulted state, then proxy.close won't work. you'll need proxy.abortthere's a few articles about this kicking around.
GordonB
+4  A: 

A collegue of mine has just pointed me at this blog post where the actual culprit is the maxItemsInObjectGraph property in the endpoint behaviours.

Bumping these up has solved the problem, I must have just passed over the default threshold of 65536 :D

Nice to see the error messages point you in the right direction :(

Cheers....

Nick