Here I
talked about a technique to convert SOAP faults into JSON objects for AJAX
scenarios. The post was primarily around using WCF extensibility to
send back exception details as JSON object with a particular HTTP status code.
The code will only works with native XMLHttpRequest object or with a library
which returns bare HTTP response (Ext JS, jQuery etc).
Microsoft
AJAX library (generated JavaScript proxy) uses a well defined error format and
will not understand the custom format I have used. So it will just ignore our
custom error object and will return a generic error object to the onFailed callback.
For
our server side extensibility feature to work with Microsoft AJAX library, we
need to change our service's error format to match to the format expected
by Microsoft AJAX library which can easily be modelled using following
DataContract.
[DataContractFormat]
public class MicrosoftAjaxError
{
[DataMember]
public string Message { get;
set; }
[DataMember]
public string ExceptionType { get;
set; }
[DataMember]
public string StackTrace { get;
set; }
}
Now
from our handler, we need to send back an instance of MicrosoftAjaxError class
rather than our own error object. Here is the modified ProvideFault method.
public void ProvideFault(
Exception
error, MessageVersion version, ref Message fault)
{
if (error is FaultException)
{
// extract the our
FaultContract object from the exception object.
var detail =
error.GetType().GetProperty("Detail").GetGetMethod().Invoke(error,
null);
var msErrObject = new MicrosoftAjaxError { Message = "Fault exception...", ExceptionType =
detail.GetType().ToString(), StackTrace = error.StackTrace };
// create a fault
message containing our FaultContract object
fault = Message.CreateMessage(version,
"", msErrObject, new DataContractJsonSerializer(msErrObject.GetType()));
// tell WCF to use
JSON encoding rather than default XML
var wbf = new WebBodyFormatMessageProperty(WebContentFormat.Json);
fault.Properties.Add(WebBodyFormatMessageProperty.Name, wbf);
var rmp = new HttpResponseMessageProperty();
rmp.Headers[HttpResponseHeader.ContentType]
= "application/json";
rmp.Headers["jsonerror"] = "true";
rmp.StatusCode = System.Net.HttpStatusCode.BadRequest;
// put appropraite
description here..
rmp.StatusDescription = "See fault object for more information.";
fault.Properties.Add(HttpResponseMessageProperty.Name, rmp);
}
}