Context
I've written a class to handle settings for my ASP.NET MVC app. However after testing how it handles a malformed/ missing XML file the exception it seems to throw is uncatchable and it repeats endlessly without catching or moving on with execution.
I've disabled the V.S. Debug Dialog popup in the past but again it seems repeat the same segment of code. I do not have a loop anywhere else that calls this property and there is default behavior if the property doesn't return a valid value.
Breakpoints beyond the failing function are not reached, however the breakpoint on or before the XML exception are repeatedly reached...
P.S. there is a lot of failed testing code left over to get a workaround working.
Screenshot:
Screenshot:
EDIT: I must clarify I have tried alternate XML parsing tools, any XMLException here is not caught.
Code ['Setting container' Property]:
private static Settings _singletonSettings;
public static Settings SettingsContainer
{
get
{
if (_singletonSettings == null)
{
_singletonSettings = new Settings();
_singletonSettings .LoadSettings();
}
return _singletonSettings;
}
private set
{
_singletonSettings = value;
}
}
Code ['LoadSettings function']:
public void LoadSettings()
{
string filePath = "Config/Settings.txt";
if (!Directory.Exists(Path.GetDirectoryName(filePath)))
{
Directory.CreateDirectory(Path.GetDirectoryName(filePath));
}
if (File.Exists(filePath))
{
try
{
SettingsContainer = LoadViaDataContractSerialization<Settings>(filePath); // Desperately trying to catch the exception.
}
catch (Exception ex)
{
Log.GlobalLog.WriteError("LoadViaDataContractSerialization() error:\n" + ex.Message + "\nStackTrace: \n" + ex.StackTrace);
}
}
else
{
File.Create(filePath);
}
if (SettingsContainer == null)
{
SettingsContainer = new Settings();
}
}
Code ['LoadViaDataContractSerialization']:
public static T LoadViaDataContractSerialization<T>(string filepath)
{
try
{
T serializableObject;
using (var fileStream = new FileStream(filepath, FileMode.Open))
{
try
{
using (var reader = XmlDictionaryReader.CreateTextReader(fileStream, new XmlDictionaryReaderQuotas())) //All execution stops here with the
{
var serializer = new DataContractSerializer(typeof(T));
serializableObject = (T)serializer.ReadObject(reader, true);
reader.Close();
}
}
catch (XmlException ex)
{
Log.GlobalLog.WriteError("LoadViaDataContractSerialization() XML Fail: Message: " + ex.Message + "\n StackTrace: " + ex.StackTrace);
return default(T);
}
fileStream.Close();
}
return serializableObject;
}
catch (Exception ex)
{
Log.GlobalLog.WriteError("LoadViaDataContractSerialization() Fail: Message: " + ex.Message + "\n StackTrace: " + ex.StackTrace);
return default(T);
}
}
Looks like the issue lay with a lack of understanding in 'return default(T)'.
I'm not sure why it was repeating but by removing the try catch blocks that returned 'default(T)' and responding to the exception 'return new settings()' it allowed the properties value to not be null and function as intended.
Code LoadViaDataContractSerialization:
public static T LoadViaDataContractSerialization<T>(string filepath)
{
T serializableObject;
using (var fileStream = new FileStream(filepath, FileMode.Open))
{
using (var reader = XmlDictionaryReader.CreateTextReader(fileStream, new XmlDictionaryReaderQuotas()))
{
var serializer = new DataContractSerializer(typeof(T));
serializableObject = (T)serializer.ReadObject(reader, true);
reader.Close();
}
fileStream.Close();
}
return serializableObject;
}
Code LoadSettings:
public void LoadSettings()
{
string filePath = "Config/Settings.txt";
if (!Directory.Exists(Path.GetDirectoryName(filePath)))
{
Directory.CreateDirectory(Path.GetDirectoryName(filePath));
}
if (File.Exists(filePath))
{
try
{
SettingsContainer = LoadViaDataContractSerialization<Settings>(filePath);
}
catch (Exception ex) //only exception needed
{
Log.GlobalLog.WriteError("LoadViaDataContractSerialization() error:\n" + ex.Message + "\nStackTrace: \n" + ex.StackTrace);
SettingsContainer = new Settings();//<---this was the fix
}
}
else
{
File.Create(filePath);
}
if(SettingsContainer == null)
{
SettingsContainer = new Settings();
}
}
Thank you to 'Generic Snake' for pointing me at the right place.
Related
I'm trying to use Mutex to handle different process/application to write on same file.
This is my code
ILogTest logTest = new LogTest(new FileLog());
logTest.PerformanceTest();
public class ILogTest
{
public void PerformanceTest()
{
for (int i = 0; i < this.numberOfIterations; i++)
{
try
{
Thread threadC = Thread.CurrentThread;
threadC = new Thread(ThreadProc);
threadC.Name = i.ToString();
threadC.Start();
threadC.Suspend();
threadC.IsBackground = true;
}
catch (Exception)
{
throw new Exception("errore");
}
}
}
private void ThreadProc()
{
try
{
log.Write("Thread : " + Thread.CurrentThread.Name.ToString());
this.log.Write("Thread : " + Thread.CurrentThread.Name.ToString());
this.log.Write("Thread : " + Thread.CurrentThread.Name.ToString());
this.log.Write("Thread : " + Thread.CurrentThread.Name.ToString());
}
catch (Exception)
{
throw new Exception("errore");
}
}
}
FileLog is an implementation of ILogTest.
Write method :
public void Write(string message)
{
try
{
rwl.WaitOne();
try
{
string tID = Thread.CurrentThread.ManagedThreadId.ToString(CultureInfo.CurrentCulture);
sw.WriteLine(sev.ToString() + "\t" + DateTime.Now.ToString("dd.MM.yyyy hh:mm:ss", CultureInfo.CurrentCulture) + "\t\t" + System.Reflection.Assembly.GetCallingAssembly().GetName().Name + "\t" + Process.GetCurrentProcess().Id.ToString(CultureInfo.CurrentCulture) + "\t" + tID + " \t " + message);
sw.WriteLine("------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------");
}
catch (Exception ex)
{
throw new ArgumentException("Cannot write to file " + ex.Message);
}
finally
{
rwl.ReleaseMutex();
}
}
catch (ApplicationException)
{
}
}
FileLog main :
public FileLog()
{
try
{
rwl.WaitOne();
string filePath = Path.GetTempPath() + "Test.txt";
if (!File.Exists(filePath))
{
swa = new FileStream(filePath, FileMode.Append, FileAccess.Write);
sw = new StreamWriter(swa);
}
}
catch (Exception ex)
{
throw new ArgumentException("Cannot open or create file " + ex.Message);
}
try
{
if (sw == null)
{
swa = new FileStream(filePath, FileMode.Append, FileAccess.Write);
sw = new StreamWriter(swa);
}
sw.AutoFlush = true;
}
catch (Exception ex)
{
throw new ArgumentException("Cannot write to file " + ex.Message);
}
}
Trying simulate it, it doesn't write anything to file, only create it..
I don't know why.
Could anyone help me? thanks
The FileLog constructor calls rwl.WaitOne() which acquires the mutex (I'm assuming rwl is a Mutex object), but never calls rwl.ReleaseMutex().
Thus, every thread that calls Write() blocks on its call to rwl.WaitOne() because the mutex is still owned by another thread.
You will need to release the Mutex in the FileLog constructor so that other threads can acquire it.
Also, you have a call to threadC.Suspend(); in PerformanceTest; unless there is code that resumes the threads, they will never finish running.
Actually, I want to log the data in such a way that it should have the methods that the application goes through in c#, and if there is an error then the error content also should be logged. the problem is where to call the log methods inside of catch or inside of every method? as I have nearly 200 methods.
I wrote the code like this:
public static bool Logging(System.Reflection.MethodBase methodInfo)
{
var fullMethodName = methodInfo.DeclaringType.FullName + "." + methodInfo.Name;
if (error_flag == false)
{
using (StreamWriter outputFile = new StreamWriter(path + #"\log.txt", true))
{
outputFile.WriteLine(fullMethodName + ": OK");
}
}
else
{
using (StreamWriter outputFile = new StreamWriter(path + #"\log.txt", true))
{
outputFile.WriteLine("\n\n --> Error in : " + fullMethodName);
}
}
return true;
}
//Logging Method 2
public static bool WriteErrorLog(Exception ErrorMessage)
{
using (StreamWriter outputFile = new StreamWriter(path + #"\log.txt", true))
{
outputFile.WriteLine("{0} Exception caught.", ErrorMessage);
}
return true;
}
and I have to call those methods from where??
I would suggest the following approach:
static void Main()
{
try
{
Log.Info("Start of process");
string input = StepOne();
StepTwo(input);
Log.Info("End of process");
}
catch(Exception e)
{
Log.Error(e);
}
}
public static string StepOne()
{
Log.Info("StepOne Completed");
return "Step One";
}
public static void StepTwo(string input)
{
Log.Info("StepTwo, input: " + input);
throw new ArgumentNullException("input");
}
Rather than rolling your own, use an existing logging framework, for example Log4Net.
Add a try catch at the highest possible layer, let errors bubble up until you can actually do something sensible with them.
Add logging messages to functions where it is sensible to do so, this will be the most useful information, for example you can log method inputs.
Avoid using reflection to get the method name, you probably don't need to log individual method names. All of that information will be in the stack trace anyway.
I'm stumped on why I can't validate the XML file to a schema and then deserialize the xml into an class.
I can do either or. i.e. if I comment out the ValidateXML then the ConvertToObject works and vice versa. If leave both in that I get an error : "There is an error in XML document (0, 0)" (Usually when I get this error I usually have left the document open prior to deserializing it.
My main logic
foreach (var myFile in Directory.EnumerateFiles(#"C:MyFolder", "*.xml"))
{
try
{
using (var fileStream = new FileStream(myFile, FileMode.Open, FileAccess.Read))
{
if (ValidateXML(fileStream))
{
CreateObjects(fileStream);
goodCounter++;
}
else
{
sb.AppendLine("Validation failed for: " + myFile);
badCounter++;
}
}
}
catch
{
sb.AppendLine(myFile);
}
}
My validate method:
private bool ValidateXML(Stream stream)
{
try
{
XmlDocument xDoc = new XmlDocument();
xDoc.Load(stream);
xDoc.Schemas.Add(null, #"C:My_XSD.xsd");
ValidationEventHandler eventHandler = new ValidationEventHandler(ValidationEventHandler);
xDoc.Validate(eventHandler);
return true;
}
catch
{
return false;
}
}
static void ValidationEventHandler(object sender, ValidationEventArgs e)
{
switch (e.Severity)
{
case XmlSeverityType.Error:
//Console.WriteLine("Error: {0}", e.Message);
throw new Exception(e.Message);
//break;
case XmlSeverityType.Warning:
//Console.WriteLine("Warning {0}", e.Message);
throw new Exception(e.Message);
//break;
}
}
Kevin was right...
fileStream.Seek(0, SeekOrigin.Begin);
If at all returning within try/catch/finally in not considered a structured programming how can I return from the below code block ?
public static string ReadFile()
{
StreamReader streamReader = null;
try
{
try
{
streamReader = new StreamReader(#"C:\Users\Chiranjib\Downloads\C# Sample Input Files\InputParam.txt"); //Usage of the Verbatim Literal
return streamReader.ReadToEnd();
}
catch (FileNotFoundException exfl)
{
string filepath = #"C:\Users\Chiranjib\Downloads\C# Sample Input Files\LogFiles.txt";
if (File.Exists(filepath))
{
StreamWriter sw = new StreamWriter(filepath);
sw.WriteLine("Item you are searching for {0} just threw an {1} error ", exfl.FileName, exfl.GetType().Name);
Console.WriteLine("Application stopped unexpectedly");
}
else
{
throw new FileNotFoundException("Log File not found", exfl);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.StackTrace);
return string.Empty;
}
//Code inside finally gets executed even if the catch block returns when an exception happens
finally
{
//Resource de-allocation happens here
if (streamReader != null)
{
streamReader.Close();
}
Console.WriteLine("Finally block executed");
}
}
catch (FileNotFoundException ex)
{
Console.WriteLine("Log file not found ");
Console.WriteLine("Original exception " + ex.GetType().Name);
Console.WriteLine("Inner Exception " + ex.InnerException.GetType().Name);
}
finally
{
if (streamReader != null)
{
streamReader.Close();
}
Console.WriteLine("Finally block executed");
}
return streamReader.ReadToEnd() ?? string.Empty;
}
Thing is if I at all close the streamReader object before even getting it's value I would not be able to obtain a returned result.
But again it does not allow me to put a return in finally.
Please help me understand and overcome this difficulty in a standard way.
The easiest way for you to resolve this would be to just declare a variable inside your code and then read that out at the end.
For example.
public static string ReadFile()
{
var stringFile = "";
StreamReader streamReader = null;
try
{
try
{
streamReader = new StreamReader(#"C:\Users\Chiranjib\Downloads\C# Sample Input Files\InputParam.txt"); //Usage of the Verbatim Literal
stringFile = streamReader.ReadToEnd();
return stringFile
}
catch (FileNotFoundException exfl)
{
string filepath = #"C:\Users\Chiranjib\Downloads\C# Sample Input Files\LogFiles.txt";
if (File.Exists(filepath))
{
StreamWriter sw = new StreamWriter(filepath);
sw.WriteLine("Item you are searching for {0} just threw an {1} error ", exfl.FileName, exfl.GetType().Name);
Console.WriteLine("Application stopped unexpectedly");
}
else
{
throw new FileNotFoundException("Log File not found", exfl);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.StackTrace);
return string.Empty;
}
//Code inside finally gets executed even if the catch block returns when an exception happens
finally
{
//Resource de-allocation happens here
if (streamReader != null)
{
streamReader.Close();
}
Console.WriteLine("Finally block executed");
}
}
catch (FileNotFoundException ex)
{
Console.WriteLine("Log file not found ");
Console.WriteLine("Original exception " + ex.GetType().Name);
Console.WriteLine("Inner Exception " + ex.InnerException.GetType().Name);
}
finally
{
if (streamReader != null)
{
streamReader.Close();
}
Console.WriteLine("Finally block executed");
}
return stringFile;
}
This should then read out your file by executing the following code
static void Main(string[] args)
{
var file = ReadFile();
Console.WriteLine(file);
Console.ReadLine();
}
I think you could eliminate several of those try/catch sequences and take care of disposing StreamWriter and StreamReader by using "using" statements. Here's an example:
using System;
using System.IO;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
var fileContents = ReadFile();
Console.ReadLine(); // cause program to pause at the end
}
public static string ReadFile()
{
try
{
using (var streamReader = new StreamReader(
#"C:\MyTestFile.txt"))
{
var fileContents = streamReader.ReadToEnd();
Console.WriteLine("File was read successfully");
return fileContents;
}
}
catch (FileNotFoundException fileNotFoundException)
{
LogReadFileException(fileNotFoundException);
}
catch (DirectoryNotFoundException directoryNotFoundException)
{
LogReadFileException(directoryNotFoundException);
}
catch (IOException ioException)
{
LogReadFileException(ioException);
}
// If we get here, an exception occurred
Console.WriteLine("File could not be read successfully");
return string.Empty;
}
private static void LogReadFileException(Exception exception)
{
string logFilePath = #"C:\MyLogFile.txt";
using (var streamWriter = new StreamWriter(logFilePath,
append: true))
{
var errorMessage = "Exception occurred: " +
exception.Message;
streamWriter.WriteLine(errorMessage);
Console.WriteLine(errorMessage);
}
}
}
}
Is it possible to return a bool and also rethrow an exception within the same method? Ive tried with the following code and it keeps saying that unreachable code is detected or that i cant exit the finally block.
public bool AccessToFile(string filePath)
{
FileStream source = null;
try
{
source = File.OpenRead(filePath);
source.Close();
return true;
}
catch (UnauthorizedAccessException e)
{
string unAuthorizedStatus = "User does not have sufficient access privileges to open the file: \n\r" + filePath;
unAuthorizedStatus += e.Message;
MessageBox.Show(unAuthorizedStatus, "Error Message:");
throw;
}
catch (Exception e)
{
string generalStatus = null;
if (filePath == null)
{
generalStatus = "General error: \n\r";
}
else
{
generalStatus = filePath + " failed. \n\r";
generalStatus += e.Message;
}
MessageBox.Show(generalStatus, "Error Message:");
throw;
}
finally
{
if (source != null)
{
source.Dispose();
}
}
}
Once you throw an exception, processing in your current method finishes and the exception works up the call stack. Either handle your exceptions locally and then return your boolean, or throw them and let them bubble up and handle them at the front end.