SoapServerException.HandleException() - c#

I'm confused about how this method is actually handling the exception that is passed to it, it doesn't appear to do anything extra.
I have it in a segment of my code as it was the standard being used in one of the examples I looked at the other day but I've since found that it seems to eat my Exception messages so I am left with the generic SoapServerException with no InnerException.
// "Exception of type 'Microsoft.SharePoint.SoapServer.SoapServerException' was thrown."
catch (Exception ex)
{
throw SoapServerException.HandleException(exception);
}
// "Server was unable to process request. ---> Error in MyService.asmx --->
// Could not load file or assembly 'That.Assembly.I.Forgot' or one of its dependencies."
catch (Exception ex)
{
throw new Exception("Error in MyService.asmx", ex);
}
Is there a reason I should throw SoapServerException.HandleException() instead of my own more descriptive exception?

Per: http://msdn.microsoft.com/en-us/library/gg552614(v=office.14).aspx#bestpractice_infodisc
SoapServerException.HandleException() is intended to reduce the details returned to the user for security reasons. So this behavior is intentional.
The documentation for this method: http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.soapserver.soapserverexception.handleexception.aspx
doesn't really explain what this method does as at all, which is unfortunate. If you deliberately want to provide more details to the user, then you should use your own exception. But be careful about providing such details. It may not be a good idea for security reasons. It really depends on how much you trust/know the party you are sending the error to.
-Dave

Related

C# catch(FileNotFoundException) and CA1031

So this code triggers CA1031.
try
{
// logic
}
catch (FileNotFoundException) // exception type
{
// handle error
}
While this one does not:
try
{
// logic
}
catch (FileNotFoundException ex) // exception var
{
// handle error
}
Because the exception type is meaningful, I don't need the ex in the first example. But it's not a a general exception type. It's not IOException or Exception. So why does it still trigger the CA1031?
So is there a difference between catch(FileNotFoundException) and catch(FileNotFoundException ex) outside the fact that I don't capture exception info?
So this code triggers CA1031
try
{
// logic
}
catch (FileNotFoundException) // exception type
{
// handle error
}
This occurs because a "general exception such as System.Exception or System.SystemException is caught in a catch statement, or a general catch clause such as catch() is used". To fix it, assign it and handle the error and or rethrow the general exception for it to be handled further up.
Upon further investigation, it seems this used to be an bug, you can see more here; it was a Roslyn issue for FxCop.
To Fix:
Just update the latest FxCop analyzers package and it should go way.
NuGet:
Install-Package Microsoft.CodeAnalysis.FxCopAnalyzers -Version 2.9.7
References:
CA1031
I have two Articles I use as basis for my Exception handling:
https://blogs.msdn.microsoft.com/ericlippert/2008/09/10/vexing-exceptions/
https://www.codeproject.com/Articles/9538/Exception-Handling-Best-Practices-in-NET
I also link those often when I notice Exception handling errors.
FileNotFound is clearly a exogenous Exception, so it is correct to catch it. However those articles also tell that as a general rule, to always log or expose those Exceptions. Ideally the result of Exception.ToString(). If you do not have a way to reference the caught exception, how could you do either of those two? You can only give a generic error message, but with none of the details you will actually need to debug it.
While there are many cases where you only want to expose the Exception type to the user, there is never one where you only want to log the Exception type. The linked articles mention that explicitly, but due to downvotes and comments it seems nessesary for me to repeat that.
So it is one of those cases where the argument is still going if it is a bug or a feature.
For me it certainly feels more like a feature. I would certainly call you out as potentiall issue, if I saw it in your code. It avoids you under-logging stuff. You could test if the error persist if you write throw; at the end of the catch block. This will re-throw on the exception, so a lack of being able to reference the exception in this ExceptionHandler would not be critical.

try-catch for logging purposes?

According to this answer: https://stackoverflow.com/a/1722991/680026
you should only use try-catch if you really do something there besides logging:
Don't catch an exception if you're only going to log the exception and
throw it up the stack. It serves no meaning and clutters code.
But what about logging information that are not available at the higher level?
eg:
private void AddSomethingToTable(string tablename, string fieldname) {
try {
InsertFieldToTable(tablename, fieldname);
} catch (Exception ex) {
log.ErrorFormat("Could not insert field '{0}' into table '{1}'", fieldname, tablename);
throw;
}
}
private void main() {
try {
AddSomethingToTable("users","firstname");
AddSomethingToTable("users","lastname");
AddSomethingToTable("users","age");
} catch (Exception ex) {
MessageToUser("Sorry. Saving did not work.",ex);
}
}
As you can see: In my (completely made up) example I log the information about the field that did cause the error. This could be some good information to start finding the error.
So even though I only logged the error, this information could be crucial and be lost outside that method.
Is this a valid use of try-catch here or are there other suggested ways to log that? (I don't think that just always logging this info (regardless if an error occurred or not) would be a valid solution)
I think you answered your own question with
But what about logging information that are not available at a higher instance
and
this information could be crucial and be lost outside that method
I dislike hard and fast "always do X and never Y", because there are times where it is necessary to go against so-called "best practice" in order to do what is best for your application.
If logging the information is necessary to fix the issue, and you lose this information if you don't log it immediately, then log the information.
There is nothing wrong in what you are trying to do. The idea of the other question/answer was that it is better to log the error at the place where you really handle it. In .NET every exception contains a stack trace. This means that upper layer can report location in the code that has generated this error. Doing that in one place instead of many is way more meaningful. This was their idea.
From your linked quesion:
The basic rule of thumb for catching exceptions is to catch exceptions if and only if you have a meaningful way of handling them.
I put emphasis on "The basic rule of thumb" as it's not a law. It's a best practice. i.e. follow it until you have a good motivation to not do so.
If you catch exceptions to include information you probably should throw a new meaningful exception with more context information. something like:
try
{
//kldfsdölsdöls
}
catch (Exception ex)
{
throw new MoreDetailedException("Text with context data", ex);
}
That way you'll get all context information for each stack level collected into the same exception (since you included the inner exception in it). Thus the log entry in the top level will contain ALL information in the same line.
But what about logging information that are not available at a higher
instance?
You can pass those information back to caller while re-throwing the exception
private void AddSomethingToTable(string tablename, string fieldname) {
try {
InsertFieldToTable(tablename, fieldname);
} catch (Exception ex) {
string str = string.Format("Could not insert field '{0}' into table '{1}'", fieldname, tablename);
throw new Exception(str, ex);
}
}
We use the Try Catch block in a similar way you have suggested and it works well for us.
We have implemented ELMAH https://code.google.com/p/elmah/ which is great for logging untrapped errors. With a line of code in the Try Catch block you can also write trapped exceptions into the log.
Catch ex As Exception
Elmah.ErrorSignal.FromCurrentContext.Raise(ex)
Return False
End Try
The error is handled (the relevant function returned false) and user doesn’t get the Yellow Screen of Death, and we can look up full details of any errors in the log.

Do I need to catch each individual exception type if I'm going to perform the same action?

Simply put, I don't expect this application to receive too many errors since it's a fairly controlled environment and the users are other developers.
Having said that, errors do happen sooner or later and I simply just want to keep a log of them and alert the user. I've got this method that tries to validate the information as best as it can, then it tries to copy a file from A to B.
try
{
File.Copy(source, destination, true);
return String.Empty;
}
catch (Exception ex)
{
logOp.AddLog(ex);
return string.Format("ERROR: {0}{1}{2}", ex.Message, Environment.NewLine, ex.StackTrace);
}
The method returns an empty string if it was successful, and if not it logs the exception and returns it to the calling method for presentation.
Do I need to catch each individual Exception type that File.Copy can throw if I want the most detailed Message / Stack trace, or will just catching Exception work? I tried hardcoding it to throw new instances of the various Exceptions and it seems OK but I wasn't sure if there was some programming principle I was missing/violating
Since all you're doing in exception handler is logging, then I'd say no, just take the Exception and log the message.
Catching individual exceptions would be useful if you attempted to recover from the error.
I would keep it as is and just catch the base class Exception.
Logging the ex.ToString() like you implicitly do in logOp.AddLog(ex) should write the actual type of the exception (which could be one of these that File.Copy method can throw in the Exceptions section here )
Based on that link, the name of the actual exception should be informative enough since you are not attempting to recover from the exceptions, just logging them.

How can I add a message to an exception without losing any information in C#?

I have the following code:
catch(Exception ex)
{
throw new FatalException("An error occurred while trying to load the XSLT file.", ex);
}
This unfortunately just swallows up the Exception. I can fix this by doing the following:
catch(Exception ex)
{
throw;
}
But I would still like to include the custom message for help with event logging.
How do I add this message to the exception without losing any information? (stack trace/debug symbols, etc.)
If you just need to add information to the original exception, such as a user-readable message or specific details that will be useful to you in tracking down the error but that won't be useful to the end user, you can make use of the Exception's Data property, which is a key/value pair dictionary.
We use this extensively in order to record information such as the report being executed or file that is being processed so that operations can determine what exactly was happening at the time of the error. The user doesn't need this detail since they are working directly with the cause of the failure.
You could also use this to pass a plain text message that makes sense to the user. The only issue is that you will have to perform some additional work in your logging framework or end-user interface in order to extract the data and make it useful to the consumer.
For example, you could do:
catch (Exception ex)
{
ex.Data.Add("UserMessage", "An error occurred while trying to load the XSLT file.");
throw;
}
Then in the client-side code, you could test to see if UserMessage exists and, if so, present it to the user instead of the Exception:
catch (Exception ex)
{
if (ex.Data.Contains("UserMessage"))
{
MessageBox.Show(ex.Data["UserMessage"].ToString());
}
else
{
MessageBox.Show(ex.Message);
}
}
That original Exception is still there.
When you do your Exception logging, the Exception that you receive will be the FatalException that you made with your message. The original Exception is in ex.InnerException. You can continue to cycle through InnerException until it's null to get all of the Stack Trace information, etc.
In short, don't.
I'm sure you could find some way of getting around this with some reflection, but I would strongly caution you against this. It goes against the original design of exceptions in .NET. Exceptions are not just there to help with logging, they provide information about the original cause of an application failure.
Using the first option is generally preferred as it maintains the stack trace of the original exception but allows you to provide additional information by wrapping it in a separate exception. In my own code, whenever I log exceptions, my logging function will recurse through the InnerException property to find every bit of useful information possible about the error.
Just in case someone needs a good answer. The key is to use AppDomain.CurrentDomain.FirstChanceException
The you can create a custom object with IDisposable to put all info in it. And if exception happens then FirstChanceException handler gets that info and populate Exception.Data.
Use Local Thread Storage to make it thread safe. Then down the line the code that catches it will get the data and log it.
Example:
using(MyCustomMessage.EnterToLocalStorage("Info for logging"") )
{
...code
...exception thrown
.... FirstChanceException examines local thread storage and get's "info for logging" and puts into Exception.Data.
}
//Dispose is called and all messages that were put into LocalStorage are removed.
//So if exception was not thrown before then it like nothing happened.
Google AsyncDiagnosticStack for a good example. https://github.com/StephenCleary/AsyncDiagnostics/blob/master/src/Nito.AsyncEx.AsyncDiagnostics/AsyncDiagnosticStack.cs

What to do with a caught exception

When the WCF service is turned off, I'm gonna catch this exception like this.
public List<ProjektyEntity> GetProjekty()
{
try
{
return this.channel.GetProjekty();
}
catch (EndpointNotFoundException exception)
{
//what to do at this point ?
}
}
But i don't know what to do in the catch block.I can return only an object of type List<ProjektyEntity> I'd like to write a message to the user,something like "The service is turned off" My presentation layer is ASP.NET MVC. Is there any strategy for this kind of situations?
There's a simple rule: If you don't know how to handle an exception, don't catch it.
Catching it and retuning null or an empty list would be about the worst thing you can do because it will be hard to debug where the error is coming from, or even that an error occured at all. If you do this you will have developers pulling their hair out.
Catching an exception and rethrowing it as throw e; is also bad because you lose the original stack. Rethrowing using throw; is OK sometimes if you have special clean up you need to do only if there is an error. Usually this is not the case. If you have cleanup that should be done whether or not there was an error, it belongs in the finally clause.
So in general unless there is something sensible you can do to recover from the error, just let the exception propogate to the caller. This is how exceptions are designed to work.
There are a few times when you might want to catch an exception to add more information (e.g. for logging), in which case you should ensure that you use an InnerException to avoid losing the original information:
try
{
foo(bar);
}
catch (Exception e)
{
throw new FooException("Foo failed for " + bar.ToString(), e);
}
but in general it's best not to do this unless you have a very good reason. Doing this prevents your users from catching a specific type of exception - they will catch your exception and then they need to switch on the type of the InnerException. Not fun. Just let the caller see the original exception.
I can see a few options here. Determining which is appropriate is probably dependent on the application.
Display an error and return null. Clean and simple, but inflexible. May not be what you want in every case where this function is used.
Don't catch it, let the caller catch this exception. It may be easier to determine the appropriate response from the calling function (ie. display a message / retry in a few seconds / etc)
Catch it and throw a new ServiceNotAvailableException Slightly more complex than option two, but will make your code clearer.
Just return null. Probably the least desirable approach unless this service being down is common and no big deal.
It seems to me that you should not catch this exception at that layer; you should let the exception propagate up to the controller layer and let the controller layer displays the message.
There are several approaches:
1) Don't catch the exception, and let the caller (user interface layer) handle it
2) Catch the exception so you can do anything you need to do, and then re-throw it
catch (EndpointNotFoundException exception)
{
CleanUpMyOwnState();
throw; // Pass the exception on the to the caller to handle
}
3) Convert the exception into another type (to make it easier to handle in the caller):
catch (EndpointNotFoundException exception)
{
CleanUpMyOwnState();
throw new InvalidOperationException("Endpoint was not found", exception);
}
4) catch it, and then return an error code (e.g null), so the caller doesn't need to use exception handling to deal with it (but there's no real advantage to doing this)
5) Catch the exception and report the error to the user yourself. This is probably a bad idea - you should keep all error reporting in your UI layer.
The exception is not supposed to be caught and handled in this context. It needs to be handled at much higher level having access to any console in general.
The best you can do here is just log the exception with necessary details and rethrow properly.
Create an exception object with enough debugging details and throw it to calling method
public List<ProjektyEntity> GetProjekty()
{
try
{
return this.channel.GetProjekty();
}
catch (EndpointNotFoundException exception)
{
'Write here Some Clean Up Codes
' Log it somewhere on your server so that you can fix the error
}
}

Categories