Background
Recently while working on a WCF service I received an error which said “The underlying connection was closed: The connection was closed unexpectedly”. This error was occurring while trying to execute the service method from the client. My initial thoughts were that it could be a security issue. After doing some goggling I found that it could be due to serialization issues.Possible causes for this error
Many of the articles and blogs suggested that this can occur if we are using Enum in our service and this enum is transferred to the client as part of data contract. We did have couple of enums defined in our service layer and they were getting transferred to the client. To resolve the serialization issue with Enum we need to decorate the Enum class with DataContract attribute. Also each enum member needs to be decorated with EnumMember attribute. We already had this in place for our service.It could also occur if there is mismatch in the way collections are handled between the service proxy and the service layer. The generic lists seem to have problems while serializing and deserializing. Matevz Gacnik explains in his blog WCF: Passing Collections Through Service Boundaries, Why and How , how we can change the default ArrayList to GenericCollection type while transferring data from service to the client.
I tried debugging the service code by invoking the service method using the WCF test client utility. The method was executing as expected on the service side. And the error message was very generic. I needed a way to find out what was happening behind the scenes. That is when I came to know that we can enable tracing in WCF service. This is similar to ASP.NET Page Tracing feature. By enabling the trace we can get to know the sequence of events what occur on the service side.
How to enable trace for WCF service
One thing I like the most about WCF is the extensibility it offers to developers. Without making any code changes we can enable many things using configurations. Tracing is not enabled by default. In order to enable trace we need to add the following code to WCF Web.config file<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>
The level details that gets logged in the output file (C:\log\Traces.svclog) depends on the value of switchValue. The permissible values are
- Warning
- ActivityTracing
- Information
- Verbose
- TextWriterTraceListener
- ConsoleTraceListener
- EventLogTraceListener
- DelimitedListTraceListener
Conclusion
The trace feature was really helpful in identifying the problem I was facing. It turned out that there was a problem with the domain object that we were using within the service. We use NHibernate as ORM for our data access. We needed to set the IsReference attribute on one of the domain object. If it was not for the trace feature it would have taken me long time to resolve this issue. We can add multiple trace listeners for a trace source. That means we can write the same information as an XML as well as a comma delimited file. Or we could write the same information to different sources like a flat file and event log. If required we can create a custom trace listener if the available ones does not suffice our requirement.Until next time Happy Programming :)
Simple and easy to understand explanation!
ReplyDelete