Object reference not set to an instance of an object during initialization

Vote:
 

Hi, I'm getting Object reference not set to an instance of an object during exception during initialization.

I've tried to debug it and it seems that null exception is thrown when it tries to set acl groups in

config2.Acl.Groups[group.ID] = group

it's becasue config2.Acl.Groups is null. There is an instance of Acl object but Groups property is null. Any idea how to solve this issue? What's funny is that it's working in Azure, but locally it's not.

private void InitializeConfigFilePath(string moduleName, string configFilePath, string configDirPath)
    {
      if (HttpContext.Current == null || !File.Exists(configFilePath))
        return;
      lock (this._syncObject)
      {
        ModuleConfig config1 = this.InternalGetConfig(moduleName, configFilePath);
        if (config1 == null)
          return;
        if (this._Configs.ContainsKey(moduleName))
        {
          ModuleConfig config2 = this._Configs[moduleName];
          if (config1.Acl != null && config1.Acl.Groups != null)
          {
            foreach (AclGroup group in (CollectionBase) config1.Acl.Groups)
            {
              config2.Acl.Groups[group.ID] = group;
              this.AddModuleConfigCacheDependency(moduleName, configFilePath);
            }
          }
          if (config1.Settings != null)
          {
            foreach (ModuleSetting setting in (CollectionBase) config1.Settings)
            {
              if (config2.Settings == null)
                config2.Settings = new ModuleSettingCollection();
              config2.Settings[setting.Name] = setting;
              this.AddModuleConfigCacheDependency(moduleName, configFilePath);
            }
          }
          string path = Path.Combine(configDirPath, "View");
          if (!Directory.Exists(path) || config1.Views != null)
            return;
          config2.Views = new ViewCollection();
          foreach (string file in Directory.GetFiles(path, "*.xml", SearchOption.AllDirectories))
          {
            AdminView view = ManagementContext.Current.FindView(config1.Name, Path.GetFileName(file.Replace(".xml", "")), "", config1);
            if (view != null)
            {
              config2.Views[view.ViewId] = view;
              this.AddModuleConfigCacheDependency(moduleName, file);
            }
          }
        }
        else
          this._Configs[moduleName] = config1;
      }
    }
#201863
Edited, Mar 05, 2019 16:42
Vote:
 
    private ModuleConfig InternalGetConfig(string moduleName, string filePath)
    {
      string directoryName = Path.GetDirectoryName(filePath);
      ModuleConfig moduleConfig = new ModuleConfig(moduleName);
      foreach (string file in Directory.GetFiles(directoryName, "*.config"))
      {
        if (Path.GetFileName(file).ToLowerInvariant() == "settings.config")
        {
          XmlDocument xmlDocument = new XmlDocument();
          xmlDocument.XmlResolver = (XmlResolver) null;
          xmlDocument.Load(filePath);
          XmlNode xmlNode = xmlDocument.SelectSingleNode("Configuration");
          if (xmlNode != null)
          {
            XmlNode settingsNode = xmlNode.SelectSingleNode("Settings");
            if (settingsNode != null)
            {
              moduleConfig.Acl = new Acl();
              moduleConfig.Settings = SettingManager.CreateSettingsCollection(settingsNode);
            }
          }
        }
        if (Path.GetFileName(file).ToLowerInvariant() == "permissions.config")
        {
          XmlDocument xmlDocument = new XmlDocument();
          xmlDocument.XmlResolver = (XmlResolver) null;
          xmlDocument.Load(filePath);
          XmlNode xmlNode = xmlDocument.SelectSingleNode("Configuration");
          if (xmlNode != null)
          {
            XmlNode aclNode = xmlNode.SelectSingleNode("Acl");
            if (aclNode != null)
            {
              moduleConfig.Acl = new Acl();
              moduleConfig.Acl.Groups = AclManager.CreateAclCollection(moduleConfig, aclNode);
            }
          }
        }
      }
      string path = Path.Combine(directoryName, "View");
      if (Directory.Exists(path))
      {
        moduleConfig.Views = new ViewCollection();
        foreach (string file in Directory.GetFiles(path, "*.xml", SearchOption.AllDirectories))
        {
          AdminView view = ManagementContext.Current.FindView(moduleName, Path.GetFileName(file.Replace(".xml", "")), "", moduleConfig);
          if (view != null)
          {
            moduleConfig.Views[view.ViewId] = view;
            this.AddModuleConfigCacheDependency(moduleName, file);
          }
        }
      }
      return moduleConfig;
    }

This function is used by ConfigManager to load apps configs. Could someone explain me how it supposed to work? We have filePath, base on it we get directory and list all *.config files. We iterate through them and check if file is settings.config or permissions.config and then no matter which file we found we load file which was passed at the beginning (filePath)

xmlDocument.Load(filePath);

It doesn't make sense for me, but maybe I'm wrong. I would be grateful for some explanation :)

#201867
Mar 05, 2019 17:59
Vote:
 

In azure it seems to be working but only by coincidence.

    private void InitializeConfigByFolderPath(string moduleName, string modulePath)
    {
      string str = Path.Combine(modulePath, "Config");
      if (!Directory.Exists(str))
        return;
      foreach (string file in Directory.GetFiles(str, "*.config"))
        this.InitializeConfigFilePath(moduleName, file, str);
    }

Locally Directory.GetFiles returns files in different order then in Azure, which is fine becasue GetFiles function does not guarantee the order. When permissions.config loads as the first one then everyhting is fine but if the settings.config loads first then exception is thrown.

#201885
Mar 06, 2019 9:20
Vote:
 

Hi - have you made any changes to your Commerce Manager Apps folder? If not I would suggest to replace it with a fresh copy of a CM site which matches your version 

#201917
Mar 07, 2019 8:32
Vote:
 

Hey, Quan

I've tried on a fresh copy of Quicksilver but the result is still the same. 

I've checked this with PS:

[System.IO.Directory]::GetFiles("D:/home/site/wwwroot/Apps/Markets/Config", "*.config")

And it actually returns files in different order on my local environment and Azure. On Azure Permissions.config is the first one and on my local environment the first one is Settings.config

Ordering the files in 

private void InitializeConfigByFolderPath(string moduleName, string modulePath)
    {
      string str = Path.Combine(modulePath, "Config");
      if (!Directory.Exists(str))
        return;
      foreach (string file in Directory.GetFiles(str, "*.config"))
        this.InitializeConfigFilePath(moduleName, file, str);
    }

should solve the issue. 

#201918
Mar 07, 2019 9:16
Vote:
 

Ok I found the reason. I keep my project files on mounted drive from my Macbook. When I copy files to Windows partition then it's fine, it returns files in the same order as in Azure. But still, I think it should not be dependent on environment, and we should not rely on the order of returned files. Even the Microsoft documentation says

"The order of the returned file names is not guaranteed; use the Sort method if a specific sort order is required."
#201919
Mar 07, 2019 9:29
Vote:
 

I think I understand the problem, and I think your point is valid. I'll raise a bug to look into it.

#201920
Mar 07, 2019 9:41
Vote:
 

Thanks Quan :)

#201921
Mar 07, 2019 9:50