Exception handling in class library. Is it necessary? - asp.net

I have a class library project which i am referencing in my asp.net web forms project.
Whenever any exception happens, i want to log it. But, I am not doing any exception handling in any of the class library method. That is i have not used try-cath block in any of the methods in the class library.
Because, any excepyion that gets thrown from class library methods is caught in my presentation layer/business layer(wherever i call the functions of the class library) and proper logging is done here in the web forms project.
Is it correct to do this way.?

Its Ok to write that way, but in that case your Class Library will throw exception which system exception message, which might be sometime difficult to interpret and act accordingly.
Instead you can have Try-Catch-Finally block in class library, and Re-throw exception with user defined message to calling method, this will help in tracing issue.
Example :
Catch(FileNotFoundException Ex)
{
throw new ("File Not Found at XYZ Location, Please Check File Exist and retry ...")
}
Centralized Exception Logging:
There are multiple ways you can log error messages. One of the good way would be to use Enterprise Library Exception Block to Log error to file, which can be used in debugging issues.
This article can come handy for Enterprise Library:
http://msdn.microsoft.com/en-us/library/ff649140.aspx
You can log exception centrally to CSV, XML or even to windows Event Viewer.
Create Separate class / project to perform all exception logging in project.

Seems like a reasonable approach to me. Delegating the exception logging to the application keeps your class library abstract meaning it can be reused without having a dependency on the logging library/framework.
Logging should be the responsibility of the application, not the component. There may be some exceptional circumstances where trace-level debugging is required at component level, for those special cases having a log-enabled version of the lib that you could swap in might come in handy. However, I would argue that a properly tested component would reduce the need for that.

Related

Access WebApplication/Services from program.cs later in program without DI

Okay, I'm open to being told I'm approaching the problem incorrectly, so go ahead if that's the case, but I have a unhandled exception provider I'm adding to my builder.Services in program.cs, along with some data services. I can't figure out a good way to add an existing data service to the unhandled exception provider (custom logging to a db via the data service).
I had tried passing it, or using it via injection, but in the exception provider the data service keeps coming up as null in practice.
So I was thinking, is there a way to get a reference to the WebApplication that is running (the one we are running via app.Run() in Program.cs) from elsewhere in the running program.
Logically, I'd like to do something like this in the unhandled exception provider:
MyService = GetRunningApp().services.BuildServiceProvider().GetService<IMyService>();
Am I missing an easier way to do this?
In Blazor it's not as easy to inject the middleware for global error handling like it is with Web API (Correct me if I'm wrong!)
For Blazor I think the closest we have is the <ErrorBoundary>. Check out this solution by Alamakanambra. They provide an example on how to create a component that handles global exceptions. You can do whatever logging or handling you need in the OnErrorAsync.
protected override Task OnErrorAsync(Exception exception)
{
receivedExceptions.Add(exception);
return base.OnErrorAsync(exception);
}

Determine what is causing the error "This SqlTransaction has completed; it is no longer usable" error

We run a proprietary web based Finance system created in ASP.NET that is throwing the following error on a regular basis:-
Exception: System.InvalidOperationException
Message: This SqlTransaction has completed; it is no longer usable.
StackTrace: at System.Data.SqlClient.SqlTransaction.ZombieCheck()
at System.Data.SqlClient.SqlTransaction.Rollback()
at Agresso.Driver.Database.ManagedConnection.RollbackTransaction()
at Agresso.Driver.Database.ManagedConnection.Close()
at Agresso.Driver.Database.ManagedConnection.Dispose(Boolean isDisposing)
at Agresso.Driver.Database.ManagedDatabase.Dispose(Boolean isDisposing)
at Agresso.Driver.Database.DatabaseBase.Finalize()
The issue has been logged with the suppliers but they believe the error is due bespoke work that we have created ourselves.
What would you recommend as a way of determining what is causing the system to get into this state? We do not have access to debug the application but can run profiler on the database. However so far this has not shed any possible clues to what is causing the problem.
We are currently just restarting the app pool, which resolves the problem for a period of time before it occurs again.
Many thanks.
Pure speculation, but:
if DatabaseBase.Finalize() is a .NET finalizer, it shouldn't be attempting to dispose managed resources - so this may well be a bug in the DatabaseBase class finalizer.
However a finalizer for an IDisposable class is normally only called if the caller has failed to Dispose an instance of the class (the Dispose method usually calls GC.SuppressFinalize to prevent the finalizer from running).
I would start by looking at your own code that accesses the database, and make sure you call Dispose for all IDisposable types, typically by wrapping in a using block. FxCop / Visual Studio Code Analysis can help you identify places in your code where you're failing to do this.
This may well clear up the problem. If not, I suggest you try to create a minimal repro for the problem and contact the supplier again.

Handling ClientBase faults and SimpleIOC

I am using SimpleIOC from mvvm-light along with the ViewModelLocator class / pattern provided to provide ViewModels with the correct dependencies injected. The problem I have is that the dependency that is being injected in to my ViewModel is a WCF ClientBase instance that can "break" if it encounters a fault. One example would be if the service it is trying to connect to doesn't exist it will cause a fault. I don't know how to handle this properly. Once the ClientBase derived class is in a fault state it will no longer work. The ViewModelLocator keeps injecting this broken instance of my service proxy so even if this service becomes accessible the proxy will error out when used because it can't recover from a faulted state. How should I deal with this?
I was able to figure this one out on my own. The answer was to create a wrapper around the ClientBase proxy class so that when a call created a fault, the wrapper class could properly handle the exception yet still be ready to handle the next call.

Should I catch all my exceptions in the global.asax?

If I am just logging exception details in my web app, do I really need to put in exception handling logic for each tier? Why not just let them all bubble up the stack trace to the global.asax and log them there?
I would suggest against using any exception handling logic in any layer of your application unless:
The exception is not a fatal one, meaning that there is some action you can take to recover, or
The application should continue functioning and the exception should be "ignored." An example: when checking out at an online retailer you are sent a receipt via email. If that fails - but the other order processing stuff succeeds - the user should not be shown an error page. Here, we want the workflow to continue even though there is an exception. Most exceptions do not fall into this category.
Of course, exceptions - whether they are fatal or not or should be "ignored" or not - need to be logged and developers notified. This is best handled through an event handler for the Application.Error event. Yes, this can be done in Global.asax, but I think it's cleaner to use an HTTP Module-based approach, either Health Monitoring or ELMAH.
I've written an article on this topic that I'd like to recommend to you - Exception Handling Advice for ASP.NET Web Applications. Here is the article in summary:
My advice for handling exceptions in an ASP.NET application can be boiled down to the following guidelines:
(a) Create and use a meaningful custom error page.
(b) In general, do not catch exceptions. Let them bubble up to the ASP.NET runtime. Some cases where catching an exception makes sense include:
When there is a plausible way to recover from the exception by performing some alternative logic,
When a peripheral part of the application's workflow throws and exception and that exception should not derail the entire application, and
When you need to include additional information with the exception by throwing a new exception that has the original exception as its inner exception.
(c) Log all exceptions to some persistent store and use email (or some other medium) to notify developers when an exception occurs in production. Consider using ELMAH or ASP.NET's built-in Health Monitoring system to facilitate this process.
Exceptions should bubble up to whatever layer can handle them in a meaningful way, being aware of the Single Responsibility principle. For instance, your data layer should not be invested in logging.
The Application.Error event is a good place for catch-all error handling: that is, unexpected and/or fatal errors that require no special treatment beyond logging/alerting and redirecting to an error page.
If your web app makes use of the Microsoft AJAX extensions and partial postbacks, you'll need to handle exceptions in at least two places:
Global.asax
Your ScriptManager's OnAsyncPostBackError handler
For further information on OnAsyncPostBackError, check out:
http://msforge.net/blogs/janko/archive/2008/02/13/handling-exceptions-in-asp-net-ajax.aspx
http://msdn.microsoft.com/en-us/library/system.web.ui.scriptmanager.onasyncpostbackerror.aspx
I say that on global try to catch the error that you miss on the logic steps of your program and redirect them on an "error page", or a "not found page".
All other errors not necessary show the error on the user, and not need to send it to an error page.
For example, in page with 2 or more, different modules, if the one throw an error, just hide it, and show the rest. Similar try to catch errors when they happens and handle them the best non visual way to the user if this is possible, log them and correct them later.
Now this error that happens only on one module, you can see it on your log and correct it, but until you do that, user see something on your page and not a full error page.
Usually what I do is do a try...catch in the code, but instead of logging on the catch what I do is pass it on with a message stating where the error came from, etc. Then I use Elmah to catch all of the errors and log them.
That way you only have to deal with the logging in one area and satisfy the Single Responsiblity Principle, but you have more information available for debugging purposes. It can also be helpful when you get that data error that only seems to occur with 1 out of 500 users.

How do you log errors (Exceptions) in your ASP.NET apps?

I'm looking for the best way to log errors in an ASP.NET application.
I want to be able to receive emails when errors occurs in my application, with detailed information about the Exception and the current Request.
In my company we used to have our own ErrorMailer, catching everything in the Global.asax Application_Error. It was "Ok" but not very flexible nor configurable.
We switched recently to NLog. It's much more configurable, we can define different targets for the errors, filter them, buffer them (not tried yet). It's a very good improvement.
But I discovered lately that there's a whole Namespace in the .Net framework for this purpose : System.Web.Management and it can be configured in the healthMonitoring section of web.config.
Have you ever worked with .Net health monitoring? What is your solution for error logging?
I use elmah. It has some really nice features and here is a CodeProject article on it. I think the StackOverflow team uses elmah also!
I've been using Log4net, configured to email details of fatal errors. It's also set up to log everything to a log file, which is invaluable when trying to debug problems. The other benefit is that if that standard functionality doesn't do what you want it to, it's fairly easy to write a custom appender which can process the logging information as required.
Having said that, I'm using this in tandem with a custom error handler which sends out a html email with a bit more information than is included in the standard log4net emails - page, session variables, cookies, http server variables, etc.
These are both wired up in the Application_OnError event, where the exception is logged as a fatal exception in log4net (which then causes it to be emailed to a specified email address), and also handled using the custom error handler.
First heard about Elmah from the Coding Horror blog entry, Crash Responsibly, and although it looks promising I'm yet to implement it any projects.
I've been using the Enterprise Library's Logging objects. It allows you to have different types of logging (flat file, e-mail, and/or database). It's pretty customizable and has a pretty good interface for updating your web.config for the configuration of the logging. Usually I call my logging from the On Error in the Global.asax.
Here's a link to the MSDN
I use log4net and where ever I expect an exception I log it to the appropriate level. I tend not to re-throw the exception because it doesn't really allow for as-nice user experience, there is less info you can provide at the current state.
I'll have Application_Error also configured to catch any exception which was not expected and the error is logged as a Fatal priority through log4net (well, 404's are detected and logged as Info as they aren't that high severity).
My team uses log4net from Apache. It's pretty lightweight and easy to setup. Best of all, it's completely configurable from the web.config file, so once you've got the hooks in your code setup, you can completely change the way logging is done just by changing the web.config file.
log4net supports logging to a wide variety of locations - database, email, text file, Windows event log, etc. My team has it configured to send detailed error information to a database, and also send an email to the entire team with enough information for us to determine in which part of the code the error originated. Then we know who is responsible for that piece of code, and they can go to the database to get more detailed information.
I recently built an asp.net webservice with NLog, which I use for all my desktop apps. The logging works fine when I'm debugging in Visual Studio, but as soon as I switch to IIS the log file isn't created; I've not yet determined why, but it the fact that I need to look for a solution makes me want to try something else for my asp.net needs!
We use EnterpriseLibrary.ExceptionHandling.Logging. I like it a bit better than log4net because not only do we control the logging completely, but we can control the Throw/NoThrow decision within config as well.
We use a custom homegrown logging util we wrote. It requires you to implement logging on your own everywhere you need it. But, it also allows you to capture a lot more than just the exception.
For example our code would look like this:
Try
Dim p as New Person()
p.Name = "Joe"
p.Age = 30
Catch ex as Exception
Log.LogException(ex,"Err creating person and assigning name/age")
Throw ex
End Try
This way our logger will write all the info we need to a SQL database. We have email alerts set up at the DB level to look for certain errors or frequently occurring errors. It helps us identify exactly where the errors are coming from.
This might not be exactly what you're looking for. Another approach similar to using Global.asax is to us a code injection technique like AOP with PostSharp. This allows you to inject custom code at the beginning and end of every method or on every exception. It's an interesting approach but I believe it may have a heavy performance overhead.

Resources