I have a class called "Website", and inside of that class I have the following property:
public HtmlForm RegisterForm
{
get
{
if (Forms.RegForm != null) / Forms is a custom object called HTMLForms that is a custom list collection
{
return Forms.RegForm;
}
else
{
// FindPageWithGoogle Google = new FindPageWithGoogle();
// use Google.FindRegistrationForm(this.currentUrl) method
//throw new Exception(); // if registration form object can't be found
}
return Forms.RegForm;
}
}
Would this be an efficient way of handling the error? In the case of it not being found, how would I halt the entire flow of the program if this exception is thrown? I know how to use a simple try catch, but I don't think that's enough. I believe I need to learn how to make my own custom exception handling system to handle these custom events accordingly.
Thanks for any help. Also, if you have a specific book on exception handling, since the C# books i've read thus far didn't go into the topic much, it would be greatly appreciated.
Thanks,
Cody
To terminate the code on an exception, just don't catch it.
You should create a meaningful exception class (e.g. InitializationError) and then throw that when the error occurs. Go out to the calling code that can display the message to the user and catch the exception there. You might also terminate the program at that point.
As far as books on exception handling, I think you'll find the MSDN chapter on exceptions helpful.
Related
I have some code that currently looks somewhat like this:
public void MainFunction()
{
try
{
SomeProblemFunction();
}
catch
{
AllFineFunction();
}
}
private void SomeProblemFunction() { ... }
private void AllFineFunction() { ... }
As you can see, I'm currently wrapping the call to SomeProblemFunction around a try statement because that function could fail (it relies on an outside web service call).
My question is this: should the try statement be a) outside the problem function (like I have it now) or b) inside the problem function?
Thanks.
Typically you want to allow your exceptions propagate up to your application boundaries. You're only going to want to do one of a few things with your exception:
Wrap it
Replace it
Let it propagate
Update
From your question it seems that you are looking for a fault tolerant solution for your web service calls. This is a more complex problem than simply "where do I put my try-catch?" You would still place your exception handling at the application boundary, but there you would implement your fault tolerance strategy. This would need to have many considerations, including asynchronously calling your web service, number of retry attempts, etc. I would suggest doing a search for web service fault tolerance.
What you have is correct; see the MSDN example:
public class ThrowTestB
{
static void Main()
{
try
{
// TryCast produces an unhandled exception.
TryCast();
}
catch (Exception ex)
{
// Catch the exception that is unhandled in TryCast.
Console.WriteLine
("Catching the {0} exception triggers the finally block.",
ex.GetType());
// Restore the original unhandled exception. You might not
// know what exception to expect, or how to handle it, so pass
// it on.
throw;
}
}
public static void TryCast()
{
int i = 123;
string s = "Some string";
object obj = s;
try
{
// Invalid conversion; obj contains a string, not a numeric type.
i = (int)obj;
// The following statement is not run.
Console.WriteLine("WriteLine at the end of the try block.");
}
finally
{
// Report that the finally block is run, and show that the value of
// i has not been changed.
Console.WriteLine("\nIn the finally block in TryCast, i = {0}.\n", i);
}
}
// Output:
// In the finally block in TryCast, i = 123.
// Catching the System.InvalidCastException exception triggers the finally block.
// Unhandled Exception: System.InvalidCastException: Specified cast is not valid.
}
As a rule of thumb I try and build code that focuses try catches to the exact spot the problem may occur.
That said both of your solutions are correct.
If it were my code I would do this
public void MainFunction()
{
try
{
SomeProblemFunction();
}
catch(Exception e)
{
Messagebox.Show(e.Message);
}
}
private void SomeProblemFunction() {
try{
web call
}
catch{
throw a specific exception related to this spot
}
}
private void AllFineFunction() { ... }
With this method you can easily create applications that handle a slew of very accurate exceptions
A fine question, I think. I'll attempt an answer.
If you want to recover within SomeProblemFunction, then it would make perfect sense to move the try...catch inside of that method. If, however, you are comfortable saying that if anything fails in SomeProblemFunction, then the whole thing is a failure, then keep it as you have it now and recover in (or throw from) MainFunction.
Thanks to the comment below, I'm adding some clarity. Depending on the specific exception that is being thrown within SomeProblemFunction, you may not have the ability to recover within that method. If you have a mixture of recoverable and non-recoverable, then it would be prudent to have the try...catch in both places.
The most important thing is that you NEVER catch an exception from which you cannot recover without throwing it on after doing your thing. It's tempting to add big broad catches (catch (Exception)) to avoid your app crashing during development, but it is never worth it. If those things make it into your production code, you've introduced a problem-solving and debugging nightmare.
In my opinion, there is no straight answer for this. The try catch is used to handle the exceptions that may occur. If your exception handling code is going in the main function then you should have the try catch in the main function. If your exception handling code in the problem function then you should add it to the problem function.
My preference though is to put it in both functions. If you put the try catch in the problem function, you can throw the exception and catch it in the main function. This always appear to other developers that the exception was thought of in that function and not missed handling it by mistake.
This depends on how severe this web service call failure would be.
Is it a failure that would prevent further processing of your code to run? If so, have no try/catch here, allowing it to propagate up to the guy who needs to know that this web service call failed. Optionally, you could still catch and throw a new exception with some more meaningful Exception type/ details.
Do you simply just want to re-try the web service call again if it doesn't work? IF so, then you have the try in the correct place; you just need to add a loop.
Is it not a big deal if this web service call fails? e.g. - will the rest of your code work OK? (I've found this to be uncommon). If so, leave the try/catch where it is, and log the error somewhere so that you're alerted.
The following code snippet is a simplified version of my issue. Basically I'm trying to catch the error that occurs in my setter when updatesource is called and propagate it up to my the catch block shown below. The problem is if an exception occurs in the call stack below updatesource, BindingExpression.UpdateSource() seems to catch that error and handle it. I can't get the exception to make it back out to my catch statement. Can this behavior be disabled?
BindingExpression be = textBox.GetBindingExpression(TextBox.TextProperty);
try
{
be.UpdateSource();
}
catch (Exception ex)
{
MessageBox.Show("ex.Message");
}
//////////////////////////////////////////////////////////////////
public string MyValue
{ get {return _value;}
set {
if(value > 10)
throw new Exception("Out of Range");
}
}
Binding in WPF and Silverlight can be configured to use exceptions thrown in the setter for validation. I believe Donut's comment about ValidatesOnExceptions is at the heart of the issue. The other related attribute (at least in Silverlight) is NotifyOnValidationError. If you aren't using this feature for validation you should be able to turn it off. If you are, you might be able to get it from from the validation system.
EDIT:
I made a sample project to check out the situation, and while stepping through I found that UpdateSource() catches the exception for the purpose of the validation system, and it appears that it doesn't rethrow. You could create your own UpdateSource method (perhaps as an extension method with a different name) that updates the value of the property in the binding, but doesn't catch the exception (or catches and rethrows).
I know this is a really old topic, but just stumbled upon it.
This article provides a really nice way of catching errors that occur inside the setters: https://wpf.2000things.com/2017/06/18/1211-catching-exceptions-originating-in-property-accessors/
How it works is extremely simple and effective: it creates an override of TraceListener and re-throws the exception inside the overriden WriteLine() method.
Then, App.OnStartup() it adds the new Listener to PresentationTraceSources.DataBindingSource.Listeners and all of a sudden, the exception being thrown inside the setter can be caught.
The drawback is that if you have any binding errors throughout your application, these will be caught immediately and you'll start seeing them.
I have an xmlbuilder utility class which calls a couple of methods to build an xml file
public XMLBuilder(String searchVal)
{
this.searchVal = searchVal;
try
{
getData();
returnedData = processDataInToOriginalFormat();
WriteBasicTemplate();
}
catch (WebException)
{
//If this is thrown then there was an error processing the HTTP request for MSO data.
//In this case then i should avoid writing the xml for concordance.
serviceAvailable = false;
MessageBox.Show("Could not connect to the required Service.");
}
catch (NoDataFoundException ndfe)
{
//propegate this back up the chain to the calling class
throw;
}
processDataInToOriginalFormat(); this is a method in a class which causes an exception if the service is not available and i have propagated the exception back to here to deal with. I was going to try and set a boolean flag to indicate whether to write a certain bit of xml. If the flag is false then dont write it.
I forgot however that exceptions stop programme flow and now i realise this isnt possible as if an exception occurs the rest of the code doesn't resume. how can i get around this? just add the WriteBasicTemplate(); call in to my catch clause?
Thanks
The logic of your code is somewhat confusing and as it's not obvious what "serviceAvailable = false" will do, it's hard to give detailed tips. The general rule of excetion handling is, to catch (and not rethrow) them, if you really know what to do with them and how to fix the problem. I you don't know that or the program will be in a state where it cannot continue working, let the exception go through and let your program crash.
In your case I might structure the code like this:
try
{
returnedData = processDataInToOriginalFormat();
// put code here which should only be executed in
// case of no exception
}
catch (WebException)
{
// do what ever is required to handel the problem
MessageBox.Show("Could not connect to the required Service.");
}
// code which should be executed in every case
WriteBasicTemplate();
You shoudl also look at the "finally"-block. Depending on your requirements, you should WriteBasicTemplate in such a block. But I would probably not do so in your case. It's rather used for resource cleanup or something like that.
In my services all exposed methods have:
try
{
// the method core is written here
}
catch(Exception ex)
{
Log.Append(ex);
}
It's boring and ugly to repeat it over and over again. Is there any way to avoid that? Is there a better way to keep the service working even if exceptions occur and keep sending the exception details to the Log class?
Try AOP. This is the most widely-used selling point of AOP.
Also, see this discussion here on SO.
You could set up a generic error handling method for all uncaught exceptions like so:
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(UnhandledException);
Depending on what went wrong, you may not be able to recover from the error... but this should hopefully give you some idea of what what went wrong. If it gets to the point where your application code hasn't handled the exception gracefully, this method could attempt to reinitialize the service to a known working state.
I came up with a semi-solution right now. I can refactor the code:
public TResult ExecuteAndLogOnError(Func<TResult> func)
{
try
{
return func();
}
catch(Exception ex)
{
// logging ...
}
}
And then you can call it on each method:
return ExecuteAndLogOnError(() =>
{
// method core goes here..
});
Which is 4 lines shorter than the original scenario.
In such cases I always use centralized error handlers.
In WCF it is very easy. Some more details:
http://www.haveyougotwoods.com/archive/2009/06/24/creating-a-global-error-handler-in-wcf.aspx
Basically, you just implement the IServiceBehavior interface and then provide your own error handler. That is the best way to do this because you don't have to write any code that handles fatal exceptions (I mean exceptions that you can only log and you don't know what to do about them) in your methods.
If all your doing is logging then just log the error at a later stage... No need to log the error early. If you do more than log the error, well then you're gonna need the try..catch anyway. And if you swallow exceptions (IE. just log them and then go on as if nothings happened) then maybe you're doing it wrong...
I once used something like the Template Function Pattern to resolve a problem like this. I had a base class that did something like:
public void Execute()
{
try
{
ExecuteImplementation();
}
catch (Exception ex)
{
// Log ex
}
}
public abstract void ExecuteImplementation();
There was one derived class per web service operation. The derived classes each implemented ExecuteImplementation.
The web service operations did:
[WebMethod]
public Result WebOperation(Request request)
{
WebOperationClass instance = new WebOperationClass(request);
instance.Execute();
return instance.Result;
}
Exception filters would be good for this. Alas, .NET supports them through MSIL, C++/CLI, VB.NET, but not C#.
If all you're doing in your catch is logging the exception, you could maybe just use a custom error page and let ELMAH log all your uncaught exceptions.
A previous poster brought up AOP (Aspecte-Oriented Programming).
I use PostSharp for basic logging traces/exceptions.
It's quite easy to use and setup.
Check out this link and watch the tutorial.
http://www.sharpcrafters.com/postsharp
--crap it is no longer open source ... anyways you can grab Postsharp1.5 and mess around with it to see if it is something you are interested in it.
I am also in no way affiliated with PostSharp. I'm just a user.
I have a website built in C#.NET that tends to produce a fairly steady stream of SQL timeouts from various user controls and I want to easily pop some code in to catch all unhandled exceptions and send them to something that can log them and display a friendly message to the user.
How do I, through minimal effort, catch all unhandled exceptions?
this question seems to say it's impossible, but that doesn't make sense to me (and it's about .NET 1.1 in windows apps):
All unhandled exceptions finally passed through Application_Error in global.asax. So, to give general exception message or do logging operations, see Application_Error.
If you need to catch exeptions in all threads the best aproach is to implement UnhandledExceptionModule and add it to you application look here
for an example
Use the Application_Error method in your Global.asax file. Inside your Application_Error method implementation call Server.GetLastError(), log the details of the exception returned by Server.GetLastError() however you wish.
e.g.
void Application_Error(object sender, EventArgs e)
{
// Code that runs when an unhandled error occurs
log4net.ILog log = log4net.LogManager.GetLogger(typeof(object));
using (log4net.NDC.Push(this.User.Identity.Name))
{
log.Fatal("Unhandled Exception", Server.GetLastError());
}
}
Don't pay too much attention to the log4net stuff, Server.GetLastError() is the most useful bit, log the details however you prefer.
The ELMAH project sounds worth a try, its list of features include:
ELMAH (Error Logging Modules and
Handlers) is an application-wide error
logging facility that is completely
pluggable. It can be dynamically added
to a running ASP.NET web application,
or even all ASP.NET web applications
on a machine, without any need for
re-compilation or re-deployment.
Logging of nearly all unhandled exceptions.
A web page to remotely view the entire log of recoded exceptions.
A web page to remotely view the full details of any one logged
exception.
In many cases, you can review the original yellow screen of death that
ASP.NET generated for a given
exception, even with customErrors mode
turned off.
An e-mail notification of each error at the time it occurs.
An RSS feed of the last 15 errors from the log.
A number of backing storage implementations for the log
More on using ELMAH from dotnetslackers
You can subscribe to the AppDomain.CurrentDomain.UnhandledException event.
It's probably important to note that you are not supposed to catch unhandled exceptions. If you are having SQL timeout issues, you should specifically catch those.
Do you mean handling it in all threads, including ones created by third-party code? Within "known" threads just catch Exception at the top of the stack.
I'd recommend looking at log4net and seeing if that's suitable for the logging part of the question.
If using .net 2.0 framework, I use the built in Health Monitoring services. There's a nice article describing this method here: https://web.archive.org/web/20210305134220/https://aspnet.4guysfromrolla.com/articles/031407-1.aspx
If you're stuck with the 1.0 framework, I would use ELMAH:
http://msdn.microsoft.com/en-us/library/aa479332.aspx
hope this helps
There are 2 parts to this problem handling & identifying.
Identifying
This is what you do when the exception is finally caught, not necessarily where it is thrown. So the exception at that stage must have enough context information for you to idenitfy what the problem was
Handling
For handling, you can
a) add a HttpModeule. See
http://www.eggheadcafe.com/articles/20060305.asp
I would suggest this approach only when there is absolutely no context informaatn available and there might be issuus wiih IIS/aspnet, In short for catastrophic situations
b) Create a abstract class called AbstractBasePage which derives from Page class and have all your codebehind classes derive from AbstractBasePage
The AbstractBasePage can implement that Page.Error delegate so that all exceptions which percolate up through the n-tier architecture can be caught here(and possibly logged)
I would suggest this cause for the kind of exceptions you are talking about (SQlException) there is enough context information for you to identify that it was a timeout and take possible action. This action might include redirecting user to a custom error page with appropriate message for each different kind of exception (Sql, webservice, async call timeouts etc).
Thanks
RVZ
One short answer is to use (Anonymous) delegate methods with common handling code when the delegate is invoked.
Background: If you have targeted the weak points, or have some boilerplate error handling code you need to universally apply to a particular class of problem, and you don't want to write the same try..catch for every invocation location, (such as updating a specific control on every page, etc).
Case study: A pain point is web forms and saving data to the database. We have a control that displays the saved status to the user, and we wanted to have common error handling code as well as common display without copy-pasting-reuse in every page. Also, each page did it's own thing in it's own way, so the only really common part of the code was the error handling and display.
Now, before being slammed, this is no replacement for a data-access layer and data access code. That's all still assumed to exist, good n-tier separation, etc. This code is UI-layer specific to allow us to write clean UI code and not repeat ourselves. We're big believers in not quashing exceptions, but certain exceptions shouldn't necessitate the user getting a generic error page and losing their work. There will be sql timeouts, servers go down, deadlocks, etc.
A Solution: The way we did it was to pass an anonymous delegate to a method on a custom control and essentially inject the try block using anonymous delegates.
// normal form code.
private void Save()
{
// you can do stuff before and after. normal scoping rules apply
saveControl.InvokeSave(
delegate
{
// everywhere the save control is used, this code is different
// but the class of errors and the stage we are catching them at
// is the same
DataContext.SomeStoredProcedure();
DataContext.SomeOtherStoredProcedure();
DataContext.SubmitChanges();
});
}
The SaveControl itself has the method like:
public delegate void SaveControlDelegate();
public void InvokeSave(SaveControlDelegate saveControlDelegate)
{
// I've changed the code from our code.
// You'll have to make up your own logic.
// this just gives an idea of common handling.
retryButton.Visible = false;
try
{
saveControlDelegate.Invoke();
}
catch (SqlTimeoutException ex)
{
// perform other logic here.
statusLabel.Text = "The server took too long to respond.";
retryButton.Visible = true;
LogSqlTimeoutOnSave(ex);
}
// catch other exceptions as necessary. i.e.
// detect deadlocks
catch (Exception ex)
{
statusLabel.Text = "An unknown Error occurred";
LogGenericExceptionOnSave(ex);
}
SetSavedStatus();
}
There are other ways to achieve this (e.g. common base class, intefaces), but in our case this had the best fit.
This isn't a replacement to a great tool such as Elmah for logging all unhandled exceptions. This is a targeted approach to handling certain exceptions in a standard manner.
Timeout errors typically occur if you are not forcefully closing your sqlconnections.
so if you had a
try {
conn.Open();
cmd.ExecuteReader();
conn.Close();
} catch (SqlException ex) {
//do whatever
}
If anything goes wrong with that ExecuteReader your connection will not be closed. Always add a finally block.
try {
conn.Open();
cmd.ExecuteReader();
conn.Close();
} catch (SqlException ex) {
//do whatever
} finally {
if(conn.State != ConnectionState.Closed)
conn.Close();
}
This is old question, but the best method (for me) is not listed here. So here we are:
ExceptionFilterAttribute is nice and easy solution for me. Source: http://weblogs.asp.net/fredriknormen/asp-net-web-api-exception-handling.
public class ExceptionHandlingAttribute : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext context)
{
var exception = context.Exception;
if(exception is SqlTimeoutException)
{
//do some handling for this type of exception
}
}
}
And attach it to f.e. HomeController:
[ExceptionHandling]
public class HomeController: Controller
{
}