12

I'm not sure I'm completely happy that throwing exceptions in web services is a good idea. I wouldnt mind as much if it wasn't for the stack trace. This is not something I wan't.

I have researched around several implementations and there really doesn't seem to be a consensus on this. CampaignMonitor for example does return a Result object, yet others don't.

Architecturally, I'm not sure returning a return object makes sense, surely an exception is an exception, but what I do like about a Return object is that it is a more graceful solution for the end user.

Does anyone have any better solutions?

EDIT

BTW I am using ASMX web services, where turning CustomErrors on is not an option.

John Saunders
  • 160,644
  • 26
  • 247
  • 397
Ryan Tomlinson
  • 874
  • 2
  • 9
  • 21
  • Actually, I believe the way to remove exception detail is by playing with the customErrors tag in web.config. Believe It Or Not. – John Saunders Jun 19 '09 at 18:27
  • @John: Yes thats what I'm saying here. Unfortunately this isnt an option for me. Otherwise it would be a much simpler problem for me :(. – Ryan Tomlinson Jun 19 '09 at 18:38

7 Answers7

8

Don't let the fact that you're in a web service confuse the issue. That's just an implementation detail.

Use your normal exception handling strategy. Best practice says don't trap exceptions in low level code -- unless you can resolve that exception there and continue normally. Exceptions should be raised to the presentation layer so the user can be informed of the error.

So, as applied to web services -- in general throw exceptions (which results in a SoapFault). This allows the invoking client code to use it's built-in exception handling standard to handle it.

Maladon
  • 398
  • 2
  • 11
  • @Maladon: this is a good answer, except on layer boundaries. In general, strategies change on layer boundaries, especially at the service layer. In particular, for WCF, a layer boundary would be a good place to catch exception "A" and reaplace it with FaultException, which will send SOAP fault AFault. No stack trace, BTW. ASMX doesn't support faults properly; yet another reason to stop using it. – John Saunders Jun 19 '09 at 17:58
7

What stack trace are you talking about? Have you tried this?

In both ASMX and WCF services, an uncaught exception will be translated into a SOAP Fault. In both cases, they can be configured to not include any stack trace. In fact, that's the default in WCF.

So, the proper way to return an error like this is through a fault. One way to generate faults is to throw and not handle an exception.

John Saunders
  • 160,644
  • 26
  • 247
  • 397
  • In essence all I want to inform the user of is an exception with an error code and desciption (of my choosing). I feel there is a semantic different between exception handling for web services and for application architecture but I'm unsure as to whether they should be treat differently. You wouldn't return a Result object in code when there's a fault. Should web services be any different. No (as you imply). I suppose my question is how do I abstract the exception detail? – Ryan Tomlinson Jun 19 '09 at 18:20
  • 2
    Read up on SOAP faults. This is the standard way to return arbitrary detail to a client. In ASMX web services, you have to return them "by hand" in the Detail property of a SoapException instance, but it's the right way if you have to stay with ASMX. Of course the better way is to use WCF. Also, don't think about it as informing users about exceptions. Exceptions are an implementation detail. You're informing them about a fault. – John Saunders Jun 19 '09 at 18:26
  • This is not what I observe. My ASMX web services all return stack traces under default settings, and it drives me mad. And when there is a chain of services calling each other, and the last in the chain throws, the client receives an enourmous stack trace from all participating services (in the form of a `SoapException` the `Message` property of which contains the stack trace as concatenated text). This is horrible and I have no idea how to switch it off. – GSerg Mar 05 '14 at 13:10
  • @GSerg: you would switch it off in one of two ways: 1. Switch to WCF, where you can control whether the details are in the message, and 2. Fix your code to not be broken. – John Saunders Mar 05 '14 at 13:12
  • @JohnSaunders I'm not switching to WCF for compatibility reasons, and the code is not broken, I willingly throw the exception upon detecting bad parameters, providing helpful `Message`. I know I can return a dummy reply object with `Success = false`, but this is stupid, as you have said in your answer, the correct way is throwing exceptions. I still can't believe it is impossible to switch off the stack trace - in that case, all clients of all publicly exposed ASMX services can to peek into their source code structure every so often? – GSerg Mar 05 '14 at 13:18
  • @GSERG: There's nothing wrong with _throwing_ exceptions for argument errors; the problem is that you're not _handling_ them. You are letting them leak out to the client, and that's a bad idea. And, you're expecting the legacy technology to have all the features of the modern technology? Finally, what kind of compatibility issue are you having that keeps you from switching? – John Saunders Mar 05 '14 at 13:23
  • @JohnSaunders But I *want* to pass an exception to the client, so that it throws - this is what this Ryan Tomlinson's question is about. Even if I handle it and create a new `Exception` for throwing instead of the actual one, the client still gets to see the code file name and the line number where I threw it. If ASMX *supports* passing exceptions in the first place, surely there must be a way to do so without a stack trace, because it is very important? Compatibility: Having XML or JSON from the same service depending on `Content-Type` in the request (requires two different endpoints in WCF). – GSerg Mar 05 '14 at 13:36
  • @GSerg: SOAP web services (including ASMX and WCF) do not support passing exceptions. They support returning faults, which is not the same thing. – John Saunders Mar 05 '14 at 13:38
2

one approach is to separate system and business errors. (System error: e.g. malformed request, user-not-authorized, etc.; business error: e.g. method UpdateCars results in an error, the user doesn't own any cars).

In case of a business error, return a response object containing an error description; in case of a system error, throw an exception.

azheglov
  • 5,475
  • 1
  • 22
  • 29
  • 1
    The SOAP spec provides for faults to return error conditions, and they should be used. Otherwise, your clients will be back to having to remembe to check error return values, and won't be able to use their platform-specific translation of the faults. – John Saunders Jun 19 '09 at 17:59
0

Can you clarify a bit? The server-side of a web service can throw an exception. The server-side of a web service can return a message to the client-side. That message may contain error information, and that error information may specifically include exception details. Or it may not. On the client-side, you typically have a generated proxy to deal with the message from the server. This proxy may generate an exception if that response contains error information.

Which part of this scenario are you wondering about?

Bruce
  • 8,202
  • 6
  • 37
  • 49
  • @Bruce: uncaught exceptions will be translated into faults. Under somce circumstances, those will include excepton details. – John Saunders Jun 19 '09 at 17:45
  • @Bruce: I understand how web services work, I mean more of an architecture design. There are instances where I do require throwing exceptions. In these cases stack trace information is serialized to the client. I don't think this is a good idea. What is the best way to hide the detail? Or is the answer to return a "Return" object (the example I gave of this was CampaignMonitors api example). – Ryan Tomlinson Jun 19 '09 at 18:25
  • @Ryan: work through all combinations of the customeError tag in web.config. I believe one of them turns stack traces off. – John Saunders Jun 19 '09 at 18:29
  • @John: See comment on original question. Unfortunately not an option for me. – Ryan Tomlinson Jun 19 '09 at 18:38
0

I suppose that throwing exceptions is in general a better design pattern then returning a result. I suppose that you have to do is inside your web services to hide stack trace by applying the following pattern to each method exposed as web service:

public void MyWebServiceMethod() {
try
{

 ///Do something that may cause an error

} catch(Exception ex)
{ throw new ApplicationException("User friendly descritption of exception");

}

}

or you may also

catch(Exception ex) { throw ex; }

If you re-throw an exception, you will hide original stack trace from the clients of your web services.

Bogdan_Ch
  • 3,328
  • 4
  • 23
  • 39
  • @Bogdan: First, MS has deprecated ApplicationException way back in .NET 1.1. Use "Exception" instead. Second, I have the impression that the OP wants no stack trace at all. – John Saunders Jun 19 '09 at 17:50
  • 1
    @John, by ApplicationException I meant any custom exception. Ok, lets say it should be MyWebServiceException or something like this. Also, in fact it is not deprecated, and exceptions like System.Threading.WaitHandleCannotBeOpenedException still inherit from this. MS only tells that they dont think it is very valuable, but still what you use as the base class for your exceptions is naturally your own choice, that is also sometimes dictated by coding conventions you should obey in the current project. – Bogdan_Ch Jun 19 '09 at 18:14
0

I dont see why you can't do both? Catch the exception, log it (either to a DB or to a file), then return an error code. That way you have a graceful execution of the webservice call, and also notification of the error, and you have a spot elsewhere you can further debug.

James Hall
  • 6,469
  • 6
  • 27
  • 28
  • @James: sticking with the standard might be better. It provides for faults, so why not use them? Also, developers forget to check error codes. That's why exceptions were invented, and SOAP Faults are the web service version of exceptions. – John Saunders Jun 19 '09 at 18:30
  • As @John says, and I agree, exceptions are there to inform of a fault. Exceptions will be serialized into a SOAP fault. As a result returning an error code doesn't fit into the protocol very well. See below: http://msdn.microsoft.com/en-us/library/ds492xtk(VS.85).aspx – Ryan Tomlinson Jun 19 '09 at 18:36
0

If the web service will be consumed publicly, cyber-security red teams will love verbose error messages that allow interrogation of the infrastructure. Then we can target that server with specific exploits.(This is not a good thing). Your code will pop up in the issues register. The people suggesting using any default .NET exception messages in a public web service are just suggesting variations on a theme or disabling your diagnostic capability. Custom exception text that doesn't divulge how to attack the server is recommended.

K W
  • 1