I am maintaing a Windows Forms application using WCF and are using Net.TCP internally. The lifecycle of our connections is GET/USE/CLOSE.
We are having a problem with the application pool crashing with no trace. In looking at netstat, I can see when I come into the application as we have a login service. However, even though we are creating the proxy in a using statement, the connection in netstat does not go away until I physically close the application.
Is this right? Should I be doing something different on the client to force the connection to close?
So if the connection stays open, does it stay open for the duration of the openTimeout setting and then gets torn down?
Microsoft says that you always have to close the connection at the end (see the example at MSDN). I've found the following pattern in this article about WCF disposal handling:
WCFServiceClient c = new WCFServiceClient();
try
{
c.HelloWorld();
}
catch
{
// acknowledge the Faulted state and transition to Closed
c.Abort();
// handle or throw
throw;
}
finally
{
c.Close();
}
The article says you should avoid using since it does not properly close and dispose the WCF service client object, you should do it with a try ... catch ... finally block instead as shown above - this way you're dealing with exceptions (which will abort and then re-throw or handle the exception) and also you take care of finally closing the connection. This is also clearly stated in Microsoft's WCF troubleshooting hints.
Note: The c.Close() in the finally does not do any harm in case of an exception (faulted state), because we call c.Abort() before the exception is re-thrown so the c.Close() does actually nothing in this case. However, if no exception occurs, then c.Close() is actually executed normally and the connection closes as expected.
If your WCF service behaves in a strange way, there are many (other) things which could cause this - here you can find some debugging hints.
First, you should probably not being using your proxy within the context of a using statement even though is does implement IDisposable: http://stevesmithblog.com/blog/idisposable-and-wcf/
That being said, it all depends on how you are utilizing the proxy. Take a look at marc's response here: C#, WCF, When to reuse a client side proxy
Yes, that's the expected behavior: the Net.TCP binding has a protocol-level transport session with your server, something you cannot really control in WCF.
I don't know of any mechanism in WCF to physically tear down that transport-level session - you might be able to do that using low-level TCP calls, but I've never had the need to do anything like that.
Related
Currently i have an issue regarding the WCF Timeout. The problem is how catch the error from WCF and catch it in global.asax ? I put try and catch in the business service, however it does not work.
Appreciate much for your answer.
Regards
You should first determine what causes the time out exception - then handle the exception properly.
If your service breaks (though I doubt a timeout falls under this category) you can catch it using the following in global.asax:
serviceHost.Faulted += new EventHandler(serviceHost_Faulted);
Note this isn't a good solution. Find the exact problem then use mocking frameworks (such as Moq) to simulate how your code (both client and service) will behave/recover in case your service takes too long to respond.
I have already developed my application, which has more than a 1000 functions. Now I need to implement fault contracts or exception handling in Silverlight without changing these functions.
Is there any common method that I can implement in one place in the WCF service layer and in one place in the Silverlight Application?
I want to implement this because when any exception occurs in the WCF layer, it will not send the real exception message to silverlight.
Silverlight only gets a message like this:
"Remote server not found..."
Real problem is i have already developed the system and now i need to implement the falultcontracts without changing too much or each function in Service layer.. so is there any method to create the falutcontract wrapper and place it over the WCF service Layer?
It's not 100% clear to me from the question what's going on in your case, but I can mention:
If you get an exception in Silverlight that the "Remote server not found..." then you won't get any exception details no matter what you do in the service (how can the service respond with those details, if the Silverlight app can not find the service?).
If you want to see exception details from the service in your app for debugging purposes, you can apply it to the entire service through the IncludeExceptionDetailInFaults property in the ServiceBehavior. This is considered a security risk (disclosing internal exception details) so it's not recommended for production.
As far as I know FaultContracts have to be set on the operations themselves, and you have to be explicit when you throw them.
PS. Your real problem may be that you have over a 1000 functions in your service, that doesn't seem healthy. On the other hand, if they are generated functions it may turn out to be a mixed blessing as you may be able to generate some fault code as well?
I want to log all exceptions (including serialization exception stack traces) in a WCF server to the Windows Event Log (log4net logging would also be acceptable).
What is the easiest way to do this?
Specifically all errors in serialization, in the service itself, etc. Right now I'm using tracing to get serialization errors during development. Tracing was the only way I could find out what object was actually have a problem with serialization. See Quickly finding WCF Serialization/Deserialization Issues for an example of getting the serialization stack trace.
I can handle errors in the service code itself. However, errors in the WCF machinery don't propagate to my service code (like serialization errors).
I don't need to send the errors to the client.
I just want to get the errors into one location (like the Event Log).
Right now (from my research) it appears that the IErrorHandler Interface with some custom code might be the best way to proceed. Will using the IErrorHandling interace catch the serialization exceptions?
Edit:
This may be the answer I'm looking for:
How do I create a global exception handler for a WCF Services?
I'd just like a confirmation that this will catch serialization errors and more importantly the details of those errors, also.
More Info:
How do I create a global exception handler for a WCF Services?
Yes, IErrorHandler will also catch serialization exceptions. You will get all information stored in the exception. Whether or not this enough detail for you, I can't say.
Note that there may be client-side errors (serialization and others) which will never make it to the server. You will not see those with the IErrorHandler.
When a FaultException is returned from my WCF service, I need to Abort the channel instead of Closing it. Both my client and service work fine with this approach but after implementing IErrorHandler on the service and logging any exception, I can see that calling Abort on the client causes the service to log:
System.ServiceModel.CommunicationException: The socket connection was aborted...
I do not want to pollute my service logs with this information and only want to log service related errors. I know I can obviously stop logging any CommunicationExceptions but my service is also a WCF client for other services and CommunicationExceptions raised by these services should be logged.
How can I stop it doing this?
As nobody else has answered the question (Tomas's answer was not relevant), I asked a few experts in the field. Unfortunately, there is no nice way of stopping this and the best that they could come up with was to add logic in IErrorHandler to not log CommunicationExcepions with a message starting with 'The socket connection was aborted'. Not very elegant, but it does work.
The problem is that you get an exception that covers your underlying exception if you get an exception when calling dispose wich is possible. I wrote a wrapper to deal with scenarios like this, you can read about it on my blog: http://blog.tomasjansson.com/2010/12/disposible-wcf-client-wrapper/
The idea is that you have a wrapper around your channel that deals with the scenario if the dispose method throws an exception.
A small example of how you should use my wrapper:
public class ClientWrapperUsage : IYourInternalInterface
{
public IList<SomeEntity> GetEntitiesForUser(int userId)
{
using(var clientWrapper = new ServiceClientWrapper<ServiceType>())
{
var response = clientWrapper.Channel.GetEntitiesForUser();
var entities = response.YourListOfEntities.TranslateToInternal();
return entities;
}
}
}
Here I have assumed that it existing an extension method for a list that contains the entity that is returned by the service, then you use that method to translate it to internal entities. This is 100 % testable, at least I think :). Just moch the interface IYourInternalInterface everywhere you wan't to fake the service.
At first I treated them as any dependency passing them in the ctor to the class consuming the service:
var serviceConsumer = new ServiceConsumer(new MailingServiceClient())
The problem was that once an exception was thrown from the service it entered a faulted state and would not reply to any requests, so re-initialization was due.
Further more, I became familiar with the fact that wcf services may not be disposed properly on several occasions, because the dispose method of the generated proxy is broken (calls close without checking the fault state) and encountered a couple of ways to overcome that:
wrapping every call to every service.
override the default IDisposable behavior of the scvutil.exe-generated class
Since I wouldn't like the consumer code to create the service client himself for testing reasons, my questions are:
how can I maintain a working un-faulted service?
how can I still use dependency injection for testability?
Found a nice solution.
a proxy generator that replaces the VS one, and generates a wrapper around the default proxy that deals with proxy faults, timeouts, and correct disposal.
http://wcfproxygenerator.codeplex.com/
seems to be working fine for me.