I use the PubSub mechanism the send events in my application,
each event has a custom handler that use to handle it.
My problem is that in many places the handler suppled as the following:
SubscriberService.Subscribe(new SubscribeRequest<string>
{
Topic = TopicName,
Action = async pubSubEvent => await DoSomthingAsync()
}
the return type of Action is void so behind the scenes this lambda translated to async void.
So when an exception occur I have no chance to catch it.
I wondered to myself if there is a way to create a method at runtime that warp the method body of the action with a try-catch block that catches the exception when they occur and write them to the log.
I saw some articles about the Emit.IlGenerator class could help but I have no idea where to start.
I would love to hear any suggestions to deal with these issues.
Thanks!
Related
I was working on a larger project which uses Rx extensively. In one particular instance I noticed one of the subscriptions threw an exception. At that point I assumed the subscription would just be completed (with an error) as I did not have any Retry() call. However, what I saw was the subscription repeatedly retried.
I tried to repro a similar case in a small example, seen below. I put a break point on
Console.WriteLine("!");
and expected it to be hit after the subscription failed. But it is never reached. GetImportantValues().Subscribe is just called over and over.
I don't understand why though. I would have expected the exception that is thrown to kill the subscribe attempt.
I would like to modify the below sample to retry 3 times if an exception is thrown, and then after that just stop altogether.
using System;
using System.Reactive.Linq;
namespace RxTest
{
class Program
{
static void Main(string[] args)
{
var ob1 = GetImportantValues().Subscribe(Console.WriteLine);
Console.WriteLine("!");
Console.ReadLine();
}
private static IObservable<int> GetImportantValues()
{
var obs = GetThem();
return obs;
}
private static IObservable<int> GetThem()
{
//Do some work. Would return a valid observable if everything is ok
return Observable.Throw<int>(new Exception("test"));
}
}
}
It's not being called over and over again. You probably just have Break on first chance exceptions enabled in Visual Studio and each time you try to continue it's just breaking on the same exception. If you were to actually continue the process the application would just crash.
Observable.Throw calls OnError. You haven't provided an OnError handler in your call to Subscribe, so the default OnError handler is used. The default behavior simply throws the error and brings down the process.
To retry simply apply Retry(3) before calling Subscribe. To swallow the error after the 3rd attempt, provide an OnError handler to Subscribe, though I don't necessarily recommend the latter. Think carefully whether the application can really recover from such a scenario.
I'm working on a project at the moment where I need to inter-operate with code that swallows exceptions. In particular, I'm writing NUnit unit tests. There are some places where I want to embed assertions within code that gets passed as a delegate, as part of mocking a particular behavior. The problem I'm having is that the AssertionException gets swallowed by the code calling the delegate, which means the test passes, even though the test Assert failed.
Is there any way to inform NUnit that a test should fail that can't be circumvented by catching AssertionException? I can't modify the code that swallows the exceptions, as I don't have full ownership and it's already in semi-production use. I'm hoping there's a clean way to accomplish this.
The best I've come up with is something like this:
private static string _assertionFailure;
public static void AssertWrapper(Action action)
{
try
{
action();
}
catch (AssertionException ex)
{
_assertionFailure = ex.Message;
throw;
}
}
[Test]
[ExpectedException(typeof(AssertionException))]
public void TestDefeatSwallowing()
{
Action failure = () => AssertWrapper(() => Assert.Fail("This is a failure"));
EvilSwallowingMethod(failure);
if (_assertionFailure != null)
Assert.Fail(_assertionFailure);
}
private void EvilSwallowingMethod(Action action)
{
try
{
action();
}
catch
{
}
}
It works, but it's pretty ugly. I have to wrap every Assert call and I have to check at the end of every test if an assertion was swallowed.
So you're doing something like this? (this is using Moq syntax)
var dependency1 = new Mock<IDependency1>();
dependency1.Setup(d => d.CalledMethod([Args])
.Callback(TestOutArgsAndPossiblyThrow);
var objectUnderTest = new TestedObject(dependency1.Object);
objectUnderTest.MethodThatCallsIDependency1dotCalledMethod();
And you've got TestOutArgsAndPossiblyThrow encapsulated in your AssertWrapper class?
Unless that's way off, I'd say you're doing it just about right. You have execution re-entering your test at a point where you can record the state of the call to the dependency. Whether that's done via catching exceptions and analyzing them or just directly inspecting the values of the method parameters, you've just gotta do the work. And if you're swallowing exceptions inside the black box, you're going to have to monitor them before they get back into the black box.
I still say you'd be much better off with appropriate logging and notification (you don't have to notify the end users, necessarily). To #TrueWill's point - what do you do when there's an IOException or the database isn't available?
DISCUSSION EDIT
Is your scenario structured like this?
TEST -> TESTED CODE -> SWALLOWING CODE -> THROWING MOCK
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 am currently asking myself some questions about exception handling and eventhandlers, and i hope some of you will give me some help.
I will start to explain what i would like to achieve in my c# application:
I have a top-level method (lets call it the main method). This method calls an asynchronous method (wich is called connect), which connect to a FTP server.
An EventHandler object is associated to this connection, and a "callback" method is called when the connection is successful.
I want to handle exceptions that can be launched during the whole process. So i would like to catch it in the top level method. It works fine for exceptions launched by the connect method (which is called inside the top level method).
However, it does not work for exceptions called inside the "callback" method: the top level method does not catch them and the execution fails.
What can I do to make these exceptions beeing caught by the top level method ? I don't want to handle these exceptions in the callback.
Take a look at how the Backgroundworker deals with this: the Exception is propagated to the Completed event handler.
I assume you have some form of State object that is passed to/from the delegate, that's where you can add such a property. And you will have to catch all exceptions in the thread, at the outermost scope. But 'handling' just means passing it along.
There is a standard pattern for the RunWorkerCompleted event, see this MSDN page.
Consider the below code fragment for wrapping all of your code in a global exception handler:
namespace MyClient
{
class Program
{
static void Main(string[] args)
{
try
{
bool isSuccess = SubMain(string[] args);
}
catch (Exception e)
{
HandleExceptionGracefully(e);
}
}
static bool SubMain(string[] agrs)
{
// Do something
}
static void HandleExceptionGracefully(Exception e)
{
// Display/Send the exception in a graceful manner to the user/admin.
}
}
}
Also, don't forget to make your error handling user-friendly.
There is an event handler in the Application class called ThreadException. This event will be fired whenever an exception is thrown an not caught anywhere in the current call stack.
Edited:
Sorry, I misread the question - I didn't realise that the "main" method in your example isn't the actual main method. In that case you may want to catch the exception inside the callback, but not handle it - instead simply pass it back up to the main method as part of the event args.
The BackgroundWorker in Winforms does something similar.
Thanks for your answers.
It seems that using the BackgroundWorker solve this problem.
I did not try it, because i chose to avoid this implementation burden. So I took away my asynchronous call and made my application behaving synchronously.
One tip for people using the Compact Framework instead of the full .NET Framework:
the BackgroundWorker is not available in CF, but a similar solution is provided by OpenNETCF (see the BackgroundWorker class in the Smart Device Framework).
A more convenient way to deal with this problem of top-level exception handling is to use delegates.
These c# delegates allow to call methods in a asynchronous way. And delegates allow also top-level exception handling. Indeed, exceptions thrown inside delegates are re-thrown on the original thread.
I don't know why i did not think about delegates before.
I hope it will help.
See these nice articles about delegates:
Article 1
Article 2
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
{
}