Exception Handling in a N tier application visual basic 2015

p-plater
p-plater used Ask the Experts™
on
I'm moving from vba to vb.net.
I have a 3 tier application - UI, BLL and DAL.

How is the best way to handle Exceptions?

I Know how to catch and throw them.
I have set up a Centralised Exception handler

At what point should I log the Exceptions?
Where they are thrown or in the UI?
If Where they are thrown then how do the Upper Layers know that the exception has been logged so I don't get duplicates?

It seems far easier to do all the Logging in the UI, This is being done by calling a Shared Sub in the BLL.
Is this Bad Practice?

I am looking to log the exceptions in the database and if that fails (No Connection to Database) then write to a Text file Log.
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Glanced up at my screen and thought I had coded the Matrix...  Turns out, I just fell asleep on the keyboard.
Most Valuable Expert 2011
Top Expert 2015
Commented:
I typically capture and log the exception at the top-most level of the service/business layer. This area then reformats the error into a more friendly message that gets passed back and displayed by the UI layer. The benefit of this is that if you ever switch UI technologies, you don't have to redo the exception logic; you only have to display the friendly message.

Author

Commented:
Thanks
So do you display a message box from the BLL?
Or how do you get the Message from the BLL to the UI?

Do you still have Try...Catch in the UI at all?

Author

Commented:
Also a Good point about Switching UI as I will be changing from winforms to WPF in the near future
Bootstrap 4: Exploring New Features

Learn how to use and navigate the new features included in Bootstrap 4, the most popular HTML, CSS, and JavaScript framework for developing responsive, mobile-first websites.

ǩa̹̼͍̓̂ͪͤͭ̓u͈̳̟͕̬ͩ͂̌͌̾̀ͪf̭̤͉̅̋͛͂̓͛̈m̩̘̱̃e͙̳͊̑̂ͦ̌ͯ̚d͋̋ͧ̑ͯ͛̉Glanced up at my screen and thought I had coded the Matrix...  Turns out, I just fell asleep on the keyboard.
Most Valuable Expert 2011
Top Expert 2015
Commented:
So do you display a message box from the BLL?
You don't. A message box is a UI concern.

Or how do you get the Message from the BLL to the UI?
You have some property on your DTO/model that holds error messages. In the UI layer, you read the messages from that object and display them on the screen.

Do you still have Try...Catch in the UI at all?
I try not to, but sometimes it's unavoidable. It all depends on what your design is.
Top Expert 2015
Commented:
First of all, your link to my article about centralized exception handling has an extra http://www.http.com// prefix that leads nowhere.

An exception is... exceptional. Unexpected exception are... unexpected. So, as so many things in programming, the answer to your question is that it is a case by case decision.

You can usually deal with some kind of exceptions right at the point where they occur, without having to log it, if you took the time to consult the documentation for possible exceptions and see that this specific exception could happen in that specific place. Problem solved, End Try and we go on.

Naturally, this is not always possible, because the correction sometimes requires some kind of intervention from the user, such as when a value is not correct for the field for which it was entered. You do not necessarily need to log these, because a message as to what is expected could be sufficient. This is usually best handled at the UI level, because using the same business layer, the message to display to the user can be different from one application to another, from one user (administrator) to another (guest). So, in the data access layer and/or the the business layer, this is usually:

Catch
   Throw

The exceptions that need to be logged are the unexpected exceptions, the ones that cannot be treated without intervention from the user, the ones that the user cannot correct by himself, or the ones that you thought would never occur.

I would almost (almost and usually are always part of these types of discussions) never do anything about these in the business layer, not even the UI. What can I do? I did not expect it. Sending the error message provided by the exception object to the user is most of the time more confusing than anything.

So, once again:

Catch
    Throw

It is was not treated anywhere down the line, it will eventually end up in my global error trap, and this is where it would be logged, and the application, most of the time, terminated, because a completely unexpected exception that is able go through all the previous steps could play very bad tricks on the data or the system.

Author

Commented:
Sorry - i should have tested the Link I pasted.

So with the centralized Exception Handling I don't need to have Try... Catch everywhere in the UI (Only where I can deal with the exceptions and move on) as any Unexpected Exceptions will be Handled by this  Handler.

kaufmed
What do you mean by a property to hold error messages?
Below is a sample I have that produces an error by calling a Database procedure that doesn't exist

It checks the Error for either a Transaction Deadlock or a String Truncation error - It handles these then records and throws for all other errors

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Try
            DatabaseErrorTestBLL.Save(25, "NoName")
        Catch ex As SqlException
            If ex.Number = 1205 Then
                MessageBox.Show("Transaction Deadlock. Please Re-run the Transaction.")
            ElseIf ex.Number = 6234 Or ex.Number = 7720 Or ex.Number = 8152 Or ex.Number = 35478 Then
                MessageBox.Show("Data would be Truncated. Please check the Length of the Data and Re-run the Transaction")
            Else
                MessageBox.Show("Connection to the Database has been Lost. The Application will now close")
                ExceptionRecorder.NewRecord(ex)
                Throw
            End If
        Catch ex As Exception
            MessageBox.Show("Connection to the Database has been Lost. The Application will now close")
            Throw
        End Try

    End Sub

Open in new window


The Save Sub that throws the Error
Public Class DatabaseErrorTestBLL
    Shared Sub Save(ByVal staffNo As Int32, ByVal name As String)
        Try
            DataBaseError.Save(staffNo, name)
        Catch ex As Exception
            Throw
        End Try
    End Sub
End Class

Open in new window


I then Record the Error with
Imports System.Data.SqlClient
Public Class ExceptionRecorder
    Shared Sub NewRecord(Ex As Exception)
        ExceptionRecorderData.save(Ex)
    End Sub

    Shared Sub NewRecord(Ex As SqlException)
        ExceptionRecorderData.save(Ex)
    End Sub
End Class

Open in new window


Where would I add a Property and How Check it?

Thanks All

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial