I\'m implementing a RESTful web service using WCF and the WebHttpBinding. Currently I\'m working on the error handling logic, implementing a custom error handler (IErrorHand
Here's the solution I came up with:
Catching exceptions from WCF Web Services
Basically, you get your web service to set a OutgoingWebResponseContext
variable, and return null
as the result (yes, really !)
public List<string> GetAllCustomerNames()
{
// Get a list of unique Customer names.
//
try
{
// As an example, let's throw an exception, for our Angular to display..
throw new Exception("Oh heck, something went wrong !");
NorthwindDataContext dc = new NorthwindDataContext();
var results = (from cust in dc.Customers select cust.CompanyName).Distinct().OrderBy(s => s).ToList();
return results;
}
catch (Exception ex)
{
OutgoingWebResponseContext response = WebOperationContext.Current.OutgoingResponse;
response.StatusCode = System.Net.HttpStatusCode.Forbidden;
response.StatusDescription = ex.Message;
return null;
}
}
Then, you get your caller to look out for errors, then check if a "statusText" value was returned.
Here's how I did it in Angular:
$http.get('http://localhost:15021/Service1.svc/getAllCustomerNames')
.then(function (data) {
// We successfully loaded the list of Customer names.
$scope.ListOfCustomerNames = data.GetAllCustomerNamesResult;
}, function (errorResponse) {
// The WCF Web Service returned an error
var HTTPErrorNumber = errorResponse.status;
var HTTPErrorStatusText = errorResponse.statusText;
alert("An error occurred whilst fetching Customer Names\r\nHTTP status code: " + HTTPErrorNumber + "\r\nError: " + HTTPErrorStatusText);
});
And here's what my Angular code displayed in IE:
Cool, hey ?
Completely generic, and no need to add Success
or ErrorMessage
fields to the [DataContract]
data which your services are returning.
In the latest version of WCF (As of 11/2011) there's a better way of doing this using WebFaultException. You can use it as follows in your service catch blocks:
throw new WebFaultException<ServiceErrorDetail>(new ServiceErrorDetail(ex), HttpStatusCode.SeeOther);
[DataContract]
public class ServiceErrorDetail
{
public ServiceErrorDetail(Exception ex)
{
Error = ex.Message;
Detail = ex.Source;
}
[DataMember]
public String Error { get; set; }
[DataMember]
public String Detail { get; set; }
}