Strategy for handling unexpected database results on your website - c#

Maybe more of a general question than a .NET question, but in an instance where we get a database result that goes against expectation based on our understanding of the database structure (at the time of writing code), what do we do?
Take the code below; based on the fact that the "DataRetrievalName" of Model "DataRetrievals" is assumed to be unique at the time of coding, I should never get an InvalidOperationException. In the scenario where I do, it seems a bit phoned in to just pass the error message to the View, no? Thoughts on handling/logging strategies for these scenarios?
public ViewResult Edit(string resultSetToFind)
{
DataEntities db = new DataEntities();
DataResultSet viewModel = new DataResultSet();
try
{
//single resultset not found
viewModel.ResultSet = db.DataRetrievals.Single(r => r.DataRetrievalName == resultSetToFind);
}
catch (System.ArgumentNullException exception) {
//resultset not found
viewModel.ErrorMessage=System.Web.Http.WebHost.Properties.ErrorMessages.ResultSet_NameNotFound;
}
catch (System.InvalidOperationException exception) {
//more than one entry found, this should never happend
viewModel.ErrorMessage = System.Web.Http.WebHost.Properties.ErrorMessages.ResultSet_DuplicateNameFound;
}
return View(viewModel);
}

This is a pretty broad question. How exactly you go about handling errors is really up to your application. I'll provide what hints I can.
pass the error message to the View
Don't pass the error to the user.
Unless your application specifically requires it (perhaps an intranet could be an exception), the user doesn't need to know anything about the error. They probably don't care and, if they do, they might want to know for malicious reasons.
There is no need to show, for example:
ERROR 9001: Connection timeout for user 'root'#'200.100.50.25' (using password: NO)
An exaggeration, perhaps, but something bad could be revealed.
Instead, show a generic and friendly error page and state that something unexpected happened. Explain that is not the fault of the user and that a team of highly trained monkeys has been dispatched to deal with the situation.
Don't handle errors in controllers.
Well, maybe not never, but handling errors in controllers should be avoided. Try-catch blocks are very verbose and can quickly make code ugly and cumbersome. Controller actions should be as small and brief as possible.
Instead, I would recommend utilising Error Attributes.
public class DatabaseErrorAttribute : HandleErrorAttribute
{
public override void OnException(ExceptionContext filterContext)
{
// log exception and other details
}
}
You can handle different types of errors separately or simply use a generic error handler to capture everything. Either way you should log the error with as much detail as possible so that someone can investigate and fix the problem.
You can apply error attributes to individual actions, whole controllers or even the entire application.

Related

Designing Functions using Exception Handling

My Design Goals.
There are two cases when Further code of execution stops in that code block
1. When some run time error occurs
2. Based on some business logic
When there is an error it will throw exception and I dont want to show it to business user.
But when there is some business logic error/Validation failure then I want user to know as he/she can fix it and proceed further.
Example
Type 01: unable to cast to string Exception
Type 02: No Data is present in system against this criteria.
Code Block:
//int for Error Code to distinguish type 01 errors and type 02 errors.
//message for Error message
public int generateReport(ref string Message)
{
try
{
//Fetch Data here
if(no data present)
{
throw new Exception("No Data Present in system against this criteria").
}
string message = dataTable;
}
}
So what is the best way for "Type 02 Exception" so that I will be able to communicate problem to user.
And in case of "Type 01 Exception" I will simply say "Some Error Occured." and for developers/Support team I will show them exact reason for error without debugging facility they will be able to solve the problem.
Generally you should try not to use Exceptions for business logic flow, they're designed to be 'Exceptions' to the rule. You could instead use a return type:
public Status GenerateReport()
{
if(no data present)
return Status.NoData;
}
At this point you can use a lookup to go and find an appropriate message to display to that user. If you really want to use Exceptions, then create your own:
public class ReportException : Exception
{
public ReportException(String message) : base(message)
{}
}
At this point you can catch just ReportExceptions to to display messages to the user and ignore everything else. To improve this exception further you could instead provide an enum into the constructor, so the message is looked up:
public ReportException(Status status) { }
public String ReportStatus
{
get { return messages[this.status]; }
}
The advantage here is that it makes it easier to localize the messages if your application every requires additional languages.
Traditionally, your "type 2 exception" shouldn't be an exception at all. Exceptions are for exceptional circumstances - they occur when the program can't execute as expected, i.e. a situation such as your first example; a situation that ideally should never occur.
Your second example represents a situation that often will happen - the user is looking for something that just isn't there. That's expected so isn't cause for exceptions. In that situation, you should just return a value indicating that there is no data, then check for this value and display an appropriate message.
In some instances you may also want to log that this has occurred so you have an audit trail of user interactions, which will allow you to identify common patterns and/or explain after-the-fact why the user didn't find what he/she was looking for.
I agree with the rest, Exceptions are not supposed to control workflow and should not be used to drive business logic. With that said here are a couple of options to assist but of course there are many ways to skin this cat.
Code Contracts: for .net 4.5+
http://msdn.microsoft.com/en-us/library/dd264808(v=vs.110).aspx
Validation:
Le has an interesting way of handling this...
http://blog.longle.net/2013/06/03/building-an-extensible-fluent-validation-framework-using-generic-funcs-and-wiring-it-up-to-mvc-4/
Another validator..
https://fluentvalidation.codeplex.com/
Enterprise Library Validation:
http://www.codeproject.com/Articles/256355/Microsoft-Enterprise-Library-Introduction-to-V
Hope this helps... Le's is a pretty easy implementation.
Exceptions are used for exceptional cases. Read my article: What are exceptions
In your case you say that it's valid that no data is found, in that case you can communicate that by using a empty report (like string.Empty):
public Report GenerateReport(string message)
{
if(no data present)
{
return Report.Empty;
}
// create report here
return generatedReport;
}
Which uses a static readonly field in the report class:
public class Report
{
public static readonly Report Empty = new Report("This report is empty");
// read of the class like constructors etc.
}

AOP and Logging

Is aspect oriented programming really a solution for logging? Consider the following service call:
public MyServiceProxy : IMyServiceProxy {
public IEnumerable<string> GetAllData() {
try {
proxy.GetAllData();
} catch (NotSoCriticalException notCriticalEx) {
} catch (CriticalException criticalEx) {
}
}
In this example, I have 3 kinds of ways on how I log my message. The first one is when everything went fine, with log4net something like "logger.Info()", but even if both of the others fail, one might be critical, the other could suggest the user might try it again later, hence not considered critial. In all 3 cases, I have to log, but the advices on how to handle the aspect are totally different. How does AOP could help in such a scenario?
The AOP framework of your choice should let you create pre/post handlers for method calls. Therefore, this is the internal proxy.GetAllData() that should be wrapped.
In such wrapping handler, you catch exceptions and rethrow them so that the original code works normally, however the logging code gets the full access to the exception info.
In the other hand, wrapping the GetAllData at the class level doesn't make much sense as there is no detailed information passed to the outside of the method.

Error communication and recovery approaches in .NET

I am trying to do error communication and recovery in my C# code without using Exceptions.
To give an example, suppose there is a Func A, which can be called by Func B or Func C or other functions. Func A has to be designed keeping reuse in mind. (This application has an evolving library where new features will keep getting added over a period of time)
If Func A is not able to do what it is supposed to do, it returns an int, where any non-zero value indicates failure. I also want to communicate the reason for failure. The caller function can use this information in multiple ways:
It can show the error message to the user,
It may display its own error message more relevant to its context
It may itself return an int value indicating failure to further ancestor caller functions.
It may try to recover from the error, using some intelligent algorithm.
Hypothetically, any function on which other functions depend, may need to communicate multiple things to its caller function to take appropriate action, including status code, error message, and other variables indicating the state of data. Returning everything as a delimited string may not allow the caller function to retrieve the information without parsing the string (which will lead to its own problems and is not recommended).
The only other way is to return an object containing member variables for all required information. This may lead to too many 'state' objects, as each function will need to have its state object.
I want to understand how this requirement can be designed in the most elegant way. Note that at the time of coding, Func A may not know whether the caller function will have the intelligence to recover from the error or not, so I do not want to throw exceptions. Also, I want to see whether such a design is possible (and elegant at the same time) without using exceptions.
If the only way is to communicate using data objects for each function, then is it the way professional libraries are written. Can there be a generic data object? Note new functions may be added in future, which may have different state variables, or supporting information about their errors.
Also note that since the function's return value is a 'state' object, the actual data what it is supposed to return may need to be passed as a ref or out parameter.
Is there a design pattern for this?
I have read the following articles before posting this question:
http://blogs.msdn.com/b/ricom/archive/2003/12/19/44697.aspx
Do try/catch blocks hurt performance when exceptions are not thrown?
Error Handling without Exceptions
I have read many other articles also, which suggest not to use exceptions for code flow control, and for errors which are recoverable. Also, throwing exceptions have their own cost. Moreover, if the caller function wants to recover from exception thrown by each of the called functions, it will have to surround each function call with a try catch block, as a generic try catch block will not allow to 'continue' from the next line of the error line.
EDIT:
A few specific questions:
I need to write an application which will synchronize 2 different databases: one is a proprietory database, and the other is a SQL Server database. I want to encapsulate reusable functions in a separate layer.
The functionality is like this: The proprietory application can have many databases. Some information from each of these databases needs to be pushed to a single common SQL Server database. The proprietory application's databases can be read only when the application's GUI is open and it can be read only through XML.
The algorithm is like this:
Read List of Open databases in Proprietory Application
For each database, start Sync process.
Check whether the user currently logged in, in this database has the Sync Permission. (Note: each database may be opened using a different user id).
Read data from this database.
Transfer data to SQL Server
Proceed to next database.
While developing this application, I will be writing several reusable functions, like ReadUserPermission, ReadListOfDatabases, etc.
In this case, if ReadUserPermission finds that the permission does not exist, the caller should log this and proceed to next open database. If ReadListOfDatabases is not able to establish a connection with the Proprietory Application, the caller should automatically start the application, etc.
So which error conditions should be communicated should exceptions and which using return codes?
Note the reusable functions may be used in other projects, where the caller may have different error recovery requirements or capabilities, so that has to be kept in mind.
EDIT:
For all those advocating exceptions, I ask them:
If Func A calls Func B,C,D,E,F,G and Func B throws an exception on some error condition, but Func A can recover from this error and will like to continue rest of execution i.e. call Func B,C,D,..., how does exception handling allow to do this 'elegantly'? The only solution will be to wrap calls to each of B,C,D,... within a try catch block, so that remaining statements get executed.
Please also read these 2 comments:
https://stackoverflow.com/a/1279137/1113579
https://stackoverflow.com/a/1272547/1113579
Note I am not averse to using exceptions, if error recovery and remaining code execution can be achieved elegantly and without impacting performance. Also, slight performance impact is not a concern, but I prefer the design should be scalable and elegant.
EDIT:
Ok, Based on "Zdeslav Vojkovic" comments', I am now thinking about using exceptions.
If I were to use exceptions, can you give some use case when not to use exception, but use return codes? Note: I am talking about return codes, not the data which function is supposed to return. Is there any use case of using return codes to indicate success / failure, or no use case? That will help me understand better.
One use case of exceptions what I have understood from "Zdeslav Vojkovic" is when the callee function wants to compulsorily notify caller function of some condition and interrupt the caller execution. In the absence of exception, the caller may or may not choose to examine the return codes. But in case of exceptions, the caller function must necessarily handle the exception, if it wants to continue execution.
EDIT:
I had another interesting idea.
Any callee function which wants to support the idea of caller function recovering from its error can raise event, and check the event data after the event has been handled, and then decide to throw or not to throw exception. Error codes will not be used at all. Exceptions will be used for unrecovered errors. Basically when a callee function is unable to do what its contract says, it asks for "help" in the form of any available event handlers. Still if it is not able to perform the contract, it throws an exception. The advantage is that the added overhead of throwing exceptions is reduced, and exceptions are thrown only when the callee function or any of its caller functions are not able to recover from the error.
Suppose if the caller function does not want to handle the error, but rather the caller's caller function wants to handle the error, the custom event dispatcher will ensure that event handlers are called in the reverse order of event registration, i.e. the most recently registered event handler should be called prior to other registered event handlers, and if this event handler is able to resolve the error, the subsequent event handlers are not at all called. On the other hand, if the most recent event handler can not resolve the error, the event chain will propagate to the next handler.
Please give feedback on this approach.
How about a common FunctionResult object that you use as an out param on all your methods that you don't want to throw exceptions in?
public class FuncResultInfo
{
public bool ExecutionSuccess { get; set; }
public string ErrorCode { get; set; }
public ErrorEnum Error { get; set; }
public string CustomErrorMessage { get; set; }
public FuncResultInfo()
{
this.ExecutionSuccess = true;
}
public enum ErrorEnum
{
ErrorFoo,
ErrorBar,
}
}
public static class Factory
{
public static int GetNewestItemId(out FuncResultInfo funcResInfo)
{
var i = 0;
funcResInfo = new FuncResultInfo();
if (true) // whatever you are doing to decide if the function fails
{
funcResInfo.Error = FuncResultInfo.ErrorEnum.ErrorFoo;
funcResInfo.ErrorCode = "234";
funcResInfo.CustomErrorMessage = "Er mah gawds, it done blewed up!";
}
else
{
i = 5; // whatever.
}
return i;
}
}
Make sure all of your functions that can fail without exceptions have that out param for FuncResultInfo
"is it the way professional libraries are written?"
No, professional libraries are written by using exceptions for error handling - I am not sure if there is a pattern for using your suggested approach, but I consider it an anti-pattern (in .NET). After all, .NET itself is a professional framework and it uses exceptions. Besides, .NET developers are used to exceptions. Do you think that your library is really that special to force the users to learn completely different way of error handling?
What you just did is reinvent the COM error handling. If that is what you want to do then check this and ISupportErrorInfo interface for some ideas.
Why do you want to do this? I bet it is a performance 'optimization'.
Fear of performance issues with regard to exception handling is almost always a premature optimization. You will create an awkward API where each return value must be handled via ref/out parameters and which will hurt every user of your lib, just to solve the problem which likely doesn't exist at all.
"Func A may not know whether the caller function will have the
intelligence to recover from the error or not, so I do not want to
throw exceptions"
So you want to ensure that caller silently allows FuncA to mess up the system invariants and caller just goes on happily? It will just make it much harder to debug seemingly impossible bug which happens in another function later on due to this.
There are scenarios where it makes sense to avoid exceptions, but there should be a good justification for that. Exceptions are good idea.
EDIT: I see that you have added that you "have read many other articles also, which suggest not to use exceptions for code flow control". That is correct, exceptions in .NET are not for code flow but for error handling.
You ask:
If Func A calls Func B,C,D,E,F and it has to encapsulate each call
with try catch because it can recover from error or it will still like
to execute remaining function calls, then is not so many try catch
statements awkward
not more than alternative. You are making a mistake that you can simple handle all errors returned from functions in a same way but you usually can't.
Consider if you need to handle every function separately - worst case scenario and code is usually not written like that:
Result x, y;
try {
x = Function1();
}
catch(SomeException e) {
// handle error
}
try {
y = Function2();
}
catch(SomeOtherException e) {
// handle error
}
against:
int error;
Result x, y;
error = Function1(out x);
if(error != SOME_KNOWN_ISSUE) {
// handle error
}
error = Function2(out y);
if(error != SOME_KNOWN_ISSUE) {
// handle error
}
not a big difference. please don't tell me that you would not check the error code.
However, if you decide to ignore all errors (a horrible idea) then exceptions are simpler:
try {
var x = Function1();
var y = Function2();
var z = Function3();
}
catch Exception() { you still can see the message here and possibly rethrow }
vs
Result1 r1;
Function1(out r1);
Result2 r2;
Function2(out r2);
Result3 r3;
Function3(out r3);
// and here you still don't know whether there was an error
Can you elaborate what do you mean by "I need predictability with regard to time constraints"?
in some system level software or realtime stuff, you can't afford stack unwinding related to exception handling, as you can't guarantee the duration, and that could violate your timing requirements. But this is never the case in .NET as garbage collection is far worse in this regard.
Also, when you say "In .NET I would always use the exceptions for
error handling", can you explain how or what do you define as an error
condition? Is a recoverable situation an error condition or not an
error condition? –
#shambulater already gave a great example in comments. In FileStream, missing file is not recoverable and it will throw. In the client of FileStream it might be recoverable or not depending on context. Some clients will ignore it, some will exit the app, some will wrap it in another exception and let someone upstream to decide.
When will you not use exceptions?
In those cases where I would also not return an error code.
I use the FunctionResult approach extensively in ms-access and it works wonderfully. I consider it far better than error handling. For a start, each error message is application specific and is not the usually off target default error message. If the error propagates up a call list of functions, the error messages can be daisy chained together. This eventual error message looks like a call stack but is cleaner e.g. [Could not read photos from Drive F:, Could not read files, Drive not ready]. Wacko, I have just discovered that some Drives can be mounted but not ready. I could not have unit tested for that error as I didn't know that such an error could occur (means SD card reader is empty). Yet even without prior knowledge of this error, I could write an application that handled it gracefully.
My method is to call a method in a class that is written as a function that returns a boolean value. The return value is set to True in the last line of the function so if the function is exited before the last line, it is by default unsuccessful. I code, calling the function looks like if getphotos(folderID) then...do something .. Else report error. Inside the class module is a module level error variable (Str mEM) and it is read via a getter, so the class has an .em property which holds the error message. I also have a comment variable which is sometimes used like an error message, for example if the folder is empty, the code that looked for photos worked but did not return any photos. That would not be an error but it is something that I might want to communicate to the calling program. If there was an error, the user would get an error message and the calling procedure would exit. In contrast, if there was a cmt, such as 'no photos', then I might skill trying to read the photo metadata for example. How does Zdeslav Vojkovic handle subtlies like that with exceptions?
I am moving to C# hence finding this thread. I like the certainty of knowing why function calls failed (I interact with databases and filing systems all the time so I struggle to cover my projects with Unit Tests). I do agree with Zdeslav Vojkovic about using exceptions where their used is standard, but will not be be doing so in my own code. I am looking for a clean design pattern that allows me to validate parameters within the called function and to inform the caller if the parameters were not right.

Try - Catch return strategy

When using try-catch in methods, if you want you application to continue even if errors come along, is it okay to return the default value as return through the catch block, and log the error for later review?
For Example:
public static string GetNameById(int id)
{
string name;
try
{
//Connect to Db and get name - some error occured
}
catch(Exception ex)
{
Log(ex);
name = String.Empty;
}
return name;
}
Example 2:
public static string GetIdByName(string name)
{
int id;
try
{
//Connect to Db and get id- some error occured
}
catch(Exception ex)
{
Log(ex);
id = 0;
}
return id;
}
Is it okay to return any default value (depending on the return type of the method ...???) so that the application logic that required the result from this method do not crash and keeps going ....
Thanks in advance...
Regards.
The advice for exception handling is that mostly you should only catch exceptions that you can do something about (e.g. retry an operation, try a different approach, elevate security etc). If you have logging elsewhere in your application at a global level, this kind of catch-log-return is unnecessary.
Personally - typically - in this situation I'd do this:
public static string GetNameById(int id)
{
string name;
try
{
//Connect to Db and get name - some error occured
}
catch(Exception ex)
{
Log(ex);
throw; // Re-throw the exception, don't throw a new one...
}
return name;
}
So as usual - it depends.
Be aware of other pitfalls though, such as the calling method not being aware that there was a failure, and continuing to perform work on the assumption that the method throwing the exception actually worked. At this point you start the conversation about "return codes vs. throwing exceptions", which you'll find a lot of resources for both on SO.com and the internets in general.
I do not think that is a good solution. In my opinion it would be better to let the caller handle the exception. Alternatively you can catch the exception in the method and throw a custom exception (with the caught exception as the inner exception).
Another way of going about it would be to make a TryGet method, such as:
public static bool TryGetNameById(int id, out string name)
{
try
{
//Connect to Db and get name - some error occured
name = actualName
return true;
}
catch(Exception ex)
{
Log(ex);
name = String.Empty;
return false;
}
}
I think this approach is more intention revealing. The method name itself communicates that it may not always be able to produce a useful result. In my opinion this is better than returning some default value that the caller has to be able to know about to do the correct business logic.
My opinion is I'll never mute errors.
If some exception is thrown, it should be treated as a fatal error.
Maybe the problem is throwing exceptions for things that aren't exceptions. For example, business validation shoudn't be throwing such exceptions.
I'd prefer to validate the business and translate the errors in "broken rules" and transmit them to the presentation or wherever, that would save CPU and memory because there's no stack trace.
Another situation is a data connection loss or another situation that makes the application fall in a wrong state. Then, I'd prefer to log the error and prompt the user to re-open the application or maybe the application may restart itself.
I want to make you some suggestion: have you ever heard about PostSharp? Check it, you can implement that exception logging with an AOP paradigm.
It is advised that you only catch errors that you can handle and recover from. Catching and consuming exceptions that you cannot handle is bad form. However, some environments / applications define strict rules that go against this ideal behaviour.
In those cases, I would say in cases you don't have a choice, you can do what you like with returns - it is up to your application to work with them.
Based on the assumption that your application can handle any sort of failure in trying to get an ID, then returning a default ID is a good enough choice. You can go further and use something like the special case pattern to return empty / missing objects, but for simple data types this seems unwarranted.
this depends very much on the context and on the way your calling method is designed. I have used to return default values in the past as you are doing now and I understood only afterwards that it was deeply wrong...
you should imagine the catch block to throw the exception back, after logging it properly, then the calling method could have another try catch and depending on the severity of the error could inform the user or behave accordingly.
the fact is that if you return an empty string, in some cases, could be that the caller "thinks" there is a user with empty name, while would probably be better to notify the user that the record was not found, for example.
depending on the way your logger works you could log the exception only where you handle it and not in all catches...
That depends on what you want. If it's important for you that you log the exception, but that everything else keeps working, then this is - in my honest opinion- ok.
On the other hand: if an exception occurs, you have to make sure this does not have an impact on the further working of your application.
The point of a try/catch is to allow you to catch and handle errors in a graceful manor, allowing application execution to continue, rather than simply crashing the application and stopping execution.
Therefore it is perfectly acceptable to return a default value. However, be sure that all following code will continue to function if a default value is returned rather than causing further errors.
Eg - in your example, if the DB connection fails, ensure there are no further commands to edit / retrieve values from the database.
It REALLY depends. In most scenarios it is not - problems i that if there is a scenario specific issue you amy never find out. Soemtiems a recovery attempt is good. This normalyl depends on circumstances and actual logic.
The scenarios where "swallow and document" are really valid are rare and far in between in the normal world. They come in more often when writing driver type of thigns (like loaded moduels talkign to an external system). Whether a return value or default(T) equivalent maeks sense also depends.
I would say in 99% of the cases let the exception run up. In 1% of the cases it may well make sense to return some sensible default.
It is better to log the exception but then re-trow it so that it can be properly handled in the upper layers.
Note: the "log the exception part" is of course optional and depends a lot on your handling strategy(will you log it again somewhere else?)
Instead of making the app not crash by swalowing exception, it is better to let them pass and try to find the root cause why they were thrown in the first place.
Depends on what you want your app to do...
For example, display a friendly message, "Cannot Login" if you get a SqlException when trying to connect to the Database is OK.
Handling all errors is sometimes considered bad, although people will disagree...
Your application encountered an exception you did not expect, you can no longer be 100% sure what state your application is in, which lines of codes executed and which didn't, etc. Further reading on this: http://blogs.msdn.com/b/larryosterman/archive/2005/05/31/423507.aspx.
And more here : http://blogs.msdn.com/b/oldnewthing/archive/2011/01/20/10117963.aspx
I think the answer would have to be "it depends".
In some cases it may be acceptable to return an empty string from a function in case of an error. If you are looking up somebody's address to display then an empty string works fine rather than crashing the whole thing.
In other cases it may not work so well. If you are returning a string to use for a security lookup for example (eg getSecurityGroup) then you are going to have very undesired behaviour if you return the wrong thing and you might be better off keeping the error thrown and letting the user know something has gone wrong rather than pretending otherwise.
Even worse might be if you are persisting data provided to you by the user. Something goes wrong when you are getting their data, you return a default and store that without even telling them... That's gotta be bad.
So I think you need to look at each method where you are considering this and decide if it makes sense to throw an error or return a default value.
In fact as a more general rule any time you catch an error you should be thinking hard about whether it is an acceptable error and continuing is permissable or whether it is a show stopping error and you should just give up.

Using a message class static method taking in an action to wrap Try/Catch

I have a Result object that lets me pass around a List of event messages and I can check whether an action was successful or not.
I've realized I've written this code in alot of places
Result result;
try
{
//Do Something
...
//New result is automatically a success for not having any errors in it
result = new Result();
}
catch (Exception exception)
{
//Extension method that returns a Result from the exception
result = exception.ToResult();
}
if(result.Success) ....
What I'm considering is replacing this usage with
public static Result CatchException(Action action)
{
try
{
action();
return new Result();
}
catch (Exception exception)
{
return exception.ToResult();
}
}
And then use it like
var result = Result.CatchException(() => _model.Save(something));
Does anyone feel there's anything wrong with this or that I'm trading reusability for obscurity?
Edit: The reason I am trapping all exceptions is I use this code inside of my ViewPresenter classes at any point I interact with my model since if I get an unhandled exception I'd rather display the actual error to the user (internal app) as opposed to just redirecting them the generic error page.
I don't think there is anything wrong with using a functional approach, and passing in a lambda. That is perfectly valid.
That being said, I'd question your use in this specific scenario. Trapping all exceptions into a general purpose "Result" class seems dangerous. Ideally, you should be catching exceptions which you can handle correctly - not every possible exception and continuing.
That being said, if you really want to do this, I have a couple of suggestions for you:
1) I'd make a static, immutable result for success, and just do:
result = result.Success;
This avoids generating a new "success" each time you succeed, which hopefully is the most common option.
2) I'd probably avoid the extension method, and do:
result = new Result(exception);
This will be much more clear and obvious in intent, and there's really no reason to do an extension method in this case...
You shouldn't be catching Exception like this. You should only be catching known exception types that you know how to handle.
If you did that, you code would no longer be so repetitive, so there would be no case for using this pattern for re-usability.
All round this looks like a very bad idea, not just the lambda pattern, I'm talking about the handling of exceptions by converting them into results objects. You are basically allowing yourself to ignore all exceptions and continue working. There is a reason why C# error handling is done with exceptions and not with return codes, and that is because exceptions allow for structured, hierarchical and call stack based handling. Unless you have simplified the code for this question, I would reconsider your exception handling process.
In general though, I don't see anything wrong with the lambda pattern. I use something similar myself for wrapping multiple retries of a code block. But in this case I don't think it's what you need.
If you feel the need to write such an automated exception handler system you may be over-using exceptions, which could have serious performance implications.
However, this appears to be a generic system for converting exceptions into error codes - so why not just use error codes in the first place? Or learn to use exceptions more effectively so you don't feel the need to convert them into error codes? The fact that you are trying to convert them to something else should raise alarms and suggest to you that you're missing the point somewhere.

Categories