Live Update Configuration Manager .Net Core

For the Resgrid Open Source CAD system, I have a need to set configuration values normally managed by the configuration manager from an outside system. The requirement due to a centralized JSON config file that users can manage that flows through all the parts of the Computer Aided Dispatch system, instead of having to update and manage a half dozen config files.

Recently I’ve started migrating Resgrid from the Full .Net 4.7 Framework to .Net Standard and .Net Core 3.1. When I did the Reflection code I was using no longer worked, the element and collection fields were null and threw an error.

Full .Net Framework Version

var settings = ConfigurationManager.ConnectionStrings;
var element = typeof(ConfigurationElement).GetField("_bReadOnly", BindingFlags.Instance | BindingFlags.NonPublic);
var collection = typeof(ConfigurationElementCollection).GetField("bReadOnly", BindingFlags.Instance | BindingFlags.NonPublic);

element.SetValue(settings, false);
collection.SetValue(settings, false);

if (!configResult)
    settings.Add(new ConnectionStringSettings("ResgridContext", Configuration["ConnectionStrings:ResgridContext"]));
else
    settings.Add(new ConnectionStringSettings("ResgridContext", DataConfig.ConnectionString));

collection.SetValue(settings, true);
element.SetValue(settings, true);

The above code worked for all the .Net Framework’s I had been using it for, I believe 4+, but stopped working in .Net Core. As .Net Core was written from the ground up, I’m pretty sure the Read Only field had changed, or that the properties of the field may have changed.

.Net Core Version

var settings = ConfigurationManager.ConnectionStrings;
var element = typeof(ConfigurationElement).GetField("_readOnly", BindingFlags.Instance | BindingFlags.NonPublic);
var collection = typeof(ConfigurationElementCollection).GetField("_readOnly", BindingFlags.Instance | BindingFlags.NonPublic);

element.SetValue(settings, false);
collection.SetValue(settings, false);

// Modify the settings here
settings.Add(new ConnectionStringSettings("ResgridContext", DataConfig.ConnectionString));

collection.SetValue(settings, true);
element.SetValue(settings, true);

The code is structured the same, but with the changed in .Net Core they changed the read only flag name, which was actually two, you can see in the .Net Framework 4.7 version it was ‘_bReadyOnly’ and ‘bReadOnly’ now in .Net Core the read only flag is ‘_readOnly’ for both objects. After this change the code worked correctly.

So, how did I find the updated field name? Reflection.

var element = typeof(ConfigurationElement).GetFields(BindingFlags.Instance | BindingFlags.NonPublic);
var collection = typeof(ConfigurationElementCollection).GetFields(BindingFlags.Instance | BindingFlags.NonPublic);

In the code above, instead of calling ‘GetField’ I called ‘GetFields’ which returned an array of elements, on debugging I looked through that and find the correct name for the Read Only field for each object.

Hope this helps you out!

I’m the Founder of Resgrid an open source computer aided dispatch (CAD) solution for First Responders, Industrial and Business environments. If you or someone you know is part of a first responder organization like volunteer fire departments, career fire departments, EMS, search and rescue, CERT, public safety or disaster relief organizations check Resgrid out!

About: Shawn Jackson

I’ve spent the last 18 years in the world of Information Technology on both the IT and Development sides of the aisle. I’m currently a Software Engineer for Paylocity. In addition to working at Paylocity, I’m also the Founder of Resgrid, a cloud services company dedicated to providing logistics and management solutions to first responder organizations, volunteer and career fire departments, EMS, ambulance services, search and rescue, public safety, HAZMAT and others.