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.
Related
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.
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'm writing a WCF Service, and was wondering if there is a recommended pattern for returning various messages from a service method.
For example, if I call the public User Login(string userName, string passWord) method in my service, I want it to return my user object when they are valid users. However, if the details are not correct, or the account is disabled, I want to be able to return that data to the client.
I initially thought I would throw a LogonFailureException (custom exception class) when one of these two scenarios occurred. In the client, I could then catch this type and process it as I wanted. However, if I'm debugging the application, it breaks when the exception is thrown (even if I wrap it in a FaultException).
I could also create a ServiceResponse class that all my methods use as a return type - in there I could then have a "Messages" collection, but that seems potentially counter-intuitive. I'd rather the returntypes of my methods were simply what I expect to get back in normal circumstances.
So, bottom line, is there a particular pattern of dealing with messages coming back from the service method that is recommended?
Thanks
You need to throw a strongly-typed soap fault:
[DataContract]
public class ConnectionFault
{
[DataMember]
public string Issue { get; set; }
[DataMember]
public string Details { get; set; }
}
[FaultContract(typeof(ConnectionFault))]
[FaultContract(typeof(DataReaderFault))]
[OperationContract]
Int16 GetInStock(int productId);
//when it's time to throw the exception
var connectionFault = new ConnectionFault();
connectionFault.Issue = "Problem connecting to the database";
connectionFault.Details = ex.Message;
throw new FaultException<ConnectionFault>(connectionFault);
Then the client can catch it.
In my opinion, There are 2 scenarios.
1. You wish to throw a sort of exception on the Service side.
2. You wish to return a class that contains error data of something went wrong in Service.
What is the difference ? The first would be just like yaron wrote, you throw and catch a FaultException.
The second would be just to return an object, for example if something went wrong in your service, you always return ErrorData - this is a data contract that contains message and exception stack as string - you can add ErrorData.Update method, and every time you catch a new exception in service, update the ErrorData message.. this is good for long running calls that might catch several exception but you dont want to abort on the first one.
No matter which of these you choose, DO NOT INHERIT from Exception, I have read this is bad practice, you dont want to serialize and transfer Exception based data contracts over WCF.
When throwing a FaultException<CustomFault> like this:
throw new FaultException<CustomFault>(new CustomFault("Custom fault message"));
I get the following: "The creator of this fault did not specify a Reason."
Now according to this MSDN article one isn't required to use the FaultReason
I have the following Service Contract:
[OperationContract]
[FaultContract(typeof(CustomFault))]
CustomType[] SomeMethod(int someParameter);
[DataContract]
public class CustomFault
{
private string report;
public CustomFault(string message)
{
this.report = message;
}
[DataMember]
public string Message
{
get { return this.report; }
set { this.report = value; }
}
}
There is a comment on the MSDN article that suggest it is mandatory to use the other FaultReason, but in several other places I have seen people arguing that you shouldn't use the FaultReason unless necessary.
So my question is as follows; is it really mandatory to use the FaultReason and if not - how can i prevent the exception raised when trying to throw a FaultException?
EDIT
By running the sample project from this article I get the excact same behavior. Maybe it's caused by an update in .NET an the documentation/samples not being updated.
The fault reason is required while the details are optional.
WCF uses the value of the FaultException.Reason property to populate the <faultstring> element of the SOAP Fault, which is required by the SOAP specification:
faultstring
The faultstring element is intended to provide a human readable explanation of the fault and is not intended for algorithmic
processing. [...] It MUST be present in a SOAP Fault element and
SHOULD provide at least some information explaining the nature of the
fault.
Hence, you must provide a reason for the fault when throwing a FaultException from a WCF service.