I’ll provide some details about an integration issue I had to resolve, to allow a separate team consuming one of the web services my team created, and be able to consistently handle known custom exceptions.
Here is a brief description of the scenario:
- Team A created an ASP.NET web service to enable interaction with the corporate Yammer network.
- Team B leverages the service to provide social capabilities to some LOB applications
- In several scenarios, the service raises custom exceptions. ie: user not found, user is inactive, user cannot be null, etc.
- Team B handles those scenarios by catching the custom exceptions raised by the service and implementing fallback logic.
- Team B reported that under the same conditions (same code base and same arguments) they were able to successfully capture the custom exceptions in the Integration Environment, but they were unable to do so in Test and Staging environments.
- The service logic implements something like this:
public string SomeMethod(string arg1)
Throw New Exception("Something bad happened");
- If the service is consumed from the Integration Environment the result look like this:
<faultstring>System.Web.Services.Protocols.SoapException: Server was
unable to process request. ---> System.Exception: Something bad
happened at AYS17Sept2002.Service1.CallFault() in
--- End of inner exception stack trace ---</faultstring>
- If the service is consumed from the TST or STG environments, the result look like this:
<faultstring>Server was unable to process request. --> Something
- Team B was unable to catch the expected custom exception in TST and STG environments, hence the code failed to implement the fallback logic.
By looking at the results, and more specifically at the error message, it is clear that the same custom exception is being raised from the service, but it is not being delivered consistently to the client. After some research I found the MSDN article that explains this behavior, and it has to do with the way ASP.NET framework handles the SOAP exceptions.
Whenever the code within a web service raises an exception, ASP.NET catches that exception and transforms it into a SOAP Fault. Depending on the /configuration/system.web/customErrors/@mode setting in the web.config, the SOAP exception will contain more or less information:
- On setting tells ASP.NET not to add the stack trace information to any Faults.
- RemoteOnly causes the extra information to show up for clients on the same server and hides the information for remote users.
- Off setting tells ASP.NET to add extra information for all calls to the Web service.
This is the same behavior for ASP.NET web pages.
So after verifying this setting in all environments, I confirmed that <CustomErrors> was set to “Off” in Integration Environment, and “On” in all other environments, which makes sense from the deployment perspective.
With this in mind, the next step was to coordinate between the two teams on how to handle the custom exceptions consistently.
We assessed several options, each one with pros and cons:
- Modify the web service logic, adding additional details to the SOAP exception
- Instead of raising a custom exception from the web service, return a response code that could be interpreted and handled appropriately by the other application
- Create a separate web.config file only for the service, and set the <customErrors> mode to “Off”, and deploy to all environments
Using SOAP Faults