Caves Travel Diving Graphics Mizar Texts Cuisine Lemkov Contact Map RSS Polski
Trybiks' Dive Texts VB.NET The creator of this fault did not specify a Reason. YAC Software
  Back

List

Charsets

Charts

DBExpress

Delphi

HTML

Intraweb

MSTest

PHP

Programming

R

Rhino Mocks

Software

Testing

UI Testing

VB.NET

VCL

WPF

The creator of this fault did not specify a Reason.
I revisited the handling of exceptions in our WCF services recently. By default, we don't pass exception details back to the caller (includeExceptionDetailInFaults is set to False); well, except maybe in DEBUG builds. Anyway, it turned out that we need a bit more details when one of the service calls fails. The obvious solution is to implement fault contracts - something similar to what is described on Microsoft's pages (for instance, here).

The implementation is pretty easy and straightforward; And I wouldn't be writing this text if not for one tiny gotcha (tiny or not tiny - I wasted several hours on this).

Consider the code below - code on the server-side of the service. and let's assume that we have a class that will be passed as the fault - MathFault (just like in the document referenced above).
  Try
    ' server-side implementation of the service
    . . .
  Catch ex As DivideByZeroException
    ' do whatever you need to do on the server-side to handle this exception
    . . .
    ' and pass the fault to the client (as a strongly-typed object):
    Dim mathFault As New MathFault()
    mathFault.ProblemType = "Division by zero."
    Throw New FaultException(Of MathFault)(mathFault)
  End Try
The problem is that, if you debug this code, and an exception is thrown in the Try..Catch block, a new exception will be thrown in the Throw New line (the last line before the End Try):

FaultException'1 was unhandled by user code
The creator of this fault did not specify a Reason.

Come again? I just did what the MSDN documentation suggested! After reading a bit more, I added a Reason (a text description of the fault) to the original Throw New code... This fixed the exception, but something kept nagging me - I didn't need the text reason for anything - already had the fault type itself and the description in ProblemType...

So, first, it turns out that you can safely ignore this exception when executing your code. The exception is just an internal, to WCF, mechanism to handle those faults that... don't provide a SOAP text reason for the fault! Nothing more, nothing less. The exception is reported by Visual Studio because it's configured to show all exceptions by default, but then the exception is handled internally by WCF.

Note that on the client-side, you can get to the fault class (with all its DataMember properties) via FaultException's Detail property:
  Try
    ' call to the service proxy on the client-side
    . . .
  Catch ex As FaultException(Of MathFault)
    logger.Log(ex.Detail.ProblemType)
  End Try
So what's all this about not specifying a Reason? Well, basically, if the server-side is responsible for providing text descriptions to the caller about encountered problems, then the Reason is a standard way of passing that information through service calls.

One way to do that is to just add a text message to the FaultException's constructor call:
  Try
    ' server-side implementation of the service
    . . .
  Catch ex As DivideByZeroException
    ' do whatever you need to do on the server-side to handle this exception
    . . .
    ' and pass the fault to the client (as a strongly-typed object):
    Dim mathFault As New MathFault()
    Throw New FaultException(Of MathFault)(mathFault, "Division by zero.")
  End Try
This reason is passed as a separate property of the FaultException - Reason:
  Try
    ' call to the service proxy on the client-side
    . . .
  Catch ex As FaultException(Of MathFault)
    logger.Log(ex.Reason)
  End Try
Note that we're getting the Reason directly from the exception, not the Detail part of the exception.

And, finally, let's return to the original "The creator of this fault did not specify a Reason." exception. If a reason is not specified, the only thing that happens is that FaultException's Reason is just set to this default message.

And that's it...

Top

Comments
#1
Paul wrote on 2012-06-26 22:57:53
this helped me. thanks for taking the timeout to write this.

Top

Add a comment (fields with an asterisk are required)
Name / nick *
Mail (will remain hidden) *
Your website
Comment (no tags) *
Enter the text displayed below *
 

Top

Tags

VB.NET


Related pages

AssertWasCalled and Methods Called Multiple Times

AssertWas[Not]Called and Object Properties

Rhino Mocks's AssertWasNotCalled

PrivateObject and Out/ByRef parameters

PrivateObject, WithEvents, and generics

Accessing private members of base classes

CA1800:DoNoCastUnnecessarily

PrivateObject and WithEvents

Accessing private and protected members - PrivateObject and PrivateType

Saving / restoring window placements in .NET

Checking Property Change Notifications

Rhino Mocks's AssertWasCalled in VB.NET

First steps with Rhino Mocks (in VB.NET)

Meaningful identifiers

Public fields vs. properties