i have this application structure:
1. Presentation Layer which calls
2. Business Logic Layer which in turn calls
3. Data Access Layer to do the dealing with the database.
Now i have a Contacts page from where i can add a new contact to the database.
So to add a New Contact i fill in all the required details and then call a Add Method (residing in the BLL) from the page, which in turn call a Add Method residing in the DAL.
this method in the DAL returns the Current Identity of the record which is then return back to the BLL method and finally delivered on the page.
this is fine. but what if a get an exception how do i handle it properly because the method in DAL has a return type of int and i dont want to throw another error!! coz other wise i will have to write try catch in almost all the methods.
//something like this
public int AddMethod(ContactClass contactObj)
{
int result = 0;
try
{
result = ExecuteSomeSP("SPName", SP_Parameters);
}
catch(SQLException se)
{
throw new SQLException
}
return result;
}
rather i want to show the user a user-friendly message which they can easily understand and in the mean while i will send a mail to myself documenting the Error that just occurred.
Also kindly tell me how can i implement my custom exception classes.
Please tell me how do i do this!!
thank you.
You shouldn't need a try/catch in every method. But you usually need a try/catch in every Layer (for a certain action).
And that is proper, each layer has to deal with its own broken contracts, cleanup etc.
The conversion from Exception to "friendly message" is something for the GUI, not a lower layer.
And when you catch and re-throw an exception, make sure you don't loose information, forward it in the InnerException property:
try
{
// DAL
}
catch (DALException de)
{
// Log, ....
throw new BLLException(message, de);
}
Do not try catch in every method or layer, only were it is reasonable. A try catch should never act like a conditional. The presentation layer should never have logic in it.
Since your using a DAL interface I would create a custom DalException and throw that over the SQLException
public int addMethod(ContactClass contactObj) throws DalException {
try {
return ExecuteSomeSP("SPName", SP_Parameters);
}
catch(SQLException e) {
throw new DalException(e);
}
}
In your business logic layer catch the exception and produce the popup using the presentation layer
public void addMethod(ContactClass contactObj) {
try {
dal.addMethod(contactObj);
}
catch(DalException e) {
// notify user
view.alert(e.getMessage());
}
}
Related
I have seen similar questions, but not exactly this:
I would like to know the right way of determining whether a method is executed correctly or not, returning a boolean, and if the method is not executed know the reason, even if an exception is thrown.
I do it in this way, but I think that return inside the catch is a bad practice, so which is the right way?:
if(!myObject.DoSomething('A', out result))
{
MessageBox.Show(myObject.ErrorMessage);
[...]
}else{
MessageBox.Show(result);
[...]
}
class myObject()
{
public string ErrorMessage;
bool DoSomething(char inputValue, out string result)
{
try
{
if(inputValue == 'A')
{
ErrorMessage = "Bad input value: " + inputValue;
return false;
}
[...]
return true;
}catch(Exception ex){
ErrorMessage = ex.Message;
return false;
}
}
I don't like trhow the exception inside the catch because I lose the control of the application (and I can't get the description), and the exception always finish in the form. And if I show the exception in the form, I don't need try catch in the rest of the classes.
I mean that try {} catch(Exception ex) { throw ex;} is the same as not putting try catch.
thanks a lot
My suggestion would be to create your own Exception type (possibly global), and pass it in as a reference.
Thereafter you can still get back your boolean indicating success or failure (and having only one return outside of the try..catch).
public class CustomException
{
private string _message;
private string _title;
public CustomException()
{
_title = "";
_message = "";
}
public CustomException(string title, string message)
{
_title = title;
_message = message;
}
}
Then call DoSomething passing in an instance of CustomException (ce in this case).
CustomException ce = new CustomException();
Be advised this is the best process to solve the problem of having to return a boolean indicating success or failure and know the message, for example; dumping it to a log file or logging to database (particularly for Service Calls - WCF)
However this is not a solution for bad logic in handling business process.
Return false inside a catch isn't by itself bad practice. It's useful when you handle a piece of code's exceptions and it must not fail.
For example, I'm working on a printer piloting DLL at the time, and this DLL must read a XML file containing multiple records to print. The method must not fail because one record fails to print, but it still can return exception if the XML file is not correctly formated.
public void Print(string xmlFile)
{
if (String.IsNullOrWhiteSpace(xmlFile))
throw new ArgumentNullException("No xml file has been passed to the Print method.");
// This line will most likely throw an exception if the XMl file is not well formated
XDocument dom = XDocument.Load(xmlFile);
foreach (XElement n in dom.XPathSelectElements("//RECORDS/RECORD"))
{
try
{
// send commands to the printer, if the printer fails to print, throw a PrinterRecordException
}
catch (PrinterRecordException e)
{
// log print failure, but keep on printing the rest
continue;
}
catch (Exception e)
{
// dunno what happened, but still have to print the rest
continue;
}
}
}
In this example, my function could return false instead of throwing exceptions to the main program, if this program doesn't care. In my case it does :p In my opinion, that's how you should think your method.
Exception handling methods and best practices are a some-what subjective matter. I cannot attest to the method I'm about to present because I have only just started to use it in my own project.
What I suggest is having a static ExceptionHandler class with which you can register any exception to be handled by Generic Parameter and its corresponding handler. This will decouple your business logic from your UI in case you wanted to display some kind of message box when a particular exception occurs.
Here's an example:
/// the real implementation uses lambda's and/or implementations of IExceptionHandler<TException>
ExceptionHandler.Register<InvalidPasswordException>(() => /*some handler logic*/);
// ... else where in the code ...
catch (InvalidPasswordException ex)
{
// do resource clean-up and raise exception for listeners such as the UI or logging infrastructure.
ExceptionHandler.Raise(ex);
}
So far this looks promising, especially when compared with my previous approaches. But only time will tell.
Update
The ExceptionHandler class itself need not be static, for example you might want to have different instances of ExceptionHandlers at different layers of your application if you are using a layered architecture.
I am trying to figure out how to return exceptions and errors up to the controller level from my repository and be able to return custom errors to the client when they call my web service.
I have the following example from my BookRepository class:
public BookViewModel GetBookById(Guid id)
{
var Book = _Books.Collection.Find(Query.EQ("_id", id)).Single();
return Book;
}
obviously my function would be a little more complicated than this, but if i called this method on a id that did not exist i would get an exception. How can I have my exceptions and custom errors bubble up to my controller and then displayed nicely in the client response
Even a web service should follow the same patterns as any other code, with respect to exception handling. Those best practices include not using custom exceptions unless the caller is going to make a programmatic choice based on the exception type. So,
public BookViewModel GetBookById(Guid id)
{
try
{
var Book = _Books.Collection.Find(Query.EQ("_id", id)).Single();
return Book;
}
catch (SpecificExceptionType1 ex)
{
Log.Write(ex);
throw new Exception("Some nicer message for the users to read", ex);
}
catch (SpecificExceptionType2 ex)
{
Log.Write(ex);
throw new Exception("Some nicer message for the users to read", ex);
}
catch (Exception ex)
{
Log.Write(ex);
throw; // No new exception since we have no clue what went wrong
}
}
what edmastermind29 mentioned is one common way to do it. i would usually the same way.
but sometimes developers like to catch the exception before the controller and return a result message based on enumerated value for example , so the controller would have no try catch blocks for that call, it will only need to check the status message.
you can use out parameter to check status and display messages for users accordingly.
this is how ASP.NET Membership provider is implemented.
check the method create user in Membership provider for example:
http://msdn.microsoft.com/en-us/library/system.web.security.membershipprovider.createuser(v=vs.100).aspx
Place a try-catch around methods, LINQ queries, etc. that may fail given a circumstance (null value, empty value, invalid value, etc.). From there, you can catch the exception, and throw a custom exception tailored to what you are looking for. See below.
public BookViewModel GetBookById(Guid id)
{
try
{
var Book = _Books.Collection.Find(Query.EQ("_id", id)).Single();
return Book;
}
catch (Exception e)
{
Log.Write(e)
status = "Some Custom Message";
}
catch (DoesNotExistException dne)
{
Log.Write(dne)
status = "Some Custom Message about DNE";
}
}
Is there a way to check if exception is handled on a higher application level to skip logging and re-throw? Like this, for example:
try
{
// Execute some code
}
catch (Exception e)
{
if(!ExceptionIsHandled())
LogError(e);
throw e;
}
Nothing that I'm aware of. If you're committed to this design (see note at end), you could write a wrapper for an Exception that's some sort of HandledException and just make its InnerException be the one that was thrown. Then you could make your code look like:
try
{
// Execute some code
}
catch (HandledException e)
{
LogError(e.InnerException);
// Do something else
}
catch (Exception e)
{
throw ;
}
Here comes the stereotypical Stackoverflow "you're doin it wrong" part of the answer...
However, if you've truly "handled" the exception, it doesn't make a lot of sense to be re-throwing it. Maybe your method should just return a failure result, possibly including the Exception as a detail item for what went wrong.
This is old, but I do have some input here. There is a design pattern I've used before that does this very well, but does add a little bit of overhead to everything.
Basically, all methods would return a response object (e.g., Response<T>). Any exceptions that occur should be wrapped in the response object and returned instead of thrown.
public class Response<T>
{
public T Payload { get; set; }
public bool IsSuccessful { get; set; } = false;
public string Message { get; set; }
public Exception Error { get; set; }
}
public class MyService
{
public Response<IEnumerable<Customer>> GetCustomers()
{
var response = new Response<IEnumerable<Customer>>();
try
{
var customers = new List<Customer>()
{
new Customer() { CompanyName = "ABC Co." },
new Customer() { CompanyName = "ACME" }
};
response.Payload = customers;
response.IsSuccessful = true;
}
catch (Exception e)
{
response.IsSuccessful = false;
response.Error = e;
// A friendly message, safe to show to users.
response.Message = "An error occurred while attempting to retrieve customers.";
}
return response;
}
}
You can bubble up the exception without rethrowing it, and handle appropriately. You can then add exception catches for more custom user-friendly messages.
I also use a custom base Exception type for any errors that are safe to show the client. This way I can add a generic catch at the controller level to propagate those prepared error messages.
Well no, hasn't got there yet has it. Exceptions bubble up through handlers.
Usual way to go about this.
Is define your own exceptions, then only catch the ones you are going to handle where you are.
If you could be certain that code was wrapped within a specially-designed try-catch block which was written in a language that supports exception filters, it would be possible to determine before or during stack unwinding whether the exception was likely to be caught by that outer block or by an inner one. The usefulness of this is rather limited, however, especially given the extremely common anti-pattern of code catching and rethrowing exceptions that it knows it's not going to resolve, simply for the purpose of finding out that they occurred.
If your goal is simply to avoid redundant logging, I'd suggest that you should use a logging facility which can deal efficiently with redundancy. While some people might argue that it's better to have exceptions logged just once at the outer layers, there are advantages to having more logging opportunities. If an exception occurs within the inner layer and a middle layer swallows it, logging code within the outer layer will never find out about it. By contrast, if the inner layer starts out by capturing the exception and arranging for it to get logged, then even if the middle layer swallows the exception the fact that it occurred could still get recorded.
I have an MVC EF5 setup, with classes:
Program - this is the controller
UserInterface - this is the view, responsible for displaying and prompting for data.
DataAccess - Model, this Creates, Reads, Updates, and Deletes data in my EF model classes
When the DataAccess class tries to do a CRUD operation on my database, if it catches an error, it needs to be handled, my UserInterface class needs to print messages to the user, reporting any errors if neccessary. So, when an error happens, it needs to go through the program class first, then to the UserInterface class, because data layer shouldn't directly communicate to the presentation layer.
It was suggested to me that I don't pass or return the exception to a calling function, but that I should "throw a new simpler exception to the layers above". All this talk about exceptions is confusing to me because My experience with exceptions is limited to this format:
try
{
// stuff
}
catch (exception ex)
{
console.writeline(ex.ToString());
}
I've done some of my own research to try and find the answer to this problem, and I've learned a few things but don't know how to put it all together:
I learned:
throw; rethrows an exception and preserves the stack trace
throw ex throws an existing exception, such as one caught in a catch block. and resets the stack trace.
There is a property called Exception.StackTrace. I understand that each time an exception is thrown, the frames in the call stack are recorded to the Exception.StackTrace property.
However, I don't know where to place my try/catch blocks to utilize rethrowing
Is it something like the following code? Or am I missing the point on how this works?
EDITED: (added a little more to make sense of this guesswork to others)
void MethodA()
{
try
{
MethodB();
}
catch (MyExceptionType ex)
{
// Do stuff appropriate for MyExceptionType
throw;
}
}
void MethodB()
{
try
{
MethodC();
}
catch (AnotherExceptionType ex)
{
// Do stuff appropriate for AnotherExceptionType
throw;
}
}
void MethodC()
{
try
{
// Do Stuff
}
catch (YetAnotherExceptionType ex)
{
// Do stuff appropriate for YetAnotherExceptionType
throw;
}
}
There is more than how you use different type of exception handling. Functionally you should define what layers has to do what with a exception.
Like data layer => dont throw anything other than DataException or SQLException. Log them and throw back a generic database exception back to UI.
Business layer => log and rethrow simple bussiness exception
UI layer => catch only business exception and alert it in a message inside business exception
Once all this is defined, you can use what you have learned and summarized in question to build this.
What (I think) was suggested you do by throw a new simpler exception is that you translate the exceptions from the lower layers into new, higher level exceptions for consuming in the outer layers. The lower level exceptions are not suitable for consumption at the upper levels of the program.
For example, in LINQ to Entities, the method Single() will throw an InvalidOperationException when the sequence has no elements. However, this exception type is very common, so catching it in the user interface levels is hard to do: how would you differentiate between different possibilities of this exception being thrown (for example, modifying a read-only collection)? The solution is to translate the exception into another (new, user-defined) type that the application can easily handle.
Here is a simple example of the idea:
public class MyUserService {
public User GetById(int id) {
try {
using(var ctx = new ModelContainer()) {
return ctx.Where(u => u.Id == id).Single();
}
}
catch(InvalidOperationException) {
// OOPs, there is no user with the given id!
throw new UserNotFoundException(id);
}
}
}
Then the Program layer can catch the UserNotFoundException and know instantly what happened, and thus find the best way to explain the error to the user.
The details will depend on the exact structure of your program, but something like this would work in an ASP.NET MVC app:
public class MyUserController : Controller {
private MyUserService Service = new MyUserService();
public ActionResult Details(int id) {
User user;
try {
user = Service.GetById(id);
}
catch(UserNotFoundException) {
// Oops, there is no such user. Return a 404 error
// Note that we do not care about the InvalidOperationException
// that was thrown inside GetById
return HttpNotFound("The user does not exist!");
}
// If we reach here we have a valid user
return View(user);
}
}
I have a question about handling exception. I have a Winform that uses a webservice proxy on each form for data retrieval and processing. Here is where I really got confused and having a long time deciding which is better.
A. For each call in the web service do a try catch to display the error message and allow the user to re try the process by clicking the button again.
B. Since the error occurred on the web-service and the error was probably because the web service was inaccessible, just make a generic try catch in the WinMain function in the Program.cs and show an error message that web service is inaccessible before the application closes.
The main argument in this is A is more user friendly but needs a lot of try catch code. B is easier to code but just lets the application ends. I am leaning on A but am trying to search the net with options how to lessen the code needed to be written to do this. Any ideas there?
When you add a web reference, the code generator automatically adds "Async" methods to access the web service.
I would recommend that you use the Async methods rather than the synchronous methods. The nice thing about that is that the EventArgs for the Async methods provide an Error property that you can use to see if the request was successful or not.
private void CheckWebservice(string data)
{
WebService.Server server = new WebService.server();
server.methodCompleted += server_methodCompleted;
server.methodAsync(data);
}
private void server_methodCompleted(object sender, methodCompletedEventArgs e)
{
if (e.Error != null)
if (MessageBox.Show("Error", "Error", MessageBoxButtons.AbortRetryIgore) == DialogResult.Retry)
{
// call method to retry
}
else
{
if (e.Result == "OK") { // Great! }
}
}
If you must use the synchronous methods for some reason, then you could, of course, write a class to encapsulate the methods to call your web service so that you can call it from various places without duplicating the code. Your encapsulation class could do all the error handling and return a result.
class CallWebService
{
public enum Result
{ Unknown, Success, NotAvailable, InvalidData } // etc
public Call(string data)
{
Webservice.Server server = new Webservice.Server();
string result = string.Empty;
try
{
result = server.getResult(data);
}
catch (Exception ex) // replace with appropriate exception class
{
return Result.NotAvailable;
}
if (result == "OK") return Result.Success
else return Result.InvalidData;
}
}
Encapsulate the webservice call and the try/catch block inside a class =)