I would like to be able to access properties on the original exception that is thrown from a Consumer inside a Fault Consumer. For example, if the unhandled exception is a ValidationException with a collection of Errors, am I able to access that collection from a Fault Consumer?
The only thing I seem to have access to is the ExceptionType and the Message. I suppose I could parse the exception message to get the Errors collection, but is there a way to achieve this without parsing the message and generating the collection?
public async Task Consume(ConsumeContext<Fault<MyMessage>> context)
{
string exceptionType = context.Message.Exceptions[0].ExceptionType;
string exceptionMessage = context.Message.Exceptions[0].Message;
if (exceptionType == "FluentValidation.ValidationException")
{
// here I want to get the Errors collection on the exception of type ValidationException
}
}
MassTransit does not serialize Exception, it encapsulates the exception details in an ExceptionInfo type that is included with the Fault event.
There is no access to the original Exception type, and for good reason. Serializing exceptions as part of a message contract is just bad practice, in my opinion.
Related
I want to get back good error info from a WebApi action, so if there's an exception, I do this:
catch (Exception e)
{
return Content(HttpStatusCode.InternalServerError, e);
}
In another WebApi which consumes the first one, I do this so that I can view that exception, in case of an error:
if (response.IsSuccessStatusCode)
{
return await response.Content.ReadAsJsonAsync<MyModel>();
}
Exception x = await response.Content.ReadAsJsonAsync<Exception>();
// ...look at exception information
The problem is that it's not being serialized/deserialized correctly. Specifically, I'm not getting the array of Error objects in the deserialized Exception object, nor am I getting the StackTrace. It looks like the object is getting serialized incorrectly, so it won't deserialize into the Exception object. For example, the StackTrace property is coming across the wire as "StackTraceString." Obviously, that's not going to deserialize into a property called "StackTrace."
Anyone know why some of the property names are changed when serializing?
Let's say my function is the following:
public static void Run([QueueTrigger(queueName, Connection = connection)]string message,
TraceWriter logger) {
throw new CustomException();
}
Here's what the log looks like:
SomeTime [Error] ExceptionNameSpace.CustomException ---> System.Exception
When I go to App Insights and view the exception breakdown, I find this failed request under the "Exception" type. I don't even see a CustomException type listed! Why is my exception being transformed into a generic exception?
For those of you who ran into the same issue:
I found the "solution" for this by being able to recover my original exception by querying for the outerType column in the exceptions table inside the Analytics part of App Insights. Strange that the generic exception shows up under the "type" column but "outerType" is my original exception.
Is there anyway to capture handled exceptions when CreateErrorResponse() is used to return Error response with API methods?
I currently have registered a simple global exception loggger for any exceptions, however for some api responses including Model Filter attribute, I'm CreateErrorResponse() to return error responses but this doesn't to enter the Log() method in the Global Exception Logger.
Example usage of CreateErrorResponse in an API method :
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e);
Global Exception Logger:
public class GlobalExceptionLogger : ExceptionLogger
{
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
public override void Log(ExceptionLoggerContext context)
{
log.Error(context.Exception);
}
}
The only way to get Log() method to be called is rather than use CreateErrorResponse, throw an Exception instead.
Is this correct?
You should log the error and any trace info in the same negative flow where you are constructing and returning the Error Response.
Using exceptions to control application flow is bad practice, avoid it.
The global handlers use is to handle anything that you haven't already handled and should be for Very exceptional cases, you also log there and present the user with a generic error message, while you sort out the chaos in the back of course :)
If I misunderstood your question please correct me.
I have been debugging an issue with my newly minted WCF services Fault contract and finally found out what was breaking it.
I defined the service like so:
[ServiceContract]
public interface IService1
{
[OperationContract]
[FaultContract(typeof(ApplicationException))]
string GetData();
}
in my service I was handling exception in the service like so:
public string GetData()
{
try
{
// do stuff
}
catch(Exception e)
{
ApplicationException ae = new ApplicationException("oh dear!", e );
throw new FaultException<ApplicationException>( ae,
new FaultReason(ae.Message));
}
}
However, the client would never receive the fault exception, instead it would get an exception which said:
An error occurred while receiving the HTTP response to ... This could
be due to the service endpoint binding not using the HTTP protocol.
This could also be due to an HTTP request context being aborted by the
server ( possibly due to the service shutting down).See server logs
for more details
If I changed my code on the service like so (ie: do NOT set the inner exception when constructing the ApplicationException) it works as expected.
public string GetData()
{
try
{
// do stuff
}
catch(Exception e)
{
ApplicationException ae = new ApplicationException("oh dear!");
throw new FaultException<ApplicationException>( ae,
new FaultReason(ae.Message));
}
}
Can anyone explain why this might fail if the inner exception is set? I could not see it anywhere in the documentation.
When the ApplicationException is sent to the client via FaultException<T> without the InnerException, then it is sent only as a string. However, when the InnerException is set, then the ApplicationException itself is sent.
The Exception type is serializable in .NET (it is often incorrectly cited as not being serializable), however, frequently the contents of the Data property are not serializable. This will cause a serialization issue which is what I believe you are experiencing.
There are a few workarounds to this issue: You can set the Data property to null by using reflection or you can create your own class.
I have inherited a code-base which uses a compiled logging library. I cannot update the logging library. This library has method that logs details for an Exception. The method takes a single Exception as a parameter. I'm now building a mobile application that will tie into this system.
In this mobile application, I have a block of code that handles uncaught exceptions. I need to log those in the server. But now, I can only pass the details across the network in string format. Because of this, I have a service that accepts an error message, stack trace, and miscellaneous as strings. I need to take these strings and convert them into an Exception so I can pass them to my pre-existing library.
How can I take a message and a stackTrace as strings and bundle them into an Exception? The challenge here is Message and StackTrace are read-only.
Thank you!
StackTrace is virtual so you can define your own Exception like so:
public class MyException : Exception {
private readonly string stackTrace;
public override string StackTrace { get { return this.stackTrace; } }
public MyException(string message, string stackTrace) : base(message) {
this.stackTrace = stackTrace;
}
}
and then pass instances of MyException to your logging code. This gives you complete control over the value of Message and StackTrace.
Exceptions should be serializable, so you could try serializing the data. Then you can de-serializable it later on and you should have the same exception.
I think the SoapFormatter should allow you to send it over a network, or at least give you a string representation.