Ogglas Ogglas - 1 month ago 10
reST (reStructuredText) Question

Handle an unreliable/unresponsive SOAP web service or REST API from a C# applicaiton

I don't like error handling via try catch blocks but in this case I did not see any other clear path. In my code I'm calling a web service but it might soon be a rest API in the near future. This web service is external and unfortunately not 100% reliable. What I need to do is create code that can handle an unresponsive web service. Today it looks like this:

SOAP Proxy is set to have a timeout of 120 seconds

var myProxy = new WebReference.ProxyClass();
myProxy.Timeout = 120000;

try
{
CreditInformation creditInformation = myProxy.Retrieve(prospect.CorporateIdentity);
agreement.Company.Name = creditInformation.CompanyName;
agreement.FinancialInformation.NetRevenue = creditInformation.Revenue / 1000;
}
catch (WebException e) when (e.Status == WebExceptionStatus.Timeout)
{
logger.Error("Web service timed out");
}

//Continiue running code even if the web service time out


Is this a bad standard and could it be better performed? As I said before I don't like handling errors via try catch but it seemed viable here. I thought about creating some code to check if the web service was responding but i decided not to go this way. This is because the web service is quite slow, a request takes 30-60 seconds by default and that would leave the user waiting even longer for me to check if it is up. Another solution might be to ping the host but it does not guarantee that the service is actually up. Sample code:

HttpWebResponse response = (HttpWebResponse)request.GetResponse();
if (response != null && response.StatusCode == HttpStatusCode.OK)
{
//Do stuff here
}

Evk Evk
Answer

There are two opposite camps about how to handle exceptional situations. One camp prefers exceptions, another camp prefers to return error codes (or similar) from a function that might fail in one form or another. What is "better" is arguable and situation-dependent (see for example: http://www.joelonsoftware.com/items/2003/10/13.html for the arguments of "error code" camp). I'm telling this because as I understand you would prefer that myProxy.Retrieve return some error code on timeout, not throwing an exception. It might be reasonable, but that's not how it works and you cannot change that. Whole .NET framework uses exceptions almost everywhere (sometimes in situations which might be considered "part of normal flow", though definition of normal flow is again not trivial).

Long story short - a lot of code you use in .NET will throw exceptions on errors, even in sutations which you consider normal, and you have to live with that and act accordingly - catch and handle them - that's perfectly normal. Usually there are 2 points against exceptions:

  1. They cost some time and resources to construct, as you mention in comment. That's reasonable concern in some code which executes thousands of operations per second, and those operations throw thousands of exceptions. In your case however, request takes 30-60 seconds, and as such cost of exception is absolutely zero compared to that.

  2. They change control flow, sometimes moving it very far from actual exception source (like goto statement). To handle this (if you are in the "error code" camp, but have to work with exceptions anyway), you should put try-catch block as close as possible to the function which produces it, and handle exception immedatly, because you know exactly where and why it happened. This if what you already do in your example.

So, surrounding soap service call with try-catch block and handling timeout exception is the best way to go here, and there is absolutely no need to try to avoid this exception being thrown. You might want to not throw exceptions in "normal" conditions yourself, in your own code, but if that happens in third party code - you have to handle and not avoid them.