I am currently using a C# .NET Service in our client program. As part of the server design, several custom made exceptions are thrown to indicate specific errors (as in any normal desktop program).
The problem is that the Web Service catches these errors and serializes them into a FaultException, with the actual exception (like NoRoomsAvailableException) written in the Message field.
My question is whether there is a best practice for handling these errors. We have just begun working on this, and we would probably do some text pattern matching to pull out the exception type and error message, but it seems like a hacky way to do it, so any "clean" way of doing it would be much appreciated.
The proper way would be to define fault contracts. For example in your web service you could do the following:
[DataContract]
public class NoRoomsAvailableFaultContract
{
[DataMember]
public string Message { get; set; }
}
Next you declare this contract for a given service operation
[ServiceContract]
public interface IMyServiceContract
{
[OperationContract]
[FaultContract(typeof(NoRoomsAvailableFaultContract))]
void MyOperation();
}
And you implement it like so:
public class MyService : IMyServiceContract
{
public void MyOperation()
{
if (somethingWentWrong)
{
var faultContract = new NoRoomsAvailableFaultContract()
{
Message = "ERROR MESSAGE"
};
throw new FaultException<NoRoomsAvailableFaultContract>(faultContract);
}
}
}
In this case the NoRoomsAvailableFaultContract will be exposed in the WSDL and svcutil.exe could generate a proxy class. Then you could catch this exception:
try
{
myServiceProxy.MyOperation();
}
catch (FaultException<NoRoomsAvailableFaultContract> ex)
{
Console.WriteLine(ex.Message);
}
darin has the correct answer. I'll only say explicitly what he implies: web services do not pass exceptions. They return SOAP Faults. If you define your faults properly, as he does, then you get to throw FaultException<fault>. This will become a SOAP Fault with fault in the detail element. In the case of a .NET client, this will then be turned into a FaultException<fault>, which you can catch.
Other platforms may handle this somewhat differently. I've seen IBM's Rational Web Developer generate Java proxy code that creates a separate exception for each declared fault. That was a version before Java generics, so maybe by now it does the same thing as .NET does.
Related
I'm working on a distributed system composed of multiple services (processes) working together orchestrated via message broker (service bus). Some of these service are very time sensitive, so we had the idea of using the bus the propagate exceptions to a service that would be used as a central point to log (to a database/on disk) the exceptions of all other services in order not to create latency in our services because we know sending a message is faster than writing on disk. So using NLog, I create a new target for sending exceptions on bus and redirect all service exception handling to it.
It works fine for basic framework exceptions, but of course some exceptions can be pretty complex objects. When using different libraries, not only are some exception not serializable (ex: IronPython), but more importantly our ExceptionLogger service don't have reference to every external dll used by every other endpoints, so it can't instantiate the typed exception.
Here's a few idea that I had to fix my problem, but none work:
Have the exception logger service reference every dlls used by the other services. In my opinion this is not clean, pretty overkill and still don't handle the case of exceptions that can't even be serialized and passed on the bus.
Creating a custom class that doesn't inherit from exception to pass only the data (as Antony Booth method here: How to serialize an Exception object in C#?). Problem with this is that when I receive an instance of this class on my exception logger endpoint and want to trigger a log, I can't create a new Exception() from it to create a NLog LogEventInfo object.
Transform the specially typed exception to a base native Exception type before sending it on the bus. This way, I lose some information, but I would keep the Message, Stacktrace and the InnerException stack, which is pretty much everything I need. Unfortunately, I did not find a way to do it and don't think it is possible.
That makes me question the relevance of the whole idea, am I simply going into a wrong path?
Option 4. Create an Exception assembly to store all of the custom exception types within your organization and reference that assembly in every other service. It's a centralized store of Exceptions.
[Serializable]
public sealed class SerializableException : Exception
{
public SerializableException()
{
}
public SerializableException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
public SerializableException(Exception exception)
: base(exception.Message, exception.InnerException == null ? null : new SerializableException(exception.InnerException))
{
_data = exception.Data;
HelpLink = exception.HelpLink;
HResult = exception.HResult;
Source = exception.Source;
_stackTrace = exception.StackTrace;
}
public override IDictionary Data { get { return _data; } }
public override string StackTrace { get { return _stackTrace; } }
private readonly IDictionary _data;
private readonly string _stackTrace;
}
Our company is making the switch from Microsoft.Practices.Enterprise.Library logging and exception handling to using Log4Net. I removed all of the standard logging and exception handling calls, replacing them with the Log4Net equivalents, but when I removed the Practices Dlls, I noticed that we were using them for ExceptionShielding:
using System;
using System.ServiceModel;
using Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.WCF;
namespace CRM.WCFServices.LeadIntegration.ServiceContracts
{
/// <summary>
/// Interface for systems external to CRM to interact with outbound calls.
/// </summary>
[ExceptionShielding("WCF Exception Shielding")]
[ServiceContract]
public interface IOutboundIntegrationService
{
#region Contracts
[OperationContract]
[FaultContract(typeof (Common.Services.WCF.FaultContracts.ServiceFault))]
void SendOutboundData(string entityName, Guid entityId, DateTime modifiedOn, Guid modifiedBy,
string crmOrganization);
#endregion
}
}
The basic question is "How can I safely remove it?" which involves answering most of these questions:
What does it do? - From What I've read it allows you to catch any exceptions in your WCF Service before it is returned to the client, allowing you to log the exception and create an exception that doesn't contain any security sensitive information.
Is it valid on an Interface (it's not referenced anywhere on the ?
Does Log4Net have something similar?
If I remember correctly, the purpose of the Exception Shielding feature was to
Prevent the release of implementation detail across the service boundary, or
Allow the developer to be lazy and not add try/catch blocks around all service operations at the service boundary.
Make your choice.
If my memory is correct, then all you need to do is either turn includeExceptionDetailInFaults to false in the web.config, or to put try/catch blocks around your service methods:
try
{
// service code
}
catch (Exception ex)
{
// Log the exception
throw new FaultException("Unknown service failure");
}
So I'm designing a Web Service and of course; I need this Service to automatically write to a Database. Which is quite straight forward; but obviously Sql has a tendency to not play nice.
Which pretty much creates a nightmare when troubleshooting, not to mention through a Web Service would make it even more of a nightmare to debug.
So I checked the internet and stumbled across an article on Stack Overflow that talked about a SqlHelper Class that essentially had a massive list of these:
public static bool IsDuplicateId(SqlException sex)
{
return (sex.Number == 2601);
}
So that implementation would be tedious, as you'd have to call all of these Methods. However, someone answered with:
switch (e.Number)
case 2601:
// Do Something
break;
default:
throw;
So I thought why not create a Class to handle a majority of these possible errors. With this particular implementation in mind:
public class SqlExceptionHelper
{
public SqlExceptionHelper(SqlException sqlException)
{
// Do Nothing.
}
public static string GetSqlDescription(SqlException sqlException)
{
switch (sqlException.Number)
{
case 21:
return "Fatal Error Occurred: Error Code 21.";
case 53:
return "Error in Establishing a Database Connection: 53.";
default
return ("Unexpected Error: " + sqlException.Message.ToString());
}
}
}
So my thought process is I have a Class that can be reused to detect some common errors; and in other classes I simply using SomeNamespace.ExceptionHelpers; I could implement something like so:
public class SiteHandler : ISiteHandler
{
public string InsertDataToDatabase(Handler siteInfo)
{
try
{
// Open Database Connection, Run Commands, Some additional Checks.
}
catch(SqlException exception)
{
SqlExceptionHelper errorCompare = new SqlExceptionHelper(exception);
return errorCompare.ToString();
}
}
}
So essentially it should handle all those lovely exceptions; but I started thinking which isn't good. Is returning such Exceptions as a return good? Can that in itself be bad? Or is this really the best way to handle such Exception catching through a Service?
So my question boils down to:
Is this the best way to handle error catching through a Service?
Thank you for the help.
Ideally web services should return relevant HTTP status codes, not exceptions. These are usually in the 200's (for OK), 400's (for errors that the user can fix themselves), or 500's (for server errors - these can be auto-retried too).
Based on your database error you get back, you can translate this to the appropriate HTTP status code. The description of the error code could be set to the exception message if you think it will help the user.
Assume that I am building an ASP.NET Web API application and it has the following structure:
As you can see from the diagram, the ASP.NET Web API core will talk to domain service layer (e.g. MembershipService class which has methods such as GetUsers, CreateUser, etc.) and my service classes will talk to one or multiple repositories to handle the operations.
It's very obvious that a service operation (such as MembershipService.CreateUser method) would fail for several reasons (unmet conditions, an exception thrown by the repository, etc.) and this is the place where I have the doubts.
Do you think that service classes should handle exceptions and return some sort of result object such as the below one:
public class OperationResult {
public OperationResult(bool isSuccess) : this(isSuccess) {
IsSuccess = isSuccess;
}
public OperationResult(bool isSuccess, Exception exception) : this(isSuccess) {
Exception = exception;
}
public bool IsSuccess { get; private set; }
public Exception IsSuccess { get; private set; }
}
public class OperationResult<TEntity> : OperationResult {
public OperationResult(bool isSuccess)
: base(isSuccess) { }
public OperationResult(bool isSuccess, Exception exception)
: base(isSuccess, exception) { }
public TEntity Entity { get; set; }
}
Or do you think that the service methods shouldn't abstract the exception like that and should throw the exception directly or indirectly (creating a new meaningful exception type specific to operation and put the thrown exception as its inner exception)?
When you are in-process, use exceptions.
I don't see ANY point in avoiding exceptions. Exceptions are there for good reasons, mainly to be used!
Just try to look at the big picture: you are trying to change Exception mechanism with the old fashion way of error checking. This way you'll lose all the merits of Exceptions (like separation of the error-handling and regular code, CallStack, ...) and gain nothing in return.
What I usually do in this situation is to catch the exception in service layer and rewrap it into a custom exception (with the reference to the original exception in the InnerException field).
Taking a page from Microsoft's book, the implementation of the Membership API throws exceptions rather than handling them and returning a result object, so I would consider this a best practice as long as you don't control both the client and the API.
In the case where you do control both the client and the API, it is my personal preference to return a result object or an error message. The reason for this is that I want to log capture detailed information about the source of actual exceptions, but I don't want an exception for everything that could go wrong, such as the password being incorrect.
In this case, a simple error message to the user will be more than sufficient. From real-world experience, recording exceptions to the event log or log file every time a validation error occurs is a major burden on operations personnel that are trying to determine whether or not there is an actual fault occurring or whether it is just a user's typo.
I have a program that calls an external web service, and I want to present the user with a friendly dialog if e.g. the server is down, someone cut the cable etc. Assuming the following code
try {
client.MyWebService()
}
catch(? ex)
{
// display friendly dialog explaining what went wrong
}
what exception(s) should I put in place of the question mark in the code? It is kind of hard to actually test situations like this when everything is working smoothly and I have no control over the external part, so some insight would be appreciated.
Thanks!
The first thing to do is take advantage of the .Faulted event on your proxy, which you can wire up like this:
((ICommunicationObject)client).Faulted += new EventHandler(client_Faulted);
In your client_Faulted event handler you can then try re-connecting, or shifting to a backup server, or disabling the UI, logging the error, or displaying a message there.
It's obviously still good practice to wrap each call in a try-catch as well, but the .Faulted event can let you deal with most channel problems even earlier.
As for the exception itself, you can have your service throw a FaultException that gets passed back to the client with the details you provide. See an example of its use at this blog posting.
You won't get a FaultException if the channel itself fails (FaultException is a way for the server to communicate its own internal faults to the client).
For channel faults, you may get a CommunicationException or TimeoutException.
Finally, take a look at this project on Codeplex for generating Exception Handling WCF proxies. It may give you a more flexible way of handing faults.
It's not really the client's job to provide as much detail as possible. The maximum amount you really have to provide at the client side is as much as you get back in your exception.
var userName = "bob";
try
{
client.MyWebService(userName);
}
catch(Exception ex)
{
//Maybe we know WellKnownExceptions and can provide Foo advice:
if (ex is WellKnownException)
{
Console.WriteLine("WellKnownException encountered, do Foo to fix Bar.");
}
//otherwise, this is the best you can do:
Console.WriteLine(string.Format(
"MyWebService call failed for {0}. Details: {1}", userName, ex));
}
I was asking the same question, as I have to implement some exception handling on web services calls at my client application, so I ended up here. Although it's an old question, I'd like to give my two cents, updating it a little bit.
The answer given by C. Lawrence Wenham was already very good and points to some interesting information, although the blog link is broken and Codeplex is now archived.
I found those articles very valuables:
Sending and Receiving Faults
https://learn.microsoft.com/en-us/dotnet/framework/wcf/sending-and-receiving-faults
Expected Exceptions
https://learn.microsoft.com/en-us/dotnet/framework/wcf/samples/expected-exceptions
And this article from Michèle Leroux Bustamante (apparently the creator of the Exception Handling WCF Proxy Generator CodePlex project) is very insighful also:
An Elegant Exception-Handling Proxy Solution
http://www.itprotoday.com/microsoft-visual-studio/elegant-exception-handling-proxy-solution
I'm still studying the subject but I guess I'll use a lot of ideias from Michèle. I'm just a little bit concerned about using reflection to call the web service's methods, but I wonder if this would have any impact in such kind of operation, that is inherently slow already.
Just to answer here explicitly what was asked originally, which are the exceptions that could be tested against a web service call:
string errorMessage = null;
// A class derived from System.ServiceModel.ClientBase.
MyWebService wcfClient = new MyWebService();
try
{
wcfClient.Open();
wcfClient.MyWebServiceMethod();
}
catch (TimeoutException timeEx)
{
// The service operation timed out.
errorMessage = timeEx.Message;
}
catch (FaultException<ExceptionDetail> declaredFaultEx)
{
// An error on the service, transmitted via declared SOAP
// fault (specified in the contract for an operation).
errorMessage = declaredFaultEx.Detail.Message;
}
catch (FaultException unknownFaultEx)
{
// An error on the service, transmitted via undeclared SOAP
// fault (not specified in the contract for an operation).
errorMessage = unknownFaultEx.Message;
}
catch (CommunicationException commEx)
{
// A communication error in either the service or client application.
errorMessage = commEx.Message;
}
finally
{
if (wcfClient.State == CommunicationState.Faulted)
wcfClient.Abort();
else
wcfClient.Close();
}
As stated by the articles, the order the exceptions are catched is important, since FaultException<TDetail> derives from FaultException, and FaultException derives from CommunicationException.