2

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:

Image of repeating "Exception thrown: 'System.Xml.XmlException'"

Screenshot:

Image of Visual studio pin-pointing the exception

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);
    }
}
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
  • 1
    Is this failing to catch when you run it normally, or only when in the debugger? – Generic Snake Oct 03 '22 at 19:53
  • 1
    Secondly, If you put a breakpoint inside the catch, and then continue after the error, what happens? Does it hit the breakpoint inside the catch or not? – Generic Snake Oct 03 '22 at 19:59
  • 1
    It fails to behave properly even in "Release" However it does catch within the 'catch (xmlException ex)' block any insite on why it might be repeating? perhaps some behavior behind 'return default(T)' that I don't understand? – Joshua Walker Oct 03 '22 at 20:56
  • 1
    I'm glad you got it! Apologies for not replying quickly. – Generic Snake Oct 04 '22 at 14:32

1 Answers1

0

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.