Error message handling due to exceptions - c#

i have a code to restart a service in an event which does other functions too.
I have a try catch in the event for everything within the event like this:
private void btnApply_Click(object sender, EventArgs e)
{
try
{
applyChangesAndCheckRestartService();
}
catch (Exception ex)
{
MessageBox.Show("Error loading page.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void applyChangesAndCheckRestartService()
{
string svrPortNo = CommonCodeClass.getTagValue(CommonCodeClass.xml_SvrPortNoTag, CommonCodeClass.configLocation + CommonCodeClass.configXML);
if (!ApplyChangesForSettings())
{
return;
}
if (svrPortNo != tbSvrPortNo.Text)
{
CommonCodeClass.CheckToRestartService();
}
}
Now if there is an error during ApplyChangesForSettings() i will get an error popup "Error loading page".
If there is an error in CheckToRestartService() i will get the same error because of the try catch.
Is there a better way to handle this.
Like i dont mind the error loading page for ApplyChangesForSettings() but for CheckToRestartService() i would like to see an error like "unable to restart service".
Any suggestions are appreciated.
Thanks
internal static void CheckToRestartService()
{
DialogResult result = MessageBox.Show(CommonCodeClass.resartServiceMessage, "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
if (result == DialogResult.Yes)
{
CommonCodeClass.RestartService(CommonCodeClass.serviceName, 60000);
}
}

Do they throw different exceptions? If they do you could use exception filtering:
private void btnApply_Click(object sender, EventArgs e)
{
try
{
applyChangesAndCheckRestartService();
}
// catch service start exceptions
catch (InvalidOperationException ioex)
{
// display message that couldn't start service
}
// catch rest
catch (Exception ex)
{
MessageBox.Show("Error loading page.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
UPDATE this is assuming you're calling something like ServiceController.Start() which throws InvalidOperationException on failure, you could easily throw this yourself on your own error condition or create your own custom exception.
if (/* service didn't start */)
{
throw new InvalidOperationException("Could not start service.");
}

You either need to
catch the exception in applyChangesAndCheckRestartService
or you could pass an enum by ref f.e. called RestartStatus
enum RestartStatus{success, unableToRestart, unableToApplySettings};
RestartStatus status = RestartStatus.success;
applyChangesAndCheckRestartService(status);
if(status != RestartStatus.success) //....
private void applyChangesAndCheckRestartService(out RestartStatus status)
{
// set the status variable accordingly
}
A third way is to use custom exceptions that you can catch separately.

Well maybe you just need to wrap the different functions with separate try/catch blocks:
try {
if (!ApplyChangesForSettings())
return;
}
catch (Exception ex) {
MessageBox.Show("Error loading page.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
if (svrPortNo != tbSvrPortNo.Text) {
try {
CommonCodeClass.CheckToRestartService();
}
catch (Exception ex) {
MessageBox.Show("Unable to restart services.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
Or, you could consider catching different types of exceptions, if they threw different types:
string errmsg = string.empty;
try {
DoSomething();
}
catch (FooException) {
errmsg = "There was a Foo error";
}
catch (WidgetException) {
errmsg = "There was a problem with a Widget";
}
catch (Exception ex) {
errmsg = "General problem: " + ex.Message;
}
if (!string.IsNullOrEmpty(errmsg))
MessageBox.Show(errmsg);
See also:
Exception Handling

The fastest way to handle this situation is throwing an exception when someone of your internal methods fails and catch the message in the btnApply_Click.
MessageBox.Show(ex.Message, "Error", .....);
The rightest way is to create your own exception type and inside the methods, if there is a fail condition throw your own exception. For example create a class like this
public class RestartServiceException : Exception
{
public RestartServiceException(string message)
: base(message)
{
}
// You could also write other constructors with different parameters and use internal logic
// to process your error message
}
and then, use an instance of that class when the fail condition arise inside your CheckToRestartService method
if(fail == true)
throw new RestartServiceException("The service could not be started because .....");

Related

ASP.NET Core Web API try catch exception question

In my API, I have over 25 API controllers, in every controller, using the following code to catch exception, I think it is too many code here, any good suggestion for the structure, thanks.
try
{
*code here*
}
catch (UnauthorizedAccessException ex)
{
}
catch (BadRequestException ex)
{
}
catch (HttpRequestException ex)
{
}
catch (TimeoutRejectedException ex)
{
}
catch (FileNotFoundException ex)
{
}
catch (SqlException ex)
{
}
catch (ValidationException ex)
{
}
catch (Exception ex)
{
}
Any simple way to do that.
IF
you plan to handle each exception separately - your approach is the way to go. I suggest to use this "ugly" code simply because it is more readable. If all your exceptions have common handling (for example logging) - you can use only catch (Exception e) and call your logging methods. This will work for all types of exceptions.
OR
If you decide that some of your exceptions might have common handling - you can go with:
try
{
// do
}
catch (Exception e)
{
if (e is BadRequestException ||
e is HttpRequestException ||
e is TimeoutRejectedException )
{
// Log exception
}
}
OR
A good approach is to use a delegate for exception handling. Since you're going to log exceptions, the delegate will handle this.
Action<Exception> HandleError = (e) => {
// Log exception
};
catch (UnauthorizedAccessException e) { HandleError(e); }
catch (BadRequestException e) { HandleError(e); }
catch (HttpRequestException e) { HandleError(e); }
OR
You can combine the first and the second approach
if (e is BadRequestException ||
e is HttpRequestException ||
e is TimeoutRejectedException )
{
HandleError(e);
}

how to give an error at the line in my function

I've the function that uses a password, when I was running the program, the error in the function does not appear in the message box that I put on the catch, how to give an error on the line that give an error?
public void CheckContent(string FileExe, string password)
{
try
{
SevenZipExtractor szip = new SevenZipExtractor(FileExe, password); // <-- error if wrong password
foreach (ArchiveFileInfo file in szip.ArchiveFileData)
{
string NamaFile = file.FileName;
string format = file.Extension;
string[] row;
row = new string[] { NamaFile, format };
DGVDekripsi.Rows.Add(row);
}
}
catch (IOException ex)
{
MessageBox.Show(this, ex.Message, "Proses Cek Isi File Exe", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
Probably the type of throwing exception is different than IOException, your catch block will catch only IOException's. Try this:
catch (Exception ex)
{
MessageBox.Show(this, ex.Message, "Proses Cek Isi File Exe", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
If you write ex.GetType() you will see the type of exception.Then if you wish you can add extra cath block to catch that exception and you can handle it properly.
Are you sure that your exception rise? or it's a general exception, did you trace it?
i think you have a normal exception not IOException

How to go from one exception handler to another?

The best way to explain my question is with the following pseudo-code:
try
{
//Do work
}
catch (SqlException ex)
{
if (ex.Number == -2)
{
debugLogSQLTimeout(ex);
}
else
{
//How to go to 'Exception' handler?
}
}
catch (Exception ex)
{
debugLogGeneralException(ex);
}
Exception ex = null;
try
{
//Do work
}
catch (SqlException sqlEx)
{
ex = sqlEx;
if (ex.Number == -2)
{
//..
}
else
{
//..
}
}
catch (Exception generalEx)
{
ex = generalEx;
}
finally()
{
if (ex != null) debugLogGeneralException(ex);
}
The first catch clause that matches is the only one that can possibly run on the same try block.
The best way I can think of to do what you're attempting is to include casts and conditionals in the more general type:
try
{
//Do work
}
catch (Exception ex)
{
var sqlEx = ex as SqlException;
if (sqlEx != null && sqlEx.Number == -2)
{
debugLogSQLTimeout(ex);
}
else
{
debugLogGeneralException(ex);
}
}
If you find yourself writing this over and over again throughout your data layer, at least take the time to encapsulate it in a method.
I do not believe there is any way to do this as the catch blocks are in different scopes. There's no way to re-throw without exiting the try block and no way to 'call' the final catch block because it's only triggered during an exception.
I would suggest the same as roman m above and just make the same call. Otherwise you have to do something really bad. Like the below crazy code which you should never ever use but i included because it does something like what you want.
In general I think what you are doing is controlling normal flow via exceptions which isn't recommended. If you are trying to track for timeouts, you should probably just handle that another way.
Note that you could do something like the code below with the insanity of a goto statement, but i included it so no one can forget what a bad idea this is. =)
void Main()
{
Madness(new NotImplementedException("1")); //our 'special' case we handle
Madness(new NotImplementedException("2")); //our 'special' case we don't handle
Madness(new Exception("2")); //some other error
}
void Madness(Exception e){
Exception myGlobalError;
try
{
throw e;
}
catch (NotImplementedException ex)
{
if (ex.Message.Equals("1"))
{
Console.WriteLine("handle special error");
}
else
{
myGlobalError = ex;
Console.WriteLine("going to our crazy handler");
goto badidea;
}
}
catch (Exception ex)
{
myGlobalError = ex;
Console.WriteLine("going to our crazy handler");
goto badidea;
}
return;
badidea:
try{
throw myGlobalError;
}
catch (Exception ex)
{
Console.WriteLine("this is crazy!");
}
}
// Define other methods and classes here

Catch oledb Exception with a specific error code

I'm trying to catch a duplicate key violation. I can see the System.OleDB.OleDBException in the Intellisense pop up, but the inner exception is null. How do I access the Error Code in the System.OleDB.OleDBException?
Greg
try
{
MyData.ConExec(sSQL);
}
catch (Exception ex)
{
OleDbException innerException = ex.InnerException as OleDbException;
if (innerException.ErrorCode == -2147217873)
{
// handle exception here..
}
else
{
throw;
}
}
don't declare an instance of the exception. It will surely return empty if you do.
try
{
MyData.ConExec(sSQL);
}
catch (OleDbException ex)
{
// handle excpetion here...
if (ex.ErrorCode == -2147217873)
{
}
}
catch (Exception e)
{
// if other exception will occur
}

Can I not catch a specific or custom exception?

I dont want to catch some exception. Can I do it somehow?
Can I say something like this:
catch (Exception e BUT not CustomExceptionA)
{
}
?
try
{
// Explosive code
}
catch (CustomExceptionA){ throw; }
catch (Exception ex)
{
//classic error handling
}
try
{
}
catch (Exception ex)
{
if (ex is CustomExceptionA)
{
throw;
}
else
{
// handle
}
}
Starting with C# 6, you can use an exception filter:
try
{
// Do work
}
catch (Exception e) when (!(e is CustomExceptionA))
{
// Catch anything but CustomExceptionA
}
You can filter it:
if (e is CustomExceptionA) throw;
And of course you can catch it and rethrow it:
try
{
}
catch (CustomExceptionA) { throw; }
catch (Exception ex) { ... }
First off, it's bad practice to catch Exception unless you log and re-throw it. But if you must, you need to catch your custom exception and re-throw it like so:
try
{
}
catch (CustomExceptionA custome)
{
throw custome;
}
catch (Exception e)
{
// Do something that hopefully re-throw's e
}
After being schooled by #Servy in the comments, I thought of a solution that'll let you do [what I think] you want to do. Let's create a method IgnoreExceptionsFor() that looks like this:
public void PreventExceptionsFor(Action actionToRun())
{
try
{
actionToRun();
}
catch
{}
}
This can then be called like this:
try
{
//lots of other stuff
PreventExceptionsFor(() => MethodThatCausesTheExceptionYouWantToIgnore());
//other stuff
}
catch(Exception e)
{
//do whatever
}
That way, every line except for the one with PreventExceptionsFor() will throw exceptions normally, while the one inside PreventExceptionsFor() will get quietly passed over.

Categories

Resources