I had this situation not sure how to best handle this. Input would be appreciated. Imagine I Have such method:
void loaddata()
{
try
{
// EXTRA: I also want to skip below SaveSomething if there was exeption
// last time I called DecryptAndloadXMLdata. This may happen
// if user calls loaddata twice. This is exaclty similar situation
// as app quitting just it happens is user calls loaddata twice
// and during first call there was exception say with DecryptAndloadXMLdata
Savesomething(listOfObjects, xmlPath);//save old data first
xmlPath = newValue;
// some operations
xmlDoc = DecryptAndloadXMLdata(xmlPath);
// some other operations- populate List with data from above XML file
listOfObjects.Add(objectFromXML);
// Here also possibly modify contents of listOfObjects elements
}
catch(Exception ex)
{
xlmPath="";
}
}
Now the thing is when app is quiting I have such feature
to automatically save the List object populated in above
method to a file. Like:
void whenAppisQuitting()
{
Savesomething(listOfObjects, xmlPath);
}
But the problem is. Imagine xmlDoc = loadXMLdata(); throws in above method. What will happen is the List I mentioned won't be populated and when app is quitting empty elements (e.g. empty listOfObjects) will be written to xmlPath - thus damaging my original file because there was unrelated exception say due to encryption in loadXMLData method.
I hope I have made my issue clear. What is the way to deal with such situations? For example what I did you can see I set xmlPath to empty in catch - thus in case of any exception I considered data was not loaded successfully - hence now on application exit I can be calm because nothing will be written to file because its xmlPath ="". Is it reasonable way to solve this issue?
Getting bit confused because this kind of issues now raise error handling to different level - I need to account for all possible kind of failures?
What is the way to deal with such situations?
I would set a flag indicating there was an error when parsing. Setting the path to string.Empty can lead to confusion (IMO). Perhaps an empty string could be a possible value bring passed to your method.
catch(Exception ex)
{
// Log
IsParsingSuccessful = false;
}
And look upon that flag when you want to write:
void AppIsQuitting()
{
if (IsParsingSuccessful)
{
SaveSomething(listOfObjects, xmlPath);
}
}
As a general guidance, you probably should never overwrite files without explicit intent from the user.
As for your error handling, use a simple flag / boolean to indicate valid behavior. Only set that flag to true after everything is processed and only if that flag is true, save the contents to the file.
Related
We had a problem recently where one of the developers had changed a line of code from using HttpResponse.End to using HttpApplication.CompleteRequest when forcing a PDF to download in a similar fashion to the following:
https://stackoverflow.com/a/8590579/3856039
Doing so caused some PDF's to fail to download due to a non-breaking space issue so the code was changed back to using HttpResponse.End.
However, in helping my colleague I was carrying out some research and I came across the following question:
Is Response.End() considered harmful?
Which links to:
https://blogs.msdn.microsoft.com/aspnetue/2010/05/25/response-end-response-close-and-how-customer-feedback-helps-us-improve-msdn-documentation/
Given what is documented in the MSDN blog post, it sounds like using HttpResponse.End is the wrong approach, so I was wondering if it is even needed or whether there is a better approach?
Here is the actual code from Response.End:
public void End()
{
if (this._context.IsInCancellablePeriod)
{
HttpResponse.AbortCurrentThread();
return;
}
this._endRequiresObservation = true;
if (!this._flushing)
{
this.Flush();
this._ended = true;
if (this._context.ApplicationInstance != null)
{
this._context.ApplicationInstance.CompleteRequest();
}
}
}
The ThreadAbortException is used for control of flow-- basically allowing you to use Response.End in place of return. But if you've designed your handler well, you may not need it, e.g. if there is no code after Response.End(). It is generally better not to throw the exception if you can avoid it, since it (like all exceptions) will cause a stack unwind and some performance overhead.
Perhaps you can write your own version of Response.End and pick and choose which lines of code actually execute, e.g. maybe you want to flush the buffer and call CompleteRequest but you don't want to throw the exception.
Here is the approach I have used in the past
// Sends all currently buffered output
HttpContext.Current.Response.Flush(); to the client.
// Gets or sets a value indicating whether to send HTTP content to the client.
HttpContext.Current.Response.SuppressContent = true;
/* Causes ASP.NET to bypass all events and filtering in the HTTP pipeline
chain of execution and directly execute the EndRequest event. */
HttpContext.Current.ApplicationInstance.CompleteRequest();
I have some code that currently looks somewhat like this:
public void MainFunction()
{
try
{
SomeProblemFunction();
}
catch
{
AllFineFunction();
}
}
private void SomeProblemFunction() { ... }
private void AllFineFunction() { ... }
As you can see, I'm currently wrapping the call to SomeProblemFunction around a try statement because that function could fail (it relies on an outside web service call).
My question is this: should the try statement be a) outside the problem function (like I have it now) or b) inside the problem function?
Thanks.
Typically you want to allow your exceptions propagate up to your application boundaries. You're only going to want to do one of a few things with your exception:
Wrap it
Replace it
Let it propagate
Update
From your question it seems that you are looking for a fault tolerant solution for your web service calls. This is a more complex problem than simply "where do I put my try-catch?" You would still place your exception handling at the application boundary, but there you would implement your fault tolerance strategy. This would need to have many considerations, including asynchronously calling your web service, number of retry attempts, etc. I would suggest doing a search for web service fault tolerance.
What you have is correct; see the MSDN example:
public class ThrowTestB
{
static void Main()
{
try
{
// TryCast produces an unhandled exception.
TryCast();
}
catch (Exception ex)
{
// Catch the exception that is unhandled in TryCast.
Console.WriteLine
("Catching the {0} exception triggers the finally block.",
ex.GetType());
// Restore the original unhandled exception. You might not
// know what exception to expect, or how to handle it, so pass
// it on.
throw;
}
}
public static void TryCast()
{
int i = 123;
string s = "Some string";
object obj = s;
try
{
// Invalid conversion; obj contains a string, not a numeric type.
i = (int)obj;
// The following statement is not run.
Console.WriteLine("WriteLine at the end of the try block.");
}
finally
{
// Report that the finally block is run, and show that the value of
// i has not been changed.
Console.WriteLine("\nIn the finally block in TryCast, i = {0}.\n", i);
}
}
// Output:
// In the finally block in TryCast, i = 123.
// Catching the System.InvalidCastException exception triggers the finally block.
// Unhandled Exception: System.InvalidCastException: Specified cast is not valid.
}
As a rule of thumb I try and build code that focuses try catches to the exact spot the problem may occur.
That said both of your solutions are correct.
If it were my code I would do this
public void MainFunction()
{
try
{
SomeProblemFunction();
}
catch(Exception e)
{
Messagebox.Show(e.Message);
}
}
private void SomeProblemFunction() {
try{
web call
}
catch{
throw a specific exception related to this spot
}
}
private void AllFineFunction() { ... }
With this method you can easily create applications that handle a slew of very accurate exceptions
A fine question, I think. I'll attempt an answer.
If you want to recover within SomeProblemFunction, then it would make perfect sense to move the try...catch inside of that method. If, however, you are comfortable saying that if anything fails in SomeProblemFunction, then the whole thing is a failure, then keep it as you have it now and recover in (or throw from) MainFunction.
Thanks to the comment below, I'm adding some clarity. Depending on the specific exception that is being thrown within SomeProblemFunction, you may not have the ability to recover within that method. If you have a mixture of recoverable and non-recoverable, then it would be prudent to have the try...catch in both places.
The most important thing is that you NEVER catch an exception from which you cannot recover without throwing it on after doing your thing. It's tempting to add big broad catches (catch (Exception)) to avoid your app crashing during development, but it is never worth it. If those things make it into your production code, you've introduced a problem-solving and debugging nightmare.
In my opinion, there is no straight answer for this. The try catch is used to handle the exceptions that may occur. If your exception handling code is going in the main function then you should have the try catch in the main function. If your exception handling code in the problem function then you should add it to the problem function.
My preference though is to put it in both functions. If you put the try catch in the problem function, you can throw the exception and catch it in the main function. This always appear to other developers that the exception was thought of in that function and not missed handling it by mistake.
This depends on how severe this web service call failure would be.
Is it a failure that would prevent further processing of your code to run? If so, have no try/catch here, allowing it to propagate up to the guy who needs to know that this web service call failed. Optionally, you could still catch and throw a new exception with some more meaningful Exception type/ details.
Do you simply just want to re-try the web service call again if it doesn't work? IF so, then you have the try in the correct place; you just need to add a loop.
Is it not a big deal if this web service call fails? e.g. - will the rest of your code work OK? (I've found this to be uncommon). If so, leave the try/catch where it is, and log the error somewhere so that you're alerted.
First of all I am stumped. I have a search-module for a CMS that runs fine on one site, but it won't run as it's supposed to on another site.
I have this code I call both with an Ajax call and simply when loading the search site:
private string GetSearchContent()
{
Query q = GetQuery();
//for each area, set it up, perform search and render result
IArea products = new ProductArea(GetEcomExcludedGroupIDs(), GetEcomLanguage()).Search(q);
IArea pages = new PageArea(GetAreaId())
.Search(q);
IArea news = new NewsArea(GetIncludedNewsCategoryIDs())
.Search(q);
....
}
The important part here is the Search function. This is implemented in the classes, but for some reason the code won't be executed.
I have tried splitting the code up so I am sure that is where the error lies. The freaky part is that it does not throw any exceptions, but it just stops executing whenever I try to call the Search function. It doesn't even enter the function.
The Search function looks like this:
public override IArea Search(Query q)
{
log.Debug("Product search");
....
}
The function it overrides is simply an abstract function on an interface that declares the function.
I have tried copying the function to the same class that are executing it with no luck, and I have tried accessing other functions on the classes, and that worked fine.
My question is then. What could cause this behavior? I have tried looking around but couldn't really find any others with the same problem. And as mentioned before, the exact same code is running smoothly on another site.
I really hope someone can help me get closer to a fix, or at least to understand the problem.
The question is unanswerable as written. You assert that the Search method never runs, and that the faulty line is this one:
IArea news = new NewsArea(GetIncludedNewsCategoryIDs()).Search(q);
There are a few different things that could be wrong outside of the Search method:
The NewsArea constructor throws an exception
The GetIncludedNewsCategoryIDs method throws an exception
Either of the above could call into unmanaged code and generate a native Win32 exception, which under some circumstances will simple cause the process to terminate rather than ever returning to managed code.
You state that "there is no try-catch" -- all the more reason to disbelieve your assertion that the method just stops without throwing an exception. Try the following for diagnostic purposes:
try
{
IArea news = new NewsArea(GetIncludedNewsCategoryIDs()).Search(q);
}
catch (Exception e)
{
Logger.Log("Caught in the act: " + e.ToString());
throw;
}
If you've run this and still see that the execution stops without logging any exception, then we'll look at other possibilities.
I have an xmlbuilder utility class which calls a couple of methods to build an xml file
public XMLBuilder(String searchVal)
{
this.searchVal = searchVal;
try
{
getData();
returnedData = processDataInToOriginalFormat();
WriteBasicTemplate();
}
catch (WebException)
{
//If this is thrown then there was an error processing the HTTP request for MSO data.
//In this case then i should avoid writing the xml for concordance.
serviceAvailable = false;
MessageBox.Show("Could not connect to the required Service.");
}
catch (NoDataFoundException ndfe)
{
//propegate this back up the chain to the calling class
throw;
}
processDataInToOriginalFormat(); this is a method in a class which causes an exception if the service is not available and i have propagated the exception back to here to deal with. I was going to try and set a boolean flag to indicate whether to write a certain bit of xml. If the flag is false then dont write it.
I forgot however that exceptions stop programme flow and now i realise this isnt possible as if an exception occurs the rest of the code doesn't resume. how can i get around this? just add the WriteBasicTemplate(); call in to my catch clause?
Thanks
The logic of your code is somewhat confusing and as it's not obvious what "serviceAvailable = false" will do, it's hard to give detailed tips. The general rule of excetion handling is, to catch (and not rethrow) them, if you really know what to do with them and how to fix the problem. I you don't know that or the program will be in a state where it cannot continue working, let the exception go through and let your program crash.
In your case I might structure the code like this:
try
{
returnedData = processDataInToOriginalFormat();
// put code here which should only be executed in
// case of no exception
}
catch (WebException)
{
// do what ever is required to handel the problem
MessageBox.Show("Could not connect to the required Service.");
}
// code which should be executed in every case
WriteBasicTemplate();
You shoudl also look at the "finally"-block. Depending on your requirements, you should WriteBasicTemplate in such a block. But I would probably not do so in your case. It's rather used for resource cleanup or something like that.
I have a fairly large program (C#) that needs its functionality expanded by adding an option to turn off logging. The program takes a directory location as an argument, where it stores the log. I want it to not log anything if args[0] is empty. Right now the program has lines like this nested all over it:
DiagnosticLog.WriteLine("\t\t----Verifying Plugins were installed correctly----");
My first idea was to just create and do a check for a global flag within that function and run that line if it wasn't set. That way I could avoid using the same if statement around each of these lines all over the code. Is there a more clever way of just "turning off" these lines during run-time?
You could implement a version of DiagnosticLog that doesn't actually log anything, and use it in stead of your logging version if you don't want to log. That's assuming you know whether or not you want to log when you create the instance of DiagnosticLog (which I gather from the way you ask, you do).
How about modifying your DiagnosticLog.WriteLine function to take a second parameter doActualLog (bool) which has as default value true? Make some very minor modifications to DiagnoticLog to take this value into account. You can then decide at instantiation of DiagnosticLog if you want actual logging to happen or not.
You could just add an enabled flag to DiagnosticLog that is true by default. If args[0] is empty, call DiagnosticLog.Disable() to set it to false. Then in WriteLine and any other logging functions, check enabled before doing the actual logging.
Why don't you just call a log function that checks to see if the arg is empty?
public void WriteLine(string log) {
if (!firstArgIsEmpty) {
// Print to file.
}
}
How about using a System.Diagnostics.TraceListener class in conjunction with a System.Diagnostics.TraceSwitch? The functionality you seem to be after is already baked in.
You could create a property
public bool Log { get; set; }
string logFilePath;
public string LogFilePath
{
get { return logFilePath; }
set
{
logFilePath = ValidateLogFilePath(value);
Log = logFilePath.Length > 0;
}
}
public void WriteLine(string line)
{
if (!Log)
return;
//...
}
If you make a boolean property to indicate whether logging is occuring, then you could also use it to skip other sections of code that are not necessary if logging is not occuring. This could be useful if you are building any long strings just for logging purposes.
if (DiagnosticLog.Log)
{
DiagnosticLog.WriteLine("The following plugins were not installed:\r\n\t" +
string.Join("\r\n\t", GetMissingPluginNames()));
}