This is the follow up post on my
previous one, about writing a custom ExceptionHandler that serializes the real exception object into the detail element of a SoapException.
I will only look into the override of HandleException of the SoapClientExceptionHandler since everything else is the same as for SoapServerExceptionHandler.
///
/// Replaces the exception with the serialized exception in .
///
/// The original exception.
/// The name of the
/// The unique ID attached to the handling chain for this handling instance.
/// Modified exception to pass to the next handler in the chain.
///
/// The handler will not do anything if the exception isn't a or if the
/// SoapException.DetailSoapException.Detail doesn't contain a serialized exception.
///
public override Exception HandleException(Exception exception, string policyName, Guid handlingInstanceId)
{
SoapException soapEx = exception as SoapException;
if (soapEx == null) return exception;
Exception ex = null;
XmlReader reader = null;
XmlWriter writer = null;
System.IO.MemoryStream stream = new System.IO.MemoryStream();
try
{
SoapFormatter formatter = new SoapFormatter();
reader = new XmlNodeReader(soapEx.Detail.ChildNodes[1]);
writer = new XmlTextWriter(stream, System.Text.Encoding.UTF8);
writer.WriteNode(reader, true);
writer.Flush();
stream.Position = 0;
ex = formatter.Deserialize(stream) as Exception;
}
finally
{
if (reader != null)
reader.Close();
if (writer != null)
writer.Close();
((IDisposable)stream).Dispose();
}
if (ex == null) ex = exception;
return ex;
}
This method gets the serialized exception out from the detail element, by first getting it into a stream object which is sent to the Deserialize method of the SoapFormatter. This method could definitely be better by not making so many assumptions that it only will be called with SoapExceptions that have been created by the SoapServerExceptionHandler. For example by checking that is has the required child node and by handling exceptions that could occur when Deserialize is called, but I leave that to you as a reader (Sunday lazy me ;-).
In the configuration of the client I set up a "Soap Policy" where all SoapExceptions will be handled by SoapClientException and to throw new exception. The effect of using the combination SoapServerExceptionHandler and SoapClientExceptionHandler is that I could write excpetion handling in the client like I use to (that is catching specific exceptions like BusinessRuleException).
catch (IRM.BusinessRuleException ex)
{
this.databindingSource.Merge(ex.DataSet);
}